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.util.Iterator;
020    import java.util.Map;
021    import java.util.Set;
022    import java.util.LinkedHashSet;
023    import java.util.LinkedHashMap;
024    import java.net.URI;
025    
026    import com.thoughtworks.xstream.converters.Converter;
027    import com.thoughtworks.xstream.converters.MarshallingContext;
028    import com.thoughtworks.xstream.converters.UnmarshallingContext;
029    import com.thoughtworks.xstream.converters.ConversionException;
030    import com.thoughtworks.xstream.io.HierarchicalStreamReader;
031    import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
032    import com.thoughtworks.xstream.mapper.Mapper;
033    import org.apache.geronimo.gbean.AbstractName;
034    import org.apache.geronimo.gbean.GBeanData;
035    import org.apache.geronimo.gbean.GBeanInfo;
036    import org.apache.geronimo.gbean.ReferencePatterns;
037    
038    /**
039     * @version $Rev: 476049 $ $Date: 2006-11-16 23:35:17 -0500 (Thu, 16 Nov 2006) $
040     */
041    public class GBeanDataConverter implements Converter {
042        private final Mapper mapper;
043    
044        public GBeanDataConverter(Mapper mapper) {
045            this.mapper = mapper;
046        }
047    
048        public boolean canConvert(Class clazz) {
049            return GBeanData.class.isAssignableFrom(clazz);
050        }
051    
052        public void marshal(Object object, HierarchicalStreamWriter writer, MarshallingContext marshallingContext) {
053            GBeanData gbeanData = (GBeanData) object;
054    
055            // name
056            AbstractName abstractName = gbeanData.getAbstractName();
057            if (abstractName != null) {
058                writer.addAttribute("name", abstractName.toString());
059            }
060    
061            // gbeanInfo
062            GBeanInfo gbeanInfo = gbeanData.getGBeanInfo();
063            String sourceClass = gbeanInfo.getSourceClass();
064            if (sourceClass != null) {
065                writer.addAttribute("sourceClass", sourceClass);
066            } else {
067                writer.startNode("gbean-info");
068                marshallingContext.convertAnother(gbeanInfo);
069                writer.endNode();
070            }
071    
072            // dependencies Set<ReferencePatterns>
073            Set dependencies = gbeanData.getDependencies();
074            for (Iterator iterator = dependencies.iterator(); iterator.hasNext();) {
075                ReferencePatterns referencePatterns = (ReferencePatterns) iterator.next();
076                writer.startNode("dependency");
077                marshallingContext.convertAnother(referencePatterns);
078                writer.endNode();
079            }
080    
081            // attributes Map<String, Object>
082            Map attributes = gbeanData.getAttributes();
083            for (Iterator iterator = attributes.entrySet().iterator(); iterator.hasNext();) {
084                Map.Entry entry = (Map.Entry) iterator.next();
085                String attributeName = (String) entry.getKey();
086                Object attributeValue = entry.getValue();
087                if (attributeValue != null) {
088                    writer.startNode("attribute");
089                    writer.addAttribute("name", attributeName);
090    
091                    writer.startNode(mapper.serializedClass(attributeValue.getClass()));
092                    marshallingContext.convertAnother(attributeValue);
093                    writer.endNode();
094    
095                    writer.endNode();
096                }
097            }
098            // references Map<String, ReferencePatterns>
099            Map references = gbeanData.getReferences();
100            for (Iterator iterator = references.entrySet().iterator(); iterator.hasNext();) {
101                Map.Entry entry = (Map.Entry) iterator.next();
102                String referenceName = (String) entry.getKey();
103                ReferencePatterns referencePatterns = (ReferencePatterns) entry.getValue();
104                writer.startNode("reference");
105                writer.addAttribute("name", referenceName);
106                marshallingContext.convertAnother(referencePatterns);
107                writer.endNode();
108            }
109        }
110    
111        public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext unmarshallingContext) {
112            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
113            if (classLoader == null) {
114                classLoader = this.getClass().getClassLoader();
115            }
116    
117            // name
118            String gbeanName = reader.getAttribute("name");
119            AbstractName abstractName = null;
120            if (gbeanName != null) {
121                abstractName = new AbstractName(URI.create(gbeanName));
122            }
123    
124            // gbeanInfo
125            GBeanInfo gbeanInfo = null;
126            String sourceClass = reader.getAttribute("sourceClass");
127            if (sourceClass != null) {
128                gbeanInfo = GBeanInfo.getGBeanInfo(sourceClass, classLoader);
129            }
130    
131            Set dependencies = new LinkedHashSet();
132            Map attributes = new LinkedHashMap();
133            Map references = new LinkedHashMap();
134            while (reader.hasMoreChildren()) {
135                reader.moveDown();
136    
137                String nodeName = reader.getNodeName();
138                if (nodeName.equals("gbean-info")) {
139                    if (gbeanInfo != null) {
140                        throw new ConversionException("GBean info declared more than once in gbean " + abstractName);
141                    }
142                    gbeanInfo = (GBeanInfo) unmarshallingContext.convertAnother(reader, GBeanInfo.class);
143                } else if (nodeName.equals("dependency")) {
144                    ReferencePatterns referencePatterns = (ReferencePatterns) unmarshallingContext.convertAnother(reader, ReferencePatterns.class);
145                    dependencies.add(referencePatterns);
146                } else if (nodeName.equals("attribute")) {
147                    String attributeName = reader.getAttribute("name");
148    
149                    reader.moveDown();
150                    String classAttribute = reader.getAttribute(mapper.attributeForImplementationClass());
151                    Class type;
152                    if (classAttribute == null) {
153                        type = mapper.realClass(reader.getNodeName());
154                    } else {
155                        type = mapper.realClass(classAttribute);
156                    }
157                    Object attributeValue = unmarshallingContext.convertAnother(reader, type);
158                    reader.moveUp();
159    
160                    attributes.put(attributeName, attributeValue);
161                } else if (nodeName.equals("reference")) {
162                    String referenceName = reader.getAttribute("name");
163                    ReferencePatterns referencePatterns = (ReferencePatterns) unmarshallingContext.convertAnother(reader, ReferencePatterns.class);
164                    references.put(referenceName, referencePatterns);
165                } else {
166                    throw new ConversionException("Unknown nested node in GBean: " + nodeName);
167                }
168    
169                reader.moveUp();
170            }
171    
172            if (gbeanInfo == null) {
173                throw new ConversionException("GBean info not declared in gbean " + abstractName);
174            }
175    
176            GBeanData gbeanData = new GBeanData(abstractName, gbeanInfo);
177            gbeanData.setDependencies(dependencies);
178            for (Iterator iterator = attributes.entrySet().iterator(); iterator.hasNext();) {
179                Map.Entry entry = (Map.Entry) iterator.next();
180                String attributeName = (String) entry.getKey();
181                Object attributeValue = entry.getValue();
182                gbeanData.setAttribute(attributeName, attributeValue);
183            }
184            for (Iterator iterator = references.entrySet().iterator(); iterator.hasNext();) {
185                Map.Entry entry = (Map.Entry) iterator.next();
186                String referenceName = (String) entry.getKey();
187                ReferencePatterns referencePatterns = (ReferencePatterns) entry.getValue();
188                gbeanData.setReferencePatterns(referenceName, referencePatterns);
189            }
190    
191            return gbeanData;
192        }
193    }