| /* |
| * Copyright (C) 2010-2011 The University of Manchester |
| * |
| * See the file "LICENSE" for license terms. |
| */ |
| package org.taverna.server.master.common; |
| |
| import static javax.xml.bind.Marshaller.JAXB_ENCODING; |
| import static javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT; |
| import static org.apache.commons.logging.LogFactory.getLog; |
| import static org.taverna.server.master.common.Namespaces.T2FLOW; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.Externalizable; |
| import java.io.IOException; |
| import java.io.InputStreamReader; |
| import java.io.ObjectInput; |
| import java.io.ObjectOutput; |
| import java.io.OutputStreamWriter; |
| import java.io.Reader; |
| import java.io.Serializable; |
| import java.io.StringReader; |
| import java.io.StringWriter; |
| import java.util.zip.DeflaterOutputStream; |
| import java.util.zip.InflaterInputStream; |
| |
| import javax.xml.bind.JAXBContext; |
| import javax.xml.bind.JAXBException; |
| import javax.xml.bind.Marshaller; |
| import javax.xml.bind.Unmarshaller; |
| import javax.xml.bind.annotation.XmlAnyElement; |
| import javax.xml.bind.annotation.XmlRootElement; |
| import javax.xml.bind.annotation.XmlTransient; |
| import javax.xml.bind.annotation.XmlType; |
| |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| |
| /** |
| * Encapsulation of a T2flow document. |
| * |
| * @author dkf |
| */ |
| @XmlRootElement(name = "workflow") |
| @XmlType(name = "Workflow") |
| public class Workflow implements Serializable,Externalizable { |
| /** |
| * Literal document. |
| */ |
| @XmlAnyElement(lax = true) |
| public Element[] content; |
| |
| private static Marshaller marshaller; |
| private static Unmarshaller unmarshaller; |
| private final static String ENCODING = "UTF-8"; |
| static { |
| try { |
| JAXBContext context = JAXBContext.newInstance(Workflow.class); |
| marshaller = context.createMarshaller(); |
| unmarshaller = context.createUnmarshaller(); |
| marshaller.setProperty(JAXB_ENCODING, ENCODING); |
| marshaller.setProperty(JAXB_FORMATTED_OUTPUT, true); |
| } catch (JAXBException e) { |
| getLog("Taverna.Server.Webapp").fatal( |
| "failed to build JAXB context for working with " |
| + Workflow.class, e); |
| } |
| } |
| |
| public static Workflow unmarshal(String representation) |
| throws JAXBException { |
| StringReader sr = new StringReader(representation); |
| return (Workflow) unmarshaller.unmarshal(sr); |
| } |
| |
| public String marshal() throws JAXBException { |
| StringWriter sw = new StringWriter(); |
| marshaller.marshal(this, sw); |
| return sw.toString(); |
| } |
| |
| @Override |
| public void readExternal(ObjectInput in) throws IOException, |
| ClassNotFoundException { |
| try { |
| int len = in.readInt(); |
| byte[] bytes = new byte[len]; |
| in.readFully(bytes); |
| try (Reader r = new InputStreamReader(new InflaterInputStream( |
| new ByteArrayInputStream(bytes)), ENCODING)) { |
| this.content = ((Workflow) unmarshaller.unmarshal(r)).content; |
| } |
| return; |
| } catch (JAXBException e) { |
| throw new IOException("failed to unmarshal", e); |
| } catch (ClassCastException e) { |
| throw new IOException("bizarre result of unmarshalling", e); |
| } |
| } |
| |
| @Override |
| public void writeExternal(ObjectOutput out) throws IOException { |
| try { |
| ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| try (OutputStreamWriter w = new OutputStreamWriter( |
| new DeflaterOutputStream(baos), ENCODING)) { |
| marshaller.marshal(this, w); |
| } |
| byte[] bytes = baos.toByteArray(); |
| out.writeInt(bytes.length); |
| out.write(bytes); |
| } catch (JAXBException e) { |
| throw new IOException("failed to marshal", e); |
| } |
| } |
| |
| /** |
| * Make up for the lack of an integrated XPath engine. |
| * |
| * @param name |
| * The element names to look up from the root of the contained |
| * document. |
| * @return The looked up element, or <tt>null</tt> if it doesn't exist. |
| */ |
| private Element getEl(String... name) { |
| Element el = null; |
| for (Element e : content) |
| if (e.getNamespaceURI().equals(T2FLOW) |
| && e.getLocalName().equals(name[0])) { |
| el = e; |
| break; |
| } |
| boolean skip = true; |
| for (String n : name) { |
| if (skip) { |
| skip = false; |
| continue; |
| } |
| if (el == null) |
| return null; |
| NodeList nl = el.getElementsByTagNameNS(T2FLOW, n); |
| if (nl.getLength() == 0) |
| return null; |
| Node node = nl.item(0); |
| if (node instanceof Element) |
| el = (Element) node; |
| else |
| return null; |
| } |
| return el; |
| } |
| |
| /** |
| * @return The content of the embedded |
| * <tt><workflow><dataflow><name></tt> element. |
| */ |
| @XmlTransient |
| public String getName() { |
| return getEl("workflow", "dataflow", "name").getTextContent(); |
| } |
| |
| /** |
| * @return The embedded <tt><workflow></tt> element. |
| */ |
| @XmlTransient |
| public Element getWorkflowRoot() { |
| return getEl("workflow"); |
| } |
| } |