1
|
/**
|
2
|
* '$RCSfile: XSLTransform.java,v $'
|
3
|
* Copyright: 2003 Regents of the University of California and the
|
4
|
* National Center for Ecological Analysis and Synthesis
|
5
|
*
|
6
|
* '$Author: jones $'
|
7
|
* '$Date: 2003/08/18 20:27:03 $'
|
8
|
* '$Revision: 1.4 $'
|
9
|
*
|
10
|
* This program is free software; you can redistribute it and/or modify
|
11
|
* it under the terms of the GNU General Public License as published by
|
12
|
* the Free Software Foundation; either version 2 of the License, or
|
13
|
* (at your option) any later version.
|
14
|
*
|
15
|
* This program is distributed in the hope that it will be useful,
|
16
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
17
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
18
|
* GNU General Public License for more details.
|
19
|
*
|
20
|
* You should have received a copy of the GNU General Public License
|
21
|
* along with this program; if not, write to the Free Software
|
22
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
23
|
*/
|
24
|
|
25
|
package edu.ucsb.nceas.metacat.util;
|
26
|
|
27
|
import java.io.*;
|
28
|
import java.sql.PreparedStatement;
|
29
|
import java.sql.ResultSet;
|
30
|
import java.sql.SQLException;
|
31
|
import java.text.SimpleDateFormat;
|
32
|
import java.util.Enumeration;
|
33
|
import java.util.Hashtable;
|
34
|
import java.util.Vector;
|
35
|
|
36
|
import org.apache.log4j.Logger;
|
37
|
|
38
|
import edu.ucsb.nceas.metacat.DocumentImpl;
|
39
|
import edu.ucsb.nceas.metacat.DocumentImplWrapper;
|
40
|
import edu.ucsb.nceas.metacat.McdbException;
|
41
|
import edu.ucsb.nceas.metacat.database.DBConnection;
|
42
|
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
|
43
|
import edu.ucsb.nceas.metacat.properties.PropertyService;
|
44
|
|
45
|
import javax.xml.transform.TransformerFactory;
|
46
|
import javax.xml.transform.Transformer;
|
47
|
import javax.xml.transform.stream.StreamSource;
|
48
|
import javax.xml.transform.stream.StreamResult;
|
49
|
import javax.xml.transform.TransformerException;
|
50
|
import javax.xml.transform.TransformerConfigurationException;
|
51
|
import javax.xml.transform.URIResolver;
|
52
|
import org.ecoinformatics.eml.EMLParser;
|
53
|
|
54
|
|
55
|
/**
|
56
|
* A Class that transforms older eml version to newer eml version utitlizing XSL style sheets.
|
57
|
*/
|
58
|
public class EMLVersionsTransformer {
|
59
|
|
60
|
private static org.apache.log4j.Logger logMetacat = Logger.getLogger(EMLVersionsTransformer.class);
|
61
|
private static String eml210StyleFile = null;
|
62
|
static{
|
63
|
try
|
64
|
{
|
65
|
eml210StyleFile =PropertyService.getProperty("application.deployDir")+"/"+PropertyService
|
66
|
.getProperty("application.context")+ "/style/common/eml201to210.xsl"; //eml201to210.xsl place
|
67
|
}
|
68
|
catch(Exception e)
|
69
|
{
|
70
|
logMetacat.warn("Couldn't get eml201to210.xsl stylesheet");
|
71
|
}
|
72
|
}
|
73
|
private static String DOT = ".";
|
74
|
private static int CAP = 100000; // How many documents you want to transform.
|
75
|
|
76
|
/**
|
77
|
* Public constructor because all methods are static and do not need
|
78
|
* an instance.
|
79
|
*/
|
80
|
public EMLVersionsTransformer()
|
81
|
{
|
82
|
|
83
|
}
|
84
|
|
85
|
/**
|
86
|
* Method to upgrade old versions of eml to new version
|
87
|
*/
|
88
|
public void upgrade()
|
89
|
{
|
90
|
upgradeEML200ToEML210();
|
91
|
}
|
92
|
|
93
|
/*
|
94
|
* Upgrade every eml200 or eml210 documents into eml210
|
95
|
*/
|
96
|
private void upgradeEML200ToEML210()
|
97
|
{
|
98
|
Vector list = getEML2DocList();
|
99
|
if(list != null)
|
100
|
{
|
101
|
// Choose the smaller value between the size of vector and CAP
|
102
|
int size = list.size();
|
103
|
if (size > CAP)
|
104
|
{
|
105
|
size = CAP;
|
106
|
}
|
107
|
for(int i=0; i<size; i++)
|
108
|
{
|
109
|
OwnerAndDocid pair = (OwnerAndDocid)list.elementAt(i);
|
110
|
String docid = pair.getDocid();
|
111
|
String owner = pair.getOwner();
|
112
|
try
|
113
|
{
|
114
|
handleSingleEML200Document(docid, owner);
|
115
|
try
|
116
|
{
|
117
|
Thread.sleep(5000);
|
118
|
}
|
119
|
catch(Exception e)
|
120
|
{
|
121
|
logMetacat.warn("Couldn't sleep 5 seconds");
|
122
|
}
|
123
|
}
|
124
|
catch(Exception e)
|
125
|
{
|
126
|
logMetacat.warn("The docid "+docid+" with owner "+owner+" couldn't be transformed to eml-2.1.0 since "+e.getMessage());
|
127
|
transformErrorLog("The docid "+docid+" with owner "+owner+" couldn't be transformed to eml-2.1.0 since "+e.getMessage());
|
128
|
}
|
129
|
}
|
130
|
}
|
131
|
}
|
132
|
|
133
|
/*
|
134
|
* Handle single eml201 or eml 200 document: read the document, transform it to eml210 document
|
135
|
* then save it to 210 document into metacat
|
136
|
*/
|
137
|
private void handleSingleEML200Document(String docidWithRev, String owner) throws Exception
|
138
|
{
|
139
|
DocumentImpl docImpl = new DocumentImpl(docidWithRev);
|
140
|
String eml200Content = docImpl.toString();
|
141
|
StringReader eml200Source= new StringReader(eml200Content);
|
142
|
//PipedWriter eml210OutputAfterTransform = new PipedWriter();
|
143
|
//PipedReader eml210SourceForNewDoc = new PipedReader();
|
144
|
//eml210SourceForNewDoc.connect(eml210OutputAfterTransform);
|
145
|
StringWriter strWriter = new StringWriter();
|
146
|
String newId = increaseRevisionNumber(docidWithRev);
|
147
|
if(newId != null)
|
148
|
{
|
149
|
transformEML200ToEML210(eml200Source, eml210StyleFile, strWriter, newId);
|
150
|
String eml210Content = strWriter.toString();
|
151
|
String rule = DocumentImpl.EML210;
|
152
|
// using emlparser to check id validation
|
153
|
EMLParser parser = new EMLParser(eml210Content);
|
154
|
DocumentImplWrapper documentWrapper = new DocumentImplWrapper(rule, true);
|
155
|
// StringReader xml = new StringReader(eml210Content);
|
156
|
String doAction = "UPDATE";
|
157
|
String pub = null;
|
158
|
String []groups = null;
|
159
|
DBConnection dbconn = null;
|
160
|
StringReader dtd = null;
|
161
|
int serialNumber = -1;
|
162
|
try
|
163
|
{
|
164
|
dbconn = DBConnectionPool
|
165
|
.getDBConnection("EMLVersionsTransformer.handleSingleEML200Document");
|
166
|
serialNumber = dbconn.getCheckOutSerialNumber();
|
167
|
documentWrapper.write(dbconn, eml210Content, pub, dtd,
|
168
|
doAction, newId, owner, groups);
|
169
|
logMetacat.warn("Doc "+docidWithRev+" was transformed to eml210 with new id "+newId);
|
170
|
transformLog("Doc "+docidWithRev+" was transformed to eml210 with new id "+newId);
|
171
|
}
|
172
|
catch(Exception e)
|
173
|
{
|
174
|
throw e;
|
175
|
}
|
176
|
finally
|
177
|
{
|
178
|
// Return db connection
|
179
|
DBConnectionPool.returnDBConnection(dbconn, serialNumber);
|
180
|
}
|
181
|
}
|
182
|
else
|
183
|
{
|
184
|
logMetacat.warn("Couldn't increase docid "+docidWithRev+"'s revision");
|
185
|
}
|
186
|
}
|
187
|
|
188
|
/*
|
189
|
* Transform single eml201 (Reader) to eml 210 (Writer)
|
190
|
*/
|
191
|
private static void transformEML200ToEML210(Reader reader, String xslfile, Writer writer, String packageid) throws Exception{
|
192
|
Hashtable param = null;
|
193
|
if (packageid != null)
|
194
|
{
|
195
|
param = new Hashtable();
|
196
|
param.put("package-id", packageid);
|
197
|
}
|
198
|
EMLVersionsTransformer.transform(reader, xslfile, writer, param);
|
199
|
|
200
|
}
|
201
|
|
202
|
|
203
|
/*
|
204
|
* Transform an XML document using an XSLT stylesheet to another format,
|
205
|
* probably HTML or another XML document format.
|
206
|
*
|
207
|
* @param doc the document to be transformed
|
208
|
* @param xslSystemId the system location of the stylesheet
|
209
|
* @param pw the PrintWriter to which output is printed
|
210
|
* @param params some parameters for inclusion to the transformation
|
211
|
*/
|
212
|
private static void transform(Reader doc, String xslSystemId,
|
213
|
Writer pw, Hashtable param) throws Exception
|
214
|
{
|
215
|
|
216
|
StreamSource xslSource =
|
217
|
new StreamSource(xslSystemId);
|
218
|
xslSource.setSystemId(xslSystemId);
|
219
|
// Create a stylesheet from the system id that was found
|
220
|
TransformerFactory tFactory = TransformerFactory.newInstance();
|
221
|
Transformer transformer = tFactory.newTransformer(xslSource);
|
222
|
|
223
|
// Set up parameters for transformation
|
224
|
if ( param != null) {
|
225
|
Enumeration en = param.keys();
|
226
|
while (en.hasMoreElements()) {
|
227
|
String key =(String)en.nextElement();
|
228
|
String value = ((String)(param.get(key)));
|
229
|
transformer.setParameter(key, value);
|
230
|
}
|
231
|
}
|
232
|
|
233
|
// Run the transform engine
|
234
|
StreamSource ss = new StreamSource(doc);
|
235
|
StreamResult sr = new StreamResult(pw);
|
236
|
transformer.transform(ss, sr);
|
237
|
|
238
|
}
|
239
|
|
240
|
/*
|
241
|
* Get list of document (docid and owner) which type is eml200 or eml201.
|
242
|
* The docid in the list will have revision number too.
|
243
|
*/
|
244
|
private Vector getEML2DocList()
|
245
|
{
|
246
|
Vector list = new Vector();
|
247
|
DBConnection dbconn = null;
|
248
|
int serialNumber = -1;
|
249
|
String sql = "select docid, rev, user_owner from xml_documents where doctype like 'eml://ecoinformatics.org/eml-2.0.1' or doctype like 'eml://ecoinformatics.org/eml-2.0.0'";
|
250
|
PreparedStatement pstmt = null;
|
251
|
try {
|
252
|
dbconn = DBConnectionPool
|
253
|
.getDBConnection("EMLVersionsTransformer.getEML2DocList");
|
254
|
serialNumber = dbconn.getCheckOutSerialNumber();
|
255
|
pstmt = dbconn.prepareStatement(sql.toString());
|
256
|
pstmt.execute();
|
257
|
ResultSet rs = pstmt.getResultSet();
|
258
|
boolean tableHasRows = rs.next();
|
259
|
while (tableHasRows) {
|
260
|
String docidWithoutRev = rs.getString(1);
|
261
|
int rev = rs.getInt(2);
|
262
|
String owner = rs.getString(3);
|
263
|
String docidWithRev = docidWithoutRev+DOT+rev;
|
264
|
logMetacat.info("The docid "+docidWithRev+" with owner "+owner+" will be added into list which will be transformed to eml-2.1.0");
|
265
|
OwnerAndDocid pair = new OwnerAndDocid(owner, docidWithRev);;
|
266
|
list.add(pair);
|
267
|
tableHasRows = rs.next();
|
268
|
}
|
269
|
pstmt.close();
|
270
|
|
271
|
|
272
|
} catch (SQLException e) {
|
273
|
logMetacat.error("error in DocumentImpl.getDocumentInfo: "
|
274
|
+ e.getMessage());
|
275
|
e.printStackTrace(System.out);
|
276
|
} finally {
|
277
|
try {
|
278
|
pstmt.close();
|
279
|
} catch (SQLException ee) {
|
280
|
logMetacat.error(
|
281
|
"error in DocumentImple.getDocumentInfo: "
|
282
|
+ ee.getMessage());
|
283
|
} finally {
|
284
|
DBConnectionPool.returnDBConnection(dbconn, serialNumber);
|
285
|
}
|
286
|
}
|
287
|
return list;
|
288
|
}
|
289
|
|
290
|
/*
|
291
|
* Increase revision number for the given docid. tao.1.1 will be tao.1.2. null will be returned
|
292
|
* if couldn't increase it.
|
293
|
*/
|
294
|
private static String increaseRevisionNumber(String docidWithRev)
|
295
|
{
|
296
|
String newid = null;
|
297
|
try
|
298
|
{
|
299
|
if (docidWithRev != null)
|
300
|
{
|
301
|
int index = docidWithRev.lastIndexOf(DOT);
|
302
|
if (index != -1)
|
303
|
{
|
304
|
String firstTwoParts = docidWithRev.substring(0,index);
|
305
|
String revStr = docidWithRev.substring(index+1);
|
306
|
Integer revObj = new Integer(revStr);
|
307
|
int rev = revObj.intValue();
|
308
|
rev= rev+1;
|
309
|
newid = firstTwoParts+DOT+rev;
|
310
|
}
|
311
|
}
|
312
|
}
|
313
|
catch(Exception e)
|
314
|
{
|
315
|
logMetacat.warn("Couldn't increase revision number since "+e.getMessage());
|
316
|
}
|
317
|
return newid;
|
318
|
}
|
319
|
|
320
|
|
321
|
/*
|
322
|
* Method for writing transformation messages to a log file specified in
|
323
|
* metacat.properties
|
324
|
*/
|
325
|
private static void transformLog(String message) {
|
326
|
try {
|
327
|
FileOutputStream fos =
|
328
|
new FileOutputStream(PropertyService.getProperty("replication.logdir")
|
329
|
+ "/transform.log", true);
|
330
|
PrintWriter pw = new PrintWriter(fos);
|
331
|
SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
|
332
|
java.util.Date localtime = new java.util.Date();
|
333
|
String dateString = formatter.format(localtime);
|
334
|
dateString += " :: " + message;
|
335
|
// time stamp each entry
|
336
|
pw.println(dateString);
|
337
|
pw.flush();
|
338
|
} catch (Exception e) {
|
339
|
logMetacat.warn("error writing to transform log from "
|
340
|
+ "EMLVersionTransformer.transformlLog: " + e.getMessage());
|
341
|
// e.printStackTrace(System.out);
|
342
|
}
|
343
|
}
|
344
|
|
345
|
/*
|
346
|
* Method for writing transform messages to a log file specified in
|
347
|
* metacat.properties
|
348
|
*/
|
349
|
private static void transformErrorLog(String message)
|
350
|
{
|
351
|
try
|
352
|
{
|
353
|
FileOutputStream fos =
|
354
|
new FileOutputStream(PropertyService.getProperty("replication.logdir")
|
355
|
+ "/transformerror.log", true);
|
356
|
PrintWriter pw = new PrintWriter(fos);
|
357
|
SimpleDateFormat formatter = new SimpleDateFormat ("yy-MM-dd HH:mm:ss");
|
358
|
java.util.Date localtime = new java.util.Date();
|
359
|
String dateString = formatter.format(localtime);
|
360
|
dateString += " :: " + message;
|
361
|
//time stamp each entry
|
362
|
pw.println(dateString);
|
363
|
pw.flush();
|
364
|
}
|
365
|
catch(Exception e)
|
366
|
{
|
367
|
logMetacat.warn("error writing to transforming error log from " +
|
368
|
"EMLVersionTransformer.transformErrorLog: " + e.getMessage());
|
369
|
//e.printStackTrace(System.out);
|
370
|
}
|
371
|
}
|
372
|
|
373
|
/*
|
374
|
* Class reprents a document's docid and its owner
|
375
|
* @author tao
|
376
|
*
|
377
|
*/
|
378
|
class OwnerAndDocid{
|
379
|
private String owner = null;
|
380
|
private String docidWithRev = null;
|
381
|
|
382
|
public OwnerAndDocid(String owner, String docidWithRev)
|
383
|
{
|
384
|
this.owner = owner;
|
385
|
this.docidWithRev = docidWithRev;
|
386
|
}
|
387
|
|
388
|
public String getOwner()
|
389
|
{
|
390
|
return owner;
|
391
|
}
|
392
|
|
393
|
public String getDocid()
|
394
|
{
|
395
|
return docidWithRev;
|
396
|
}
|
397
|
}
|
398
|
|
399
|
|
400
|
|
401
|
}
|
402
|
|