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
import java.io.File;
33
import java.io.BufferedInputStream;
34
import java.io.FileWriter;
35
import java.io.BufferedWriter;
36
import java.io.InputStream;
37
import java.io.IOException;
38
39 2663 sgarg
import org.apache.log4j.Logger;
40
41 4427 daigle
import edu.ucsb.nceas.metacat.service.XMLSchemaService;
42 4080 daigle
import edu.ucsb.nceas.metacat.util.SystemUtil;
43
44 1391 tao
/**
45
 * A database aware Class to handle schema location. If namespace is in the
46
 * xml_catalog table (public_id), the schema location specified in xml document
47
 * will be ignored by parser setting external schema location. If the
48
 * name space is not in the table, it will be download to metacat and register
49
 * in table
50
 */
51
public class SchemaLocationResolver
52
{
53
54
  private String nameSpace = null; //public id
55
  private String schemaLocation = null; // system id
56 4427 daigle
//  private Vector<String> nameSpaceList = new Vector<String>();// name space in the table
57
//  private String nameSpaceAndLocationString = ""; // the parameter will be set
58
//                                              // in external property in parser
59 1391 tao
  //private String schemaFileName = null;
60
  // constant
61 1442 tao
  //private String SCHEMATYPE ="Schema";
62 4409 tao
  private String WHITESPACESTRING =" ";
63
  private boolean downloadNewSchema = false;
64 1391 tao
65 2663 sgarg
  private static Logger logMetacat = Logger.getLogger(SchemaLocationResolver.class);
66
67 1391 tao
  public SchemaLocationResolver()
68 4427 daigle
  {
69 1391 tao
  }
70 4427 daigle
71 1391 tao
  /**
72
   * Construct an instance of the SchemaLocationResolver class
73
   *
74
   * @param  myNameSpaceAndLocation it is come from xsi:schemaLocation=
75
   *         "namespace location"
76
   */
77
  public SchemaLocationResolver(String myNameSpaceAndLocation)
78
  {
79 4427 daigle
	  parse(myNameSpaceAndLocation);
80
81 1391 tao
  }
82 4427 daigle
83 1391 tao
  /**
84 4427 daigle
   * Construct an instance of the SchemaLocationResolver class
85
   *
86
   * @param  myNameSpaceAndLocation it is come from xsi:schemaLocation=
87
   *         "namespace location"
88 1391 tao
   */
89 4427 daigle
  public SchemaLocationResolver(String myNameSpace, String myLocation)
90 1391 tao
  {
91 4427 daigle
      nameSpace = myNameSpace;
92
      schemaLocation = myLocation;
93 1391 tao
  }
94
95
  /**
96
   * When got a name space, check if it is in the database, if it is do nothing
97
   * else upload it to metacat to store it and register it in catalog table
98
   */
99
  public void resolveNameSpace ()
100
  {
101
102
    // if name space is not in table
103
    if (nameSpace !=null && schemaLocation != null &&
104 4427 daigle
        !XMLSchemaService.getNameSpaceList().contains(nameSpace))
105 1391 tao
    {
106
       try
107
       {
108
109
        // upload schema into metacat
110
        InputStream in = DBEntityResolver.checkURLConnection(schemaLocation);
111
112
        String newURLInMetacat = uploadSchemaFromURL(in);
113 4427 daigle
        XMLSchemaService.refresh();
114 1391 tao
115 4427 daigle
        // check the name space list again.  It may not have appeared the first time
116
        // because the schema was in the db but there was no file on disk.  If that's
117
        // the case, it will show up in the name space list now.  If it doesn't we need
118
        // to register the schema in the database.
119
        if (!XMLSchemaService.getNameSpaceList().contains(nameSpace)) {
120
        	registerSchema(newURLInMetacat);
121
        	XMLSchemaService.refresh();
122
        }
123 4409 tao
        downloadNewSchema = true;
124 1391 tao
125
       }
126
       catch(Exception e)
127
       {
128 2663 sgarg
         logMetacat.error("Error in SchemaLocation.resolveNameSpace" +
129
                                  e.getMessage());
130 1391 tao
       }
131
132
    }//if
133
134
  }
135
136
  /**
137
   * Upload new Schema located at outside URL to Metacat file system
138
   */
139
  private String uploadSchemaFromURL(InputStream istream) throws Exception
140
  {
141
142 4427 daigle
	String relativeSchemaPath = XMLSchemaService.SCHEMA_DIR;
143
    String fullSchemaPath = SystemUtil.getContextDir() + relativeSchemaPath;
144
    String schemaURL = SystemUtil.getContextURL()  + relativeSchemaPath;
145 1391 tao
146
    // get filename from systemId
147 4427 daigle
    String filename = XMLSchemaService.getSchemaFileNameFromUri(schemaLocation);
148 1391 tao
149
    if (filename != null && !(filename.trim()).equals(""))
150
    {
151
      int slash = Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\'));
152
      if ( slash > -1 )
153
      {
154
        filename = filename.substring(slash + 1);
155
      }
156
    }
157
    else
158
    {
159
      return null;
160
    }
161
    // writing schema text on Metacat file system as filename
162
    try {
163
      // create a buffering character-input stream
164
      // that uses a default-sized input buffer
165
      BufferedInputStream in = new BufferedInputStream(istream);
166
167
      // open file writer to write the input into it
168 4427 daigle
      File f = new File(fullSchemaPath, filename);
169 1391 tao
      synchronized (f)
170
      {
171
        try
172
        {
173
          if ( f.exists() )
174
          {
175
           throw new IOException("File already exist: " + f.getCanonicalFile());
176
          }
177
        }
178
        catch (SecurityException se)
179
        {
180
         // if a security manager exists,
181
          throw se;
182
       }
183
      // create a buffered character-output stream
184
      // that uses a default-sized output buffer
185
      FileWriter fw = new FileWriter(f);
186
      BufferedWriter out = new BufferedWriter(fw);
187
188
      // read the input and write into the file writer
189
      int inputByte;
190
      while ( (inputByte = in.read()) != -1 )
191
      {
192
        out.write(inputByte);
193
        //out.newLine(); //instead of out.write('\r\n');
194
      }
195
196
      // the input and the output streams must be closed
197
      in.close();
198
      out.flush();
199
      out.close();
200
      fw.close();
201
     } // end of synchronized
202
    }
203
    catch (Exception e)
204
    {
205
      throw new Exception
206
      ("shemaLocationResolver.uploadSchemaFromURL(): " + e.getMessage());
207
    }
208 2663 sgarg
    logMetacat.warn("new schema location is: " + schemaURL +
209
                              filename);
210 4427 daigle
    return  relativeSchemaPath + filename;
211 1391 tao
  }
212
213
214
  /*
215
   * Register new schema identified by @systemId in Metacat XML Catalog
216
   */
217
  private void registerSchema(String systemId )
218
  {
219
    // check systemid is not null
220
    if (systemId == null || nameSpace == null || (nameSpace.trim()).equals(""))
221 4427 daigle
    {
222 1391 tao
      return;
223
    }
224
225
    DBConnection conn = null;
226
    int serialNumber = -1;
227
    PreparedStatement pstmt = null;
228
    String sql = "INSERT INTO xml_catalog " +
229
             "(entry_type, public_id, system_id) " +
230 1442 tao
             "VALUES ('" + DocumentImpl.SCHEMA + "', ?, ?)";
231 1391 tao
232
233
    try
234
    {
235
      //check out DBConnection
236
      conn=DBConnectionPool.getDBConnection("schemaLocation.registerSchema");
237
      serialNumber=conn.getCheckOutSerialNumber();
238
      pstmt = conn.prepareStatement(sql);
239
240
      // Bind the values to the query
241
      pstmt.setString(1, nameSpace);
242
      pstmt.setString(2, systemId);
243
      // Do the insertion
244
      pstmt.execute();
245
      pstmt.close();
246
    }
247
    catch (SQLException e)
248
    {
249 2663 sgarg
      logMetacat.error("SchemaLocation.egisterSchema(): " + e.getMessage());
250 1391 tao
    }
251
    finally
252
    {
253
      try
254
      {
255
        pstmt.close();
256
      }//try
257
      catch (SQLException sqlE)
258
      {
259 2663 sgarg
        logMetacat.error("Error in SchemaLocation.egisterSchema(): "
260
                                    +sqlE.getMessage());
261 1391 tao
      }//catch
262
      DBConnectionPool.returnDBConnection(conn, serialNumber);
263 4427 daigle
264 1391 tao
    }//finally
265 4427 daigle
    XMLSchemaService.populateRegisteredSchemaList();
266 1391 tao
  }
267
268
  /*
269
   * A method to parse the value for xis:schemaLocation="namespace location"
270
   * and store the namespace in nameSpace and location in schemaLocaion
271
   */
272
  private void parse(String nameSpaceAndLocation)
273
  {
274
    // check the parameter
275
    if (nameSpaceAndLocation == null||(nameSpaceAndLocation.trim()).equals(""))
276
    {
277
      return;
278
    }
279
    //Get white space index (delimiter)
280
    int indexOfWhiteSpace = nameSpaceAndLocation.lastIndexOf(WHITESPACESTRING);
281
    if (indexOfWhiteSpace != -1)
282
    {
283
      // before white space is namespace
284
      nameSpace = nameSpaceAndLocation.substring(0,indexOfWhiteSpace);
285
      // after white sapce is schema location
286
      schemaLocation = nameSpaceAndLocation.substring(indexOfWhiteSpace+1);
287
      // Gebug message
288 2663 sgarg
      logMetacat.info("Namespace after parsing: " + nameSpace);
289
      logMetacat.info("Location after parsing: " + schemaLocation);
290 1391 tao
    }
291
  }
292
293
  public static void main(String[] argus)
294
  {
295
     try
296
     {
297
       DBConnectionPool pool = DBConnectionPool.getInstance();
298
       // Print out a empty schema list
299
       SchemaLocationResolver schema = new SchemaLocationResolver();
300 2663 sgarg
       logMetacat.warn("Namespace and Location String: "+
301 4427 daigle
                                XMLSchemaService.getNameSpaceAndLocationString());
302 1391 tao
       // input a schemalocation
303
       SchemaLocationResolver schema2 = new SchemaLocationResolver(
304
                                        "eml://ecoinformatics.org/eml-2.0.0 " +
305
                                "http://dev.nceas.ucsb.edu/tao/schema/eml.xsd");
306
       schema2.resolveNameSpace();
307
       // input a wrong name space location
308
       SchemaLocationResolver schema3 = new SchemaLocationResolver(
309 1442 tao
                                        "http://www.xm.org/schema/stmml " +
310 1391 tao
                              "http://dev.nceas.ucsb.edu/tao/schema/stmml.xsd");
311
       schema3.resolveNameSpace();
312
       // print out new schema list in db
313
       SchemaLocationResolver schema4 = new SchemaLocationResolver();
314 2663 sgarg
       logMetacat.warn("Namespace and Location String: "+
315 4427 daigle
    		   XMLSchemaService.getNameSpaceAndLocationString());
316 1391 tao
     }
317
     catch(Exception e)
318
     {
319 2663 sgarg
       logMetacat.error("erorr in Schemalocation.main: " +
320
                                e.getMessage());
321 1391 tao
     }
322
  }
323 4409 tao
324
  /**
325
   * Gets the downloadNewSchema's value.
326
   * @return
327
   */
328
 public boolean getDownloadNewSchema()
329
 {
330
	 return this.downloadNewSchema;
331
 }
332 1391 tao
}