/* The contents of this file are subject to the license and copyright terms * detailed in the license directory at the root of the source tree (also * available online at http://fedora-commons.org/license/). */ package fedora.server.storage.translation; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Date; import java.util.Iterator; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import com.sun.org.apache.xml.internal.serialize.OutputFormat; import com.sun.org.apache.xml.internal.serialize.XMLSerializer; import org.w3c.dom.Document; import fedora.common.Constants; import fedora.server.storage.types.BasicDigitalObject; import fedora.server.storage.types.Datastream; import fedora.server.storage.types.DigitalObject; /** * Utility class to convert objects from one serialization format to another. * * @author Edwin Shin * @author Chris Wilper * @since 3.0 * @version $Id$ */ public class ConvertObjectSerialization { private static final String ENCODING = "UTF-8"; private final Date m_now = new Date(); private final DODeserializer m_deserializer; private final DOSerializer m_serializer; private final boolean m_pretty; private final String m_inExt; private final String m_outExt; public ConvertObjectSerialization(DODeserializer deserializer, DOSerializer serializer, boolean pretty, String inExt, String outExt) { m_deserializer = deserializer; m_serializer = serializer; m_pretty = pretty; m_inExt = inExt; m_outExt = outExt; } private boolean convert(InputStream source, OutputStream destination) { DigitalObject obj = new BasicDigitalObject(); try { m_deserializer.deserialize(source, obj, ENCODING, DOTranslationUtility.AS_IS); setObjectDefaults(obj); if (m_pretty) { prettyPrint(obj, destination); } else { m_serializer.serialize(obj, destination, ENCODING, DOTranslationUtility.AS_IS); } } catch (Exception e) { e.printStackTrace(); return false; } return true; } private void prettyPrint(DigitalObject obj, OutputStream destination) throws Exception { ByteArrayOutputStream outBuf = new ByteArrayOutputStream(); m_serializer.serialize(obj, outBuf, ENCODING, DOTranslationUtility.AS_IS); InputStream inBuf = new ByteArrayInputStream(outBuf.toByteArray()); prettyPrint(inBuf, destination); } private static void prettyPrint(InputStream source, OutputStream destination) throws Exception { OutputFormat fmt = new OutputFormat("XML", ENCODING, true); fmt.setIndent(2); fmt.setLineWidth(80); fmt.setPreserveSpace(false); XMLSerializer ser = new XMLSerializer(destination, fmt); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(source); ser.serialize(doc); destination.close(); } /** * Convert files from one format to the other. * Hidden directories (directories starting with a ".") are skipped. * * @param source * @param destination * @return */ public boolean convert(File source, File destination) { boolean result = true; if (source.isDirectory()) { if (source.getName().startsWith(".")) { // skip "hidden" directories return result; } if (destination.exists()) { result = result && destination.isDirectory(); } else { result = result && destination.mkdirs(); } File[] children = source.listFiles(); for (File element : children) { String inName = element.getName(); String outName; if (element.isDirectory()) { outName = inName; } else { outName = inName.substring(0, inName.lastIndexOf('.') + 1) + m_outExt; } result = result && convert(new File(source, inName), new File(destination, outName)); } return result; } else { try { if (!source.getName().endsWith("." + m_inExt)) { return result; } InputStream in = new FileInputStream(source); if (!destination.getParentFile().exists()) { destination.getParentFile().mkdirs(); } OutputStream out = new FileOutputStream(destination); result = result && convert(in, out); out.close(); in.close(); return result; } catch (IOException e) { return false; } } } // - Sets dates to current date if unset // - Sets datastream sizes to 0 private void setObjectDefaults(DigitalObject obj) { if (obj.getCreateDate() == null) obj.setCreateDate(m_now); if (obj.getLastModDate() == null) obj.setLastModDate(m_now); Iterator<String> dsIds = obj.datastreamIdIterator(); while (dsIds.hasNext()) { String dsid = dsIds.next(); for (Datastream ds : obj.datastreams(dsid)) { ds.DSSize = 0; if (ds.DSCreateDT == null) { ds.DSCreateDT = m_now; } } } } /** * Command-line utility to convert objects from one format to another. * * @param args command-line args. */ public static void main(String[] args) { if (args.length < 4 || args.length > 7) { die("Expected 4 to 7 arguments", true); } File sourceDir = new File(args[0]); if (!sourceDir.isDirectory()) { die("Not a directory: " + sourceDir.getPath(), false); } File destDir = new File(args[1]); DODeserializer deserializer = (DODeserializer) getInstance(args[2]); DOSerializer serializer = (DOSerializer) getInstance(args[3]); // So DOTranslationUtility works... System.setProperty("fedora.hostname", "localhost"); System.setProperty("fedora.port", "8080"); System.setProperty("fedora.appServerContext", Constants.FEDORA_DEFAULT_APP_CONTEXT); boolean pretty = args.length > 4 && args[4].equals("true"); String inExt = "xml"; if (args.length > 5) inExt = args[5]; String outExt = "xml"; if (args.length > 6) outExt = args[6]; ConvertObjectSerialization converter = new ConvertObjectSerialization(deserializer, serializer, pretty, inExt, outExt); converter.convert(sourceDir, destDir); } private static Object getInstance(String className) { try { return Class.forName(className).newInstance(); } catch (Exception e) { e.printStackTrace(); die("Unable to instantiate: " + className, false); return null; // unreachable } } private static void die(String message, boolean showUsage) { System.out.println("ERROR: " + message); if (showUsage) { System.out.println("Usage: ConvertObjectSerialization srcDir dstDir serClass deserClass"); System.out.println(" [pretty] [inExt] [outExt]"); System.out.println("Where: srcDir : source directory"); System.out.println(" dstDir : destination directory (created if necessary)"); System.out.println(" deserClass : DODeserializer class name"); System.out.println(" serClass : DOSerializer class name"); System.out.println(" pretty : if true and output is xml, it will be pretty-printed"); System.out.println(" inExt : extension for input files, default is xml"); System.out.println(" outExt : extension for output files, default is xml"); } System.exit(1); } }