/** * '$RCSfile: XSLTransform.java,v $' * Copyright: 2003 Regents of the University of California and the * National Center for Ecological Analysis and Synthesis * * '$Author: jones $' * '$Date: 2003/08/18 20:27:03 $' * '$Revision: 1.4 $' * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package edu.ucsb.nceas.metacat.util; import java.io.*; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.text.SimpleDateFormat; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import org.apache.log4j.Logger; import edu.ucsb.nceas.metacat.DocumentImpl; import edu.ucsb.nceas.metacat.DocumentImplWrapper; import edu.ucsb.nceas.metacat.McdbException; import edu.ucsb.nceas.metacat.database.DBConnection; import edu.ucsb.nceas.metacat.database.DBConnectionPool; import edu.ucsb.nceas.metacat.properties.PropertyService; import edu.ucsb.nceas.metacat.service.XMLSchemaService; import javax.xml.transform.TransformerFactory; import javax.xml.transform.Transformer; import javax.xml.transform.stream.StreamSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.URIResolver; import org.dataone.service.types.v1.Checksum; import org.ecoinformatics.eml.EMLParser; /** * A Class that transforms older eml version to newer eml version utitlizing XSL style sheets. */ public class EMLVersionsTransformer { private static org.apache.log4j.Logger logMetacat = Logger.getLogger(EMLVersionsTransformer.class); private static String eml210StyleFile = null; static{ try { eml210StyleFile =PropertyService.getProperty("application.deployDir")+"/"+PropertyService .getProperty("application.context")+ "/style/common/eml201to210.xsl"; //eml201to210.xsl place } catch(Exception e) { logMetacat.warn("Couldn't get eml201to210.xsl stylesheet"); } } private static String DOT = "."; private static int CAP = 100000; // How many documents you want to transform. /** * Public constructor because all methods are static and do not need * an instance. */ public EMLVersionsTransformer() { } /** * Method to upgrade old versions of eml to new version */ public void upgrade() { upgradeEML200ToEML210(); } /* * Upgrade every eml200 or eml210 documents into eml210 */ private void upgradeEML200ToEML210() { Vector list = getEML2DocList(); if(list != null) { // Choose the smaller value between the size of vector and CAP int size = list.size(); if (size > CAP) { size = CAP; } for(int i=0; i<size; i++) { OwnerAndDocid pair = (OwnerAndDocid)list.elementAt(i); String docid = pair.getDocid(); String owner = pair.getOwner(); try { handleSingleEML200Document(docid, owner); try { Thread.sleep(5000); } catch(Exception e) { logMetacat.warn("Couldn't sleep 5 seconds"); } } catch(Exception e) { logMetacat.warn("The docid "+docid+" with owner "+owner+" couldn't be transformed to eml-2.1.0 since "+e.getMessage()); transformErrorLog("The docid "+docid+" with owner "+owner+" couldn't be transformed to eml-2.1.0 since "+e.getMessage()); } } } } /* * Handle single eml201 or eml 200 document: read the document, transform it to eml210 document * then save it to 210 document into metacat */ private void handleSingleEML200Document(String docidWithRev, String owner) throws Exception { DocumentImpl docImpl = new DocumentImpl(docidWithRev); String eml200Content = docImpl.toString(); StringReader eml200Source= new StringReader(eml200Content); //PipedWriter eml210OutputAfterTransform = new PipedWriter(); //PipedReader eml210SourceForNewDoc = new PipedReader(); //eml210SourceForNewDoc.connect(eml210OutputAfterTransform); StringWriter strWriter = new StringWriter(); String newId = increaseRevisionNumber(docidWithRev); if(newId != null) { transformEML200ToEML210(eml200Source, eml210StyleFile, strWriter, newId); String eml210Content = strWriter.toString(); String rule = DocumentImpl.EML210; // using emlparser to check id validation EMLParser parser = new EMLParser(eml210Content); DocumentImplWrapper documentWrapper = new DocumentImplWrapper(rule, true, true); // StringReader xml = new StringReader(eml210Content); String doAction = "UPDATE"; String pub = null; String []groups = null; DBConnection dbconn = null; StringReader dtd = null; int serialNumber = -1; String formatId = null; try { dbconn = DBConnectionPool .getDBConnection("EMLVersionsTransformer.handleSingleEML200Document"); serialNumber = dbconn.getCheckOutSerialNumber(); String schemaLocation = XMLSchemaService.getInstance().getNameSpaceAndLocationStringWithoutFormatId(); Checksum checksum = null; documentWrapper.write(dbconn, eml210Content, pub, dtd, doAction, newId, owner, groups, null, schemaLocation, checksum); logMetacat.warn("Doc "+docidWithRev+" was transformed to eml210 with new id "+newId); transformLog("Doc "+docidWithRev+" was transformed to eml210 with new id "+newId); } catch(Exception e) { throw e; } finally { // Return db connection DBConnectionPool.returnDBConnection(dbconn, serialNumber); } } else { logMetacat.warn("Couldn't increase docid "+docidWithRev+"'s revision"); } } /* * Transform single eml201 (Reader) to eml 210 (Writer) */ private static void transformEML200ToEML210(Reader reader, String xslfile, Writer writer, String packageid) throws Exception{ Hashtable param = null; if (packageid != null) { param = new Hashtable(); param.put("package-id", packageid); } EMLVersionsTransformer.transform(reader, xslfile, writer, param); } /* * Transform an XML document using an XSLT stylesheet to another format, * probably HTML or another XML document format. * * @param doc the document to be transformed * @param xslSystemId the system location of the stylesheet * @param pw the PrintWriter to which output is printed * @param params some parameters for inclusion to the transformation */ private static void transform(Reader doc, String xslSystemId, Writer pw, Hashtable param) throws Exception { StreamSource xslSource = new StreamSource(xslSystemId); xslSource.setSystemId(xslSystemId); // Create a stylesheet from the system id that was found TransformerFactory tFactory = TransformerFactory.newInstance(); Transformer transformer = tFactory.newTransformer(xslSource); // Set up parameters for transformation if ( param != null) { Enumeration en = param.keys(); while (en.hasMoreElements()) { String key =(String)en.nextElement(); String value = ((String)(param.get(key))); transformer.setParameter(key, value); } } // Run the transform engine StreamSource ss = new StreamSource(doc); StreamResult sr = new StreamResult(pw); transformer.transform(ss, sr); } /* * Get list of document (docid and owner) which type is eml200 or eml201. * The docid in the list will have revision number too. */ private Vector getEML2DocList() { Vector list = new Vector(); DBConnection dbconn = null; int serialNumber = -1; 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'"; PreparedStatement pstmt = null; try { dbconn = DBConnectionPool .getDBConnection("EMLVersionsTransformer.getEML2DocList"); serialNumber = dbconn.getCheckOutSerialNumber(); pstmt = dbconn.prepareStatement(sql.toString()); pstmt.execute(); ResultSet rs = pstmt.getResultSet(); boolean tableHasRows = rs.next(); while (tableHasRows) { String docidWithoutRev = rs.getString(1); int rev = rs.getInt(2); String owner = rs.getString(3); String docidWithRev = docidWithoutRev+DOT+rev; logMetacat.info("The docid "+docidWithRev+" with owner "+owner+" will be added into list which will be transformed to eml-2.1.0"); OwnerAndDocid pair = new OwnerAndDocid(owner, docidWithRev);; list.add(pair); tableHasRows = rs.next(); } pstmt.close(); } catch (SQLException e) { logMetacat.error("error in DocumentImpl.getDocumentInfo: " + e.getMessage()); e.printStackTrace(System.out); } finally { try { pstmt.close(); } catch (SQLException ee) { logMetacat.error( "error in DocumentImple.getDocumentInfo: " + ee.getMessage()); } finally { DBConnectionPool.returnDBConnection(dbconn, serialNumber); } } return list; } /* * Increase revision number for the given docid. tao.1.1 will be tao.1.2. null will be returned * if couldn't increase it. */ private static String increaseRevisionNumber(String docidWithRev) { String newid = null; try { if (docidWithRev != null) { int index = docidWithRev.lastIndexOf(DOT); if (index != -1) { String firstTwoParts = docidWithRev.substring(0,index); String revStr = docidWithRev.substring(index+1); Integer revObj = new Integer(revStr); int rev = revObj.intValue(); rev= rev+1; newid = firstTwoParts+DOT+rev; } } } catch(Exception e) { logMetacat.warn("Couldn't increase revision number since "+e.getMessage()); } return newid; } /* * Method for writing transformation messages to a log file specified in * metacat.properties */ private static void transformLog(String message) { try { FileOutputStream fos = new FileOutputStream(PropertyService.getProperty("replication.logdir") + "/transform.log", true); PrintWriter pw = new PrintWriter(fos); SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss"); java.util.Date localtime = new java.util.Date(); String dateString = formatter.format(localtime); dateString += " :: " + message; // time stamp each entry pw.println(dateString); pw.flush(); } catch (Exception e) { logMetacat.warn("error writing to transform log from " + "EMLVersionTransformer.transformlLog: " + e.getMessage()); // e.printStackTrace(System.out); } } /* * Method for writing transform messages to a log file specified in * metacat.properties */ private static void transformErrorLog(String message) { try { FileOutputStream fos = new FileOutputStream(PropertyService.getProperty("replication.logdir") + "/transformerror.log", true); PrintWriter pw = new PrintWriter(fos); SimpleDateFormat formatter = new SimpleDateFormat ("yy-MM-dd HH:mm:ss"); java.util.Date localtime = new java.util.Date(); String dateString = formatter.format(localtime); dateString += " :: " + message; //time stamp each entry pw.println(dateString); pw.flush(); } catch(Exception e) { logMetacat.warn("error writing to transforming error log from " + "EMLVersionTransformer.transformErrorLog: " + e.getMessage()); //e.printStackTrace(System.out); } } /* * Class reprents a document's docid and its owner * @author tao * */ class OwnerAndDocid{ private String owner = null; private String docidWithRev = null; public OwnerAndDocid(String owner, String docidWithRev) { this.owner = owner; this.docidWithRev = docidWithRev; } public String getOwner() { return owner; } public String getDocid() { return docidWithRev; } } }