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
 *
9
 *   '$Author: jones $'
10
 *     '$Date: 2000-06-29 17:52:04 -0700 (Thu, 29 Jun 2000) $'
11
 * '$Revision: 245 $'
12
 */
13

    
14
package edu.ucsb.nceas.metacat;
15

    
16
import org.xml.sax.*;
17

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

    
29
/** 
30
 * A database aware Class implementing EntityResolver interface for the SAX 
31
 * parser to call when processing the XML stream and intercepting any 
32
 * external entities (including the external DTD subset and external 
33
 * parameter entities, if any) before including them.
34
 */
35
public class DBEntityResolver implements EntityResolver
36
{
37
   private Connection conn = null;
38
   private DBSAXHandler handler = null;
39

    
40
   /** 
41
    * Construct an instance of the DBEntityResolver class
42
    *
43
    * @param conn the JDBC connection to which information is written
44
    */
45
   public DBEntityResolver(Connection conn)
46
   {
47
      this.conn = conn;
48
   }
49

    
50
   /** 
51
    * Construct an instance of the DBEntityResolver class
52
    *
53
    * @param conn the JDBC connection to which information is written
54
    * @param handler the SAX handler to determine parsing context
55
    */
56
   public DBEntityResolver(Connection conn, DBSAXHandler handler)
57
   {
58
      this(conn);
59
      this.handler = handler;
60
   }
61
   
62
   /** 
63
    * The Parser call this method before opening any external entity 
64
    * except the top-level document entity (including the external DTD subset,
65
    * external entities referenced within the DTD, and external entities 
66
    * referenced within the document element)
67
    */
68
   public InputSource resolveEntity (String publicId, String systemId)
69
                throws SAXException, IOException
70
   {
71
     String dbSystemId;
72
     String doctype = null;
73
     
74
     if (publicId != null) {       // If we have a public ID, use it
75
       doctype = publicId;
76
       MetaCatUtil.debugMessage("DOCTYPE-c: " + doctype);
77
     } else if (systemId != null) {  // Otherwise, use system id if we can
78
       if (handler != null) {        // Won't have a handler under all cases
79
         if (handler.processingDTD()) {  // Assume the public ID is the docname
80
           doctype = handler.getDocname();
81
           MetaCatUtil.debugMessage("DOCTYPE-d: " + doctype);
82
         }
83
       }
84
     }    
85

    
86
     // look at the db XML Catalog and get dbSystemId for this doctype
87
     if (doctype != null) {
88
       dbSystemId = getDTDSystemID (conn, doctype);
89
       if (dbSystemId == null) {
90
         MetaCatUtil.debugMessage("  RESOLVED NOTHING");
91
         // if it is not found in the database, then
92
         // register publicId in db and use the provided systemId
93
         if (systemId != null) {
94
           InputStream istream = checkURLConnection(systemId);
95
           if (handler != null) {    // Won't have a handler under all cases
96
             if (handler.processingDTD()) {
97
               registerDTDSystemID (conn, doctype, doctype, systemId);
98
             }
99
           }
100
           return null;
101
         }
102
       } else {
103
         MetaCatUtil.debugMessage("  RESOLVED SYSTEMID: " + dbSystemId);
104
         // If it is in the database, return the systemid from the database
105
         InputStream istream = checkURLConnection(dbSystemId);
106
         InputSource is = new InputSource(dbSystemId);
107
         is.setByteStream(istream);
108
         MetaCatUtil.debugMessage("  INPUTSOURCE SYSTEMID: " 
109
                                      + is.getSystemId());
110
         return is;
111
       } 
112
     }
113
    
114
     // use the provided systemID for other cases
115
     InputStream istream = checkURLConnection(systemId);
116
     return null;
117
   }
118

    
119
   /** 
120
    * Look at db XML Catalog to get System ID (if any) for that doctype.
121
    * Return empty string if there are not 
122
    */
123
   private String getDTDSystemID (Connection conn, String doctype)  {
124
        String system_id = null;
125
        Statement stmt;
126
        try {
127
          stmt = conn.createStatement();
128
          stmt.execute("SELECT system_id FROM xml_catalog " + 
129
                       "WHERE entry_type = 'DTD' AND public_id = '" + 
130
                       doctype + "'");
131
          try {
132
            ResultSet rs = stmt.getResultSet();
133
            try {
134
              boolean tableHasRows = rs.next();
135
              if (tableHasRows) {
136
                try {
137
                  system_id = rs.getString(1);
138
                } catch (SQLException e) {
139
                  System.out.println("DBEntityResolver.getDTDSystemID() " +
140
                             "- Error with getString: " + e.getMessage());
141
                }
142
              }
143
            } catch (SQLException e) {
144
              System.out.println("DBEntityResolver.getDTDSystemID() " +
145
                             "- Error with next: " + e.getMessage());
146
            }
147
          } catch (SQLException e) {
148
            System.out.println("DBEntityResolver.getDTDSystemID() " +
149
                             "- Error with getrset: " + e.getMessage());
150
          }
151
          stmt.close();
152
        } catch (SQLException e) {
153
          System.out.println("DBEntityResolver.getDTDSystemID() " +
154
                             "- Error getting id: " + e.getMessage());
155
        }
156

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

    
161
   /** 
162
    * Register DTD System ID in db XML Catalog 
163
    */
164
   private void registerDTDSystemID (Connection conn, String doctype, 
165
                                     String publicId, String systemId)
166
   {
167
     try {
168
       PreparedStatement pstmt;
169
       pstmt = conn.prepareStatement(
170
             "INSERT INTO xml_catalog " +
171
             "(catalog_id, entry_type, source_doctype, " +
172
             "public_id, system_id) " +
173
             "VALUES (null, 'DTD', ?, ?, ?)");
174
       // Bind the values to the query
175
       pstmt.setString(1, doctype);
176
       pstmt.setString(2, publicId);
177
       pstmt.setString(3, systemId);
178
       // Do the insertion
179
       pstmt.execute();
180
       pstmt.close();
181
     } catch (SQLException e) {
182
       System.out.println(e.getMessage());
183
     }
184
   }
185

    
186
   /** 
187
    * Check URL Connection for systemId, and return an InputStream
188
    * that can be used to read from the systemId URL.  The parser ends
189
    * up using this via the InputSource to read the DTD.
190
    *
191
    * @param systemID a URI (in practice URL) to be checked and opened
192
    */
193
   private InputStream checkURLConnection (String systemId)
194
                throws MalformedURLException, IOException
195
   {
196
     try {
197

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

    
200
     } catch (MalformedURLException e) {
201
       System.out.println("from checkURLConnection(): " + e.getMessage());
202
       throw e;
203
     } catch (IOException e) {
204
       System.out.println("from checkURLConnection(): " + e.getMessage());
205
       throw e;
206
     }    
207
   }   
208
}
209

    
210
/**
211
 * '$Log$
212
 * 'Revision 1.13  2000/06/29 23:27:08  jones
213
 * 'Fixed bug in DBEntityResolver so that it now properly delegates to
214
 * 'the system id found inthe database.
215
 * 'Changed DBValidate to use DBEntityResolver, rather than the OASIS
216
 * 'catalog, and to return validation results in XML format.
217
 * '
218
 * 'Revision 1.12  2000/06/27 04:31:07  jones
219
 * 'Fixed bugs associated with the new UPDATE and DELETE functions of
220
 * 'DBWriter.  There were problematic interactions between some static
221
 * 'variables used in DBEntityResolver and the way in which the
222
 * 'Servlet objects are re-used across multiple client invocations.
223
 * '
224
 * 'Generally cleaned up error reporting.  Now all errors and success
225
 * 'results are reported as XML documents from MetaCatServlet.  Need
226
 * 'to make the command line tools do the same.
227
 * '
228
 * 'Revision 1.11  2000/06/26 10:35:04  jones
229
 * 'Merged in substantial changes to DBWriter and associated classes and to
230
 * 'the MetaCatServlet in order to accomodate the new UPDATE and DELETE
231
 * 'functions.  The command line tools and the parameters for the
232
 * 'servlet have changed substantially.
233
 * '
234
 * 'Revision 1.10.2.2  2000/06/25 23:38:16  jones
235
 * 'Added RCSfile keyword
236
 * '
237
 * 'Revision 1.10.2.1  2000/06/25 23:34:17  jones
238
 * 'Changed documentation formatting, added log entries at bottom of source files
239
 * ''
240
 */
(7-7/25)