| // 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; |
| } |
| |
| } |