Project

General

Profile

1 1391 tao
/**
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$'
10
 *     '$Date$'
11
 * '$Revision$'
12
 *
13
 * This program is free software; you can redistribute it and/or modify
14
 * it under the terms of the GNU General Public License as published by
15
 * the Free Software Foundation; either version 2 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program; if not, write to the Free Software
25
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
 */
27
28
package edu.ucsb.nceas.metacat;
29
30
31
import java.sql.*;
32 5945 tao
import java.util.Vector;
33 1391 tao
import java.io.File;
34
import java.io.BufferedInputStream;
35
import java.io.FileWriter;
36
import java.io.BufferedWriter;
37
import java.io.InputStream;
38
import java.io.IOException;
39
40 2663 sgarg
import org.apache.log4j.Logger;
41 5945 tao
import org.xml.sax.SAXException;
42 2663 sgarg
43 5015 daigle
import edu.ucsb.nceas.metacat.database.DBConnection;
44
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
45 4698 daigle
import edu.ucsb.nceas.metacat.service.ServiceService;
46 5945 tao
import edu.ucsb.nceas.metacat.service.XMLSchemaParser;
47 4427 daigle
import edu.ucsb.nceas.metacat.service.XMLSchemaService;
48 4080 daigle
import edu.ucsb.nceas.metacat.util.SystemUtil;
49 5945 tao
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
50 4080 daigle
51 1391 tao
/**
52
 * A database aware Class to handle schema location. If namespace is in the
53
 * xml_catalog table (public_id), the schema location specified in xml document
54
 * will be ignored by parser setting external schema location. If the
55
 * name space is not in the table, it will be download to metacat and register
56
 * in table
57
 */
58
public class SchemaLocationResolver
59
{
60
61
  private String nameSpace = null; //public id
62
  private String schemaLocation = null; // system id
63 4409 tao
  private String WHITESPACESTRING =" ";
64
  private boolean downloadNewSchema = false;
65 1391 tao
66 2663 sgarg
  private static Logger logMetacat = Logger.getLogger(SchemaLocationResolver.class);
67
68 1391 tao
  public SchemaLocationResolver()
69 4427 daigle
  {
70 1391 tao
  }
71 4427 daigle
72 1391 tao
  /**
73
   * Construct an instance of the SchemaLocationResolver class
74
   *
75
   * @param  myNameSpaceAndLocation it is come from xsi:schemaLocation=
76
   *         "namespace location"
77
   */
78
  public SchemaLocationResolver(String myNameSpaceAndLocation)
79
  {
80 4427 daigle
	  parse(myNameSpaceAndLocation);
81
82 1391 tao
  }
83 4427 daigle
84 1391 tao
  /**
85 4427 daigle
   * Construct an instance of the SchemaLocationResolver class
86
   *
87
   * @param  myNameSpaceAndLocation it is come from xsi:schemaLocation=
88
   *         "namespace location"
89 1391 tao
   */
90 4427 daigle
  public SchemaLocationResolver(String myNameSpace, String myLocation)
91 1391 tao
  {
92 4427 daigle
      nameSpace = myNameSpace;
93
      schemaLocation = myLocation;
94 1391 tao
  }
95
96
  /**
97
   * When got a name space, check if it is in the database, if it is do nothing
98
   * else upload it to metacat to store it and register it in catalog table
99
   */
100
  public void resolveNameSpace ()
101
  {
102
103
    // if name space is not in table
104
    if (nameSpace !=null && schemaLocation != null &&
105 5340 berkley
        !XMLSchemaService.getInstance().getNameSpaceList().contains(nameSpace))
106 1391 tao
    {
107
       try
108
       {
109
110
        // upload schema into metacat
111 5945 tao
        String newURLInMetacat = uploadSchemaFromURL(schemaLocation);
112 4698 daigle
        ServiceService.refreshService("XMLSchemaService");
113 1391 tao
114 4427 daigle
        // check the name space list again.  It may not have appeared the first time
115
        // because the schema was in the db but there was no file on disk.  If that's
116
        // the case, it will show up in the name space list now.  If it doesn't we need
117
        // to register the schema in the database.
118 5340 berkley
        if (!XMLSchemaService.getInstance().getNameSpaceList().contains(nameSpace)) {
119 4427 daigle
        	registerSchema(newURLInMetacat);
120 4698 daigle
        	ServiceService.refreshService("XMLSchemaService");
121 4427 daigle
        }
122 4409 tao
        downloadNewSchema = true;
123 5945 tao
        //handle included schema in above schema
124
        String externalBaseURL = XMLSchemaService.getBaseUrlFromSchemaURL(schemaLocation);
125
        //System.out.println("==========the externalBaseURL is "+externalBaseURL);
126
        handleIncludedSchema(newURLInMetacat, externalBaseURL);
127 1391 tao
       }
128
       catch(Exception e)
129
       {
130 2663 sgarg
         logMetacat.error("Error in SchemaLocation.resolveNameSpace" +
131
                                  e.getMessage());
132 1391 tao
       }
133
134
    }//if
135
136
  }
137 5945 tao
138
  /*
139
   * Some schemas (parent schema)also include other schemas (children) in
140
   * its definition. The syntax is:  <xsd:include schemaLocation="product.xsd"/>
141
   * The included schemas need to be downloaded as well.
142
   * The included schemas always have the same target namespace. So there
143
   * is no need to register the schema into xml_catalog table.
144
   * Note: the included schemas may have included schemas (grandchildren) as well.
145
   */
146
  private void handleIncludedSchema(String parentSchemaNewURLInMetacat,
147
                                                                          String externalBaseURL)
148
                                                          throws SAXException, IOException,PropertyNotFoundException
149
  {
150
    //Gets the included schema information from parent schema
151
    //System.out.println("the parent schema new url in metacat ============="+parentSchemaNewURLInMetacat);
152
    if(externalBaseURL != null)
153
    {
154
      InputStream in = DBEntityResolver.checkURLConnection(SystemUtil.getContextURL()+parentSchemaNewURLInMetacat);
155
      XMLSchemaParser parser = new XMLSchemaParser(in);
156
      parser.parse();
157
      Vector<String> includedSchemaPaths = parser.getIncludedSchemaFilePathes();
158
      //System.out.println("the include schema paths is ============ "+includedSchemaPaths);
159
      if(includedSchemaPaths!=  null)
160
      {
161
        for(int i=0; i<includedSchemaPaths.size(); i++)
162
        {
163
          String schemaFilePath = includedSchemaPaths.elementAt(i);
164
          //System.out.println("start to handle the included path ========="+schemaFilePath);
165
          try
166
          {
167
            String newShemaURLInMetacat =
168
                           uploadSchemaFromURL(externalBaseURL+schemaFilePath);
169
            //System.out.println("success download the included schema and new url is  ========="+newShemaURLInMetacat);
170
            //recursively download the included schema
171
            handleIncludedSchema(newShemaURLInMetacat, externalBaseURL);
172
          }
173
          catch(Exception e)
174
          {
175
            logMetacat.warn("Warning on SchemaLocationResolver.handleIncludedSchema"+e.getMessage());
176
          }
177
178
        }
179
      }
180
    }
181
182
  }
183 1391 tao
184
  /**
185
   * Upload new Schema located at outside URL to Metacat file system
186
   */
187 5945 tao
  private String uploadSchemaFromURL(String schemaLocationURL) throws Exception
188 1391 tao
  {
189
190 5945 tao
	  String relativeSchemaPath = XMLSchemaService.SCHEMA_DIR;
191 4427 daigle
    String fullSchemaPath = SystemUtil.getContextDir() + relativeSchemaPath;
192
    String schemaURL = SystemUtil.getContextURL()  + relativeSchemaPath;
193 1391 tao
194
    // get filename from systemId
195 5945 tao
    String filename = XMLSchemaService.getSchemaFileNameFromUri(schemaLocationURL);
196 1391 tao
197
    if (filename != null && !(filename.trim()).equals(""))
198
    {
199
      int slash = Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\'));
200
      if ( slash > -1 )
201
      {
202
        filename = filename.substring(slash + 1);
203
      }
204
    }
205
    else
206
    {
207
      return null;
208
    }
209
    // writing schema text on Metacat file system as filename
210
    try {
211 5945 tao
      InputStream istream = DBEntityResolver.checkURLConnection(schemaLocationURL);
212 1391 tao
      // create a buffering character-input stream
213
      // that uses a default-sized input buffer
214
      BufferedInputStream in = new BufferedInputStream(istream);
215
216
      // open file writer to write the input into it
217 4427 daigle
      File f = new File(fullSchemaPath, filename);
218 1391 tao
      synchronized (f)
219
      {
220
        try
221
        {
222
          if ( f.exists() )
223
          {
224
           throw new IOException("File already exist: " + f.getCanonicalFile());
225
          }
226
        }
227
        catch (SecurityException se)
228
        {
229
         // if a security manager exists,
230
          throw se;
231
       }
232
      // create a buffered character-output stream
233
      // that uses a default-sized output buffer
234
      FileWriter fw = new FileWriter(f);
235
      BufferedWriter out = new BufferedWriter(fw);
236
237
      // read the input and write into the file writer
238
      int inputByte;
239
      while ( (inputByte = in.read()) != -1 )
240
      {
241
        out.write(inputByte);
242
        //out.newLine(); //instead of out.write('\r\n');
243
      }
244
245
      // the input and the output streams must be closed
246
      in.close();
247
      out.flush();
248
      out.close();
249
      fw.close();
250
     } // end of synchronized
251
    }
252
    catch (Exception e)
253
    {
254
      throw new Exception
255
      ("shemaLocationResolver.uploadSchemaFromURL(): " + e.getMessage());
256
    }
257 2663 sgarg
    logMetacat.warn("new schema location is: " + schemaURL +
258
                              filename);
259 4427 daigle
    return  relativeSchemaPath + filename;
260 1391 tao
  }
261
262
263
  /*
264
   * Register new schema identified by @systemId in Metacat XML Catalog
265
   */
266
  private void registerSchema(String systemId )
267
  {
268
    // check systemid is not null
269
    if (systemId == null || nameSpace == null || (nameSpace.trim()).equals(""))
270 4427 daigle
    {
271 1391 tao
      return;
272
    }
273
274
    DBConnection conn = null;
275
    int serialNumber = -1;
276
    PreparedStatement pstmt = null;
277
    String sql = "INSERT INTO xml_catalog " +
278
             "(entry_type, public_id, system_id) " +
279 1442 tao
             "VALUES ('" + DocumentImpl.SCHEMA + "', ?, ?)";
280 1391 tao
281
282
    try
283
    {
284
      //check out DBConnection
285
      conn=DBConnectionPool.getDBConnection("schemaLocation.registerSchema");
286
      serialNumber=conn.getCheckOutSerialNumber();
287
      pstmt = conn.prepareStatement(sql);
288
289
      // Bind the values to the query
290
      pstmt.setString(1, nameSpace);
291
      pstmt.setString(2, systemId);
292
      // Do the insertion
293
      pstmt.execute();
294
      pstmt.close();
295
    }
296
    catch (SQLException e)
297
    {
298 2663 sgarg
      logMetacat.error("SchemaLocation.egisterSchema(): " + e.getMessage());
299 1391 tao
    }
300
    finally
301
    {
302
      try
303
      {
304
        pstmt.close();
305
      }//try
306
      catch (SQLException sqlE)
307
      {
308 2663 sgarg
        logMetacat.error("Error in SchemaLocation.egisterSchema(): "
309
                                    +sqlE.getMessage());
310 1391 tao
      }//catch
311
      DBConnectionPool.returnDBConnection(conn, serialNumber);
312 4427 daigle
313 1391 tao
    }//finally
314 5340 berkley
    XMLSchemaService.getInstance().populateRegisteredSchemaList();
315 1391 tao
  }
316
317
  /*
318
   * A method to parse the value for xis:schemaLocation="namespace location"
319
   * and store the namespace in nameSpace and location in schemaLocaion
320
   */
321
  private void parse(String nameSpaceAndLocation)
322
  {
323
    // check the parameter
324
    if (nameSpaceAndLocation == null||(nameSpaceAndLocation.trim()).equals(""))
325
    {
326
      return;
327
    }
328
    //Get white space index (delimiter)
329
    int indexOfWhiteSpace = nameSpaceAndLocation.lastIndexOf(WHITESPACESTRING);
330
    if (indexOfWhiteSpace != -1)
331
    {
332
      // before white space is namespace
333
      nameSpace = nameSpaceAndLocation.substring(0,indexOfWhiteSpace);
334
      // after white sapce is schema location
335
      schemaLocation = nameSpaceAndLocation.substring(indexOfWhiteSpace+1);
336
      // Gebug message
337 2663 sgarg
      logMetacat.info("Namespace after parsing: " + nameSpace);
338
      logMetacat.info("Location after parsing: " + schemaLocation);
339 1391 tao
    }
340
  }
341
342
  public static void main(String[] argus)
343
  {
344
     try
345
     {
346
       DBConnectionPool pool = DBConnectionPool.getInstance();
347
       // Print out a empty schema list
348
       SchemaLocationResolver schema = new SchemaLocationResolver();
349 2663 sgarg
       logMetacat.warn("Namespace and Location String: "+
350 5340 berkley
                                XMLSchemaService.getInstance().getNameSpaceAndLocationString());
351 1391 tao
       // input a schemalocation
352
       SchemaLocationResolver schema2 = new SchemaLocationResolver(
353
                                        "eml://ecoinformatics.org/eml-2.0.0 " +
354
                                "http://dev.nceas.ucsb.edu/tao/schema/eml.xsd");
355
       schema2.resolveNameSpace();
356
       // input a wrong name space location
357
       SchemaLocationResolver schema3 = new SchemaLocationResolver(
358 1442 tao
                                        "http://www.xm.org/schema/stmml " +
359 1391 tao
                              "http://dev.nceas.ucsb.edu/tao/schema/stmml.xsd");
360
       schema3.resolveNameSpace();
361
       // print out new schema list in db
362
       SchemaLocationResolver schema4 = new SchemaLocationResolver();
363 2663 sgarg
       logMetacat.warn("Namespace and Location String: "+
364 5340 berkley
    		   XMLSchemaService.getInstance().getNameSpaceAndLocationString());
365 1391 tao
     }
366
     catch(Exception e)
367
     {
368 2663 sgarg
       logMetacat.error("erorr in Schemalocation.main: " +
369
                                e.getMessage());
370 1391 tao
     }
371
  }
372 4409 tao
373
  /**
374
   * Gets the downloadNewSchema's value.
375
   * @return
376
   */
377
 public boolean getDownloadNewSchema()
378
 {
379
	 return this.downloadNewSchema;
380
 }
381 1391 tao
}