http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNFileHandler.java
----------------------------------------------------------------------
diff --git 
a/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNFileHandler.java
 
b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNFileHandler.java
new file mode 100644
index 0000000..016d714
--- /dev/null
+++ 
b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNFileHandler.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.product.handlers.ofsn;
+
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.apache.oodt.product.LargeProductQueryHandler;
+import org.apache.oodt.product.ProductException;
+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.xmlquery.LargeResult;
+import org.apache.oodt.xmlquery.Result;
+import org.apache.oodt.xmlquery.XMLQuery;
+import org.apache.tika.mime.MediaType;
+import org.apache.tika.mime.MimeTypesFactory;
+
+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.concurrent.ConcurrentHashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+/**
+ * 
+ * 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 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 ConcurrentHashMap<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) {
+    // 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.equals("")) || (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 + "]!");
+    }
+
+    return cfg.getType().equals(LISTING_CMD);
+  }
+
+  private boolean isGetCmd(String cmd) {
+    OFSNHandlerConfig cfg = this.conf.getHandlerConfig(cmd);
+
+    return cfg.getType().equals(GET_CMD);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNFileHandlerConfiguration.java
----------------------------------------------------------------------
diff --git 
a/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNFileHandlerConfiguration.java
 
b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNFileHandlerConfiguration.java
new file mode 100644
index 0000000..46d97c9
--- /dev/null
+++ 
b/webapp/fmprod/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.concurrent.ConcurrentHashMap;
+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 ConcurrentHashMap<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) {
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNFileHandlerConfigurationReader.java
----------------------------------------------------------------------
diff --git 
a/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNFileHandlerConfigurationReader.java
 
b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNFileHandlerConfigurationReader.java
new file mode 100644
index 0000000..feeb738
--- /dev/null
+++ 
b/webapp/fmprod/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;
+  }
+}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNGetHandler.java
----------------------------------------------------------------------
diff --git 
a/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNGetHandler.java
 
b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNGetHandler.java
new file mode 100644
index 0000000..c619883
--- /dev/null
+++ 
b/webapp/fmprod/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.
+   */
+  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.
+   */
+  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.
+   */
+  void configure(Properties conf);
+
+}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNHandlerConfig.java
----------------------------------------------------------------------
diff --git 
a/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNHandlerConfig.java
 
b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNHandlerConfig.java
new file mode 100644
index 0000000..8c8aa18
--- /dev/null
+++ 
b/webapp/fmprod/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;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNListHandler.java
----------------------------------------------------------------------
diff --git 
a/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNListHandler.java
 
b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNListHandler.java
new file mode 100644
index 0000000..5e23d58
--- /dev/null
+++ 
b/webapp/fmprod/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.
+   */
+  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.
+   */
+  void configure(Properties conf);
+}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/RawSizeListHandler.java
----------------------------------------------------------------------
diff --git 
a/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/RawSizeListHandler.java
 
b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/RawSizeListHandler.java
new file mode 100644
index 0000000..883e1b5
--- /dev/null
+++ 
b/webapp/fmprod/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) };
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/SingleFileListHandler.java
----------------------------------------------------------------------
diff --git 
a/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/SingleFileListHandler.java
 
b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/SingleFileListHandler.java
new file mode 100644
index 0000000..45d559c
--- /dev/null
+++ 
b/webapp/fmprod/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) };
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/SingleZipFileListHandler.java
----------------------------------------------------------------------
diff --git 
a/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/SingleZipFileListHandler.java
 
b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/SingleZipFileListHandler.java
new file mode 100644
index 0000000..748a534
--- /dev/null
+++ 
b/webapp/fmprod/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 };
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/StdOFSNGetHandler.java
----------------------------------------------------------------------
diff --git 
a/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/StdOFSNGetHandler.java
 
b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/StdOFSNGetHandler.java
new file mode 100644
index 0000000..cb344e9
--- /dev/null
+++ 
b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/StdOFSNGetHandler.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;
+
+//JDK imports
+
+import org.apache.oodt.product.ProductException;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+
+/**
+ * 
+ * Standard way of retrieving a file without performing 
+ * any transformation on it.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class StdOFSNGetHandler implements OFSNGetHandler {
+  private static Logger LOG = 
Logger.getLogger(StdOFSNGetHandler.class.getName());
+  /*
+   * (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) {
+      LOG.log(Level.SEVERE, e.getMessage());
+      throw new ProductException("IO exception retrieving chunk of product: ["
+          + filepath + "]: Message: " + e.getMessage());
+    } finally {
+      if (in != null) {
+        try {
+          in.close();
+        } catch (Exception ignore) {
+        }
+
+      }
+    }
+
+    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    
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/URLGetHandler.java
----------------------------------------------------------------------
diff --git 
a/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/URLGetHandler.java
 
b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/URLGetHandler.java
new file mode 100644
index 0000000..20944f3
--- /dev/null
+++ 
b/webapp/fmprod/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 = "";
+       private String prodServerPort = "";
+       private String prodServerContext = "";
+       private String productRoot = "";
+       private String returnType = "";
+       
+       /*
+        * (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 (File aFileListing : fileListing) {
+               File file = (File) aFileListing;
+               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

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OFSNMetKeys.java
----------------------------------------------------------------------
diff --git 
a/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OFSNMetKeys.java
 
b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OFSNMetKeys.java
new file mode 100644
index 0000000..e56d7aa
--- /dev/null
+++ 
b/webapp/fmprod/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 {
+
+  String LISTING_CMD = "listing";
+
+  String GET_CMD = "get";
+  
+  String OFSN_XML_CONF_FILE_KEY = 
"org.apache.oodt.product.handlers.ofsn.xmlConfigFilePath";
+  
+  String OFSN_COMPUTE_DIR_SIZE = 
"org.apache.oodt.product.handlers.ofsn.computeDirSize";
+  
+  String OFSN_COMPUTE_FILE_SIZE = 
"org.apache.oodt.product.handlers.ofsn.computeFileSize";
+
+
+}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OFSNXMLConfigMetKeys.java
----------------------------------------------------------------------
diff --git 
a/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OFSNXMLConfigMetKeys.java
 
b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OFSNXMLConfigMetKeys.java
new file mode 100644
index 0000000..f4f8c53
--- /dev/null
+++ 
b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OFSNXMLConfigMetKeys.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.metadata;
+
+
+/**
+ * 
+ * Met Keys for the {@link 
org.apache.oodt.product.handlers.ofsn.OFSNFileHandlerConfigurationReader}
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public interface OFSNXMLConfigMetKeys {
+
+  String OFSN_CFG_ID_ATTR = "id";
+
+  String OFSN_CFG_NAME_ATTR = "name";
+
+  String OFSN_PRODUCT_ROOT_ATTR = "productRoot";
+
+  String HANDLER_TAG = "handler";
+
+  String HANDLER_CLASSNAME_ATTR = "class";
+
+  String HANDLER_NAME_ATTR = "name";
+
+  String HANDLER_TYPE_ATTR = "type";
+
+  String PROPERTY_TAG = "property";
+
+  String PROPERTY_NAME_ATTR = "name";
+
+  String PROPERTY_VALUE_ATTR = "value";
+  
+  /* optional handler property attributes supported by all handlers */
+  String PROPERTY_MIMETYPE_ATTR = "mimeType";
+
+}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OFSNXMLMetKeys.java
----------------------------------------------------------------------
diff --git 
a/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OFSNXMLMetKeys.java
 
b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OFSNXMLMetKeys.java
new file mode 100644
index 0000000..0bcdd75
--- /dev/null
+++ 
b/webapp/fmprod/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 {
+    
+    String DIR_RESULT_TAG = "dirResult";
+    
+    String DIR_ENTRY_TAG = "dirEntry";
+    
+    String OFSN_TAG = "OFSN";
+    
+    String FILE_SIZE_TAG = "fileSize";
+    
+    String XML_MIME_TYPE = "text/xml";
+    
+    // FIXME: change namespace URI?
+    String DIR_LISTING_NS = 
"http://oodt.jpl.nasa.gov/xml/namespaces/dirlist/1.0";;
+
+}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OODTMetKeys.java
----------------------------------------------------------------------
diff --git 
a/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OODTMetKeys.java
 
b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OODTMetKeys.java
new file mode 100644
index 0000000..56ff703
--- /dev/null
+++ 
b/webapp/fmprod/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 {
+    
+    String XMLQUERY_QUERYELEM_ROLE_ELEM = "elemName";
+
+}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/XMLQueryMetKeys.java
----------------------------------------------------------------------
diff --git 
a/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/XMLQueryMetKeys.java
 
b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/XMLQueryMetKeys.java
new file mode 100644
index 0000000..b9f1f79
--- /dev/null
+++ 
b/webapp/fmprod/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 {
+    
+    String OFSN = "OFSN";
+    
+    String RETURN_TYPE = "RT";
+}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/util/OFSNObjectFactory.java
----------------------------------------------------------------------
diff --git 
a/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/util/OFSNObjectFactory.java
 
b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/util/OFSNObjectFactory.java
new file mode 100644
index 0000000..6de92e9
--- /dev/null
+++ 
b/webapp/fmprod/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) {
+      LOG.log(Level.SEVERE, e.getMessage());
+      LOG.log(Level.WARNING,
+          "ClassNotFoundException when loading list handler class " + className
+              + " Message: " + e.getMessage());
+    } catch (InstantiationException e) {
+      LOG.log(Level.SEVERE, e.getMessage());
+      LOG.log(Level.WARNING,
+          "InstantiationException when loading list handler class " + className
+              + " Message: " + e.getMessage());
+    } catch (IllegalAccessException e) {
+      LOG.log(Level.SEVERE, e.getMessage());
+      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) {
+      LOG.log(Level.SEVERE, e.getMessage());
+      LOG.log(Level.WARNING,
+          "ClassNotFoundException when loading get handler class " + className
+              + " Message: " + e.getMessage());
+    } catch (InstantiationException e) {
+      LOG.log(Level.SEVERE, e.getMessage());
+      LOG.log(Level.WARNING,
+          "InstantiationException when loading get handler class " + className
+              + " Message: " + e.getMessage());
+    } catch (IllegalAccessException e) {
+      LOG.log(Level.SEVERE, e.getMessage());
+      LOG.log(Level.WARNING,
+          "IllegalAccessException when loading get handler class " + className
+              + " Message: " + e.getMessage());
+    }
+
+    return null;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/util/OFSNUtils.java
----------------------------------------------------------------------
diff --git 
a/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/util/OFSNUtils.java
 
b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/util/OFSNUtils.java
new file mode 100644
index 0000000..b8b4583
--- /dev/null
+++ 
b/webapp/fmprod/src/main/java/org/apache/oodt/product/handlers/ofsn/util/OFSNUtils.java
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.commons.io.FileUtils;
+import org.apache.commons.io.FilenameUtils;
+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;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+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.logging.Level;
+import java.util.logging.Logger;
+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;
+
+//JDK imports
+//APACHE imports
+
+/**
+ * 
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public final class OFSNUtils implements OODTMetKeys, OFSNXMLMetKeys,
+    OFSNMetKeys {
+  public static final int INT = 1024;
+  private static Logger LOG = Logger.getLogger(OFSNUtils.class.getName());
+  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;
+
+    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) {
+      LOG.log(Level.SEVERE, e.getMessage());
+      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[INT];
+    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) {
+      LOG.log(Level.SEVERE, e.getMessage());
+    } finally {
+      if (out != null) {
+        try {
+          out.close();
+        } catch (Exception ignore) {
+        }
+
+      }
+    }
+
+    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();
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/ByteArrayCodec.java
----------------------------------------------------------------------
diff --git 
a/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/ByteArrayCodec.java 
b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/ByteArrayCodec.java
new file mode 100755
index 0000000..356b468
--- /dev/null
+++ b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/ByteArrayCodec.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.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;
+       }
+}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/ChunkedProductInputStream.java
----------------------------------------------------------------------
diff --git 
a/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/ChunkedProductInputStream.java
 
b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/ChunkedProductInputStream.java
new file mode 100644
index 0000000..f4376f0
--- /dev/null
+++ 
b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/ChunkedProductInputStream.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.xmlquery;
+
+import org.apache.oodt.product.ProductException;
+import org.apache.oodt.product.Retriever;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * 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?
+         retriever.close(id);                                         // Tell 
retriever we're done
+         open = false;                                                // Flag 
it
+       }
+
+       /**
+        * 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 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;
+
+  public static final int VAL = 4096;
+  /** Size of chunks. */
+       private static final int BLOCK_SIZE = 
Integer.getInteger("org.apache.oodt.xmlquery.blockSize", VAL);
+}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/Codec.java
----------------------------------------------------------------------
diff --git a/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/Codec.java 
b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/Codec.java
new file mode 100755
index 0000000..febcbba
--- /dev/null
+++ b/webapp/fmprod/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;
+}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/CodecFactory.java
----------------------------------------------------------------------
diff --git 
a/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/CodecFactory.java 
b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/CodecFactory.java
new file mode 100755
index 0000000..658617c
--- /dev/null
+++ b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/CodecFactory.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.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/** 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 ConcurrentHashMap();
+}

Reply via email to