001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    package org.apache.geronimo.kernel.config.xstream;
018    
019    import java.io.IOException;
020    import java.util.ArrayList;
021    import java.util.Arrays;
022    import java.util.Collection;
023    import java.util.Collections;
024    import java.util.List;
025    import javax.xml.parsers.DocumentBuilder;
026    import javax.xml.parsers.DocumentBuilderFactory;
027    import javax.xml.parsers.ParserConfigurationException;
028    
029    import com.thoughtworks.xstream.XStream;
030    import com.thoughtworks.xstream.io.xml.DomReader;
031    import com.thoughtworks.xstream.io.xml.DomWriter;
032    import org.apache.geronimo.gbean.AbstractName;
033    import org.apache.geronimo.gbean.GBeanData;
034    import org.apache.geronimo.gbean.GBeanInfo;
035    import org.apache.geronimo.kernel.Naming;
036    import org.apache.geronimo.kernel.util.XmlUtil;
037    import org.apache.geronimo.kernel.config.InvalidConfigException;
038    import org.apache.geronimo.kernel.config.GBeanState;
039    import org.apache.geronimo.kernel.repository.Environment;
040    import org.w3c.dom.Document;
041    import org.w3c.dom.Element;
042    
043    /**
044     * @version $Rev: 476049 $ $Date: 2006-11-16 23:35:17 -0500 (Thu, 16 Nov 2006) $
045     */
046    public class XStreamGBeanState implements GBeanState {
047        /**
048         * GBeans contained in this configuration.
049         */
050        private final List gbeans = new ArrayList();
051    
052        /**
053         * The serialized form of the gbeans.  Once this is set on more gbeans can be added.
054         */
055        private Element gbeanState;
056    
057        public XStreamGBeanState(Element gbeanState) {
058            this.gbeanState = gbeanState;
059        }
060    
061        public XStreamGBeanState(Collection gbeans) {
062            if (gbeans != null){
063                this.gbeans.addAll(gbeans);
064            }
065        }
066    
067        public Element getGBeanState() throws IOException {
068            if (gbeanState == null) {
069                gbeanState = XStreamGBeanState.storeGBeans(gbeans);
070                gbeans.clear();
071            }
072            return gbeanState;
073        }
074    
075        public List getGBeans(ClassLoader classLoader) throws InvalidConfigException {
076            if (gbeanState == null) {
077                return Collections.unmodifiableList(gbeans);
078            }
079            gbeans.addAll(XStreamGBeanState.loadGBeans(gbeanState, classLoader));
080            return Collections.unmodifiableList(gbeans);
081        }
082    
083        public void addGBean(GBeanData gbeanData) {
084            if (gbeanState != null) {
085                throw new IllegalStateException("GBeans have been serialized, so no more GBeans can be added");
086            }
087    
088            gbeans.add(gbeanData);
089        }
090    
091        public GBeanData addGBean(String name, GBeanInfo gbeanInfo, Naming naming, Environment environment) {
092            if (gbeanState != null) {
093                throw new IllegalStateException("GBeans have been serialized, so no more GBeans can be added");
094            }
095    
096            String j2eeType = gbeanInfo.getJ2eeType();
097            if (j2eeType == null) j2eeType = "GBean";
098            AbstractName abstractName = naming.createRootName(environment.getConfigId(), name, j2eeType);
099            GBeanData gBeanData = new GBeanData(abstractName, gbeanInfo);
100            addGBean(gBeanData);
101            return gBeanData;
102        }
103    
104        private static List loadGBeans(Element element, ClassLoader classLoader) throws InvalidConfigException {
105            if (element != null) {
106                // Set the thread context classloader so deserializing classes can grab the cl from the thread
107                ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
108                try {
109                    Thread.currentThread().setContextClassLoader(classLoader);
110    
111                    DomReader reader = new DomReader(element);
112                    XStream xstream = XStreamUtil.createXStream();
113                    xstream.setClassLoader(classLoader);
114                    Object o = xstream.unmarshal(reader);
115                    GBeanData[] gbeanDatas = (GBeanData[]) o;
116                    return Arrays.asList(gbeanDatas);
117                } catch (Exception e) {
118                    throw new InvalidConfigException("Unable to load gbeans", e);
119                } finally {
120                    Thread.currentThread().setContextClassLoader(oldCl);
121                }
122            }
123            return Collections.EMPTY_LIST;
124        }
125    
126        private static Element storeGBeans(List gbeans) throws IOException {
127            GBeanData[] gbeanDatas = (GBeanData[]) gbeans.toArray(new GBeanData[gbeans.size()]);
128    
129            DocumentBuilderFactory documentBuilderFactory = XmlUtil.newDocumentBuilderFactory();
130            DocumentBuilder documentBuilder = null;
131            try {
132                documentBuilder = documentBuilderFactory.newDocumentBuilder();
133            } catch (ParserConfigurationException e) {
134                throw (IOException)new IOException("Cannot instantiate " + Document.class.getName()).initCause(e);
135            }
136            Document document = documentBuilder.newDocument();
137            DomWriter writer = new DomWriter(document);
138    
139            XStream xstream = XStreamUtil.createXStream();
140            xstream.marshal(gbeanDatas, writer);
141    
142    //        FileWriter w = new FileWriter("target/foo.xml");
143    //        xstream.toXML(gbeanDatas, w);
144    //        w.close();
145    
146            return document.getDocumentElement();
147        }
148    }