Package gov.nasa.jsc.mct.importExport.utilities

Source Code of gov.nasa.jsc.mct.importExport.utilities.XMLPersistence

/*******************************************************************************
* Mission Control Technologies, Copyright (c) 2009-2012, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* The MCT platform is 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.
*
* MCT includes source code licensed under additional open source licenses. See
* the MCT Open Source Licenses file included with this distribution or the About
* MCT Licenses dialog available at runtime from the MCT Help menu for additional
* information.
*******************************************************************************/
package gov.nasa.jsc.mct.importExport.utilities;

import gov.nasa.arc.mct.components.ExtendedProperties;
import gov.nasa.arc.mct.importExport.provider.generated.ComponentListType;
import gov.nasa.arc.mct.importExport.provider.generated.ObjectFactory;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.concurrent.ConcurrentHashMap;

import javax.xml.XMLConstants;
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.bind.ValidationEvent;
import javax.xml.bind.util.ValidationEventCollector;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;

/**
* Class to marshal and unmarshal data to/from an XML file or a string.
*/
public class XMLPersistence {
 
  /** Location and name of schema to be added to the XML file **/
  private static final String schemaLocation = "http://gov.nasa.arc.mct importExport.xsd";
  private static final Logger LOGGER = LoggerFactory
                                  .getLogger(XMLPersistence.class);

  /**
   * Private unaccessible constructor
   */
  private XMLPersistence() {
  }

  /**
   * Given an object of type ComponentListType write it to an XML file
   * @param primaryObject An object of type ComponentListType
   * @param file File to write the data to
   * @throws IOException
   * @throws ValidationException
   */
  public static void marshal(ComponentListType primaryObject, File file)
                 throws IOException, ValidationException{
    String errStr = null;
   
    if (primaryObject == null || primaryObject.getComponent() == null ||
        primaryObject.getComponent().size() == 0) {
      return;
    }
   
    // Convert the ComponentListType into a JAXBElement.
    ObjectFactory objFactory = new ObjectFactory();
    JAXBElement<ComponentListType> element = objFactory.createComponents(primaryObject);
    ValidationEventCollector validationEventCollector =
                                             new ValidationEventCollector();

    FileOutputStream fileOut = null;

    // open file
    if (file == null || file.equals("")) {
      throw new IllegalArgumentException(
          "XMLPersistence: File name is null or empty string");
    }

    try {
      fileOut = new FileOutputStream(file);
     
      // create marshaller
      Marshaller marshaller = createNewMarshaller(primaryObject);
     
      // Get schema and set marshaller for validation
      Schema schema = getSchema();
            marshaller.setSchema(schema);
      marshaller.setEventHandler(validationEventCollector);
     
      // Marshal
      marshaller.marshal(element, fileOut);
      fileOut.close();
     
    } catch (JAXBException e) {
      errStr = String.format("JAXBException on file:%s due to: %s",
          file, e.getMessage());
    } catch (FileNotFoundException e) {
      errStr = String.format("Unable to find schema for xml file: %s Cause: %s. " +
          "Ensure Schema Path is set.", file, e.getMessage());
    } catch (IOException e) {
      errStr = String.format("IOException on file:%s due to: %s",
          file, e.getMessage());
    } catch (SAXException e) {
      errStr = String.format("SAXException on file:%s due to: %s",
          file, e.getMessage());
    } finally {
      handleError(errStr, validationEventCollector, file);
    }
  }

  /**
     * Marshals the data and return the marshalled String. The object is
     * converted between byte and Unicode characters using the named encoding
     * "UTF-8".
     *
     * @param toBeMarshalled
     *            the object whose data is to be marshalled.
     * @throws JAXBException - JAXB XML exception handling.
     * @throws UnsupportedEncodingException - Unsupported encoding exception handling.
     * @return out marshalled string.
     * @param <T> string
     */
    public static <T> String marshal(T toBeMarshalled) throws JAXBException,
                                                         UnsupportedEncodingException {
      Map<Class<?>, JAXBContext> marshalCache =
                                    new ConcurrentHashMap<Class<?>, JAXBContext>();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        Class<?> clazz = toBeMarshalled.getClass();
        JAXBContext ctxt = marshalCache.get(clazz);
        if (ctxt == null) {
            ctxt = JAXBContext.newInstance(clazz);
            marshalCache.put(clazz, ctxt);
        }
        Marshaller marshaller = ctxt.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "ASCII");
        marshaller.marshal(toBeMarshalled, out);
        return out.toString("ASCII");
    }
 
  /**
   * Create a new marshaller to write data to an XML file
   * @return a new marshaller
   * @throws JAXBException
   */
  private static Marshaller createNewMarshaller(ComponentListType primaryObject)
      throws JAXBException {
    Marshaller marshaller = null;
    // Package location of object
    String objectPackage = primaryObject.getClass().getPackage().getName();

    JAXBContext jaxbContext = JAXBContext.newInstance(objectPackage,
        XMLPersistence.class.getClassLoader());

    marshaller = jaxbContext.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
    // Add schema location and name to XML file
    marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, schemaLocation);
   
    return marshaller;
  }
 
  /**
   * Validates that the XML file conforms to the ImportExport.xsd schema and
   * unmarshalls it into a JAXBElement. Uses a JABXContext created from the
   * package of classes generated with the xjc binding compiler applied to the
   * schema. Must read the ImportExport.xsd schema file for validation.
   *
   * @param xmlFile to be unmarshalled
   * @return null upon error, else ComponentListType
   * @throws ValidationException
   */
  public static ComponentListType unmarshal(File xmlFile) throws IOException, ValidationException {
   
    if (xmlFile == null || xmlFile.equals("") || !xmlFile.exists()) {
      throw new IllegalArgumentException(
          "XMLPersistence: File name is null, the empty string, or does not" +
          " exist.");
    }
   
    ValidationEventCollector validationEventCollector =
                                       new ValidationEventCollector();
    Schema schema;
    JAXBElement<ComponentListType> root = null;
    String errStr = null;
    ComponentListType componentListType = null;
   
    try {
      JAXBContext jaxbContext = JAXBContext.newInstance(
                          ComponentListType.class.getPackage().getName(),
                          XMLPersistence.class.getClassLoader());
      Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

      // Get schema and add to unmarshaller
      schema = getSchema();
      unmarshaller.setSchema(schema);
     
      unmarshaller.setEventHandler(validationEventCollector);
      // Unmarshal the file
      root = unmarshaller.unmarshal(new StreamSource(xmlFile),
          ComponentListType.class);
     
      componentListType = root.getValue();

    } catch (SAXException saxe) {
      errStr = String.format("SAXException on file:%s due to: %s ",
          xmlFile, saxe.getMessage());
    } catch (JAXBException jaxbe) {
      errStr = String.format("JAXBException on file:%s due to: %s",
          xmlFile, jaxbe.toString());
    } catch (FileNotFoundException e) {
      errStr = String.format("Unable to find schema for xml file: %s Cause: %s. " +
          "Ensure Schema Path is set.", xmlFile, e.getMessage());
    } finally {
      handleError(errStr, validationEventCollector, xmlFile);
    }
   
    return componentListType;
  }
 
  /**
   * Unmarshal the string and return it as an ExtendedProperties object
   * @param props String to unmarshal
   * @return An ExtendedProperties object
   */
  public static ExtendedProperties unmarshal(String props) {
    Unmarshaller unmarshaller;
    try {
      JAXBContext jaxbContext = JAXBContext.newInstance(ExtendedProperties.class);
      unmarshaller = jaxbContext.createUnmarshaller();
      InputStream is = new ByteArrayInputStream(props.getBytes("ASCII"));
      return ExtendedProperties.class.cast(unmarshaller.unmarshal(is));
    } catch (JAXBException je) {
      throw new RuntimeException(je);
    } catch (UnsupportedEncodingException e) {
      throw new RuntimeException(e);
    }
  }
 
  /**
   * Get the Schema
   * @return
   * @throws FileNotFoundException If schema can't be found
   * @throws SAXException
   */
  private static Schema getSchema() throws FileNotFoundException, SAXException {
    SchemaFactory schemaFactory = SchemaFactory
        .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    StreamSource streamSource = getSchemaSource();
    return schemaFactory.newSchema(streamSource);
  }
 
  /**
   * Get the StreamSource attached to the ImportExport.xsd schema file. The
   * schema file can be found in two mutually exclusive ways. If property
   * mccAppSchemaPath is set, then the file location will be opened.
   * Alternatively, if mccAppSchemaPath is not set, this will attempt to get
   * the schema as a resource from the classpath defined by
   * xsdSchemaResourceClasspath. Note that the file method does not fallback
   * to the resource method.
   *
   * @return The schema's StreamSource
   * @throws FileNotFoundException
   */
  private static StreamSource getSchemaSource() throws FileNotFoundException {
    String schemaPath = System.getProperty("importExportSchemaPath");
    StreamSource streamSource = null;
    if (schemaPath != null) {
      streamSource = new StreamSource(new FileInputStream(schemaPath));
    } else {
      ResourceBundle bundle = ResourceBundle.getBundle("ImportExportProvider");
      String xsdSchemaResourceClasspath = bundle
          .getString("xsdSchemaResourceClasspath");
      assert xsdSchemaResourceClasspath != null;

      InputStream is = XMLPersistence.class.getClassLoader()
                         .getResourceAsStream(xsdSchemaResourceClasspath);
      if (is == null) {
        is = ClassLoader.getSystemClassLoader().getResourceAsStream(
            xsdSchemaResourceClasspath);
      }
      if (is == null) {
        throw new FileNotFoundException();
      } else {
        streamSource = new StreamSource(is);
      }
    }

    return streamSource;
  }
 
  /**
   * If an exception was thrown or if the validation event collector has an error, log
   * the error and throw an IOException
   * @param errStr Error message created when/if an exception was thrown
   * @param validationEventCollector
   * @param file XML file that was attempted to be processed
   * @throws ValidationException
   */
  private static void handleError(String errStr,
                      ValidationEventCollector validationEventCollector, File file)
                      throws IOException, ValidationException {
   
    if (validationEventCollector.hasEvents()) {
      for (ValidationEvent validationEvent : validationEventCollector
          .getEvents()) {
        String msg = validationEvent.getMessage();
        String m = String.format(
            "xml file: %s reports validation event: %s", file,
            msg);
        LOGGER.error(m);
        throw new ValidationException(m);
      }
    } else {
      if (errStr != null) {
        LOGGER.error(errStr);
        throw new IOException(errStr);
      }
    }
  }

}
TOP

Related Classes of gov.nasa.jsc.mct.importExport.utilities.XMLPersistence

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.