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: tao $'
11
 *     '$Date: 2003-03-03 12:16:12 -0800 (Mon, 03 Mar 2003) $'
12
 * '$Revision: 1442 $'
13
 *
14
 * This program is free software; you can redistribute it and/or modify
15
 * it under the terms of the GNU General Public License as published by
16
 * the Free Software Foundation; either version 2 of the License, or
17
 * (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program; if not, write to the Free Software
26
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27
 */
28

    
29
package edu.ucsb.nceas.metacat;
30

    
31

    
32
import java.sql.*;
33
import java.io.File;
34
import java.io.Reader;
35
import java.io.BufferedReader;
36
import java.io.BufferedInputStream;
37
import java.io.FileWriter;
38
import java.io.BufferedWriter;
39
import java.io.InputStream;
40
import java.io.IOException;
41
import java.net.URL;
42
import java.net.URLConnection;
43
import java.net.MalformedURLException;
44
import java.util.Vector;
45

    
46
/**
47
 * A database aware Class to handle schema location. If namespace is in the
48
 * xml_catalog table (public_id), the schema location specified in xml document
49
 * will be ignored by parser setting external schema location. If the
50
 * name space is not in the table, it will be download to metacat and register
51
 * in table
52
 */
53
public class SchemaLocationResolver
54
{
55
  
56
  private String nameSpace = null; //public id
57
  private String schemaLocation = null; // system id
58
  private Vector nameSpaceList = new Vector();// name space in the table
59
  private String nameSpaceAndLocationString = null; // the parameter will be set
60
                                              // in external property in parser
61
  //private String schemaFileName = null;
62
  // constant
63
  //private String SCHEMATYPE ="Schema"; 
64
  private String WHITESPACESTRING =" ";                                                         
65

    
66
  public SchemaLocationResolver()
67
  {
68
    createNameSpaceAndLocationStringFromDB();
69
  }
70
  /**
71
   * Construct an instance of the SchemaLocationResolver class
72
   *
73
   * @param  myNameSpaceAndLocation it is come from xsi:schemaLocation=
74
   *         "namespace location"
75
   */
76
  public SchemaLocationResolver(String myNameSpaceAndLocation)
77
  {
78
    parse(myNameSpaceAndLocation);
79
  }
80
  
81
  /**
82
   * A method to get nameSpaceAndLocationString
83
   */
84
  public String getNameSpaceAndLocationString()
85
  {
86
    MetaCatUtil.debugMessage("namespace and location list is: " +
87
                             nameSpaceAndLocationString, 30);
88
    return nameSpaceAndLocationString;
89
  }
90
  
91
  /**
92
   * When got a name space, check if it is in the database, if it is do nothing
93
   * else upload it to metacat to store it and register it in catalog table
94
   */
95
  public void resolveNameSpace ()
96
  {
97
    //get name space lists
98
    createNameSpaceListFromDB();
99
  
100
    // if name space is not in table
101
    if (nameSpace !=null && schemaLocation != null &&
102
        !nameSpaceList.contains(nameSpace))
103
    {
104
       try
105
       {
106
        
107
        // upload schema into metacat
108
        InputStream in = DBEntityResolver.checkURLConnection(schemaLocation);
109
       
110
        String newURLInMetacat = uploadSchemaFromURL(in);
111
       
112
        // reigister schema
113
        registerSchema(newURLInMetacat);
114
     
115
       }
116
       catch(Exception e)
117
       {
118
         MetaCatUtil.debugMessage("Error in SchemaLocation.resolveNameSpace" +
119
                                  e.getMessage(), 30);
120
       }
121
 
122
    }//if
123
 
124
  }
125

    
126
  /* This method will take look xml_catalog table and create a string look like
127
   * "namespace1 location namespacke2 location". This string will be set as 
128
   * a extenalschemalocation in SAX parser. Then when parser check the 
129
   * it will ignore the schema location specified by xml document
130
   */
131
  private void createNameSpaceAndLocationStringFromDB()
132
  {
133
    DBConnection conn = null;
134
    int serialNumber = -1;
135
    PreparedStatement pstmt = null;
136
    ResultSet result = null;
137
    String sql = "SELECT public_id, system_id FROM xml_catalog where " +
138
                 "entry_type ='" + DocumentImpl.SCHEMA +"'";
139
    try 
140
    {
141
      //check out DBConnection
142
      conn=DBConnectionPool.getDBConnection("SchemaLocationResl.createName");
143
      serialNumber=conn.getCheckOutSerialNumber();
144
      pstmt = conn.prepareStatement(sql);
145
      pstmt.execute();
146
      result = pstmt.getResultSet();
147
      
148
      // Get string for namespace and location form DB
149
      boolean hasRow = result.next();
150
      StringBuffer buffer = new StringBuffer();
151
      boolean firstTime = true;
152
      while (hasRow)
153
      {
154
        String namespace = result.getString(1);
155
        String location  = result.getString(2);
156
        String pairOfNameSpaceAndLocation = namespace + WHITESPACESTRING 
157
                                            +location;
158
        if (!firstTime)
159
        {
160
          buffer.append(WHITESPACESTRING);
161
        }
162
        buffer.append(pairOfNameSpaceAndLocation);
163
        firstTime = false;
164
        hasRow = result.next();
165
        
166
      }
167
      // give the buffer to the string if buffer has something in it
168
      if (buffer.length() != 0)
169
      {
170
        nameSpaceAndLocationString = buffer.toString();
171
      }
172
      result.close();
173
      pstmt.close();
174
    } 
175
    catch (SQLException e) 
176
    {
177
      MetaCatUtil.debugMessage
178
                        ("schemaLocation.createNameSpaceAndLocationString: " + 
179
                         e.getMessage(), 30);
180
    }
181
    finally
182
    {
183
      try
184
      {
185
        pstmt.close();
186
      }//try
187
      catch (SQLException sqlE)
188
      {
189
        MetaCatUtil.debugMessage("Error in schema.createNameSpaceAndLocation "
190
                                    + sqlE.getMessage(), 30);
191
      }//catch
192
      DBConnectionPool.returnDBConnection(conn, serialNumber);
193
    }//finally
194
    
195

    
196
  }
197

    
198
  /* This method will take look xml_catalog table and create a name space
199
   * vector already in the table
200
   */
201
  private void createNameSpaceListFromDB()
202
  {
203
    DBConnection conn = null;
204
    int serialNumber = -1;
205
    PreparedStatement pstmt = null;
206
    ResultSet result = null;
207
    String sql = "SELECT public_id FROM xml_catalog where " +
208
                 "entry_type ='" + DocumentImpl.SCHEMA +"'";
209
    try 
210
    {
211
      //check out DBConnection
212
      conn=DBConnectionPool.getDBConnection("SchemaLocationResl.createNameList");
213
      serialNumber=conn.getCheckOutSerialNumber();
214
      pstmt = conn.prepareStatement(sql);
215
      pstmt.execute();
216
      result = pstmt.getResultSet();
217
      
218
      // Get string for namespace form DB and store in the vector
219
      boolean hasRow = result.next();
220
      while (hasRow)
221
      {
222
        String namespace = result.getString(1);
223
        nameSpaceList.addElement(namespace);
224
        hasRow = result.next();
225
        
226
      }
227
      pstmt.close();
228
      result.close();
229
    } 
230
    catch (SQLException e) 
231
    {
232
      MetaCatUtil.debugMessage
233
                        ("schemaLocation.createNameSpaceList: " + 
234
                         e.getMessage(), 30);
235
    }
236
    finally
237
    {
238
      try
239
      {
240
        pstmt.close();
241
      }//try
242
      catch (SQLException sqlE)
243
      {
244
        MetaCatUtil.debugMessage("Error in schemaLocation.createNameSpaceList: "
245
                                    +sqlE.getMessage(), 30);
246
      }//catch
247
      DBConnectionPool.returnDBConnection(conn, serialNumber);
248
    }//finally
249
  
250
  }
251
  
252
   
253

    
254
  /**
255
   * Upload new Schema located at outside URL to Metacat file system
256
   */
257
  private String uploadSchemaFromURL(InputStream istream) throws Exception
258
  {
259
   
260
    String schemaPath = MetaCatUtil.getOption("schemaPath");
261
    String schemaURL = MetaCatUtil.getOption("schemaURL");
262

    
263
    // get filename from systemId
264
    String filename = schemaLocation;
265
  
266
    if (filename != null && !(filename.trim()).equals(""))
267
    {
268
      int slash = Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\'));
269
      if ( slash > -1 ) 
270
      {
271
        filename = filename.substring(slash + 1);
272
      }
273
    }
274
    else
275
    {
276
      return null;
277
    }
278
    // writing schema text on Metacat file system as filename
279
    try {
280
      // create a buffering character-input stream
281
      // that uses a default-sized input buffer
282
      BufferedInputStream in = new BufferedInputStream(istream);
283

    
284
      // open file writer to write the input into it
285
      File f = new File(schemaPath, filename);
286
      synchronized (f) 
287
      {
288
        try 
289
        {
290
          if ( f.exists() ) 
291
          {
292
           throw new IOException("File already exist: " + f.getCanonicalFile());
293
          }
294
        } 
295
        catch (SecurityException se) 
296
        {
297
         // if a security manager exists,
298
          throw se;
299
       }
300
      // create a buffered character-output stream
301
      // that uses a default-sized output buffer
302
      FileWriter fw = new FileWriter(f);
303
      BufferedWriter out = new BufferedWriter(fw);
304

    
305
      // read the input and write into the file writer
306
      int inputByte;
307
      while ( (inputByte = in.read()) != -1 ) 
308
      {
309
        out.write(inputByte);
310
        //out.newLine(); //instead of out.write('\r\n');
311
      }
312

    
313
      // the input and the output streams must be closed
314
      in.close();
315
      out.flush();
316
      out.close();
317
      fw.close();
318
     } // end of synchronized
319
    } 
320
    catch (Exception e) 
321
    {
322
      throw new Exception
323
      ("shemaLocationResolver.uploadSchemaFromURL(): " + e.getMessage());
324
    } 
325
    MetaCatUtil.debugMessage("new schema location is: " + schemaURL + 
326
                              filename, 20);
327
    return  schemaURL + filename;
328
  }
329

    
330
  
331
  /*
332
   * Register new schema identified by @systemId in Metacat XML Catalog
333
   */
334
  private void registerSchema(String systemId )
335
  {
336
    // check systemid is not null
337
    if (systemId == null || nameSpace == null || (nameSpace.trim()).equals(""))
338
    {
339
     
340
      return;
341
    }
342
    
343
    DBConnection conn = null;
344
    int serialNumber = -1;
345
    PreparedStatement pstmt = null;
346
    String sql = "INSERT INTO xml_catalog " +
347
             "(entry_type, public_id, system_id) " +
348
             "VALUES ('" + DocumentImpl.SCHEMA + "', ?, ?)";
349
    
350
 
351
    try 
352
    {
353
      //check out DBConnection
354
      conn=DBConnectionPool.getDBConnection("schemaLocation.registerSchema");
355
      serialNumber=conn.getCheckOutSerialNumber();
356
      pstmt = conn.prepareStatement(sql);
357
     
358
      // Bind the values to the query
359
      pstmt.setString(1, nameSpace);
360
      pstmt.setString(2, systemId);
361
      // Do the insertion
362
      pstmt.execute();
363
      pstmt.close();
364
    } 
365
    catch (SQLException e) 
366
    {
367
      MetaCatUtil.debugMessage
368
      ("SchemaLocation.egisterSchema(): " + e.getMessage(), 30);
369
    }
370
    finally
371
    {
372
      try
373
      {
374
        pstmt.close();
375
      }//try
376
      catch (SQLException sqlE)
377
      {
378
        MetaCatUtil.debugMessage("Error in SchemaLocation.egisterSchema(): "
379
                                    +sqlE.getMessage(), 30);
380
      }//catch
381
      DBConnectionPool.returnDBConnection(conn, serialNumber);
382
    }//finally
383

    
384
  }
385
  
386
  /*
387
   * A method to parse the value for xis:schemaLocation="namespace location"
388
   * and store the namespace in nameSpace and location in schemaLocaion
389
   */
390
  private void parse(String nameSpaceAndLocation)
391
  {
392
    // check the parameter
393
    if (nameSpaceAndLocation == null||(nameSpaceAndLocation.trim()).equals(""))
394
    {
395
      return;
396
    }
397
    //Get white space index (delimiter)
398
    int indexOfWhiteSpace = nameSpaceAndLocation.lastIndexOf(WHITESPACESTRING);
399
    if (indexOfWhiteSpace != -1)
400
    {
401
      // before white space is namespace
402
      nameSpace = nameSpaceAndLocation.substring(0,indexOfWhiteSpace);
403
      // after white sapce is schema location
404
      schemaLocation = nameSpaceAndLocation.substring(indexOfWhiteSpace+1);
405
      // Gebug message
406
      MetaCatUtil.debugMessage("Namespace after parsing: " + nameSpace, 30);
407
      MetaCatUtil.debugMessage("Location after parsing: " + schemaLocation, 30);
408
    } 
409
  }
410
  
411
  public static void main(String[] argus)
412
  {
413
     try
414
     {
415
       DBConnectionPool pool = DBConnectionPool.getInstance();
416
       // Print out a empty schema list
417
       SchemaLocationResolver schema = new SchemaLocationResolver();
418
       MetaCatUtil.debugMessage("Namespace and Location String: "+ 
419
                                schema.getNameSpaceAndLocationString(), 20);
420
       // input a schemalocation
421
       SchemaLocationResolver schema2 = new SchemaLocationResolver(
422
                                        "eml://ecoinformatics.org/eml-2.0.0 " +
423
                                "http://dev.nceas.ucsb.edu/tao/schema/eml.xsd");
424
       schema2.resolveNameSpace();
425
       // input a wrong name space location
426
       SchemaLocationResolver schema3 = new SchemaLocationResolver(
427
                                        "http://www.xm.org/schema/stmml " +
428
                              "http://dev.nceas.ucsb.edu/tao/schema/stmml.xsd");
429
       schema3.resolveNameSpace();
430
       // print out new schema list in db
431
       SchemaLocationResolver schema4 = new SchemaLocationResolver();
432
       MetaCatUtil.debugMessage("Namespace and Location String: "+ 
433
                                schema4.getNameSpaceAndLocationString(), 20);
434
     }
435
     catch(Exception e)
436
     {
437
       MetaCatUtil.debugMessage("erorr in Schemalocation.main: " + 
438
                                e.getMessage(), 30);
439
     }
440
  }
441
}
(61-61/64)