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