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: berkley $'
10
 *     '$Date: 2010-05-10 13:15:48 -0700 (Mon, 10 May 2010) $'
11
 * '$Revision: 5340 $'
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.database.DBConnection;
42
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
43
import edu.ucsb.nceas.metacat.service.ServiceService;
44
import edu.ucsb.nceas.metacat.service.XMLSchemaService;
45
import edu.ucsb.nceas.metacat.util.SystemUtil;
46

    
47
/**
48
 * A database aware Class to handle schema location. If namespace is in the
49
 * xml_catalog table (public_id), the schema location specified in xml document
50
 * will be ignored by parser setting external schema location. If the
51
 * name space is not in the table, it will be download to metacat and register
52
 * in table
53
 */
54
public class SchemaLocationResolver
55
{
56
  
57
  private String nameSpace = null; //public id
58
  private String schemaLocation = null; // system id
59
  private String WHITESPACESTRING =" ";   
60
  private boolean downloadNewSchema = false;
61

    
62
  private static Logger logMetacat = Logger.getLogger(SchemaLocationResolver.class);
63

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

    
78
  }
79

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

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

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

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

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

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

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

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