org.artifactory.jaxb.JaxbHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.artifactory.jaxb.JaxbHelper.java

Source

/*
 * Artifactory is a binaries repository manager.
 * Copyright (C) 2012 JFrog Ltd.
 *
 * Artifactory 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 3 of the License, or
 * (at your option) any later version.
 *
 * Artifactory 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 Artifactory.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.artifactory.jaxb;

import com.google.common.base.Charsets;
import com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationException;
import com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException;
import org.apache.commons.io.IOUtils;
import org.artifactory.descriptor.config.CentralConfigDescriptor;
import org.artifactory.descriptor.config.CentralConfigDescriptorImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.SchemaOutputResolver;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlSchema;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.List;

/**
 * @author yoavl
 */
public class JaxbHelper<T> {
    private static final Logger log = LoggerFactory.getLogger(JaxbHelper.class);

    public static CentralConfigDescriptorImpl readConfig(String configXmlString) {
        URL schemaUrl = CentralConfigDescriptorImpl.class.getClassLoader().getResource("artifactory.xsd");
        if (schemaUrl == null) {
            throw new RuntimeException("Cannot load artifactory.xsd schema file from classpath.\n"
                    + "Please make sure the artifactory.war contains it.");
        }
        CentralConfigDescriptorImpl descriptor = new JaxbHelper<CentralConfigDescriptorImpl>().read(
                new ByteArrayInputStream(configXmlString.getBytes(Charsets.UTF_8)),
                CentralConfigDescriptorImpl.class, schemaUrl);
        return descriptor;
    }

    public static void writeConfig(CentralConfigDescriptor descriptor, File configFile) {
        try {
            PrintStream ps = new PrintStream(configFile, Charsets.UTF_8.name());
            new JaxbHelper<CentralConfigDescriptor>().write(ps, descriptor);
        } catch (FileNotFoundException e) {
            throw new RuntimeException("File " + configFile.getAbsolutePath() + " cannot be written to!", e);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    public static String toXml(CentralConfigDescriptor descriptor) {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            new JaxbHelper<CentralConfigDescriptor>().write(bos, descriptor);
            return bos.toString("utf-8");
        } catch (IOException e) {
            throw new RuntimeException("Configuration could be converted to string!", e);
        }
    }

    public static <T> String toXml(T object) {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            new JaxbHelper<T>().write(bos, object);
            return bos.toString("utf-8");
        } catch (IOException e) {
            throw new RuntimeException("Object could be converted to string!", e);
        }
    }

    public void write(OutputStream stream, T object) {
        try {
            JAXBContext context = JAXBContext.newInstance(object.getClass());
            Marshaller marshaller = context.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            XmlSchema schemaAnnotation = object.getClass().getPackage().getAnnotation(XmlSchema.class);
            if (schemaAnnotation != null && schemaAnnotation.location() != null) {
                marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, schemaAnnotation.location());
                // TODO: May just this ArtifactoryConfigVersion.getCurrent().getXsdLocation());
            }
            marshaller.marshal(object, stream);
        } catch (Exception e) {
            throw new RuntimeException("Failed to write object to stream.", e);
        } finally {
            IOUtils.closeQuietly(stream);
        }
    }

    @SuppressWarnings({ "unchecked" })
    public T read(InputStream stream, Class clazz, URL schemaUrl) {
        T o = null;
        try {
            JAXBContext context = JAXBContext.newInstance(clazz);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            if (schemaUrl != null) {
                SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
                Schema schema = sf.newSchema(schemaUrl);
                unmarshaller.setSchema(schema);
            }
            o = (T) unmarshaller.unmarshal(stream);
        } catch (Throwable t) {
            // The following code resolves the errors from JAXB result.
            // Just throwing new RuntimeException doesn't shows the root cause of the failure and it is almost impossible
            // to conclude it without this log.
            if (t instanceof IllegalAnnotationsException) {
                List<IllegalAnnotationException> errors = ((IllegalAnnotationsException) t).getErrors();
                if (errors != null) {
                    for (IllegalAnnotationException error : errors) {
                        log.error("Failed to read object from stream, error:", error);
                    }
                }
            }
            throw new RuntimeException("Failed to read object from stream.", t);
        } finally {
            IOUtils.closeQuietly(stream);
        }
        return o;
    }

    public void generateSchema(final OutputStream stream, final Class<T> clazz, final String namespace) {
        try {
            JAXBContext context = JAXBContext.newInstance(clazz);
            context.generateSchema(new SchemaOutputResolver() {
                @Override
                public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException {
                    StreamResult result = new StreamResult(stream);
                    result.setSystemId(namespace);
                    return result;
                }
            });
        } catch (Exception e) {
            throw new RuntimeException("Failed to write object to stream.", e);
        }
    }
}