1 10 11 package org.nanocontainer.script.groovy; 12 13 import groovy.lang.Closure; 14 import groovy.lang.GroovyObject; 15 import groovy.util.BuilderSupport; 16 17 import java.io.File ; 18 import java.net.MalformedURLException ; 19 import java.net.URL ; 20 import java.security.AccessController ; 21 import java.security.Permission ; 22 import java.security.PrivilegedAction ; 23 import java.util.Collections ; 24 import java.util.HashMap ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 import java.util.Map ; 28 29 import org.codehaus.groovy.runtime.InvokerHelper; 30 import org.nanocontainer.ClassNameKey; 31 import org.nanocontainer.ClassPathElement; 32 import org.nanocontainer.DefaultNanoContainer; 33 import org.nanocontainer.NanoContainer; 34 import org.nanocontainer.script.NanoContainerMarkupException; 35 import org.nanocontainer.script.NodeBuilderDecorationDelegate; 36 import org.nanocontainer.script.NullNodeBuilderDecorationDelegate; 37 import org.picocontainer.ComponentMonitor; 38 import org.picocontainer.MutablePicoContainer; 39 import org.picocontainer.Parameter; 40 import org.picocontainer.PicoContainer; 41 import org.picocontainer.ComponentAdapter; 42 import org.picocontainer.defaults.ComponentAdapterFactory; 43 import org.picocontainer.defaults.ComponentMonitorStrategy; 44 import org.picocontainer.defaults.ConstantParameter; 45 import org.picocontainer.defaults.DefaultComponentAdapterFactory; 46 import org.picocontainer.defaults.DefaultPicoContainer; 47 import org.picocontainer.defaults.DelegatingComponentMonitor; 48 49 70 public class OldGroovyNodeBuilder extends BuilderSupport { 71 72 private static final String NEW_BUILDER = "newBuilder"; 73 private static final String CONTAINER = "container"; 74 private static final String COMPONENT = "component"; 75 private static final String INSTANCE = "instance"; 76 private static final String KEY = "key"; 77 private static final String PARAMETERS = "parameters"; 78 private static final String BEAN = "bean"; 79 private static final String BEAN_CLASS = "beanClass"; 80 private static final String CLASS = "class"; 81 private static final String CLASS_NAME_KEY = "classNameKey"; 82 private static final String CLASSPATH_ELEMENT = "classPathElement"; 83 private static final String CLASSLOADER = "classLoader"; 84 private static final String PATH = "path"; 85 private static final String GRANT = "grant"; 86 private static final String HTTP = "http://"; 87 private static final String PARENT = "parent"; 88 private static final String COMPONENT_ADAPTER_FACTORY = "componentAdapterFactory"; 89 private static final String COMPONENT_MONITOR = "componentMonitor"; 90 private static final String EMPTY = ""; 91 private static final String DO_CALL = "doCall"; 92 93 private final NodeBuilderDecorationDelegate decorationDelegate; 94 95 public OldGroovyNodeBuilder(NodeBuilderDecorationDelegate decorationDelegate) { 96 this.decorationDelegate = decorationDelegate; 97 } 98 99 public OldGroovyNodeBuilder() { 100 this(new NullNodeBuilderDecorationDelegate()); 101 } 102 103 protected void setParent(Object parent, Object child) { 104 } 105 106 protected Object doInvokeMethod(String s, Object name, Object args) { 107 Object answer = super.doInvokeMethod(s, name, args); 109 List list = InvokerHelper.asList(args); 110 if (!list.isEmpty()) { 111 Object o = list.get(list.size() - 1); 112 if (o instanceof Closure) { 113 Closure closure = (Closure) o; 114 closure.setDelegate(answer); 115 } 116 } 117 return answer; 118 } 119 120 protected void setClosureDelegate(Closure closure, Object o) { 121 super.setClosureDelegate(closure, o); 122 } 123 124 protected Object createNode(Object name) { 125 return createNode(name, Collections.EMPTY_MAP); 126 } 127 128 protected Object createNode(Object name, Object value) { 129 Map attributes = new HashMap (); 130 attributes.put(CLASS, value); 131 return createNode(name, attributes); 132 } 133 134 143 protected Object createNode(Object name, Map attributes, Object value) { 144 Object current = getCurrent(); 145 if (current != null && current instanceof GroovyObject) { 146 return createChildBuilder(current, name, attributes); 147 } else if (current == null || current instanceof NanoContainer) { 148 NanoContainer parent = (NanoContainer) current; 149 Object parentAttribute = attributes.get(PARENT); 150 if (parent != null && parentAttribute != null) { 151 throw new NanoContainerMarkupException("You can't explicitly specify a parent in a child element."); 152 } 153 if (parent == null && (parentAttribute instanceof MutablePicoContainer)) { 154 parent = new DefaultNanoContainer((MutablePicoContainer) parentAttribute); 156 } 157 if (parent == null && (parentAttribute instanceof NanoContainer)) { 158 parent = (NanoContainer) parentAttribute; 160 } 161 if (name.equals(CONTAINER)) { 162 return createChildContainer(attributes, parent); 163 } else { 164 try { 165 return createChildOfContainerNode(parent, name, attributes, current); 166 } catch (ClassNotFoundException e) { 167 throw new NanoContainerMarkupException("ClassNotFoundException: " + e.getMessage(), e); 168 } 169 } 170 } else if (current instanceof ClassPathElement) { 171 if (name.equals(GRANT)) { 172 return createGrantPermission(attributes, (ClassPathElement) current); 173 } 174 return EMPTY; 175 } else if (current instanceof ComponentAdapter && name.equals("instance")) { 176 177 181 return decorationDelegate.createNode(name, attributes, current); 182 183 } else { 184 return decorationDelegate.createNode(name, attributes, current); 186 } 187 } 188 189 private Object createChildBuilder(Object current, Object name, Map attributes) { 190 GroovyObject groovyObject = (GroovyObject) current; 191 return groovyObject.invokeMethod(name.toString(), attributes); 192 } 193 194 private Object createGrantPermission(Map attributes, ClassPathElement cpe) { 195 Permission perm = (Permission ) attributes.remove(CLASS); 196 return cpe.grantPermission(perm); 197 198 } 199 200 private Object createChildOfContainerNode(NanoContainer parentContainer, Object name, Map attributes, Object current) throws ClassNotFoundException { 201 if (name.equals(COMPONENT)) { 202 decorationDelegate.rememberComponentKey(attributes); 203 return createComponentNode(attributes, parentContainer, name); 204 } else if (name.equals(BEAN)) { 205 return createBeanNode(attributes, parentContainer.getPico()); 206 } else if (name.equals(CLASSPATH_ELEMENT)) { 207 return createClassPathElementNode(attributes, parentContainer); 208 } else if (name.equals(DO_CALL)) { 209 return null; 211 } else if (name.equals(NEW_BUILDER)) { 212 return createNewBuilderNode(attributes, parentContainer); 213 } else if (name.equals(CLASSLOADER)) { 214 return createComponentClassLoader(parentContainer); 215 } else { 216 return decorationDelegate.createNode(name, attributes, current); 218 } 219 220 } 221 222 private Object createNewBuilderNode(Map attributes, NanoContainer parentContainer) { 223 String builderClass = (String ) attributes.remove(CLASS); 224 NanoContainer factory = new DefaultNanoContainer(); 225 MutablePicoContainer parentPico = parentContainer.getPico(); 226 factory.getPico().registerComponentInstance(MutablePicoContainer.class, parentPico); 227 try { 228 factory.registerComponentImplementation(GroovyObject.class, builderClass); 229 } catch (ClassNotFoundException e) { 230 throw new NanoContainerMarkupException("ClassNotFoundException " + builderClass); 231 } 232 Object componentInstance = factory.getPico().getComponentInstance(GroovyObject.class); 233 return componentInstance; 234 } 235 236 private ClassPathElement createClassPathElementNode(Map attributes, NanoContainer nanoContainer) { 237 238 final String path = (String ) attributes.remove(PATH); 239 URL pathURL = null; 240 try { 241 if (path.toLowerCase().startsWith(HTTP)) { 242 pathURL = new URL (path); 243 } else { 244 Object rVal = AccessController.doPrivileged(new PrivilegedAction () { 245 public Object run() { 246 try { 247 File file = new File (path); 248 if (!file.exists()) { 249 return new NanoContainerMarkupException("classpath '" + path + "' does not exist "); 250 } 251 return file.toURL(); 252 } catch (MalformedURLException e) { 253 return e; 254 } 255 256 } 257 }); 258 if (rVal instanceof MalformedURLException ) { 259 throw (MalformedURLException ) rVal; 260 } 261 if (rVal instanceof NanoContainerMarkupException) { 262 throw (NanoContainerMarkupException) rVal; 263 } 264 pathURL = (URL ) rVal; 265 } 266 } catch (MalformedURLException e) { 267 throw new NanoContainerMarkupException("classpath '" + path + "' malformed ", e); 268 } 269 return nanoContainer.addClassLoaderURL(pathURL); 270 } 271 272 private Object createBeanNode(Map attributes, MutablePicoContainer pico) { 273 Object bean = createBean(attributes); 274 pico.registerComponentInstance(bean); 275 return bean; 276 } 277 278 private Object createComponentNode(Map attributes, NanoContainer nano, Object name) throws ClassNotFoundException { 279 Object key = attributes.remove(KEY); 280 Object cnkey = attributes.remove(CLASS_NAME_KEY); 281 Object classValue = attributes.remove(CLASS); 282 Object instance = attributes.remove(INSTANCE); 283 Object retval = null; 284 List parameters = (List ) attributes.remove(PARAMETERS); 285 286 MutablePicoContainer pico = nano.getPico(); 287 288 if (cnkey != null) { 289 key = new ClassNameKey((String )cnkey); 290 } 291 292 Parameter[] parameterArray = getParameters(parameters); 293 if (classValue instanceof Class ) { 294 Class clazz = (Class ) classValue; 295 key = key == null ? clazz : key; 296 retval = pico.registerComponentImplementation(key, clazz, parameterArray); 297 } else if (classValue instanceof String ) { 298 String className = (String ) classValue; 299 key = key == null ? className : key; 300 retval = nano.registerComponentImplementation(key, className, parameterArray); 301 } else if (instance != null) { 302 key = key == null ? instance.getClass() : key; 303 retval = pico.registerComponentInstance(key, instance); 304 } else { 305 throw new NanoContainerMarkupException("Must specify a class attribute for a component as a class name (string) or Class. Attributes:" + attributes); 306 } 307 308 return retval; 309 } 310 311 protected Object createNode(Object name, Map attributes) { 312 return createNode(name, attributes, null); 313 } 314 315 326 protected NanoContainer createChildContainer(Map attributes, NanoContainer parent) { 327 328 ClassLoader parentClassLoader = null; 329 MutablePicoContainer childContainer = null; 330 if (parent != null) { 331 parentClassLoader = parent.getComponentClassLoader(); 332 if ( isAttribute(attributes, COMPONENT_ADAPTER_FACTORY) ) { 333 ComponentAdapterFactory componentAdapterFactory = createComponentAdapterFactory(attributes); 334 childContainer = new DefaultPicoContainer( 335 decorationDelegate.decorate(componentAdapterFactory, attributes), parent.getPico()); 336 if ( isAttribute(attributes, COMPONENT_MONITOR) ) { 337 changeComponentMonitor(childContainer, createComponentMonitor(attributes)); 338 } 339 parent.getPico().addChildContainer(childContainer); 340 } else if ( isAttribute(attributes, COMPONENT_MONITOR) ) { 341 ComponentAdapterFactory componentAdapterFactory = new DefaultComponentAdapterFactory( 342 createComponentMonitor(attributes)); 343 childContainer = new DefaultPicoContainer( 344 decorationDelegate.decorate(componentAdapterFactory, attributes), parent.getPico()); 345 } else { 346 childContainer = parent.getPico().makeChildContainer(); 347 } 348 } else { 349 parentClassLoader = (ClassLoader ) AccessController.doPrivileged(new PrivilegedAction () { 350 public Object run() { 351 return PicoContainer.class.getClassLoader(); 352 } 353 }); 354 ComponentAdapterFactory componentAdapterFactory = createComponentAdapterFactory(attributes); 355 childContainer = new DefaultPicoContainer( 356 decorationDelegate.decorate(componentAdapterFactory, attributes)); 357 if ( isAttribute(attributes, COMPONENT_MONITOR) ) { 358 changeComponentMonitor(childContainer, createComponentMonitor(attributes)); 359 } 360 } 361 362 MutablePicoContainer decoratedPico = decorationDelegate.decorate(childContainer); 363 if ( isAttribute(attributes, CLASS) ) { 364 Class clazz = (Class ) attributes.get(CLASS); 365 return createNanoContainer(clazz, decoratedPico, parentClassLoader); 366 } else { 367 return new DefaultNanoContainer(parentClassLoader, decoratedPico); 368 } 369 } 370 371 private void changeComponentMonitor(MutablePicoContainer childContainer, ComponentMonitor monitor) { 372 if ( childContainer instanceof ComponentMonitorStrategy ){ 373 ((ComponentMonitorStrategy)childContainer).changeMonitor(monitor); 374 } 375 } 376 377 private NanoContainer createNanoContainer(Class clazz, MutablePicoContainer decoratedPico, ClassLoader parentClassLoader) { 378 DefaultPicoContainer instantiatingContainer = new DefaultPicoContainer(); 379 instantiatingContainer.registerComponentInstance(ClassLoader .class, parentClassLoader); 380 instantiatingContainer.registerComponentInstance(MutablePicoContainer.class, decoratedPico); 381 instantiatingContainer.registerComponentImplementation(NanoContainer.class, clazz); 382 Object componentInstance = instantiatingContainer.getComponentInstance(NanoContainer.class); 383 return (NanoContainer) componentInstance; 384 } 385 386 private boolean isAttribute(Map attributes, String key) { 387 return attributes.containsKey(key) && attributes.get(key) != null; 388 } 389 390 private ComponentAdapterFactory createComponentAdapterFactory(Map attributes) { 391 final ComponentAdapterFactory factory = (ComponentAdapterFactory) attributes.remove(COMPONENT_ADAPTER_FACTORY); 392 if ( factory == null ){ 393 return new DefaultComponentAdapterFactory(); 394 } 395 return factory; 396 } 397 398 private ComponentMonitor createComponentMonitor(Map attributes) { 399 final ComponentMonitor monitor = (ComponentMonitor) attributes.remove(COMPONENT_MONITOR); 400 if ( monitor == null ){ 401 return new DelegatingComponentMonitor(); 402 } 403 return monitor; 404 } 405 406 protected NanoContainer createComponentClassLoader(NanoContainer parent) { 407 return new DefaultNanoContainer(parent.getComponentClassLoader(), parent.getPico()); 408 } 409 410 411 protected Object createBean(Map attributes) { 412 Class type = (Class ) attributes.remove(BEAN_CLASS); 413 if (type == null) { 414 throw new NanoContainerMarkupException("Bean must have a beanClass attribute"); 415 } 416 try { 417 Object bean = type.newInstance(); 418 for (Iterator iter = attributes.entrySet().iterator(); iter.hasNext();) { 420 Map.Entry entry = (Map.Entry ) iter.next(); 421 String name = entry.getKey().toString(); 422 Object value = entry.getValue(); 423 InvokerHelper.setProperty(bean, name, value); 424 } 425 return bean; 426 } catch (IllegalAccessException e) { 427 throw new NanoContainerMarkupException("Failed to create bean of type '" + type + "'. Reason: " + e, e); 428 } catch (InstantiationException e) { 429 throw new NanoContainerMarkupException("Failed to create bean of type " + type + "'. Reason: " + e, e); 430 } 431 } 432 433 private Parameter[] getParameters(List paramsList) { 434 if (paramsList == null) { 435 return null; 436 } 437 int n = paramsList.size(); 438 Parameter[] parameters = new Parameter[n]; 439 for (int i = 0; i < n; ++i) { 440 parameters[i] = toParameter(paramsList.get(i)); 441 } 442 return parameters; 443 } 444 445 private Parameter toParameter(Object obj) { 446 return obj instanceof Parameter ? (Parameter) obj : new ConstantParameter(obj); 447 } 448 449 } 450 | Popular Tags |