blob: 34fae67b7f63cad6c8a566362ee7add8a49c1d48 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE.txt file distributed with this work for
// additional information regarding copyright ownership. The ASF licenses this
// file to you under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
package org.apache.oodt.cas.metadata;
//JDK imports
import org.apache.oodt.commons.xml.XMLUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.net.URLEncoder;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
/**
* @author mattmann
* @author bfoster
* @version $Revision$
*
* <p>
* {@link Metadata} that's {@link Serializable}.
* </p>.
*/
public class SerializableMetadata extends Metadata implements Serializable {
private static final long serialVersionUID = 6863087581652632499L;
private String xmlEncoding;
private boolean useCDATA;
public SerializableMetadata() {
super();
this.xmlEncoding = "UTF-8";
this.useCDATA = false;
}
/**
* Accepts any encoding which is supported by java.net.URLEncoder If
* useCDATA is set true then element text will be wrapped in a CDATA tag.
*
* @param xmlEncoding
* The encoding to use when generating XML version of a
* SerializableMetadata
* @param useCDATA
* whether or not to use CDATA tags around an element's text.
* @throws InstantiationException
* if xmlEncoding equals null
*/
public SerializableMetadata(String xmlEncoding, boolean useCDATA)
throws InstantiationException {
super();
if (xmlEncoding == null)
throw new InstantiationException("xmlEncoding cannot be null");
this.xmlEncoding = xmlEncoding;
this.useCDATA = useCDATA;
}
public SerializableMetadata(Metadata metadata) {
this(metadata, "UTF-8", false);
}
public SerializableMetadata(InputStream inputStream) throws IOException {
this(inputStream, "UTF-8", false);
}
public SerializableMetadata(InputStream inputStream, String xmlEncoding,
boolean useCDATA) throws IOException {
this.xmlEncoding = xmlEncoding;
this.useCDATA = useCDATA;
this.loadMetadataFromXmlStream(inputStream);
}
/**
* Builds a SerializableMetadata object from a Metadata object
*
* @param metadata
* @param xmlEncoding
*/
public SerializableMetadata(Metadata metadata, String xmlEncoding,
boolean useCDATA) {
this.replaceMetadata(metadata);
this.xmlEncoding = xmlEncoding;
this.useCDATA = useCDATA;
}
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
out.writeObject(this.xmlEncoding);
out.writeBoolean(useCDATA);
this.writeMetadataToXmlStream(out);
}
private void readObject(java.io.ObjectInputStream in) throws IOException,
ClassNotFoundException {
this.xmlEncoding = (String) in.readObject();
this.useCDATA = in.readBoolean();
this.loadMetadataFromXmlStream(in);
}
public String getEncoding() {
return this.xmlEncoding;
}
public boolean isUsingCDATA() {
return this.useCDATA;
}
/**
* Writes out this SerializableMetadata object in XML format to the
* OutputStream provided
*
* @param os
* The OutputStream this method writes to
* @throws IOException
* for any Exception
*/
public void writeMetadataToXmlStream(OutputStream os) throws IOException {
try {
// Prepare the DOM document for writing
Source source = new DOMSource(this.toXML());
Result result = new StreamResult(os);
// Write the DOM document to the file
Transformer xformer = TransformerFactory.newInstance()
.newTransformer();
xformer.setOutputProperty(OutputKeys.ENCODING, this.xmlEncoding);
xformer.setOutputProperty(OutputKeys.INDENT, "yes");
xformer.transform(source, result);
} catch (Exception e) {
e.printStackTrace();
throw new IOException("Error generating metadata xml file!: "
+ e.getMessage());
}
}
public Document toXML() throws IOException {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
factory.setNamespaceAware(true);
Document document = factory.newDocumentBuilder().newDocument();
Element root = document.createElementNS("http://oodt.jpl.nasa.gov/1.0/cas", "metadata");
root.setPrefix("cas");
document.appendChild(root);
// now add the set of metadata elements in the properties object
for (String key : this.getAllKeys()) {
Element metadataElem = document.createElement("keyval");
Element keyElem = document.createElement("key");
if (this.useCDATA)
keyElem.appendChild(document.createCDATASection(key));
else
keyElem.appendChild(document.createTextNode(URLEncoder.encode(key, this.xmlEncoding)));
metadataElem.appendChild(keyElem);
metadataElem.setAttribute("type", "vector");
for (String value : this.getAllMetadata(key)) {
Element valElem = document.createElement("val");
if (value == null) {
throw new Exception("Attempt to write null value "
+ "for property: [" + key + "]: val: ["
+ value + "]");
}
if (this.useCDATA)
valElem.appendChild(document
.createCDATASection(value));
else
valElem.appendChild(document.createTextNode(URLEncoder
.encode(value, this.xmlEncoding)));
metadataElem.appendChild(valElem);
}
root.appendChild(metadataElem);
}
return document;
} catch (Exception e) {
e.printStackTrace();
throw new IOException(
"Failed to create XML DOM Document for SerializableMetadata : "
+ e.getMessage());
}
}
/**
* Reloads this SerializableMetadata from an InputStream in the format
* created by writeMetadataToXmlStream(OutputStream).
*
* @param in
* The InputStream which this object is loaded from
* @throws IOException
* for any exception
*/
public void loadMetadataFromXmlStream(InputStream in) throws IOException {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder parser = factory.newDocumentBuilder();
Element root = parser.parse(new InputSource(in))
.getDocumentElement();
NodeList keyValElems = root.getElementsByTagName("keyval");
for (int i = 0; i < keyValElems.getLength(); i++) {
Element keyValElem = (Element) keyValElems.item(i);
String elemName = XMLUtils.read(keyValElem, "key",
this.xmlEncoding);
List<String> elemValues = XMLUtils.readMany(keyValElem, "val",
this.xmlEncoding);
this.addMetadata(elemName, elemValues);
}
} catch (Exception e) {
throw new IOException(
"Failed to load SerializableMetadata from ObjectInputStream : "
+ e.getMessage());
}
}
/**
* Converts SerializableMetadata into a plain metadata object
*
* @return Metadata object with the same metadata that this
* SerializableMetadata contains
*/
public Metadata getMetadata() {
Metadata metadata = new Metadata();
metadata.addMetadata(this.getHashtable());
return metadata;
}
}