/** * Abiquo community edition * cloud management application for hybrid clouds * Copyright (C) 2008-2010 - Abiquo Holdings S.L. * * This application 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 under * version 3 of the License * * 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 v.3 for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.abiquo.api.services.appslibrary; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.abiquo.appliancemanager.client.ExternalHttpConnection; import com.abiquo.appliancemanager.repositoryspace.RepositorySpace; import com.abiquo.ovfmanager.ovf.exceptions.XMLException; import com.abiquo.ovfmanager.ovf.xml.Stax2Factory; /** * Responsible of RepositorySpace serialization into/from XML (used to read ''ovfindex.xml''). */ public class RepositorySpaceXML { private final static Logger logger = LoggerFactory.getLogger(RepositorySpaceXML.class); private final static Boolean JAXB_FORMATTED_OUTPUT = true; /** Define the allowed objects to be binded form/into the OVFIndex schema definition. */ private final JAXBContext contextIndex; /** Generated factory to create XML elements on OVFIndex name space. */ private final com.abiquo.appliancemanager.repositoryspace.ObjectFactory factoryIndex; /** The singleton instance. */ private static RepositorySpaceXML instance; /** * Get the OVFSerializer singelton instance. * * @return the OVFSerializer instance or null if it can not be created. */ public static synchronized RepositorySpaceXML getInstance() { if (instance == null) { try { instance = new RepositorySpaceXML(); } catch (JAXBException e) { logger.error("OVFSerializer instance can not be created ", e); throw new RuntimeException("OVFSerializer instance can not be created ", e); // TODO runtime exception } } return instance; } /** * @throws JAXBException, if some JAXB context can not be created. */ private RepositorySpaceXML() throws JAXBException { contextIndex = JAXBContext.newInstance(new Class[] {RepositorySpace.class}); factoryIndex = new com.abiquo.appliancemanager.repositoryspace.ObjectFactory(); } /** * Creates an XML document representing the provided repository space based object and write it * to output stream. The provided stream is closed. * * @param repoSpace, the object to be binded into an XML document. * @param os, the destination of the XML document. * @throws OVFSchemaException, any XML problem. */ public void writeAsXML(final RepositorySpace rs, final OutputStream os) throws XMLException { XMLStreamWriter writer = null; Marshaller marshall; try { writer = Stax2Factory.createXMLStreamWriter(os); marshall = contextIndex.createMarshaller(); marshall.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, new Boolean(JAXB_FORMATTED_OUTPUT)); marshall.marshal(factoryIndex.createRepositorySpace(rs), writer); } catch (JAXBException ea) { throw new XMLException(ea); } catch (XMLStreamException ex) { throw new XMLException(ex); } finally { try { writer.close(); os.close(); } catch (Exception e) { logger.error("Can not close the output source, writing a RepositorySpace", e); } } } /** * @param is, the input stream source where read XML documents. * @param cl Represents the class that should be created from the XML structure in the in the * InputStream * @return the RepositorySpace read from source. * @throws XMLException, if it is not a RepositorySpace type or any XML problem. */ public RepositorySpace readAsXML(final InputStream is) throws XMLException { XMLStreamReader reader = null; try { reader = Stax2Factory.createXMLStreamReader(is); Unmarshaller unmarshall = contextIndex.createUnmarshaller(); JAXBElement<RepositorySpace> jaxb = unmarshall.unmarshal(reader, RepositorySpace.class); return jaxb.getValue(); } catch (XMLStreamException e) { throw new XMLException(e); } catch (JAXBException e) { throw new XMLException(e); } finally { try { reader.close(); is.close(); } catch (Exception e) { logger.error("Can not close the input source, reading a RepositorySpace", e); } } } /** * Read a {@link RepositorySpace} from an ovfindex.xml url */ public RepositorySpace obtainRepositorySpace(final String repositorySpaceURL) throws XMLException, IOException, MalformedURLException { RepositorySpace repo; ExternalHttpConnection connection = new ExternalHttpConnection(); try { new URL(repositorySpaceURL); // check MalformaedUrl InputStream isRs = connection.openConnection(repositorySpaceURL); repo = readAsXML(isRs); if (!repo.getRepositoryURI().equalsIgnoreCase(repositorySpaceURL)) { logger.warn("chang the ''RepositoryURI'' in the ovfindex.xml to " + repositorySpaceURL); repo.setRepositoryURI(repositorySpaceURL); } return repo; } catch (XMLException e) // XMLStreamException or JAXBException { final String msg = "Invalid OVFIndex.xml on RepositorySpace: " + repositorySpaceURL; throw new XMLException(msg, e); } catch (MalformedURLException e) { final String msg = "Invalid repository space identifier : " + repositorySpaceURL; throw new MalformedURLException(msg); } catch (Exception e) { final String msg = "Can not open a connection to : " + repositorySpaceURL; throw new IOException(msg); } finally { connection.releaseConnection(); } } }