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: daigle $'
10
 *     '$Date: 2008-10-10 17:10:00 -0700 (Fri, 10 Oct 2008) $'
11
 * '$Revision: 4439 $'
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
import org.apache.log4j.Logger;
40

    
41
import edu.ucsb.nceas.metacat.service.XMLSchemaService;
42
import edu.ucsb.nceas.metacat.util.SystemUtil;
43

    
44
/**
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
  private String WHITESPACESTRING =" ";   
57
  private boolean downloadNewSchema = false;
58

    
59
  private static Logger logMetacat = Logger.getLogger(SchemaLocationResolver.class);
60

    
61
  public SchemaLocationResolver()
62
  {	  
63
  }
64
  
65
  /**
66
   * Construct an instance of the SchemaLocationResolver class
67
   *
68
   * @param  myNameSpaceAndLocation it is come from xsi:schemaLocation=
69
   *         "namespace location"
70
   */
71
  public SchemaLocationResolver(String myNameSpaceAndLocation)
72
  {
73
	  parse(myNameSpaceAndLocation);
74

    
75
  }
76

    
77
  /**
78
   * Construct an instance of the SchemaLocationResolver class
79
   *
80
   * @param  myNameSpaceAndLocation it is come from xsi:schemaLocation=
81
   *         "namespace location"
82
   */
83
  public SchemaLocationResolver(String myNameSpace, String myLocation)
84
  {
85
      nameSpace = myNameSpace;
86
      schemaLocation = myLocation;
87
  }
88
  
89
  /**
90
   * When got a name space, check if it is in the database, if it is do nothing
91
   * else upload it to metacat to store it and register it in catalog table
92
   */
93
  public void resolveNameSpace ()
94
  {
95
  
96
    // if name space is not in table
97
    if (nameSpace !=null && schemaLocation != null &&
98
        !XMLSchemaService.getNameSpaceList().contains(nameSpace))
99
    {
100
       try
101
       {
102
        
103
        // upload schema into metacat
104
        InputStream in = DBEntityResolver.checkURLConnection(schemaLocation);
105
       
106
        String newURLInMetacat = uploadSchemaFromURL(in);
107
        XMLSchemaService.getInstance().refresh();
108
       
109
        // check the name space list again.  It may not have appeared the first time 
110
        // because the schema was in the db but there was no file on disk.  If that's 
111
        // the case, it will show up in the name space list now.  If it doesn't we need
112
        // to register the schema in the database.
113
        if (!XMLSchemaService.getNameSpaceList().contains(nameSpace)) {
114
        	registerSchema(newURLInMetacat);
115
        	XMLSchemaService.getInstance().refresh();
116
        }
117
        downloadNewSchema = true;
118
     
119
       }
120
       catch(Exception e)
121
       {
122
         logMetacat.error("Error in SchemaLocation.resolveNameSpace" +
123
                                  e.getMessage());
124
       }
125
 
126
    }//if
127
 
128
  }
129

    
130
  /**
131
   * Upload new Schema located at outside URL to Metacat file system
132
   */
133
  private String uploadSchemaFromURL(InputStream istream) throws Exception
134
  {
135
   
136
	String relativeSchemaPath = XMLSchemaService.SCHEMA_DIR;
137
    String fullSchemaPath = SystemUtil.getContextDir() + relativeSchemaPath;
138
    String schemaURL = SystemUtil.getContextURL()  + relativeSchemaPath;
139

    
140
    // get filename from systemId
141
    String filename = XMLSchemaService.getSchemaFileNameFromUri(schemaLocation);
142
  
143
    if (filename != null && !(filename.trim()).equals(""))
144
    {
145
      int slash = Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\'));
146
      if ( slash > -1 ) 
147
      {
148
        filename = filename.substring(slash + 1);
149
      }
150
    }
151
    else
152
    {
153
      return null;
154
    }
155
    // writing schema text on Metacat file system as filename
156
    try {
157
      // create a buffering character-input stream
158
      // that uses a default-sized input buffer
159
      BufferedInputStream in = new BufferedInputStream(istream);
160

    
161
      // open file writer to write the input into it
162
      File f = new File(fullSchemaPath, filename);
163
      synchronized (f) 
164
      {
165
        try 
166
        {
167
          if ( f.exists() ) 
168
          {
169
           throw new IOException("File already exist: " + f.getCanonicalFile());
170
          }
171
        } 
172
        catch (SecurityException se) 
173
        {
174
         // if a security manager exists,
175
          throw se;
176
       }
177
      // create a buffered character-output stream
178
      // that uses a default-sized output buffer
179
      FileWriter fw = new FileWriter(f);
180
      BufferedWriter out = new BufferedWriter(fw);
181

    
182
      // read the input and write into the file writer
183
      int inputByte;
184
      while ( (inputByte = in.read()) != -1 ) 
185
      {
186
        out.write(inputByte);
187
        //out.newLine(); //instead of out.write('\r\n');
188
      }
189

    
190
      // the input and the output streams must be closed
191
      in.close();
192
      out.flush();
193
      out.close();
194
      fw.close();
195
     } // end of synchronized
196
    } 
197
    catch (Exception e) 
198
    {
199
      throw new Exception
200
      ("shemaLocationResolver.uploadSchemaFromURL(): " + e.getMessage());
201
    } 
202
    logMetacat.warn("new schema location is: " + schemaURL + 
203
                              filename);
204
    return  relativeSchemaPath + filename;
205
  }
206

    
207
  
208
  /*
209
   * Register new schema identified by @systemId in Metacat XML Catalog
210
   */
211
  private void registerSchema(String systemId )
212
  {
213
    // check systemid is not null
214
    if (systemId == null || nameSpace == null || (nameSpace.trim()).equals(""))
215
    {    
216
      return;
217
    }
218
    
219
    DBConnection conn = null;
220
    int serialNumber = -1;
221
    PreparedStatement pstmt = null;
222
    String sql = "INSERT INTO xml_catalog " +
223
             "(entry_type, public_id, system_id) " +
224
             "VALUES ('" + DocumentImpl.SCHEMA + "', ?, ?)";
225
    
226
 
227
    try 
228
    {
229
      //check out DBConnection
230
      conn=DBConnectionPool.getDBConnection("schemaLocation.registerSchema");
231
      serialNumber=conn.getCheckOutSerialNumber();
232
      pstmt = conn.prepareStatement(sql);
233
     
234
      // Bind the values to the query
235
      pstmt.setString(1, nameSpace);
236
      pstmt.setString(2, systemId);
237
      // Do the insertion
238
      pstmt.execute();
239
      pstmt.close();
240
    } 
241
    catch (SQLException e) 
242
    {
243
      logMetacat.error("SchemaLocation.egisterSchema(): " + e.getMessage());
244
    }
245
    finally
246
    {
247
      try
248
      {
249
        pstmt.close();
250
      }//try
251
      catch (SQLException sqlE)
252
      {
253
        logMetacat.error("Error in SchemaLocation.egisterSchema(): "
254
                                    +sqlE.getMessage());
255
      }//catch
256
      DBConnectionPool.returnDBConnection(conn, serialNumber);
257

    
258
    }//finally
259
    XMLSchemaService.populateRegisteredSchemaList();
260
  }
261
  
262
  /*
263
   * A method to parse the value for xis:schemaLocation="namespace location"
264
   * and store the namespace in nameSpace and location in schemaLocaion
265
   */
266
  private void parse(String nameSpaceAndLocation)
267
  {
268
    // check the parameter
269
    if (nameSpaceAndLocation == null||(nameSpaceAndLocation.trim()).equals(""))
270
    {
271
      return;
272
    }
273
    //Get white space index (delimiter)
274
    int indexOfWhiteSpace = nameSpaceAndLocation.lastIndexOf(WHITESPACESTRING);
275
    if (indexOfWhiteSpace != -1)
276
    {
277
      // before white space is namespace
278
      nameSpace = nameSpaceAndLocation.substring(0,indexOfWhiteSpace);
279
      // after white sapce is schema location
280
      schemaLocation = nameSpaceAndLocation.substring(indexOfWhiteSpace+1);
281
      // Gebug message
282
      logMetacat.info("Namespace after parsing: " + nameSpace);
283
      logMetacat.info("Location after parsing: " + schemaLocation);
284
    } 
285
  }
286
  
287
  public static void main(String[] argus)
288
  {
289
     try
290
     {
291
       DBConnectionPool pool = DBConnectionPool.getInstance();
292
       // Print out a empty schema list
293
       SchemaLocationResolver schema = new SchemaLocationResolver();
294
       logMetacat.warn("Namespace and Location String: "+ 
295
                                XMLSchemaService.getNameSpaceAndLocationString());
296
       // input a schemalocation
297
       SchemaLocationResolver schema2 = new SchemaLocationResolver(
298
                                        "eml://ecoinformatics.org/eml-2.0.0 " +
299
                                "http://dev.nceas.ucsb.edu/tao/schema/eml.xsd");
300
       schema2.resolveNameSpace();
301
       // input a wrong name space location
302
       SchemaLocationResolver schema3 = new SchemaLocationResolver(
303
                                        "http://www.xm.org/schema/stmml " +
304
                              "http://dev.nceas.ucsb.edu/tao/schema/stmml.xsd");
305
       schema3.resolveNameSpace();
306
       // print out new schema list in db
307
       SchemaLocationResolver schema4 = new SchemaLocationResolver();
308
       logMetacat.warn("Namespace and Location String: "+ 
309
    		   XMLSchemaService.getNameSpaceAndLocationString());
310
     }
311
     catch(Exception e)
312
     {
313
       logMetacat.error("erorr in Schemalocation.main: " + 
314
                                e.getMessage());
315
     }
316
  }
317
  
318
  /**
319
   * Gets the downloadNewSchema's value.
320
   * @return
321
   */
322
 public boolean getDownloadNewSchema()
323
 {
324
	 return this.downloadNewSchema;
325
 }
326
}
(63-63/67)