You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@oodt.apache.org by ma...@apache.org on 2010/09/03 03:17:58 UTC

svn commit: r992166 [1/2] - in /incubator/oodt/trunk: ./ grid/ grid/src/ grid/src/main/ grid/src/main/java/ grid/src/main/java/org/ grid/src/main/java/org/apache/ grid/src/main/java/org/apache/oodt/ grid/src/main/java/org/apache/oodt/grid/ grid/src/mai...

Author: mattmann
Date: Fri Sep  3 01:17:56 2010
New Revision: 992166

URL: http://svn.apache.org/viewvc?rev=992166&view=rev
Log:
- fix for OODT-27 Import Web Grid component

Added:
    incubator/oodt/trunk/grid/
    incubator/oodt/trunk/grid/pom.xml
    incubator/oodt/trunk/grid/src/
    incubator/oodt/trunk/grid/src/main/
    incubator/oodt/trunk/grid/src/main/java/
    incubator/oodt/trunk/grid/src/main/java/org/
    incubator/oodt/trunk/grid/src/main/java/org/apache/
    incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/
    incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/
    incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/AuthenticationRequiredException.java   (with props)
    incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ConfigBean.java   (with props)
    incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ConfigServlet.java   (with props)
    incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/Configuration.java   (with props)
    incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/GridServlet.java   (with props)
    incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/LoginServlet.java   (with props)
    incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProductQueryServlet.java   (with props)
    incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProductServer.java   (with props)
    incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProfileQueryServlet.java   (with props)
    incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProfileServer.java   (with props)
    incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/QueryServlet.java   (with props)
    incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/Server.java   (with props)
    incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/Utility.java   (with props)
    incubator/oodt/trunk/grid/src/main/webapp/
    incubator/oodt/trunk/grid/src/main/webapp/META-INF/
    incubator/oodt/trunk/grid/src/main/webapp/META-INF/context.xml   (with props)
    incubator/oodt/trunk/grid/src/main/webapp/WEB-INF/
    incubator/oodt/trunk/grid/src/main/webapp/WEB-INF/jetty-web.xml   (with props)
    incubator/oodt/trunk/grid/src/main/webapp/WEB-INF/web.xml   (with props)
    incubator/oodt/trunk/grid/src/main/webapp/config.jsp   (with props)
    incubator/oodt/trunk/grid/src/main/webapp/error.jsp   (with props)
    incubator/oodt/trunk/grid/src/main/webapp/images/
    incubator/oodt/trunk/grid/src/main/webapp/images/webapp-large.png   (with props)
    incubator/oodt/trunk/grid/src/main/webapp/images/webapp-small.png   (with props)
    incubator/oodt/trunk/grid/src/main/webapp/index.html   (with props)
    incubator/oodt/trunk/grid/src/main/webapp/style.css   (with props)
    incubator/oodt/trunk/grid/src/site/
    incubator/oodt/trunk/grid/src/site/resources/
    incubator/oodt/trunk/grid/src/site/resources/images/
    incubator/oodt/trunk/grid/src/site/resources/images/web-grid.jpg   (with props)
    incubator/oodt/trunk/grid/src/site/resources/images/web-grid.psd   (with props)
    incubator/oodt/trunk/grid/src/site/resources/slides.pdf   (with props)
    incubator/oodt/trunk/grid/src/site/site.xml
    incubator/oodt/trunk/grid/src/site/xdoc/
    incubator/oodt/trunk/grid/src/site/xdoc/index.xml   (with props)
    incubator/oodt/trunk/grid/src/test/
    incubator/oodt/trunk/grid/src/test/org/
    incubator/oodt/trunk/grid/src/test/org/apache/
    incubator/oodt/trunk/grid/src/test/org/apache/oodt/
    incubator/oodt/trunk/grid/src/test/org/apache/oodt/grid/
    incubator/oodt/trunk/grid/src/test/org/apache/oodt/grid/ConfigurationTest.java   (with props)
Modified:
    incubator/oodt/trunk/CHANGES.txt

Modified: incubator/oodt/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/incubator/oodt/trunk/CHANGES.txt?rev=992166&r1=992165&r2=992166&view=diff
==============================================================================
--- incubator/oodt/trunk/CHANGES.txt (original)
+++ incubator/oodt/trunk/CHANGES.txt Fri Sep  3 01:17:56 2010
@@ -5,6 +5,8 @@ Apache OODT Change Log
 Release 0.1-incubating - Current Development
 --------------------------------------------
 
+* OODT-27 Import Web Grid component (David Kale, mattmann)
+
 * OODT-26 Typo identified in basic user's guide (Rishi Verma via mattmann)
 
 * OODT-16 OODT website (kelly)

Added: incubator/oodt/trunk/grid/pom.xml
URL: http://svn.apache.org/viewvc/incubator/oodt/trunk/grid/pom.xml?rev=992166&view=auto
==============================================================================
--- incubator/oodt/trunk/grid/pom.xml (added)
+++ incubator/oodt/trunk/grid/pom.xml Fri Sep  3 01:17:56 2010
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt file distributed with this work for
+additional information regarding copyright ownership.  The ASF licenses this
+file to you under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License.  You may obtain a copy of
+the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+<project>
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>${oodt.version}</version>
+    <relativePath>../core/pom.xml</relativePath>
+  </parent>
+  <artifactId>web-grid</artifactId>
+  <name>OODT Web Grid</name>
+  <packaging>war</packaging>
+  <description>The OODT grid services (product and profile services) use CORBA or
+    RMI as their underlying network transport.  However, limitations
+    of CORBA and RMI make them inappropriate for large-scale
+    deployments.  For one, both are procedural mechanisms, providing a
+    remote interface that resembles a method call.  This makes
+    streaming of data from a service impossible, because there are
+    limitations to the sizes of data structures that can be passed
+    over a remote method call.  Instead, repeated calls must be made
+    to retrieve each block of a product, making transfer speeds
+    horribly slow compared to HTTP or FTP.  (Block-based retrieval of
+    profiles was never implemented, resulting in out of memory
+    conditions for large profile results, which is another problem.)
+    Second, both CORBA and RMI rely on a central name registry.  The
+    registry makes an object independent of its network location,
+    enabling a client to call it by name (looking up its last known
+    location in the registry).  However, this requires that server
+    objects be able to make outbound network calls to the registry
+    (through any outbound firewall), and that the registry accept
+    those registrations (through any inbound firewall).  This required
+    administrative action at institutions hosting server objects and
+    at the institution hosting the registry.  Often, these firewall
+    exceptions would change without notice as system adminstrators
+    changed at each location (apparently firewall exceptions are
+    poorly documented everywhere).  Further, in the two major
+    deployments of OODT (PDS and EDRN), server objects have almost
+    never moved, nullifying any benefit of the registry.  This
+    project, OODT Web Grid Services, avoids the prolems of CORBA and
+    RMI by using HTTP as the transport mechanism for products and
+    profiles.  Further, it provides a password-protected mechanism to
+    add new sets of product and profile query handlers, enabling
+    seamless activation of additional capabilities.</description>
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-war-plugin</artifactId>
+        <configuration>
+          <webResources/>
+          <warSourceDirectory>src/main/webapp</warSourceDirectory>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>oodt-commons</artifactId>
+      <version>${oodt.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>oodt-profile</artifactId>
+      <version>${oodt.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>oodt-product</artifactId>
+      <version>${oodt.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>oodt-xmlquery</artifactId>
+      <version>${oodt.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.hp.hpl.jena</groupId>
+      <artifactId>jena</artifactId>
+      <version>2.6.3</version>
+    </dependency>
+    <dependency>
+       <groupId>servletapi</groupId>
+       <artifactId>servletapi</artifactId>
+       <version>2.4</version>
+       <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.2</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+        <groupId>xerces</groupId>
+        <artifactId>xerces</artifactId>
+        <version>2.4.0</version>
+    </dependency>
+    <dependency>
+      <groupId>xerces</groupId>
+      <artifactId>xercesImpl</artifactId>
+      <version>2.9.1</version>
+    </dependency>
+    <dependency>
+        <groupId>xalan</groupId>
+        <artifactId>xalan</artifactId>
+        <version>2.7.1</version>
+    </dependency>
+  </dependencies>
+</project>

Added: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/AuthenticationRequiredException.java
URL: http://svn.apache.org/viewvc/incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/AuthenticationRequiredException.java?rev=992166&view=auto
==============================================================================
--- incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/AuthenticationRequiredException.java (added)
+++ incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/AuthenticationRequiredException.java Fri Sep  3 01:17:56 2010
@@ -0,0 +1,30 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oodt.grid;
+
+/**
+ * Exception thrown to indicate that authentication is required to continue.
+ */
+public class AuthenticationRequiredException extends Exception {
+  /**
+   * Creates a new <code>AuthenticationRequiredException</code> instance.
+   */
+  public AuthenticationRequiredException() {
+    super("Authentication required");
+  }
+}

Propchange: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/AuthenticationRequiredException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/AuthenticationRequiredException.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ConfigBean.java
URL: http://svn.apache.org/viewvc/incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ConfigBean.java?rev=992166&view=auto
==============================================================================
--- incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ConfigBean.java (added)
+++ incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ConfigBean.java Fri Sep  3 01:17:56 2010
@@ -0,0 +1,175 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oodt.grid;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * Bean containing login status for and configuration info.
+ */
+public class ConfigBean implements Serializable {
+  /**
+   * Return true is administrator is authenticated.
+   * 
+   * @return True if authentic, false otherwise.
+   */
+  public boolean isAuthentic() {
+    return authentic;
+  }
+
+  /**
+   * Set whether the administrator's been authenticated.
+   * 
+   * @param authentic
+   *          True if authentic, false otherwise.
+   */
+  void setAuthentic(boolean authentic) {
+    this.authentic = authentic;
+  }
+
+  /**
+   * Get any message to display. This should never be null.
+   * 
+   * @return A message to display
+   */
+  public String getMessage() {
+    return message;
+  }
+
+  /**
+   * Set the message to display.
+   * 
+   * @param message
+   *          Message to display.
+   */
+  public void setMessage(String message) {
+    if (message == null)
+      throw new IllegalArgumentException("message cannot be null");
+    this.message = message;
+  }
+
+  /**
+   * Get the configuration of web-grid.
+   * 
+   * @return a <code>Configuration</code> value.
+   * @throws AuthenticationRequiredException
+   *           if the administrator's not authenticated.
+   */
+  public Configuration getConfiguration()
+      throws AuthenticationRequiredException {
+    checkAuthenticity();
+    return configuration;
+  }
+
+  /**
+   * Tell if HTTPS is required to access the web-grid configuration.
+   * 
+   * @return True if HTTPS is required to access the web-grid configuration.
+   * @throws AuthenticationRequiredException
+   *           if the administrator's not authenticated.
+   */
+  public boolean isHttpsRequired() throws AuthenticationRequiredException {
+    checkAuthenticity();
+    return configuration.isHTTPSrequired();
+  }
+
+  /**
+   * Tell if admin access can come only from the localhost.
+   * 
+   * @return True if admin access can come only from the localhost.
+   * @throws AuthenticationRequiredException
+   *           if the administrator's not authenticated.
+   */
+  public boolean isLocalhostRequired() throws AuthenticationRequiredException {
+    checkAuthenticity();
+    return configuration.isLocalhostRequired();
+  }
+
+  /**
+   * Get the list of {@link ProductServer}s that have been installed in this
+   * container.
+   * 
+   * @return a <code>List</code> of {@link ProductServer}s.
+   * @throws AuthenticationRequiredException
+   *           if the administrator's not authenticated.
+   */
+  public List getProductServers() throws AuthenticationRequiredException {
+    checkAuthenticity();
+    return configuration.getProductServers();
+  }
+
+  /**
+   * Get the list of {@link ProfileServer}s that have been installed in this
+   * container.
+   * 
+   * @return a <code>List</code> of {@link ProfileServer}s.
+   * @throws AuthenticationRequiredException
+   *           if the administrator's not authenticated.
+   */
+  public List getProfileServers() throws AuthenticationRequiredException {
+    checkAuthenticity();
+    return configuration.getProfileServers();
+  }
+
+  /**
+   * Set the configuration this bean will use.
+   * 
+   * @param configuration
+   *          a <code>Configuration</code> value.
+   */
+  void setConfiguration(Configuration configuration) {
+    this.configuration = configuration;
+  }
+
+  /**
+   * Get the properties defined for this container.
+   * 
+   * @return a <code>Properties</code> value.
+   * @throws AuthenticationRequiredException
+   *           if the administrator's not authenticated.
+   */
+  public Properties getProperties() throws AuthenticationRequiredException {
+    checkAuthenticity();
+    return configuration.getProperties();
+  }
+
+  /**
+   * Check if the administrator is authentic. This method does nothing if the
+   * administrator is authentic, but throws an exception if not.
+   * 
+   * @throws AuthenticationRequiredException
+   *           if the administrator's not authenticated.
+   */
+  private void checkAuthenticity() throws AuthenticationRequiredException {
+    if (isAuthentic() && configuration != null)
+      return;
+    message = "";
+    throw new AuthenticationRequiredException();
+  }
+
+  /** True if administrator is authentic. */
+  private boolean authentic;
+
+  /** Any message to display. */
+  private String message = "";
+
+  /** The configuration for this container. */
+  private transient Configuration configuration;
+}

Propchange: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ConfigBean.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ConfigBean.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ConfigServlet.java
URL: http://svn.apache.org/viewvc/incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ConfigServlet.java?rev=992166&view=auto
==============================================================================
--- incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ConfigServlet.java (added)
+++ incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ConfigServlet.java Fri Sep  3 01:17:56 2010
@@ -0,0 +1,303 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oodt.grid;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Controller servlet for making changes to configuration.
+ */
+public class ConfigServlet extends GridServlet {
+  /**
+   * Handle updates to a configuration by saving them and directing back to the
+   * config page.
+   * 
+   * @param req
+   *          a <code>HttpServletRequest</code> value.
+   * @param res
+   *          a <code>HttpServletResponse</code> value.
+   * @throws ServletException
+   *           if an error occurs.
+   * @throws IOException
+   *           if an error occurs.
+   */
+  public void doPost(HttpServletRequest req, HttpServletResponse res)
+      throws ServletException, IOException {
+    Configuration config = getConfiguration(); // Get the singleton
+                                               // configuration
+    if (!approveAccess(config, req, res))
+      return; // Check if the user can access this page
+
+    ConfigBean cb = getConfigBean(req); // Get the bean
+    cb.setMessage(""); // Clear out any message
+    if (!cb.isAuthentic())
+      throw new ServletException(new AuthenticationRequiredException());
+    boolean needSave = false; // Assume no changes for now
+
+    String newPass = req.getParameter("password"); // See if she wants to change
+                                                   // password
+    if (newPass != null && newPass.length() > 0) { // Got a password, and it's
+                                                   // not empty?
+      config.setPassword(newPass.getBytes()); // Yes, set its bytes
+      needSave = true; // We need to save
+    }
+
+    boolean https = config.isHTTPSrequired(); // Are we currently using https?
+    String httpsParam = req.getParameter("https"); // Get her https param
+    boolean newHttps = httpsParam != null && "on".equals(httpsParam); // See if
+                                                                      // she
+                                                                      // wants
+                                                                      // to use
+                                                                      // https
+                                                                      // or not
+    if (https != newHttps) { // Different?
+      config.setHTTPSrequired(newHttps); // Yes, set the new state
+      needSave = true; // We need to save
+    }
+
+    boolean local = config.isLocalhostRequired(); // Are we requiring localhost?
+    String localhostParam = req.getParameter("localhost"); // Get her localhost
+                                                           // param
+    boolean newLocal = localhostParam != null && "on".equals(localhostParam); // See
+                                                                              // if
+                                                                              // she
+                                                                              // wants
+                                                                              // to
+                                                                              // require
+                                                                              // localhost
+    if (local != newLocal) { // Different?
+      config.setLocalhostRequired(newLocal); // Yes, set the new state
+      needSave = true; // We need to save
+    }
+
+    String newKey = req.getParameter("newkey"); // See if she's got a new
+                                                // property
+    if (newKey != null && newKey.length() > 0) { // And make sure it's nonempty
+      String newVal = req.getParameter("newval"); // Got one, get its value
+      if (newVal == null)
+        newVal = ""; // Make sure it's at least an empty string
+      config.getProperties().setProperty(newKey, newVal); // Set the new
+                                                          // property
+      needSave = true; // We need to save
+    }
+
+    needSave |= updateProperties(config.getProperties(), // Make any updates to
+                                                         // existing property
+        req.getParameterMap()); // values, and see note if we need to save
+    try {
+      needSave |= updateServers(config, req.getParameterMap(), 'd'); // Same
+                                                                     // goes for
+                                                                     // product
+                                                                     // servers
+      needSave |= updateServers(config, req.getParameterMap(), 'm'); // And
+                                                                     // profile
+                                                                     // servers
+      needSave |= updateCodeBases(config, req.getParameterMap()); // And for
+                                                                  // code bases
+    } catch (MalformedURLException ex) { // Make sure code base URLs are OK
+      cb.setMessage("Code bases must be valid URLs (" // Not OK?
+          + ex.getMessage() + "); no changes made"); // Let user know via a
+                                                     // message
+      req.getRequestDispatcher("config.jsp").forward(req, res); // And make no
+                                                                // changes until
+                                                                // she fixes it
+      return;
+    }
+
+    if (needSave) { // Do we need to save?
+      config.save(); // Then do it already!
+      cb.setMessage("Changes saved."); // And let the user know
+    } else {
+      cb.setMessage("No changes made."); // Oh, no changes were made, let user
+                                         // know
+    }
+    req.getRequestDispatcher("config.jsp").forward(req, res); // Back to the
+                                                              // config page
+  }
+
+  /**
+   * Update changes to the code bases.
+   * 
+   * @param config
+   *          a <code>Configuration</code> value.
+   * @param params
+   *          a <code>Map</code> value.
+   * @return True if changes need to be saved.
+   * @throws MalformedURLException
+   *           if an error occurs.
+   */
+  private boolean updateCodeBases(Configuration config, Map params)
+      throws MalformedURLException {
+    boolean needSave = false; // Assume no change
+    List codeBases = config.getCodeBases(); // Get the current code bases
+
+    List toRemove = new ArrayList(); // Hold indexes of code bases to remove
+    for (Iterator i = params.entrySet().iterator(); i.hasNext();) { // For each
+                                                                    // parameter
+      Map.Entry entry = (Map.Entry) i.next(); // Get its entry
+      String key = (String) entry.getKey(); // And its name
+      String value = ((String[]) entry.getValue())[0]; // And its zeroth value
+      if (key.startsWith("delcb-") && "on".equals(value)) { // If it's checked
+        Integer index = new Integer(key.substring(6)); // Parse out the index
+        toRemove.add(index); // Add it to the list
+      }
+    }
+    if (!toRemove.isEmpty()) { // And if we have any indexes
+      Collections.sort(toRemove); // Sort 'em and put 'em in reverse ...
+      Collections.reverse(toRemove); // ... order so we can safely remove them
+      for (Iterator i = toRemove.iterator(); i.hasNext();) { // For each index
+                                                             // to remove
+        int index = ((Integer) i.next()).intValue(); // Get the index value
+        codeBases.remove(index); // And buh-bye.
+      }
+      needSave = true; // Definitely need to save changes now
+    }
+
+    String[] newCBs = (String[]) params.get("newcb"); // Was there a new code
+                                                      // base specified?
+    if (newCBs != null && newCBs.length == 1) { // And was there exactly one
+                                                // value?
+      String newCB = newCBs[0]; // Get that exactly one value
+      if (newCB != null && newCB.length() > 0) { // Is it nonnull and nonempty?
+        URL newURL = new URL(newCB); // Treat is as an URL
+        codeBases.add(newURL); // Add it to the list
+        needSave = true; // Ad we gotta save
+      }
+    }
+    return needSave;
+  }
+
+  /**
+   * Update the list of product/profile servers based on request parameters.
+   * 
+   * @param config
+   *          System configuration
+   * @param params
+   *          Request parameters.
+   * @param type
+   *          <code>d</code> (data) if product servers, <code>m</code>
+   *          (metadata) if profile servers
+   * @return True if any changes were made, false if no changes were made
+   */
+  private boolean updateServers(Configuration config, Map params, char type) {
+    List servers = type == 'd' ? config.getProductServers() : config
+        .getProfileServers();
+    boolean needSave = false; // Assume no changes for now
+
+    List toRemove = new ArrayList(); // Start with empty list of indexes to
+                                     // remove
+    for (Iterator i = params.entrySet().iterator(); i.hasNext();) { // Go
+                                                                    // through
+                                                                    // each
+                                                                    // parameter
+      Map.Entry entry = (Map.Entry) i.next(); // Get its key/value
+      String name = (String) entry.getKey(); // The key is a String
+      if (name.startsWith(type + "rm-")) { // Is it an "drm-" or "mrm-"?
+        Integer index = new Integer(name.substring(4)); // Yes, get it sindex
+        toRemove.add(index); // Add it to the list
+      }
+    }
+
+    if (!toRemove.isEmpty()) { // Got any to remove?
+      Collections.sort(toRemove); // We need to go through them in reverse ord-
+      Collections.reverse(toRemove); // -er, so that removals don't shift
+                                     // indexes
+      for (Iterator i = toRemove.iterator(); i.hasNext();) { // For each index
+        int index = ((Integer) i.next()).intValue(); // Get its int value
+        servers.remove(index); // and buh-bye
+      }
+      needSave = true; // Gotta save after all that, whew.
+    }
+
+    if (params.containsKey(type + "-newcn")) { // Adding a new server?
+      String[] newClasses = (String[]) params.get(type + "-newcn"); // And the
+                                                                    // new class
+                                                                    // name
+      if (newClasses != null && newClasses.length == 1) { // Are present and
+                                                          // there's only one of
+                                                          // each
+        String newClass = newClasses[0]; // Get the new class
+        if (newClass != null && newClass.length() > 0) { // And nonempty
+          Server server;
+          if (type == 'd') // If it's data
+            server = new ProductServer(config, newClass); // It's a product
+                                                          // server
+          else
+            // otherwise it's metadata
+            server = new ProfileServer(config, newClass); // Which is a profile
+                                                          // server
+          servers.add(server); // Add it to the set of servers
+          needSave = true; // And after all this, we need to save!
+        }
+      }
+    }
+
+    return needSave;
+  }
+
+  /**
+   * Update properties based on request parameters.
+   * 
+   * @param props
+   *          <code>Properties</code> to update
+   * @param params
+   *          Request parameters
+   * @return True if changes need to be saved, false otherwise
+   */
+  private boolean updateProperties(Properties props, Map params) {
+    boolean needSave = false; // Assume no save for now
+    for (Iterator i = params.entrySet().iterator(); i.hasNext();) { // Go
+                                                                    // through
+                                                                    // each
+                                                                    // request
+                                                                    // parameter
+      Map.Entry entry = (Map.Entry) i.next(); // Get the key/value
+      String name = (String) entry.getKey(); // Key is always a string
+      String newValue = ((String[]) entry.getValue())[0]; // Value is String[],
+                                                          // get the zeroth
+      if (name.startsWith("val-")) { // If the param is "val-"
+        String key = name.substring(4); // Then find the key
+        if (props.containsKey(key)) { // If that key exists
+          String value = props.getProperty(key); // Find its value
+          if (value == null || !value.equals(newValue)) {// Are they different?
+            props.setProperty(key, newValue); // Yes, set the new value
+            needSave = true; // And we need to save
+          }
+        }
+      } else if (name.startsWith("del-")) { // If the param is "del-"
+        String key = name.substring(4); // Then find the key
+        if (props.containsKey(key)) { // If that key exists
+          props.remove(key); // Then remove its mapping
+          needSave = true; // And we need to save
+        }
+      }
+    }
+    return needSave;
+  }
+}

Propchange: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ConfigServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ConfigServlet.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/Configuration.java
URL: http://svn.apache.org/viewvc/incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/Configuration.java?rev=992166&view=auto
==============================================================================
--- incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/Configuration.java (added)
+++ incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/Configuration.java Fri Sep  3 01:17:56 2010
@@ -0,0 +1,443 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oodt.grid;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Serializable;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.xml.sax.SAXException;
+
+import org.apache.oodt.commons.util.Base64;
+
+/**
+ * web-grid configuration. This holds all the runtime configuration of profile servers,
+ * product servers, properties, and other settings for the web-grid container.
+ *
+ */
+public class Configuration implements Serializable {
+    /**
+     * Creates a new <code>Configuration</code> instance.
+     *
+     * @param file File containing the serialized configuration.
+     * @throws IOException if an I/O error occurs.
+     * @throws SAXException if the file can't be parsed.
+     */
+    public Configuration(File file) throws IOException, SAXException {
+        this.file = file;
+        if (file.isFile() && file.length() > 0)
+            parse(file);
+    }
+
+    /**
+     * Convert the configuration to XML.
+     *
+     * @param owner Owning document.
+     * @return XML representation of this configuration.
+     */
+    public Node toXML(Document owner) {
+        Element elem = owner.createElement("configuration");                    // <configuration>
+        elem.setAttribute("xmlns", NS);                                         // Set default namespace
+        elem.setAttribute("https", httpsRequired? "true" : "false");            // Add https attribute
+        elem.setAttribute("localhost", localhostRequired? "true" : "false");    // Add localhost attribute
+
+        if (password != null && password.length > 0)                            // If we have a password
+            elem.setAttribute("password", encode(password));                    // Add passowrd attribute
+
+        for (Iterator i = productServers.iterator(); i.hasNext();) {            // For each product server
+            ProductServer ps = (ProductServer) i.next();                        // Get the product server
+            elem.appendChild(ps.toXML(owner));                                  // And add it under <configuration>
+        }
+
+        for (Iterator i = profileServers.iterator(); i.hasNext();) {            // For each profile server
+            ProfileServer ps = (ProfileServer) i.next();                        // Get the profile server
+            elem.appendChild(ps.toXML(owner));                                  // And add it under the <configuration>
+        }
+
+        if (!codeBases.isEmpty()) {                                             // Got any code bases?
+            Element cbs = owner.createElement("codeBases");                     // Boo yah.  Make a parent for 'em
+            elem.appendChild(cbs);                                              // Add parent
+            for (Iterator i = codeBases.iterator(); i.hasNext();) {             // Then, for each code base
+                URL url = (URL) i.next();                                       // Get the URL to it
+                Element cb = owner.createElement("codeBase");                   // And make a <codeBase> for it
+                cb.setAttribute("url", url.toString());                         // And an "url" attribute
+                cbs.appendChild(cb);                                            // Add it
+            }
+        }
+
+        if (!properties.isEmpty()) {                                            // If we have any properties>
+            Element props = owner.createElement("properties");                  // Add <properties> under <configuration>
+            props.setAttribute("xml:space", "preserve");                        // And make sure space is properly preserved
+            elem.appendChild(props);                                            // Add the space attribute
+            for (Iterator i = properties.entrySet().iterator(); i.hasNext();) { // For each property
+                Map.Entry entry = (Map.Entry) i.next();                         // Get the property key/value pair
+                String key = (String) entry.getKey();                           // Key is always a String
+                String value = (String) entry.getValue();                       // So is the value
+                Element prop = owner.createElement("property");                 // Create a <property> element
+                props.appendChild(prop);                                        // Add it under the <properties>
+                prop.setAttribute("key", key);                                  // Set the key as an attribute
+                Text text = owner.createTextNode(value);                        // Make text to hold the value
+                prop.appendChild(text);                                         // Add it under the <property>
+            }
+        }
+        return elem;
+    }
+
+    /**
+     * Get the properties.
+     *
+     * @return a <code>Properties</code> value.
+     */
+    public Properties getProperties() {
+        return properties;
+    }
+
+    /**
+     * Is localhost access required for the configuration?
+     *
+     * @return True if the configuration must be accessed from the localhost, false otherwise.
+     */
+    public boolean isLocalhostRequired() {
+        return localhostRequired;
+    }
+
+    /**
+     * Is https access required for the configuration?
+     *
+     * @return True if the configuration must be accessed via https, false if http is OK.
+     */
+    public boolean isHTTPSrequired() {
+        return httpsRequired;
+    }
+
+    /**
+     * Set if https is required to access the configuration.
+     *
+     * @param required True if the configuration must be accessed via https, false if http is OK.
+     */
+    public void setHTTPSrequired(boolean required) {
+        httpsRequired = required;
+    }
+
+    /**
+     * Set if localhost is required to access the configuration.
+     *
+     * @param required True if the configuration must be accessed from the localhost, false otherwise.
+     */
+    public void setLocalhostRequired(boolean required) {
+        localhostRequired = required;
+    }
+
+    /**
+     * Return the code bases.
+     *
+     * @return a <code>List</code> of {@link URL}s.
+     */
+    public List getCodeBases() {
+        return codeBases;
+    }
+
+    /**
+     * Get the product servers.
+     *
+     * @return a <code>List</code> of {@link ProductServer}s.
+     */
+    public List getProductServers() {
+        return productServers;
+    }
+
+    /**
+     * Get the profile servers.
+     *
+     * @return a <code>List</code> of {@link ProfileServer}s.
+     */
+    public List getProfileServers() {
+        return profileServers;
+    }
+
+    /**
+     * Get the administrator password.
+     *
+     * @return Administrator password.
+     */
+    public byte[] getPassword() {
+        return password;
+    }
+
+    /**
+     * Set the administrator password.
+     *
+     * @param password Administrator password.
+     */
+    public void setPassword(byte[] password) {
+        if (password == null)
+            throw new IllegalArgumentException("Non-null passwords not allowed");
+        this.password = password;
+    }
+
+    /**
+     * Save the configuration.
+     *
+     * @throws IOException if an I/O error occurs.
+     */
+    public synchronized void save() throws IOException {
+        BufferedWriter writer = null;                           // Start w/no writer
+        try {                                                   // Then try ...
+            writer = new BufferedWriter(new FileWriter(file));  // Create a writer
+            Document doc;                                       // As for the doc...
+            synchronized (DOCUMENT_BUILDER) {                   // Using the document builder...
+                doc = DOCUMENT_BUILDER.newDocument();           // Create an empty document
+            }
+            Node root = toXML(doc);                             // Convert this config to XML
+            doc.appendChild(root);                              // Add it to the doc
+            DOMSource source = new DOMSource(doc);              // Use the source Luke
+            StreamResult result = new StreamResult(writer);     // And serialize it to the writer
+            TRANSFORMER.transform(source, result);              // Serialize
+        } catch (TransformerException ex) {
+            throw new IllegalStateException("Unexpected TransformerException: " + ex.getMessage());
+        } finally {
+            if (writer != null) try {                           // And if we got a writer, try ...
+                writer.close();                                 // to close it
+            } catch (IOException ignore) {}                     // Ignoring any error
+        }
+    }
+
+    /**
+     * Parse a serialized configuration document.
+     *
+     * @param file File to parse
+     * @throws IOException if an I/O error occurs.
+     * @throws SAXException if a parse error occurs.
+     */
+    private void parse(File file) throws IOException, SAXException {
+        Document doc;                                                               // Start with a doc ...
+        synchronized (DOCUMENT_BUILDER) {                                           // And using the DOCUMENT_BUILDER
+            doc = DOCUMENT_BUILDER.parse(file);                                     // Try to parse the file
+        }
+        Element root = doc.getDocumentElement();                                    // Assume the root element is <configuration>
+
+        String httpsAttr = root.getAttribute("https");                              // Get the https attribute
+        httpsRequired = httpsAttr != null && "true".equals(httpsAttr);              // See if it's "true"
+
+        String localhostAttr = root.getAttribute("localhost");                      // Get the localhost attribute
+        localhostRequired = localhostAttr != null && "true".equals(localhostAttr);  // See if it's "true"
+
+        String passwordAttr = root.getAttribute("password");                        // Get the password attribute
+        if (passwordAttr != null && passwordAttr.length() > 0)                      // If it's there, and non-empty
+            password = decode(passwordAttr);                                        // Then decode it
+
+        NodeList children = root.getChildNodes();                                   // Get the child nodes
+        for (int i = 0; i < children.getLength(); ++i) {                            // For each child node
+            Node child = children.item(i);                                          // Get the child
+            if (child.getNodeType() == Node.ELEMENT_NODE) {                         // An element?
+                if ("server".equals(child.getNodeName())) {                         // A <server>?
+                    Server server = Server.create(this, (Element) child);           // Create the correct server
+
+                    // Keep these in separate sets?
+                    if (server instanceof ProductServer)                            // Is a product server?
+                        productServers.add(server);                                 // Add to product servers
+                    else if (server instanceof ProfileServer)                       // Is a profile server?
+                        profileServers.add(server);                                 // Add to profile servers
+                    else throw new IllegalArgumentException("Unexpected server type " + server + " in " + file);
+                } else if ("properties".equals(child.getNodeName())) {              // Is it a <properties>?
+                    NodeList props = child.getChildNodes();                         // Get its children
+                    for (int j = 0; j < props.getLength(); ++j) {                   // For each child
+                        Node node = props.item(j);                                  // Get the chld
+                        if (node.getNodeType() == Node.ELEMENT_NODE                 // And element?
+                            && "property".equals(node.getNodeName())) {             // And it's <property>?
+                            Element propNode = (Element) node;                      // Great, use it as an element
+                            String key = propNode.getAttribute("key");              // Get its key attribute
+                            if (key == null || key.length() == 0)                   // Make sure it's there
+                                throw new SAXException("Required 'key' attribute missing from "
+                                    + "<property> element");
+                            properties.setProperty(key, text(propNode));            // And set it
+                        }
+                    }
+                } else if ("codeBases".equals(child.getNodeName())) {               // And yadda
+                    NodeList cbs = child.getChildNodes();                           // yadda
+                    for (int j = 0; j < cbs.getLength(); ++j) {                     // yadda.
+                        Node node = cbs.item(j);
+                        if (node.getNodeType() == Node.ELEMENT_NODE
+                            && "codeBase".equals(node.getNodeName())) {
+                            Element cbNode = (Element) node;
+                            String u = cbNode.getAttribute("url");
+                            if (u == null || u.length() == 0)
+                                throw new SAXException("Required 'url' attribute missing from "
+                                    + "<codeBase> element");
+                            try {
+                                codeBases.add(new URL(u));
+                            } catch (MalformedURLException ex) {
+                                throw new SAXException("url attribute " + u + " isn't a valid URL");
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Encode a password.  This just hides it so it's not plain text, but it's just as
+     * easy to decode it if you have a base-64 decoder handy.
+     *
+     * @param password a <code>byte[]</code> value.
+     * @return a <code>String</code> value.
+     */
+    static String encode(byte[] password) {
+        return new String(Base64.encode(password));
+    }
+
+    /**
+     * Decode a password.
+     *
+     * @param password a <code>String</code> value.
+     * @return a <code>byte[]</code> value.
+     */
+    static byte[] decode(String password) {
+        return Base64.decode(password.getBytes());
+    }
+
+    /**
+     * Get the text under an XML node.
+     *
+     * @param node a <code>Node</code> value.
+     * @return a <code>String</code> value.
+     */
+    private static String text(Node node) {
+        StringBuffer b = new StringBuffer();
+        text0(node, b);
+        return b.toString();
+    }
+
+    /**
+     * Get the text from an XML node into a StringBuffer. 
+     *
+     * @param node a <code>Node</code> value.
+     * @param b a <code>StringBuffer</code> value.
+     */
+    private static void text0(Node node, StringBuffer b) {
+        NodeList children = node.getChildNodes();
+        for (int i = 0; i < children.getLength(); ++i)
+            text0(children.item(i), b);
+        short type = node.getNodeType();
+        if (type == Node.CDATA_SECTION_NODE || type == Node.TEXT_NODE)
+            b.append(node.getNodeValue());
+    }
+
+    public boolean equals(Object obj) {
+        if (obj == this) return true;
+        if (obj instanceof Configuration) {
+            Configuration rhs = (Configuration) obj;
+            return codeBases.equals(rhs.codeBases) && productServers.equals(rhs.productServers)
+                && profileServers.equals(rhs.profileServers) && Arrays.equals(password, rhs.password)
+                && httpsRequired == rhs.httpsRequired && localhostRequired == rhs.localhostRequired
+                && properties.equals(rhs.properties);
+        }
+        return false;
+    }
+
+    public int hashCode() {
+        return codeBases.hashCode() ^ productServers.hashCode() ^ profileServers.hashCode();
+    }
+
+    /** List of {@link URL}s to code bases. */
+    private List codeBases = new ArrayList();
+
+    /** List of {@link ProductServer}s. */
+    private List productServers = new ArrayList();
+
+    /** List of {@link ProfileServer}s. */
+    private List profileServers = new ArrayList();
+
+    /** Admin password. */
+    private byte[] password = DEFAULT_PASSWORD;
+
+    /** True if https is requried. */
+    private boolean httpsRequired;
+
+    /** True if localhost access is required. */
+    private boolean localhostRequired;
+
+    /** Properties to set. */
+    private Properties properties = new Properties();
+
+    /** Where to save the file. */
+    private transient File file;
+
+    /** Default password. */
+    static final byte[] DEFAULT_PASSWORD = { (byte)'h', (byte)'a', (byte)'n', (byte)'a', (byte)'l', (byte)'e', (byte)'i' };
+
+    /** XML namespace */
+    public static final String NS = "http://oodt.jpl.nasa.gov/web-grid/ns/";
+
+    /** Sole document builder we'll need. */
+    private static final DocumentBuilder DOCUMENT_BUILDER;
+
+    /** Sole transfomer we'll need. */
+    private static final Transformer TRANSFORMER;
+
+    static {
+        try {
+            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+            documentBuilderFactory.setNamespaceAware(true);
+            documentBuilderFactory.setValidating(false);
+            documentBuilderFactory.setIgnoringElementContentWhitespace(false);
+            documentBuilderFactory.setExpandEntityReferences(true);
+            documentBuilderFactory.setIgnoringComments(true);
+            documentBuilderFactory.setCoalescing(true);
+            DOCUMENT_BUILDER = documentBuilderFactory.newDocumentBuilder();
+
+            TransformerFactory transformerFactory = TransformerFactory.newInstance();
+            TRANSFORMER = transformerFactory.newTransformer();
+            TRANSFORMER.setOutputProperty(OutputKeys.METHOD, "xml");
+            TRANSFORMER.setOutputProperty(OutputKeys.VERSION, "1.0");
+            TRANSFORMER.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+            TRANSFORMER.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
+            TRANSFORMER.setOutputProperty(OutputKeys.INDENT, "yes");
+            TRANSFORMER.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
+        } catch (ParserConfigurationException ex) {
+            throw new IllegalStateException("Cannot create document builder");
+        } catch (TransformerConfigurationException ex) {
+            throw new IllegalStateException("Cannot create transformer");
+        }
+    }
+}

Propchange: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/Configuration.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/Configuration.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/GridServlet.java
URL: http://svn.apache.org/viewvc/incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/GridServlet.java?rev=992166&view=auto
==============================================================================
--- incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/GridServlet.java (added)
+++ incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/GridServlet.java Fri Sep  3 01:17:56 2010
@@ -0,0 +1,119 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oodt.grid;
+
+import java.io.File;
+import java.io.IOException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import org.xml.sax.SAXException;
+
+/**
+ * Grid servlet is an abstract servlet that provides basic behavior (configuration access)
+ * for grid servlets.
+ */
+public abstract class GridServlet extends HttpServlet {
+	/**
+	 * By default, grid servlets are POST only, so GETs get you the welcome page.
+	 *
+	 * @param req a <code>HttpServletRequest</code> value.
+	 * @param res a <code>HttpServletResponse</code> value.
+	 * @throws IOException if an error occurs.
+	 * @throws ServletException if an error occurs.
+	 */
+	public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
+		req.getRequestDispatcher("index.html").forward(req, res);
+	}
+
+	/**
+	 * Get the configuration.
+	 *
+	 * @return a <code>Configuration</code> value.
+	 * @throws ServletException if an error occurs.
+	 * @throws IOException if an error occurs.
+	 */
+	protected Configuration getConfiguration() throws ServletException, IOException {
+		if (configuration != null) return configuration;
+		String path = getServletContext().getRealPath("/WEB-INF/config.xml");
+		if (path == null)
+			throw new ServletException("The config.xml file can't be accessed. Are we running from a war file!??!");
+		File file = new File(path);
+		Configuration c = null;
+		try {
+			c = new Configuration(file);
+		} catch (SAXException ex) {
+			throw new ServletException("Cannot parse config.xml file", ex);
+		}
+		synchronized (GridServlet.class) {
+			while (configuration == null)
+				configuration = c;
+		}
+		return configuration;
+	}
+
+	/**
+	 * Get the config bean.
+	 *
+	 * @param req a <code>HttpServletRequest</code> value.
+	 * @return a <code>ConfigBean</code> value.
+	 * @throws ServletException if an error occurs.
+	 * @throws IOException if an error occurs.
+	 */
+	protected ConfigBean getConfigBean(HttpServletRequest req) throws ServletException, IOException {
+		HttpSession session = req.getSession(/*create*/true);
+		ConfigBean cb = (ConfigBean) session.getAttribute("cb");
+		if (cb == null) {
+			cb = new ConfigBean();
+			session.setAttribute("cb", cb);
+		}
+		Configuration config = getConfiguration();
+		cb.setConfiguration(config);
+		return cb;
+	}
+
+	/**
+	 * Check if administrative access is allowed.  This examines the request scheme
+	 * (http, ftp, https, etc.) and sees if https is required by the configuration.
+	 * It also checks the remote host and sees if localhost access is required.
+	 *
+	 * @param config a <code>Configuration</code> value.
+	 * @param req a <code>HttpServletRequest</code> value.
+	 * @param res a <code>HttpServletResponse</code> value.
+	 * @return True if access is approved, false otherwise.
+	 * @throws IOException if an error occurs.
+	 */
+	protected boolean approveAccess(Configuration config, HttpServletRequest req, HttpServletResponse res) throws IOException {
+		if (config.isHTTPSrequired() && !"https".equals(req.getScheme())) {
+			res.sendError(HttpServletResponse.SC_FORBIDDEN, "https required");
+			return false;
+		}
+
+		if (config.isLocalhostRequired() && !Utility.isLocalhost(req.getRemoteHost())) {
+			res.sendError(HttpServletResponse.SC_FORBIDDEN, "localhost access only");
+			return false;
+		}
+
+		return true;
+	}
+
+	/** Singleton configuration. */
+	private static volatile Configuration configuration;
+}

Propchange: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/GridServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/GridServlet.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/LoginServlet.java
URL: http://svn.apache.org/viewvc/incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/LoginServlet.java?rev=992166&view=auto
==============================================================================
--- incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/LoginServlet.java (added)
+++ incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/LoginServlet.java Fri Sep  3 01:17:56 2010
@@ -0,0 +1,61 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oodt.grid;
+
+import java.io.IOException;
+import java.util.Arrays;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Controller servlet that authenticates the administrator password.
+ * 
+ */
+public class LoginServlet extends GridServlet {
+	/**
+	 * Handle authentication from an administrator.
+	 *
+	 * @param req a <code>HttpServletRequest</code> value.
+	 * @param res a <code>HttpServletResponse</code> value.
+	 * @throws ServletException if an error occurs.
+	 * @throws IOException if an error occurs.
+	 */
+	public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
+		Configuration config = getConfiguration();			       // Get configuration
+		if (!approveAccess(config, req, res)) return;			       // Do https, localhost checking first
+
+		ConfigBean cb = getConfigBean(req);				       // Get bean
+		if (cb.isAuthentic()) {						       // Already authentic?
+			req.getRequestDispatcher("config.jsp").forward(req, res);      // Back to the config page with you!
+			return;
+		}
+
+		String password = req.getParameter("password");			       // Get submitted password
+		if (password == null) password = "";				       // If none, use an empty string
+		byte[] bytes = password.getBytes();				       // Get the bytes
+		if (!Arrays.equals(config.getPassword(), bytes)) {		       // Compare to stored password bytes 
+			cb.setMessage("Password incorrect");			       // Not equal!  Set message.
+			throw new ServletException(new AuthenticationRequiredException());
+		} else {
+			cb.setMessage("");					       // Equal, clear message
+			cb.setAuthentic(true);					       // You are now authenticated
+			req.getRequestDispatcher("config.jsp").forward(req, res);      // To the config page with you!
+		}
+	}
+}

Propchange: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/LoginServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/LoginServlet.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProductQueryServlet.java
URL: http://svn.apache.org/viewvc/incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProductQueryServlet.java?rev=992166&view=auto
==============================================================================
--- incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProductQueryServlet.java (added)
+++ incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProductQueryServlet.java Fri Sep  3 01:17:56 2010
@@ -0,0 +1,184 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oodt.grid;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.oodt.product.LargeProductQueryHandler;
+import org.apache.oodt.product.ProductException;
+import org.apache.oodt.product.QueryHandler;
+import org.apache.oodt.product.Retriever;
+import org.apache.oodt.xmlquery.LargeResult;
+import org.apache.oodt.xmlquery.Result;
+import org.apache.oodt.xmlquery.XMLQuery;
+
+
+/**
+ * Product query servlet handles product queries.  It always returns the first matching
+ * product, if any.  If no handler can provide a product, it returns 404 Not Found.  If
+ * there are no query handlers, it returns 404 Not Found.
+ * 
+ */
+public class ProductQueryServlet extends QueryServlet {
+	/** {@inheritDoc} */
+	protected List getServers(Configuration config) {
+		return config.getProductServers();
+	}
+
+	/** {@inheritDoc} */
+	protected void handleQuery(XMLQuery query, List handlers, HttpServletRequest req, HttpServletResponse res)
+		throws IOException, ServletException {
+		if (handlers.isEmpty()) {
+			res.sendError(HttpServletResponse.SC_NOT_FOUND, "no query handlers available to handle query");
+			return;
+		}
+
+		try {								       // OK, let's try
+			for (Iterator i = handlers.iterator(); i.hasNext();) {	       // Try each query handler
+				QueryHandler handler = (QueryHandler) i.next();	       // Get the query handler
+				query = handler.query(query);			       // Give it the query
+				if (!query.getResults().isEmpty()) {		       // Did it give any result?
+					Result result = (Result) query.getResults().get(0); // Yes, get the result
+					deliverResult(handler, result, res);	       // And deliver it
+					return;					       // Done!
+				}
+			}
+		} catch (ProductException ex) {
+			res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex.getMessage());
+			return;
+		}
+
+		res.sendError(HttpServletResponse.SC_NOT_FOUND, "no matching products from any query handler");
+	}
+
+	/**
+	 * Deliver a result.  This streams the product data.
+	 *
+	 * @param handler Which handler produced the result.
+	 * @param result The result.
+	 * @param res The HTTP response to which to send the result data.
+	 * @throws IOException if an error occurs.
+	 */
+	private void deliverResult(QueryHandler handler, Result result, HttpServletResponse res) throws IOException {
+		characterize(result, res);					       // First, describe it using HTTP headers
+		if (result instanceof LargeResult) {				       // Is it a large result?
+			LargeResult lr = (LargeResult) result;			       // Yes, this is gonna take some special work
+			LargeProductQueryHandler lpqh = (LargeProductQueryHandler) handler; // First treat 'em as large
+			ProductRetriever retriever = new ProductRetriever(lpqh);       // Large ones need a retriever
+			lr.setRetriever(retriever);				       // Set the retriever
+		}
+		BufferedInputStream in = null;					       // Start with no input stream
+		try {								       // Then try ...
+			in = new BufferedInputStream(result.getInputStream());	       // To open the input stream
+			byte[] buf = new byte[512];				       // And a byte buffer for data
+			int num;						       // And a place to count data
+			while ((num = in.read(buf)) != -1)			       // While we read
+				res.getOutputStream().write(buf, 0, num);	       // We write
+		} finally {							       // And finally
+			if (in != null) try {					       // If we opened it
+				in.close();					       // Close it
+			} catch (IOException ignore) {}				       // Ignoring any error during closing
+		}								       // Because come on, it's just closing!
+	}									       // For fsck's sake!
+
+	/**
+	 * Characterize a result by using HTTP headers.
+	 *
+	 * @param result Result to characterize.
+	 * @param res HTTP response to set headers in.
+	 */
+	private static void characterize(Result result, HttpServletResponse res) {
+		String contentType = result.getMimeType();			       // Grab the content type
+		res.setContentType(contentType);				       // Set it
+		long size = result.getSize();					       // Grab the size
+		res.addHeader("Content-Length", String.valueOf(size));		       // Don't use setContentLength(int)
+		if (!displayable(contentType))					       // Finally, if a browser can't show it
+			suggestFilename(result.getResourceID(), res);		       // Then suggest a save-as filename
+	}
+
+	/**
+	 * Tell if a result is displayable.  This compares its MIME type to a list of MIME
+	 * types commonly displayble by browsers.
+	 *
+	 * @param contentType MIME type.
+	 * @return a <code>boolean</code> value.
+	 */
+	private static boolean displayable(String contentType) {
+		for (int i = 0; i < DISPLAYABLE_TYPES.length; ++i)		       // For each displayable type
+			if (DISPLAYABLE_TYPES[i].equals(contentType)) return true;     // Does it match?
+		return false;							       // None of 'em do, it's not displayable
+	}
+
+	/**
+	 * We can suggest a filename (if the client happens to be a browser) using a
+	 * content-disposition header.
+	 *
+	 * @param resource Resource name
+	 * @param res a <code>HttpServletResponse</code> value.
+	 */
+	private static void suggestFilename(String resource, HttpServletResponse res) {
+		if (resource == null || resource.length() == 0)
+			resource = "product.dat";
+		res.addHeader("Content-disposition", "attachment; filename=\"" + resource + "\"");
+	}
+
+	/**
+	 * MIME types commonly displayable by browsers.
+	 */
+	private static final String[] DISPLAYABLE_TYPES = {
+		"text/plain", "text/richtext", "text/enriched", "text/tab-separated-values", "text/html", "text/xml", "text/rtf",
+		"message/rfc822", "message/partial", "message/external-body", "message/news", "message/http",
+		"message/delivery-status", "message/disposition-notification", "message/s-http", "application/rtf",
+		"application/pdf", "image/jpeg", "image/gif", "image/tiff", "image/png", "audio/basic", "audio/32kadpcm",
+		"audio/mpeg", "video/mpeg", "video/quicktime"
+	};
+
+	/**
+	 * Retriever that retrieves product data over a method call boundary to a large
+	 * product query handler.
+	 */
+	private static class ProductRetriever implements Retriever {
+		/**
+		 * Creates a new <code>ProductRetriever</code> instance.
+		 *
+		 * @param handler a <code>LargeProductQueryHandler</code> value.
+		 */
+		public ProductRetriever(LargeProductQueryHandler handler) {
+			this.handler = handler;
+		}
+
+		/** {@inheritDoc} */
+		public byte[] retrieveChunk(String id, long offset, int len) throws ProductException {
+			return handler.retrieveChunk(id, offset, len);
+		}
+
+		/** {@inheritDoc} */
+		public void close(String id) throws ProductException {
+			handler.close(id);
+		}
+
+		/** Handler to use. */
+		private LargeProductQueryHandler handler;
+	}
+}
+

Propchange: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProductQueryServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProductQueryServlet.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProductServer.java
URL: http://svn.apache.org/viewvc/incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProductServer.java?rev=992166&view=auto
==============================================================================
--- incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProductServer.java (added)
+++ incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProductServer.java Fri Sep  3 01:17:56 2010
@@ -0,0 +1,65 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oodt.grid;
+
+import org.apache.oodt.product.QueryHandler;
+
+/**
+ * A product server.
+ *
+ */
+public class ProductServer extends Server {
+	/**
+	 * Creates a new <code>ProductServer</code> instance.
+	 *
+	 * @param configuration System configuration.
+	 * @param className Class name of query handler.
+	 */
+	public ProductServer(Configuration configuration, String className) {
+		super (configuration, className);
+	}
+
+	/** {@inheritDoc} */
+	protected String getType() {
+		return "product";
+	}
+
+	public int hashCode() {
+		return super.hashCode() ^ 0xaaaaaaaa;
+	}
+
+	public boolean equals(Object obj) {
+		return super.equals(obj) && obj instanceof ProductServer;
+	}
+
+	public String toString() {
+		return "ProductServer[" + super.toString() + "]";
+	}
+
+	/**
+	 * Create a query handler from this server.
+	 *
+	 * @return a <code>QueryHandler</code> value.
+	 * @throws ClassNotFoundException if the class can't be found.
+	 * @throws InstantiationException if the handler can't be instantiated.
+	 * @throws IllegalAccessException if the handler has no public constructor.
+	 */
+	public QueryHandler createQueryHandler() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+		return (QueryHandler) createHandler();
+	}
+}

Propchange: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProductServer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProductServer.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProfileQueryServlet.java
URL: http://svn.apache.org/viewvc/incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProfileQueryServlet.java?rev=992166&view=auto
==============================================================================
--- incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProfileQueryServlet.java (added)
+++ incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProfileQueryServlet.java Fri Sep  3 01:17:56 2010
@@ -0,0 +1,138 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oodt.grid;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.HashSet;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+import org.apache.oodt.profile.Profile;
+import org.apache.oodt.profile.handlers.ProfileHandler;
+import org.apache.oodt.xmlquery.QueryElement;
+import org.apache.oodt.xmlquery.XMLQuery;
+
+
+/**
+ * Profile query servlet handles profile queries.  It returns every matching profile from
+ * every query handler that provides matching profiles.  If no handlers are installed,
+ * then it returns an empty &lt;profiles&gt; document.
+ * 
+ */
+public class ProfileQueryServlet extends QueryServlet {
+	/** {@inheritDoc} */
+	protected List getServers(Configuration config) {
+		return config.getProfileServers();
+	}
+
+	/** {@inheritDoc} */
+	protected void handleQuery(XMLQuery query, List handlers, HttpServletRequest req, HttpServletResponse res)
+		throws IOException, ServletException {
+		// Find if the query should be targeted to specific handlers.
+		Set ids = new HashSet();
+		if (query.getFromElementSet() != null) {
+			for (Iterator i = query.getFromElementSet().iterator(); i.hasNext();) {
+				QueryElement qe = (QueryElement) i.next();
+				if ("handler".equals(qe.getRole()) && qe.getValue() != null)
+					ids.add(qe.getValue());
+			}
+		}
+		
+		res.setContentType("text/xml");					       // XML, comin' at ya
+		res.getWriter().println("<?xml version='1.0' encoding='UTF-8'?>");     // UTF-8 no less.  Boo-ya.
+		res.getWriter().println("<!DOCTYPE profiles PUBLIC '"		       // Get a doctype in there for the highly ...
+			+ Profile.PROFILES_DTD_FPI + "' '"			       // ... anal ...
+			+ Profile.PROFILES_DTD_URL + "'>");		               // ... retentive.
+		res.getWriter().println("<profiles>");				       // Start tag for the whole /sbin/fsck mess
+		Transformer transformer = null;					       // Start out w/no transformer and no doc
+		Document doc = null;						       // Don't make 'em if we don't need 'em
+		boolean sentAtLeastOne = false;					       // Track if we send any profiles at all
+		Exception exception = null;					       // And save any exception
+		for (Iterator i = handlers.iterator(); i.hasNext();) try {	       // To iterate over each handler
+			ProfileHandler handler = (ProfileHandler) i.next();            // Get the handler
+			String id = handler.getID();                                   // Get the ID, and if targeting to IDs
+			if (!ids.isEmpty() && !ids.contains(id)) continue;             // ... and it's not one we want, skip it.
+			List results = handler.findProfiles(query);                    // Have it find profiles
+			if (results == null) results = Collections.EMPTY_LIST;         // Assume nothing
+			for (Iterator j = results.iterator(); j.hasNext();) {          // For each matching profile
+				Profile profile = (Profile) j.next();	               // Get the profile
+				if (transformer == null) {		               // No transformer/doc yet?
+					transformer = createTransformer();             // Then make the transformer
+					doc = Profile.createProfileDocument();         // And the doc
+				}					               // And use the doc ...
+				Node profileNode = profile.toXML(doc);	               // To render the profile into XML
+				DOMSource source = new DOMSource(profileNode);         // And the XML becomes is source
+				StreamResult result = new StreamResult(res.getWriter()); // And the response is a result
+				transformer.transform(source, result);	               // And serialize into glorious text
+				sentAtLeastOne = true;				       // OK, we got at least one out the doo
+			}
+		} catch (Exception ex) {					       // Uh oh
+			exception = ex;						       // OK, just hold onto it for now
+		}
+		if (!sentAtLeastOne && exception != null) {			       // Got none out the door and had an error?
+			res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,    // Then we can report it.
+				exception.getMessage());
+			return;
+		}
+
+		// However, if we get here, we got at least one profile out the door. In
+		// that case, hide any error that might've occurred from subsequent
+		// handlers.  (Or, if we get here, there were no errors.  Yay.)
+		res.getWriter().println("</profiles>");				       // End tag for the whole fsck'n mess
+	}
+
+	/**
+	 * Create a transformer, properly configured for XML text serialization.
+	 *
+	 * @return a <code>Transformer</code> value.
+	 * @throws TransformerException if an error occurs.
+	 */
+	private static Transformer createTransformer() throws TransformerException {
+		Transformer transformer;
+		synchronized (TRANSFORMER_FACTORY) {
+			transformer = TRANSFORMER_FACTORY.newTransformer();
+		}
+		transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+		transformer.setOutputProperty(OutputKeys.VERSION, "1.0");
+		transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+		transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+		transformer.setOutputProperty(OutputKeys.STANDALONE, "no");
+		transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+		transformer.setOutputProperty(OutputKeys.MEDIA_TYPE, "text/xml");
+		transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
+
+		return transformer;
+	}
+
+	/** Sole transformer factory this class will ever need. */
+	private static final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance();
+}
+

Propchange: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProfileQueryServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProfileQueryServlet.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProfileServer.java
URL: http://svn.apache.org/viewvc/incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProfileServer.java?rev=992166&view=auto
==============================================================================
--- incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProfileServer.java (added)
+++ incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProfileServer.java Fri Sep  3 01:17:56 2010
@@ -0,0 +1,71 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oodt.grid;
+
+import org.apache.oodt.profile.handlers.ProfileHandler;
+
+/**
+ * A profile server.
+ * 
+ */
+public class ProfileServer extends Server {
+  /**
+   * Creates a new <code>ProfileServer</code> instance.
+   * 
+   * @param configuration
+   *          System configuration.
+   * @param className
+   *          Class name of profile handler.
+   */
+  public ProfileServer(Configuration configuration, String className) {
+    super(configuration, className);
+  }
+
+  /** {@inheritDoc} */
+  protected String getType() {
+    return "profile";
+  }
+
+  public int hashCode() {
+    return super.hashCode() ^ 0x55555555;
+  }
+
+  public boolean equals(Object obj) {
+    return super.equals(obj) && obj instanceof ProfileServer;
+  }
+
+  public String toString() {
+    return "ProfileServer[" + super.toString() + "]";
+  }
+
+  /**
+   * Create a query handler from this server.
+   * 
+   * @return a <code>ProfileHandler</code> value.
+   * @throws ClassNotFoundException
+   *           if the class can't be found.
+   * @throws InstantiationException
+   *           if the handler can't be instantiated.
+   * @throws IllegalAccessException
+   *           if the handler has no public constructor.
+   */
+  public ProfileHandler createProfileHandler() throws ClassNotFoundException,
+      InstantiationException, IllegalAccessException {
+    return (ProfileHandler) createHandler();
+  }
+}

Propchange: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProfileServer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/oodt/trunk/grid/src/main/java/org/apache/oodt/grid/ProfileServer.java
------------------------------------------------------------------------------
    svn:executable = *