Index: src/edu/ucsb/nceas/metacat/MetaCatServlet.java
===================================================================
--- src/edu/ucsb/nceas/metacat/MetaCatServlet.java	(revision 698)
+++ src/edu/ucsb/nceas/metacat/MetaCatServlet.java	(revision 699)
@@ -94,6 +94,7 @@
  * action=getdatadoc -- retrieve a stored datadocument<br>
  * action=getaccesscontrol -- retrieve acl info for Metacat document<br>
  * action=getdoctypes -- retrieve all doctypes (publicID)<br>
+ * action=getdtdschema -- retrieve a DTD or Schema file<br>
  * action=getdataguide -- retrieve a Data Guide<br>
  * datadoc -- data document name (id)<br>
  * <p>
@@ -370,6 +371,9 @@
         out.println("You must be authenticated to perform the getdataport " +
                     "action!");
       }
+    } else if (action.equals("getdtdschema")) {
+      PrintWriter out = response.getWriter();
+      handleGetDTDSchemaAction(out, params, response);  
     } else if (action.equals("getdataguide")) {
       PrintWriter out = response.getWriter();
       handleGetDataGuideAction(out, params, response);  
@@ -1621,6 +1625,42 @@
   }
 
   /** 
+   * Handle the "getdtdschema" action.
+   * Read DTD or Schema file for a given doctype from Metacat catalog system
+   */
+  private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
+                                        HttpServletResponse response) {
+
+    Connection conn = null;
+    String doctype = null;
+    String[] doctypeArr = (String[])params.get("doctype");
+
+    // get only the first doctype specified in the list of doctypes
+    // it could be done for all doctypes in that list
+    if (doctypeArr != null) {
+        doctype = ((String[])params.get("doctype"))[0]; 
+    }
+
+    try {
+
+        // get connection from the pool
+        conn = util.getConnection();
+        DBUtil dbutil = new DBUtil(conn);
+        String dtdschema = dbutil.readDTDSchema(doctype);
+        out.println(dtdschema);
+
+    } catch (Exception e) {
+      out.println("<?xml version=\"1.0\"?>");
+      out.println("<error>");
+      out.println(e.getMessage());
+      out.println("</error>");
+    } finally {
+      util.returnConnection(conn);
+    }  
+    
+  }
+
+  /** 
    * Handle the "getdataguide" action.
    * Read Data Guide for a given doctype from db connection in XML format
    */
Index: src/edu/ucsb/nceas/metacat/DBUtil.java
===================================================================
--- src/edu/ucsb/nceas/metacat/DBUtil.java	(revision 698)
+++ src/edu/ucsb/nceas/metacat/DBUtil.java	(revision 699)
@@ -2,7 +2,8 @@
  *  '$RCSfile$'
  *    Purpose: A Class that implements utility methods like:
  *             1/ Reding all doctypes from db connection
- *             2/ Reading Lore type Data Guide from db connection
+ *             2/ Reading DTD or Schema file from Metacat catalog system
+ *             3/ Reading Lore type Data Guide from db connection
  *  Copyright: 2000 Regents of the University of California and the
  *             National Center for Ecological Analysis and Synthesis
  *    Authors: Jivka Bojilova
@@ -33,6 +34,14 @@
 import java.sql.SQLException;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
+
+import java.io.BufferedInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.MalformedURLException;
+
 import java.util.Enumeration;
 import java.util.Vector;
 import java.util.Stack;
@@ -57,7 +66,8 @@
      if (args.length < 1)
      {
         System.err.println("Wrong number of arguments!!!");
-        System.err.println("USAGE: java DBUtil <-dt | -dg [doctype]>");
+        System.err.println(
+        "USAGE: java DBUtil <-dt | -ds [doctype] | -dg [doctype]>");
         return;
      } else {
         try {
@@ -76,13 +86,19 @@
             if ( args.length == 2 ) { doctype = args[1]; }
             String dataguide = dbutil.readDataGuide(doctype);
             System.out.println(dataguide);
+          } else if ( args[0].equals("-ds") ) {
+            String doctype = null;
+            if ( args.length == 2 ) { doctype = args[1]; }
+            String dtdschema = dbutil.readDTDSchema(doctype);
+            System.out.println(dtdschema);
           } else {
-            System.err.println("USAGE: java DBUtil <-dt | -dg [doctype]>");
+            System.err.println(
+            "USAGE: java DBUtil <-dt | -ds [doctype] | -dg [doctype]>");
           }  
 
         } catch (Exception e) {
-          System.err.println("error in DBUtil.main");
-          System.err.println(e.getMessage());
+          //System.err.println("error in DBUtil.main");
+          //System.err.println(e.getMessage());
           e.printStackTrace(System.err);
         }
      }
@@ -121,8 +137,7 @@
       pstmt.close();
 
     } catch (SQLException e) {
-      System.out.println("DBUtil.readDoctypes(): " + e.getMessage());
-      throw e;
+      throw new SQLException("DBUtil.readDoctypes(). " + e.getMessage());
     }
 
     return formatToXML(doctypeList, "doctype");
@@ -129,6 +144,69 @@
   }
 
   /**
+   * read DTD or Schema file from Metacat's XML catalog system
+   */
+  public String readDTDSchema(String doctype)
+        throws SQLException, MalformedURLException, IOException
+  {
+    String systemID = null;
+    PreparedStatement pstmt;
+    StringBuffer cbuff = new StringBuffer();
+    
+    // get doctype's System ID from db catalog
+    try {
+      pstmt = conn.prepareStatement("SELECT system_id " + 
+                                    "FROM xml_catalog " +
+                                    "WHERE entry_type in ('DTD','Schema') " +
+                                    "AND public_id LIKE ?");
+      pstmt.setString(1, doctype);
+      pstmt.execute();
+      ResultSet rs = pstmt.getResultSet();
+      boolean hasRow = rs.next();
+      if (hasRow) {
+        systemID = rs.getString(1);
+      } else {
+        throw new SQLException("Non-registered doctype: " + doctype);
+      }
+      pstmt.close();
+
+    } catch (SQLException e) {
+      throw new SQLException("DBUtil.readDTD(). " + e.getMessage());
+    }
+
+    // read from URL stream as specified by the System ID.
+    try {
+      // open a connection to this URL and return an InputStream
+      // for reading from that connection
+      InputStream istream = new URL(systemID).openStream();
+      // create a buffering character-input stream
+      // that uses a default-sized input buffer
+      BufferedInputStream in = new BufferedInputStream(istream);
+
+      // read the input and write into the string buffer
+	    int inputByte;
+	    while ( (inputByte = in.read()) != -1 ) {
+        cbuff.append((char)inputByte);
+	    }
+
+      // the input stream must be closed
+	    in.close();
+	    
+    } catch (MalformedURLException e) {
+      throw new MalformedURLException
+      ("DBUtil.readDTD(). " + e.getMessage());
+    } catch (IOException e) {
+      throw new IOException
+      ("DBUtil.readDTD(). " + e.getMessage());
+    } catch (SecurityException e) {
+      throw new IOException
+      ("DBUtil.readDTD(). " + e.getMessage());
+    }
+    
+   return cbuff.toString();
+  }
+
+  /**
    * read Data Guide for a given doctype from db connection in XML format
    * select all distinct absolute paths from xml_index table
    */
@@ -169,8 +247,7 @@
         pstmt.close();
 
     } catch (SQLException e) {
-      System.out.println("DBUtil.readDataGuide(): " + e.getMessage());
-      throw e;
+      throw new SQLException("DBUtil.readDataGuide(). " + e.getMessage());
     }
 
     return formatToXML(dataguide);
