001    /**
002     * Copyright 2005-2012 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.rice.ksb.impl.bus;
017    
018    import java.io.StringReader;
019    import java.io.StringWriter;
020    import java.util.HashSet;
021    import java.util.Set;
022    
023    import javax.xml.bind.JAXBContext;
024    import javax.xml.bind.JAXBException;
025    
026    import org.apache.commons.lang.StringUtils;
027    import org.kuali.rice.core.api.exception.RiceRuntimeException;
028    import org.kuali.rice.ksb.api.bus.ServiceConfiguration;
029    import org.kuali.rice.ksb.api.bus.support.JavaServiceConfiguration;
030    import org.kuali.rice.ksb.api.bus.support.RestServiceConfiguration;
031    import org.kuali.rice.ksb.api.bus.support.SoapServiceConfiguration;
032    
033    /**
034     * This class is meant to be a temporary implementation of serialization operations
035     * for {@link ServiceConfiguration} classes.  Coming into Rice 2.0, there is not a
036     * "pluggable" spi for dealing with custom service configurations, definitions,
037     * connectors, and exporters.  So for now everything is hardcoded and this
038     * class creates a hardcoded JAXBContext to perform marshalling/unmarshalling
039     * of the standard {@link ServiceConfiguration} classes.
040     * 
041     * <p>NOTE: JAXBContext is thread-safe, but marshaller/unmarshaller are *NOT* thread-safe.
042     * 
043     * @author Kuali Rice Team (rice.collab@kuali.org)
044     *
045     */
046    public class ServiceConfigurationSerializationHandler {
047    
048            private static final Set<Class<?>> CONFIG_CLASSES_SET = new HashSet<Class<?>>();
049            static {
050                    CONFIG_CLASSES_SET.add(JavaServiceConfiguration.class);
051                    CONFIG_CLASSES_SET.add(SoapServiceConfiguration.class);
052                    CONFIG_CLASSES_SET.add(RestServiceConfiguration.class);
053            }
054            
055            public static String marshallToXml(ServiceConfiguration serviceConfiguration) {
056                    if (serviceConfiguration == null) {
057                            throw new IllegalArgumentException("serviceConfiguration was null");
058                    }
059                    if (!CONFIG_CLASSES_SET.contains(serviceConfiguration.getClass())) {
060                            throw new IllegalArgumentException("Illegal ServiceConfiguration class: " + serviceConfiguration.getClass());
061                    }
062                    StringWriter writer = new StringWriter();
063                    try {
064                            getContext().createMarshaller().marshal(serviceConfiguration, writer);
065                    } catch (JAXBException e) {
066                            throw new RiceRuntimeException("Failed to marshall ServiceConfiguration to XML: " + serviceConfiguration, e);
067                    }
068                    return writer.toString();
069            }
070            
071            public static ServiceConfiguration unmarshallFromXml(String xml) {
072                    if (StringUtils.isBlank(xml)) {
073                            throw new IllegalArgumentException("xml was null or blank");
074                    }
075                    try {
076                            Object unmarshalled = getContext().createUnmarshaller().unmarshal(new StringReader(xml));
077                            if (!(unmarshalled instanceof ServiceConfiguration)) {
078                                    throw new RiceRuntimeException("Unmarshalled value was not a valid ServiceConfiguration: " + unmarshalled.getClass());
079                            }
080                            return (ServiceConfiguration)unmarshalled;
081                    } catch (JAXBException e) {
082                            throw new RiceRuntimeException("Failed to unmarhsal ServiceConfiguration from XML: " + xml, e);
083                    }
084            }
085            
086            private static JAXBContext getContext() {
087                    return ContextHolder.context;
088            }
089            
090            /**
091             * Implements the lazy initialization holder class idiom as per Effective Java item 71.
092             */
093            private static class ContextHolder {
094                    private static final Class<?>[] CONFIG_CLASSES_ARRAY = CONFIG_CLASSES_SET.toArray(new Class<?>[0]);
095                    static final JAXBContext context;
096                    static {
097                            try {
098                                    context = JAXBContext.newInstance(CONFIG_CLASSES_ARRAY);
099                            } catch (JAXBException e) {
100                                    throw new RiceRuntimeException(e);
101                            }
102                    }
103            }
104            
105    }