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 }