/** * JBoss, Home of Professional Open Source * Copyright ${year}, Red Hat, Inc. and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.arquillian.rusheye.result.writer; import java.io.IOException; import java.io.OutputStream; import java.net.URL; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import org.codehaus.stax2.XMLStreamWriter2; import org.codehaus.stax2.validation.XMLValidationSchema; import org.codehaus.stax2.validation.XMLValidationSchemaFactory; import org.arquillian.rusheye.RushEye; import org.arquillian.rusheye.suite.Properties; import org.arquillian.rusheye.suite.Test; import org.arquillian.rusheye.suite.annotations.VisualSuiteResult; import org.arquillian.rusheye.suite.utils.NullingProxy; /** * @author <a href="mailto:lfryc@redhat.com">Lukas Fryc</a> * @version $Revision$ */ public abstract class XmlResultWriter implements ResultWriter { protected Properties properties; private XMLStreamWriter writer; private OutputStream out; private Marshaller marshaller; private boolean writerFailedToInitialize = false; private boolean writerFailed = false; private boolean writtenStartDocument = false; public void setProperties(Properties properties) { this.properties = properties; } public boolean write(Test test) { if (!tryInitializeWriter()) { return false; } return writeSafely(new WriterContext(test)); } private boolean writeSafely(WriterContext context) { tryWriteStartDocument(); tryWriteTest(context); return !writerFailed; } private void tryWriteStartDocument() { if (!writerFailed && !writtenStartDocument) { try { writer.writeStartDocument("UTF-8", "1.0"); writer.setDefaultNamespace(RushEye.NAMESPACE_VISUAL_SUITE_RESULT); writer.writeStartElement(RushEye.NAMESPACE_VISUAL_SUITE_RESULT, "visual-suite-result"); writer.writeDefaultNamespace(RushEye.NAMESPACE_VISUAL_SUITE_RESULT); writer.writeNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"); writer.writeAttribute("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation", RushEye.NAMESPACE_VISUAL_SUITE_RESULT + " " + RushEye.SCHEMA_LOCATION_VISUAL_SUITE_RESULT); writtenStartDocument = true; } catch (XMLStreamException e) { e.printStackTrace(); writerFailed = true; } } } private void tryWriteTest(WriterContext context) { if (!writerFailed) { try { Test test = context.getTest(); test = NullingProxy.handle(test, VisualSuiteResult.class); marshaller.marshal(test, writer); writer.flush(); } catch (Exception e) { e.printStackTrace(); writerFailed = true; } } } private boolean tryInitializeWriter() { if (!writerFailedToInitialize && out == null && writer == null) { try { out = openOutputStream(); } catch (Exception e) { e.printStackTrace(); writerFailedToInitialize = true; } try { writer = createXMLStreamWriter(); marshaller = createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true); } catch (Exception e) { e.printStackTrace(); writerFailedToInitialize = true; try { out.close(); } catch (IOException ioe) { // no need to close } } } return !writerFailedToInitialize; } private XMLStreamWriter createXMLStreamWriter() throws XMLStreamException { XMLOutputFactory factory = XMLOutputFactory.newInstance(); XMLStreamWriter2 writer = (XMLStreamWriter2) factory.createXMLStreamWriter(out); writer.validateAgainst(createXMLValidationSchema()); // return writer; return PrettyXMLStreamWriter.pretty(writer); } private Marshaller createMarshaller() throws JAXBException { JAXBContext context = JAXBContext.newInstance("org.arquillian.rusheye.suite"); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); return marshaller; } private XMLValidationSchema createXMLValidationSchema() throws XMLStreamException { XMLValidationSchemaFactory schemaFactory = XMLValidationSchemaFactory .newInstance(XMLValidationSchema.SCHEMA_ID_W3C_SCHEMA); URL schemaURL = getClass().getClassLoader().getResource("org/arquillian/rusheye/visual-suite-result.xsd"); XMLValidationSchema schema = schemaFactory.createSchema(schemaURL); return schema; } protected abstract OutputStream openOutputStream() throws Exception; protected abstract void closeOutputStream() throws Exception; public void close() { try { if (writer != null) { writer.flush(); writer.writeEndElement(); writer.close(); } } catch (XMLStreamException e) { e.printStackTrace(); // needs to be logged } try { closeOutputStream(); } catch (Exception e) { e.printStackTrace(); // needs to be logged } } }