/* 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 org.fcrepo.server.storage.types; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.SequenceInputStream; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import javax.xml.parsers.DocumentBuilder; import org.fcrepo.server.Context; import org.fcrepo.server.errors.StreamIOException; import org.fcrepo.utilities.ReadableByteArrayOutputStream; import org.fcrepo.utilities.ReadableCharArrayWriter; import org.fcrepo.utilities.XmlTransformUtility; import org.fcrepo.utilities.xml.XercesXmlSerializers; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; /** * @author Sandy Payette */ public class DatastreamXMLMetadata extends Datastream { private static final Logger logger = LoggerFactory.getLogger(DatastreamXMLMetadata.class); // techMD (technical metadata), // sourceMD (analog/digital source metadata), // rightsMD (intellectual property rights metadata), // digiprovMD (digital provenance metadata). // dmdSec (descriptive metadata). /** Technical XML metadata */ public final static int TECHNICAL = 1; /** Source XML metatdata */ public final static int SOURCE = 2; /** Rights XML metatdata */ public final static int RIGHTS = 3; /** Digital provenance XML metadata */ public final static int DIGIPROV = 4; /** Descriptive XML metadata */ public final static int DESCRIPTIVE = 5; // FIXME:xml datastream contents are held in memory...this could be expensive. public byte[] xmlContent; /** * The class of XML metadata (TECHNICAL, SOURCE, RIGHTS, DIGIPROV, or * DESCRIPTIVE) */ public int DSMDClass = 0; private final String m_encoding; public DatastreamXMLMetadata() { m_encoding = "UTF-8"; } public DatastreamXMLMetadata(String encoding) { m_encoding = encoding; } @Override public Datastream copy() { DatastreamXMLMetadata ds = new DatastreamXMLMetadata(m_encoding); copy(ds); if (xmlContent != null) { ds.xmlContent = new byte[xmlContent.length]; System.arraycopy(xmlContent, 0, ds.xmlContent, 0, xmlContent.length); } ds.DSMDClass = DSMDClass; return ds; } @Override public InputStream getContentStream() { return new ByteArrayInputStream(xmlContent); } @Override public InputStream getContentStream(Context context) { return new ByteArrayInputStream(xmlContent); } @Override public InputStream getContentStreamForChecksum() { BufferedReader br; try { ReadableCharArrayWriter out = new ReadableCharArrayWriter(xmlContent.length + (xmlContent.length /4)); DocumentBuilder builder = null; try { builder = XmlTransformUtility.borrowDocumentBuilder(); Document doc = builder.parse(new ByteArrayInputStream(xmlContent)); XercesXmlSerializers.writeXmlNoSpace(doc, m_encoding, out); out.close(); } finally { if (builder != null) XmlTransformUtility.returnDocumentBuilder(builder); } br = new BufferedReader(out.toReader()); String line; ReadableByteArrayOutputStream bytes = new ReadableByteArrayOutputStream(out.length()); PrintWriter outStream = new PrintWriter( new OutputStreamWriter(bytes, Charset.forName(m_encoding))); while ((line = br.readLine()) != null) { line = line.trim(); outStream.append(line); } outStream.close(); return bytes.toInputStream(); } catch (Exception e) { logger.warn(e.getMessage(),e); return getContentStream(); } } public InputStream getContentStreamAsDocument() throws UnsupportedEncodingException { // *with* the <?xml version="1.0" encoding="m_encoding" ?> line String firstLine = "<?xml version=\"1.0\" encoding=\"" + m_encoding + "\" ?>\n"; byte[] firstLineBytes = firstLine.getBytes(m_encoding); return new SequenceInputStream(new ByteArrayInputStream(firstLineBytes), new ByteArrayInputStream(xmlContent)); } @Override public long getContentSize(Context ctx) throws StreamIOException { return xmlContent.length; } @Override public boolean isRepositoryManaged() { return true; } }