1 10 11 package org.nanocontainer.script.xml; 12 13 import java.io.IOException ; 14 import java.io.Reader ; 15 import java.net.URL ; 16 import java.util.ArrayList ; 17 import java.util.List ; 18 19 import javax.xml.parsers.DocumentBuilderFactory ; 20 import javax.xml.parsers.ParserConfigurationException ; 21 22 import org.nanocontainer.DefaultNanoContainer; 23 import org.nanocontainer.NanoContainer; 24 import org.nanocontainer.integrationkit.ContainerPopulator; 25 import org.nanocontainer.script.NanoContainerMarkupException; 26 import org.nanocontainer.script.ScriptedContainerBuilder; 27 import org.picocontainer.ComponentAdapter; 28 import org.picocontainer.MutablePicoContainer; 29 import org.picocontainer.Parameter; 30 import org.picocontainer.PicoContainer; 31 import org.picocontainer.defaults.ComponentAdapterFactory; 32 import org.picocontainer.defaults.ComponentParameter; 33 import org.picocontainer.defaults.ConstantParameter; 34 import org.picocontainer.defaults.DefaultComponentAdapterFactory; 35 import org.picocontainer.defaults.DefaultPicoContainer; 36 import org.w3c.dom.Document ; 37 import org.w3c.dom.Element ; 38 import org.w3c.dom.Node ; 39 import org.w3c.dom.NodeList ; 40 import org.xml.sax.InputSource ; 41 import org.xml.sax.SAXException ; 42 43 import com.thoughtworks.xstream.XStream; 44 import com.thoughtworks.xstream.io.HierarchicalStreamDriver; 45 import com.thoughtworks.xstream.io.xml.DomDriver; 46 import com.thoughtworks.xstream.io.xml.DomReader; 47 48 54 public class XStreamContainerBuilder extends ScriptedContainerBuilder implements ContainerPopulator { 55 private final Element rootElement; 56 57 private final static String IMPLEMENTATION = "implementation"; 58 private final static String INSTANCE = "instance"; 59 private final static String ADAPTER = "adapter"; 60 private final static String CLASS = "class"; 61 private final static String KEY = "key"; 62 private final static String CONSTANT = "constant"; 63 private final static String DEPENDENCY = "dependency"; 64 private final static String CONSTRUCTOR = "constructor"; 65 66 private final HierarchicalStreamDriver xsdriver; 67 68 71 public XStreamContainerBuilder(Reader script) { 72 this(script,Thread.currentThread().getContextClassLoader()); 73 } 74 75 78 public XStreamContainerBuilder(Reader script, ClassLoader classLoader) { 79 this(script, classLoader, new DomDriver()); 80 } 81 82 public XStreamContainerBuilder(Reader script, ClassLoader classLoader, HierarchicalStreamDriver driver) { 83 super(script, classLoader); 84 xsdriver = driver; 85 InputSource inputSource = new InputSource (script); 86 try { 87 rootElement = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputSource).getDocumentElement(); 88 } catch (SAXException e) { 89 throw new NanoContainerMarkupException(e); 90 } catch (IOException e) { 91 throw new NanoContainerMarkupException(e); 92 } catch (ParserConfigurationException e) { 93 throw new NanoContainerMarkupException(e); 94 } 95 } 96 97 public XStreamContainerBuilder(URL script, ClassLoader classLoader, HierarchicalStreamDriver driver) { 98 super(script, classLoader); 99 xsdriver = driver; 100 try { 101 InputSource inputSource = new InputSource (getScriptReader()); 102 rootElement = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputSource).getDocumentElement(); 103 } catch (SAXException e) { 104 throw new NanoContainerMarkupException(e); 105 } catch (IOException e) { 106 throw new NanoContainerMarkupException(e); 107 } catch (ParserConfigurationException e) { 108 throw new NanoContainerMarkupException(e); 109 } 110 } 111 112 public void populateContainer(MutablePicoContainer container) { 113 populateContainer(container, rootElement); 114 } 115 116 120 private void populateContainer(MutablePicoContainer container, Element rootElement) { 121 NodeList children = rootElement.getChildNodes(); 122 Node child; 123 String name; 124 short type; 125 for (int i = 0; i < children.getLength(); i++) { 126 child = children.item(i); 127 type = child.getNodeType(); 128 129 if (type == Document.ELEMENT_NODE) { 130 name = child.getNodeName(); 131 if (IMPLEMENTATION.equals(name)) { 132 try { 133 insertImplementation(container, (Element ) child); 134 } catch (ClassNotFoundException e) { 135 throw new NanoContainerMarkupException(e); 136 } 137 } else if (INSTANCE.equals(name)) { 138 insertInstance(container, (Element ) child); 139 } else if (ADAPTER.equals(name)) { 140 insertAdapter(container, (Element ) child); 141 } else { 142 throw new NanoContainerMarkupException("Unsupported element:" + name); 143 } 144 } 145 } 146 147 } 148 149 152 protected void insertAdapter(MutablePicoContainer container, Element rootElement) { 153 String key = rootElement.getAttribute(KEY); 154 String klass = rootElement.getAttribute(CLASS); 155 try { 156 DefaultPicoContainer nested = new DefaultPicoContainer(); 157 populateContainer(nested, rootElement); 158 159 if (key != null) { 160 container.registerComponent((ComponentAdapter) nested.getComponentInstance(key)); 161 } else if (klass != null) { 162 Class clazz = getClassLoader().loadClass(klass); 163 container.registerComponent((ComponentAdapter) nested.getComponentInstanceOfType(clazz)); 164 } else { 165 container.registerComponent((ComponentAdapter) nested.getComponentInstanceOfType(ComponentAdapter.class)); 166 } 167 } catch (ClassNotFoundException ex) { 168 throw new NanoContainerMarkupException(ex); 169 } 170 171 } 172 173 176 protected void insertImplementation(MutablePicoContainer container, Element rootElement) throws ClassNotFoundException { 177 String key = rootElement.getAttribute(KEY); 178 String klass = rootElement.getAttribute(CLASS); 179 String constructor = rootElement.getAttribute(CONSTRUCTOR); 180 if (klass == null || "".equals(klass)) { 181 throw new NanoContainerMarkupException("class specification is required for component implementation"); 182 } 183 184 Class clazz = getClassLoader().loadClass(klass); 185 186 List parameters = new ArrayList (); 187 188 NodeList children = rootElement.getChildNodes(); 189 Node child; 190 String name; 191 String dependencyKey; 192 String dependencyClass; 193 Object parseResult; 194 195 for (int i = 0; i < children.getLength(); i++) { 196 child = children.item(i); 197 if (child.getNodeType() == Document.ELEMENT_NODE) { 198 name = child.getNodeName(); 199 if (CONSTANT.equals(name)) { 201 parseResult = parseElementChild((Element ) child); 203 if (parseResult == null) { 204 throw new NanoContainerMarkupException("could not parse constant parameter"); 205 } 206 parameters.add(new ConstantParameter(parseResult)); 207 } else if (DEPENDENCY.equals(name)) { 208 dependencyKey = ((Element ) child).getAttribute(KEY); 211 if (dependencyKey == null || "".equals(dependencyKey)) { 212 dependencyClass = ((Element ) child).getAttribute(CLASS); 213 if (dependencyClass == null || "".equals(dependencyClass)) { 214 throw new NanoContainerMarkupException("either key or class must be present for dependency"); 215 } else { 216 parameters.add(new ComponentParameter(getClassLoader().loadClass(dependencyClass))); 217 } 218 } else { 219 parameters.add(new ComponentParameter(dependencyKey)); 220 } 221 } 222 } 223 } 224 225 Parameter[] parameterArray = (Parameter[]) parameters.toArray(new Parameter[parameters.size()]); 227 if (parameters.size() > 0 || "default".equals(constructor)) { 228 if (key == null || "".equals(key)) { 229 container.registerComponentImplementation(clazz, clazz, parameterArray); 231 } else { 232 container.registerComponentImplementation(key, clazz, parameterArray); 234 } 235 } else { 236 if (key == null || "".equals(key)) { 237 container.registerComponentImplementation(clazz, clazz); 239 } else { 240 container.registerComponentImplementation(key, clazz); 242 } 243 244 } 245 } 246 247 251 protected void insertInstance(MutablePicoContainer container, Element rootElement) { 252 String key = rootElement.getAttribute(KEY); 253 Object result = parseElementChild(rootElement); 254 if (result == null) { 255 throw new NanoContainerMarkupException("no content could be parsed in instance"); 256 } 257 if (key != null && !"".equals(key)) { 258 container.registerComponentInstance(key, result); 260 } else { 261 container.registerComponentInstance(result); 263 } 264 } 265 266 269 protected Object parseElementChild(Element rootElement) { 270 NodeList children = rootElement.getChildNodes(); 271 Node child; 272 for (int i = 0; i < children.getLength(); i++) { 273 child = children.item(i); 274 if (child.getNodeType() == Document.ELEMENT_NODE) { 275 return (new XStream(xsdriver)).unmarshal(new DomReader((Element ) child)); 276 } 277 } 278 return null; 279 } 280 281 protected PicoContainer createContainerFromScript(PicoContainer parentContainer, Object assemblyScope) { 282 try { 283 String cafName = rootElement.getAttribute("componentadapterfactory"); 284 if ("".equals(cafName) || cafName == null) { 285 cafName = DefaultComponentAdapterFactory.class.getName(); 286 } 287 Class cafClass = getClassLoader().loadClass(cafName); 288 ComponentAdapterFactory componentAdapterFactory = (ComponentAdapterFactory) cafClass.newInstance(); 289 MutablePicoContainer picoContainer = new DefaultPicoContainer(componentAdapterFactory); 290 NanoContainer nano = new DefaultNanoContainer(getClassLoader(), picoContainer); 291 populateContainer(nano.getPico()); 292 return nano.getPico(); 293 } catch (ClassNotFoundException e) { 294 throw new NanoContainerMarkupException(e); 295 } catch (InstantiationException e) { 296 throw new NanoContainerMarkupException(e); 297 } catch (IllegalAccessException e) { 298 throw new NanoContainerMarkupException(e); 299 } 300 } 301 } 302 | Popular Tags |