Project

General

Profile

1
/**
2
 *  '$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
 *    Authors: Jivka Bojilova, Matt Jones
8
 *    Release: @release@
9
 *
10
 *   '$Author: jones $'
11
 *     '$Date: 2000-08-14 13:53:34 -0700 (Mon, 14 Aug 2000) $'
12
 * '$Revision: 349 $'
13
 */
14

    
15
package edu.ucsb.nceas.metacat;
16

    
17
import org.xml.sax.*;
18

    
19
import java.sql.*;
20
import java.io.File;
21
import java.io.FileReader;
22
import java.io.InputStream;
23
import java.io.IOException;
24
import java.net.URL;
25
import java.net.URLConnection;
26
import java.net.MalformedURLException;
27
import java.util.Stack;
28
import java.util.EmptyStackException;
29

    
30
/** 
31
 * 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
 */
36
public class DBEntityResolver implements EntityResolver
37
{
38
   private Connection conn = null;
39
   private DBSAXHandler handler = null;
40

    
41
   /** 
42
    * Construct an instance of the DBEntityResolver class
43
    *
44
    * @param conn the JDBC connection to which information is written
45
    */
46
   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
   public DBEntityResolver(Connection conn, DBSAXHandler handler)
58
   {
59
      this(conn);
60
      this.handler = handler;
61
   }
62
   
63
   /** 
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
   public InputSource resolveEntity (String publicId, String systemId)
70
                throws SAXException, IOException
71
   {
72
     String dbSystemId;
73
     String doctype = null;
74
     
75
     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
           InputStream istream = checkURLConnection(systemId);
96
           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
         InputStream istream = checkURLConnection(dbSystemId);
107
         InputSource is = new InputSource(dbSystemId);
108
         is.setByteStream(istream);
109
         MetaCatUtil.debugMessage("  INPUTSOURCE SYSTEMID: " 
110
                                      + is.getSystemId());
111
         return is;
112
       } 
113
     }
114
    
115
     // use the provided systemID for other cases
116
     InputStream istream = checkURLConnection(systemId);
117
     return null;
118
   }
119

    
120
   /** 
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
   private String getDTDSystemID (Connection conn, String doctype)  {
125
        String system_id = null;
126
        Statement stmt;
127
        try {
128
          stmt = conn.createStatement();
129
          stmt.execute("SELECT system_id FROM xml_catalog " + 
130
                       "WHERE entry_type = 'DTD' AND public_id = '" + 
131
                       doctype + "'");
132
          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
                  System.out.println("DBEntityResolver.getDTDSystemID() " +
141
                             "- Error with getString: " + e.getMessage());
142
                }
143
              }
144
            } catch (SQLException e) {
145
              System.out.println("DBEntityResolver.getDTDSystemID() " +
146
                             "- Error with next: " + e.getMessage());
147
            }
148
          } catch (SQLException e) {
149
            System.out.println("DBEntityResolver.getDTDSystemID() " +
150
                             "- Error with getrset: " + e.getMessage());
151
          }
152
          stmt.close();
153
        } catch (SQLException e) {
154
          System.out.println("DBEntityResolver.getDTDSystemID() " +
155
                             "- Error getting id: " + e.getMessage());
156
        }
157

    
158
        // return the selected System ID
159
        return system_id;
160
   }
161

    
162
   /** 
163
    * Register DTD System ID in db XML Catalog 
164
    */
165
   private void registerDTDSystemID (Connection conn, String doctype, 
166
                                     String publicId, String systemId)
167
   {
168
     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
   }
186

    
187
   /** 
188
    * Check URL Connection for systemId, and return an InputStream
189
    * 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
    */
194
   private InputStream checkURLConnection (String systemId)
195
                throws MalformedURLException, IOException
196
   {
197
     try {
198

    
199
       return (new URL(systemId).openStream());
200

    
201
     } 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
   }   
209
}
210

    
211
/**
212
 * '$Log$
213
 * 'Revision 1.14  2000/06/30 00:52:04  jones
214
 * 'changed char stream to byte stream
215
 * '
216
 * '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
 * '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
 * '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
 * '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
 */
(7-7/28)