/* 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.client.utility.export; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.OutputStream; import java.net.MalformedURLException; import java.rmi.RemoteException; import java.util.HashMap; import java.util.StringTokenizer; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.rpc.ServiceException; 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.access.FedoraAPIA; import fedora.server.management.FedoraAPIM; import fedora.server.types.gen.RepositoryInfo; import fedora.utilities.FileUtils; /** * Utility class for exporting objects from a Fedora repository. * * @author Chris Wilper * @version $Id$ */ public class AutoExporter implements Constants { private final FedoraAPIM m_apim; private final FedoraAPIA m_apia; private static HashMap<FedoraAPIA, RepositoryInfo> s_repoInfo = new HashMap<FedoraAPIA, RepositoryInfo>(); public AutoExporter(FedoraAPIA apia, FedoraAPIM apim) throws MalformedURLException, ServiceException { m_apia = apia; m_apim = apim; } public void export(String pid, String format, String exportContext, OutputStream outStream) throws RemoteException, IOException { export(m_apia, m_apim, pid, format, exportContext, outStream); } public static void export(FedoraAPIA apia, FedoraAPIM apim, String pid, String format, String exportContext, OutputStream outStream) throws RemoteException, IOException { // Get the repository info from the hash for the repository that APIA is using, // unless it isn't in the hash yet... in which case, ask the server. RepositoryInfo repoinfo = s_repoInfo.get(apia); if (repoinfo == null) { repoinfo = apia.describeRepository(); s_repoInfo.put(apia, repoinfo); } byte[] bytes; // For backward compatibility: // Pre-2.0 repositories will only export "metslikefedora1" format. // 2.x repositories will only export "metslikefedora1" and "foxml1.0" formats. // For 3.0+ repositories the format arg is sent to "export" method. StringTokenizer stoken = new StringTokenizer(repoinfo.getRepositoryVersion(), "."); int majorVersion = new Integer(stoken.nextToken()).intValue(); if (majorVersion < 2) { if (format == null || format.equals(METS_EXT1_1.uri) || format.equals(METS_EXT1_0.uri) || format.equals("METS_EXT1_0_LEGACY") || format.equals("default")) { if (format.equals(METS_EXT1_1.uri)) { System.out.println("WARNING: Repository does not support METS Fedora " + "Extension 1.1; exporting older format (v1.0) instead"); } bytes = apim.export(pid, METS_EXT1_0_LEGACY, exportContext); } else { throw new IOException("You are connected to a pre-2.0 Fedora repository " + "which will only export the XML format \"metslikefedora1\"."); } } else { if (majorVersion < 3) { if (format != null) { if (format.equals(FOXML1_1.uri)) { System.out.println("WARNING: Repository does not support FOXML 1.1; " + "exporting older format (v1.0) instead"); format = FOXML1_0_LEGACY; } else if (format.equals(FOXML1_0.uri)) { format = FOXML1_0_LEGACY; } else if (format.equals(METS_EXT1_1.uri)) { System.out.println("WARNING: Repository does not support METS Fedora " + "Extension 1.1; exporting older format (v1.0) instead"); format = METS_EXT1_0_LEGACY; } else if (format.equals(METS_EXT1_0.uri)) { format = METS_EXT1_0_LEGACY; } else { throw new IOException("You are connected to a 2.x Fedora repository " + "which will only export FOXML and METS XML formats."); } } } else { // majorVersion >= 3 if (format != null) { if (format.equals(FOXML1_0_LEGACY)) { format = FOXML1_0.uri; } else if (format.equals(METS_EXT1_0_LEGACY)) { format = METS_EXT1_0.uri; } } validateFormat(format); } bytes = apim.export(pid, format, exportContext); } try { // TODO This export method has assumed the output is always XML, // but with ATOM_ZIP (and in the future, IMS CP/SCORM) this is no // longer the case. Perhaps we move pretty printing into the // serializers themselves. if (format.equals(ATOM_ZIP1_1.uri)) { FileUtils.copy(new ByteArrayInputStream(bytes), outStream); } else { // use xerces to pretty print the xml, assuming it's well formed OutputFormat fmt = new OutputFormat("XML", "UTF-8", true); fmt.setIndent(2); fmt.setLineWidth(120); fmt.setPreserveSpace(false); XMLSerializer ser = new XMLSerializer(outStream, fmt); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(new ByteArrayInputStream(bytes)); ser.serialize(doc); } } catch (Exception e) { System.out.println("ERROR: " + e.getClass().getName() + " : " + e.getMessage()); } finally { outStream.close(); } } public void getObjectXML(String pid, OutputStream outStream) throws RemoteException, IOException { getObjectXML(m_apia, m_apim, pid, outStream); } public static void getObjectXML(FedoraAPIA apia, FedoraAPIM apim, String pid, OutputStream outStream) throws RemoteException, IOException { // Get the repository info from the hash for the repository that APIA is using, // unless it isn't in the hash yet... in which case, ask the server. RepositoryInfo repoinfo = s_repoInfo.get(apia); if (repoinfo == null) { repoinfo = apia.describeRepository(); s_repoInfo.put(apia, repoinfo); } // get the object XML as it exists in the repository's // persitent storage area. byte[] bytes = apim.getObjectXML(pid); try { // use xerces to pretty print the xml, assuming it's well formed OutputFormat fmt = new OutputFormat("XML", "UTF-8", true); fmt.setIndent(2); fmt.setLineWidth(120); fmt.setPreserveSpace(false); XMLSerializer ser = new XMLSerializer(outStream, fmt); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(new ByteArrayInputStream(bytes)); ser.serialize(doc); } catch (Exception e) { System.out.println("ERROR: " + e.getClass().getName() + " : " + e.getMessage()); } finally { outStream.close(); } } public static void validateFormat(String format) throws IOException { if (format == null) { return; } if (!format.equals(FOXML1_1.uri) && !format.equals(FOXML1_0.uri) && !format.equals(METS_EXT1_1.uri) && !format.equals(METS_EXT1_0.uri) && !format.equals(ATOM1_1.uri) && !format.equals(ATOM_ZIP1_1.uri) && !format.equals("default")) { throw new IOException("Invalid export format. Valid FORMAT values are: '" + FOXML1_1.uri + "' '" + FOXML1_0.uri + "' '" + METS_EXT1_1.uri + "' '" + METS_EXT1_0.uri + "' '" + ATOM1_1.uri + "' '" + ATOM_ZIP1_1.uri + "' and 'default'"); } } }