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