/****************************************************************************** * Copyright (c) 2012 GigaSpaces Technologies Ltd. All rights reserved * * * * Licensed 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.cloudifysource.esc.driver.provisioning.azure.client; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.cloudifysource.esc.driver.provisioning.azure.model.ModelContextFactory; import org.w3c.dom.Document; import org.xml.sax.InputSource; import org.xml.sax.SAXException; /*************************************************************************************** * A Utility class for marshaling and unmarshaling azure model related objects. * * * * @author elip ***************************************************************************************/ public final class MicrosoftAzureModelUtils { private MicrosoftAzureModelUtils() { } /** * * @param body * - the object to marshal * @param network * - whether or not this object belongs to the network domain * model. * @return - a String representation in the form of an XML of the body * @throws MicrosoftAzureException * - indicates a marshaling exception happened */ public static String marshall(final Object body, final boolean network) throws MicrosoftAzureException { JAXBContext context = ModelContextFactory.createInstance(); StringWriter sw = new StringWriter(); Marshaller m; try { m = context.createMarshaller(); m.marshal(body, sw); Document doc = createEmptyDocument(); m.marshal(body, doc); String xml = getStringFromDocument(doc); if (network) { // so stupid !! TODO eli - find a proper way to deal // with different name spaces under the space // JAXBContext instance. // i cant seem to find the azure xsd anywhere so // that i can generate proper model object using // xjc. xml = addNameSpaceToRootElement(xml, "xmlns=\"http://schemas.microsoft.com/ServiceHosting/2011/07/NetworkConfiguration\""); } else { xml = addNameSpaceToRootElement(xml, "xmlns=\"http://schemas.microsoft.com/windowsazure\""); xml = addNameSpaceToRootElement(xml, "xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\""); } return xml; } catch (JAXBException e) { throw new MicrosoftAzureException(e); } } /** * @param xml * @param nameSpace */ private static String addNameSpaceToRootElement(final String xml, final String nameSpace) { int count = 0; int i = 0; while (count < 2) { if (xml.charAt(i) == '>') { count++; } i++; } String first = xml.substring(0, i - 1); String second = xml.substring(i, xml.length()); return first + " " + nameSpace + ">" + second; } /** * * @param entity * - the string representation off the object in XML form * @return - an instance of {@link Object} representing the XML that can be * cast to a specific type * @throws MicrosoftAzureException . */ public static Object unmarshall(final String entity) throws MicrosoftAzureException { JAXBContext context = ModelContextFactory.createInstance(); Document xmlDoc = parse(entity); Unmarshaller um = null; try { um = context.createUnmarshaller(); return um.unmarshal(xmlDoc); } catch (JAXBException e) { throw new MicrosoftAzureException(e); } } private static DocumentBuilder createDocumentBuilder() { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); try { dbf.setNamespaceAware(false); return dbf.newDocumentBuilder(); } catch (ParserConfigurationException e) { throw new IllegalStateException(e); } } private static Document parse(final String xml) throws MicrosoftAzureException { try { DocumentBuilder documentBuilder = createDocumentBuilder(); Document xmlDoc = documentBuilder.parse(new InputSource( new StringReader(xml))); xmlDoc.normalizeDocument(); return xmlDoc; } catch (SAXException e) { throw new MicrosoftAzureException( "Failed to parse XML Response from server. Response was: " + xml + ", Error was: " + e.getMessage(), e); } catch (IOException e) { throw new MicrosoftAzureException( "Failed to parse XML Response from server. Response was: " + xml + ", Error was: " + e.getMessage(), e); } } private static String getStringFromDocument(final Document doc) throws MicrosoftAzureException { try { DOMSource domSource = new DOMSource(doc); StringWriter writer = new StringWriter(); StreamResult result = new StreamResult(writer); TransformerFactory tf = TransformerFactory.newInstance(); Transformer transformer = tf.newTransformer(); transformer.transform(domSource, result); return writer.toString(); } catch (TransformerException ex) { throw new MicrosoftAzureException(ex); } } private static Document createEmptyDocument() { DocumentBuilder documentBuilder = createDocumentBuilder(); return documentBuilder.newDocument(); } }