Project

General

Profile

1 72 bojilova
/**
2 203 jones
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements org.xml.sax.EntityResolver interface
4
 *             for resolving external entities
5
 *  Copyright: 2000 Regents of the University of California and the
6
 *             National Center for Ecological Analysis and Synthesis
7 243 jones
 *    Authors: Jivka Bojilova, Matt Jones
8 349 jones
 *    Release: @release@
9 72 bojilova
 *
10 203 jones
 *   '$Author$'
11
 *     '$Date$'
12
 * '$Revision$'
13 72 bojilova
 */
14
15 75 jones
package edu.ucsb.nceas.metacat;
16 72 bojilova
17
import org.xml.sax.*;
18
19
import java.sql.*;
20 243 jones
import java.io.File;
21
import java.io.FileReader;
22
import java.io.InputStream;
23
import java.io.IOException;
24 72 bojilova
import java.net.URL;
25 151 bojilova
import java.net.URLConnection;
26 72 bojilova
import java.net.MalformedURLException;
27
import java.util.Stack;
28
import java.util.EmptyStackException;
29
30
/**
31 122 jones
 * A database aware Class implementing EntityResolver interface for the SAX
32
 * parser to call when processing the XML stream and intercepting any
33
 * external entities (including the external DTD subset and external
34
 * parameter entities, if any) before including them.
35 72 bojilova
 */
36
public class DBEntityResolver implements EntityResolver
37
{
38 92 bojilova
   private Connection conn = null;
39 243 jones
   private DBSAXHandler handler = null;
40 72 bojilova
41 243 jones
   /**
42
    * Construct an instance of the DBEntityResolver class
43 72 bojilova
    *
44
    * @param conn the JDBC connection to which information is written
45
    */
46 243 jones
   public DBEntityResolver(Connection conn)
47
   {
48
      this.conn = conn;
49
   }
50
51
   /**
52
    * Construct an instance of the DBEntityResolver class
53
    *
54
    * @param conn the JDBC connection to which information is written
55
    * @param handler the SAX handler to determine parsing context
56
    */
57 204 jones
   public DBEntityResolver(Connection conn, DBSAXHandler handler)
58 72 bojilova
   {
59 243 jones
      this(conn);
60 204 jones
      this.handler = handler;
61 72 bojilova
   }
62
63 122 jones
   /**
64
    * The Parser call this method before opening any external entity
65
    * except the top-level document entity (including the external DTD subset,
66
    * external entities referenced within the DTD, and external entities
67
    * referenced within the document element)
68
    */
69 72 bojilova
   public InputSource resolveEntity (String publicId, String systemId)
70 243 jones
                throws SAXException, IOException
71 72 bojilova
   {
72
     String dbSystemId;
73 204 jones
     String doctype = null;
74 72 bojilova
75 243 jones
     if (publicId != null) {       // If we have a public ID, use it
76
       doctype = publicId;
77
       MetaCatUtil.debugMessage("DOCTYPE-c: " + doctype);
78
     } else if (systemId != null) {  // Otherwise, use system id if we can
79
       if (handler != null) {        // Won't have a handler under all cases
80
         if (handler.processingDTD()) {  // Assume the public ID is the docname
81
           doctype = handler.getDocname();
82
           MetaCatUtil.debugMessage("DOCTYPE-d: " + doctype);
83
         }
84
       }
85
     }
86
87
     // look at the db XML Catalog and get dbSystemId for this doctype
88
     if (doctype != null) {
89
       dbSystemId = getDTDSystemID (conn, doctype);
90
       if (dbSystemId == null) {
91
         MetaCatUtil.debugMessage("  RESOLVED NOTHING");
92
         // if it is not found in the database, then
93
         // register publicId in db and use the provided systemId
94
         if (systemId != null) {
95 245 jones
           InputStream istream = checkURLConnection(systemId);
96 243 jones
           if (handler != null) {    // Won't have a handler under all cases
97
             if (handler.processingDTD()) {
98
               registerDTDSystemID (conn, doctype, doctype, systemId);
99
             }
100
           }
101
           return null;
102
         }
103
       } else {
104
         MetaCatUtil.debugMessage("  RESOLVED SYSTEMID: " + dbSystemId);
105
         // If it is in the database, return the systemid from the database
106 245 jones
         InputStream istream = checkURLConnection(dbSystemId);
107 243 jones
         InputSource is = new InputSource(dbSystemId);
108 245 jones
         is.setByteStream(istream);
109 243 jones
         MetaCatUtil.debugMessage("  INPUTSOURCE SYSTEMID: "
110
                                      + is.getSystemId());
111
         return is;
112
       }
113 72 bojilova
     }
114
115 243 jones
     // use the provided systemID for other cases
116 245 jones
     InputStream istream = checkURLConnection(systemId);
117 72 bojilova
     return null;
118
   }
119 109 bojilova
120 122 jones
   /**
121
    * Look at db XML Catalog to get System ID (if any) for that doctype.
122
    * Return empty string if there are not
123
    */
124 109 bojilova
   private String getDTDSystemID (Connection conn, String doctype)  {
125 243 jones
        String system_id = null;
126 72 bojilova
        Statement stmt;
127
        try {
128
          stmt = conn.createStatement();
129 92 bojilova
          stmt.execute("SELECT system_id FROM xml_catalog " +
130 122 jones
                       "WHERE entry_type = 'DTD' AND public_id = '" +
131
                       doctype + "'");
132 72 bojilova
          try {
133
            ResultSet rs = stmt.getResultSet();
134
            try {
135
              boolean tableHasRows = rs.next();
136
              if (tableHasRows) {
137
                try {
138
                  system_id = rs.getString(1);
139
                } catch (SQLException e) {
140 122 jones
                  System.out.println("DBEntityResolver.getDTDSystemID() " +
141
                             "- Error with getString: " + e.getMessage());
142 72 bojilova
                }
143
              }
144
            } catch (SQLException e) {
145 122 jones
              System.out.println("DBEntityResolver.getDTDSystemID() " +
146
                             "- Error with next: " + e.getMessage());
147 72 bojilova
            }
148
          } catch (SQLException e) {
149 122 jones
            System.out.println("DBEntityResolver.getDTDSystemID() " +
150
                             "- Error with getrset: " + e.getMessage());
151 72 bojilova
          }
152
          stmt.close();
153
        } catch (SQLException e) {
154 122 jones
          System.out.println("DBEntityResolver.getDTDSystemID() " +
155
                             "- Error getting id: " + e.getMessage());
156 72 bojilova
        }
157
158
        // return the selected System ID
159
        return system_id;
160
   }
161
162 122 jones
   /**
163
    * Register DTD System ID in db XML Catalog
164
    */
165
   private void registerDTDSystemID (Connection conn, String doctype,
166
                                     String publicId, String systemId)
167 72 bojilova
   {
168 243 jones
     try {
169
       PreparedStatement pstmt;
170
       pstmt = conn.prepareStatement(
171
             "INSERT INTO xml_catalog " +
172
             "(catalog_id, entry_type, source_doctype, " +
173
             "public_id, system_id) " +
174
             "VALUES (null, 'DTD', ?, ?, ?)");
175
       // Bind the values to the query
176
       pstmt.setString(1, doctype);
177
       pstmt.setString(2, publicId);
178
       pstmt.setString(3, systemId);
179
       // Do the insertion
180
       pstmt.execute();
181
       pstmt.close();
182
     } catch (SQLException e) {
183
       System.out.println(e.getMessage());
184
     }
185 72 bojilova
   }
186 243 jones
187 122 jones
   /**
188 245 jones
    * Check URL Connection for systemId, and return an InputStream
189 243 jones
    * that can be used to read from the systemId URL.  The parser ends
190
    * up using this via the InputSource to read the DTD.
191
    *
192
    * @param systemID a URI (in practice URL) to be checked and opened
193 122 jones
    */
194 245 jones
   private InputStream checkURLConnection (String systemId)
195 151 bojilova
                throws MalformedURLException, IOException
196 72 bojilova
   {
197 243 jones
     try {
198 245 jones
199
       return (new URL(systemId).openStream());
200
201 243 jones
     } catch (MalformedURLException e) {
202
       System.out.println("from checkURLConnection(): " + e.getMessage());
203
       throw e;
204
     } catch (IOException e) {
205
       System.out.println("from checkURLConnection(): " + e.getMessage());
206
       throw e;
207
     }
208 151 bojilova
   }
209 72 bojilova
}
210 203 jones
211
/**
212
 * '$Log$
213 349 jones
 * 'Revision 1.14  2000/06/30 00:52:04  jones
214
 * 'changed char stream to byte stream
215
 * '
216 245 jones
 * 'Revision 1.13  2000/06/29 23:27:08  jones
217
 * 'Fixed bug in DBEntityResolver so that it now properly delegates to
218
 * 'the system id found inthe database.
219
 * 'Changed DBValidate to use DBEntityResolver, rather than the OASIS
220
 * 'catalog, and to return validation results in XML format.
221
 * '
222 243 jones
 * 'Revision 1.12  2000/06/27 04:31:07  jones
223
 * 'Fixed bugs associated with the new UPDATE and DELETE functions of
224
 * 'DBWriter.  There were problematic interactions between some static
225
 * 'variables used in DBEntityResolver and the way in which the
226
 * 'Servlet objects are re-used across multiple client invocations.
227
 * '
228
 * 'Generally cleaned up error reporting.  Now all errors and success
229
 * 'results are reported as XML documents from MetaCatServlet.  Need
230
 * 'to make the command line tools do the same.
231
 * '
232 204 jones
 * 'Revision 1.11  2000/06/26 10:35:04  jones
233
 * 'Merged in substantial changes to DBWriter and associated classes and to
234
 * 'the MetaCatServlet in order to accomodate the new UPDATE and DELETE
235
 * 'functions.  The command line tools and the parameters for the
236
 * 'servlet have changed substantially.
237
 * '
238 203 jones
 * 'Revision 1.10.2.2  2000/06/25 23:38:16  jones
239
 * 'Added RCSfile keyword
240
 * '
241
 * 'Revision 1.10.2.1  2000/06/25 23:34:17  jones
242
 * 'Changed documentation formatting, added log entries at bottom of source files
243
 * ''
244
 */