oodt-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mattm...@apache.org
Subject [5/6] oodt git commit: - add in xmlquery and product handler code necessary to build this app
Date Sun, 16 Jul 2017 18:33:34 GMT
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();
+}


Mime
View raw message