001 /**
002 *
003 * Copyright 2005 The Apache Software Foundation
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * 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: 410741 $ $Date: 2006-05-31 21:35:48 -0700 (Wed, 31 May 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 }