Source Code Cross Referenced for RSACBeanLocatorImpl.java in  » Web-Framework » RSF » uk » org » ponder » rsac » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Framework » RSF » uk.org.ponder.rsac 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Created on Sep 18, 2005
003:         */
004:        package uk.org.ponder.rsac;
005:
006:        import java.beans.PropertyChangeEvent;
007:        import java.lang.reflect.Method;
008:        import java.util.HashMap;
009:        import java.util.Iterator;
010:        import java.util.Map;
011:
012:        import org.apache.log4j.Level;
013:        import org.springframework.beans.BeanInstantiationException;
014:        import org.springframework.beans.BeansException;
015:        import org.springframework.beans.TypeMismatchException;
016:        import org.springframework.beans.factory.BeanCurrentlyInCreationException;
017:        import org.springframework.beans.factory.BeanFactoryAware;
018:        import org.springframework.beans.factory.BeanNameAware;
019:        import org.springframework.beans.factory.DisposableBean;
020:        import org.springframework.beans.factory.FactoryBean;
021:        import org.springframework.beans.factory.InitializingBean;
022:        import org.springframework.beans.factory.NoSuchBeanDefinitionException;
023:        import org.springframework.beans.factory.config.BeanDefinition;
024:        import org.springframework.beans.factory.config.BeanPostProcessor;
025:        import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
026:        import org.springframework.context.ApplicationContext;
027:        import org.springframework.context.ApplicationContextAware;
028:        import org.springframework.context.ConfigurableApplicationContext;
029:
030:        import uk.org.ponder.beanutil.BeanUtil;
031:        import uk.org.ponder.beanutil.FallbackBeanLocator;
032:        import uk.org.ponder.beanutil.WriteableBeanLocator;
033:        import uk.org.ponder.reflect.ReflectUtils;
034:        import uk.org.ponder.reflect.ReflectiveCache;
035:        import uk.org.ponder.saxalizer.AccessMethod;
036:        import uk.org.ponder.saxalizer.MethodAnalyser;
037:        import uk.org.ponder.saxalizer.SAXalizerMappingContext;
038:        import uk.org.ponder.springutil.BeanDefinitionSource;
039:        import uk.org.ponder.springutil.TLABPostProcessor;
040:        import uk.org.ponder.stringutil.StringList;
041:        import uk.org.ponder.util.Denumeration;
042:        import uk.org.ponder.util.EnumerationConverter;
043:        import uk.org.ponder.util.Logger;
044:        import uk.org.ponder.util.ObjectFactory;
045:        import uk.org.ponder.util.RunnableInvoker;
046:        import uk.org.ponder.util.UniversalRuntimeException;
047:
048:        /**
049:         * The central class managing the Request Scope Application Context.
050:         * <p>
051:         * The principal method useful to users is <code>getBeanLocator()</code> which
052:         * returns a BeanLocator holding the request context for the current thread. For
053:         * each thread entering an RSAC request, it must call
054:         * <code>startRequest()</code> before acquiring any request beans, and
055:         * <code>endRequest()</code> at the end of its cycle (the latter is most
056:         * important).
057:         * <p>
058:         * In a "pure RSAC" application, the request logic will be defined by the
059:         * getting of a single "root bean" from the BeanLocator, although initial setup
060:         * and any proxies may require additional calls to <code>getBeanLocator()</code>.
061:         * <p>
062:         * This class will be due for some refactoring as soon as the next piece of
063:         * functionality gets added, getting on for 400 lines. Please note that this
064:         * class currently illegally casts BeanDefinitions received from Spring to
065:         * AbstractBeanDefinition, which is a potential dependency weakness. This
066:         * approach is known to work with Spring 1.1.2 through 2.0.
067:         * 
068:         * @author Antranig Basman (antranig@caret.cam.ac.uk)
069:         * 
070:         */
071:
072:        public class RSACBeanLocatorImpl implements  ApplicationContextAware,
073:                BeanDefinitionSource, RSACBeanLocator {
074:
075:            private static CreationMarker BEAN_IN_CREATION_OBJECT = new CreationMarker(
076:                    0);
077:            private static String REQUEST_STARTED_KEY = ".request  started";
078:            private ConfigurableApplicationContext blankcontext;
079:            private ApplicationContext parentcontext;
080:            private SAXalizerMappingContext smc;
081:            private ReflectiveCache reflectivecache;
082:            private TLABPostProcessor tlabpp;
083:
084:            public void setBlankContext(
085:                    ConfigurableApplicationContext blankcontext) {
086:                this .blankcontext = blankcontext;
087:            }
088:
089:            // NB - currently used only for leafparsers, which are currently JVM-static.
090:            public void setMappingContext(SAXalizerMappingContext smc) {
091:                this .smc = smc;
092:            }
093:
094:            public void setApplicationContext(
095:                    ApplicationContext applicationContext) {
096:                parentcontext = applicationContext;
097:            }
098:
099:            public void setReflectiveCache(ReflectiveCache reflectivecache) {
100:                this .reflectivecache = reflectivecache;
101:            }
102:
103:            // private ThreadLocal threadlocal = new ThreadLocal() {
104:            // public Object initialValue() {
105:            // return new PerRequestInfo(RSACBeanLocator.this, lazysources);
106:            // }
107:            // };
108:            // We do not use initialValue here because of bug
109:            // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5025230 which corrupts
110:            // the table when initialising a further ThreadLocal from within
111:            // initialValue().
112:            // in this case the ThreadLocal is created within CGLib while instantiating
113:            // the RSACLazyTargetSource proxies.
114:            private ThreadLocal threadlocal = new ThreadLocal();
115:
116:            private PerRequestInfo getPerRequest() {
117:                PerRequestInfo pri = (PerRequestInfo) threadlocal.get();
118:                if (pri == null) {
119:                    pri = new PerRequestInfo(RSACBeanLocatorImpl.this ,
120:                            lazysources, tlabpp);
121:                    threadlocal.set(pri);
122:                }
123:                return pri;
124:            }
125:
126:            /**
127:             * Starts the request-scope container for the current thread.
128:             */
129:
130:            public void startRequest() {
131:                if (isStarted()) {
132:                    throw UniversalRuntimeException.accumulate(
133:                            new IllegalStateException(),
134:                            "RSAC container has already been started: ");
135:                }
136:                GlobalBeanAccessor.startRequest(parentcontext);
137:                PerRequestInfo pri = getPerRequest();
138:                pri.beans.set(REQUEST_STARTED_KEY, BEAN_IN_CREATION_OBJECT);
139:            }
140:
141:            /**
142:             * Determines whether the container has already been started for the current
143:             * thread.
144:             */
145:
146:            public boolean isStarted() {
147:                PerRequestInfo pri = getPerRequest();
148:                return pri.beans.locateBean(REQUEST_STARTED_KEY) != null;
149:            }
150:
151:            private void assertIsStarted() {
152:                if (!isStarted()) {
153:                    throw UniversalRuntimeException.accumulate(
154:                            new IllegalStateException(),
155:                            "RSAC container has not been started properly: ");
156:                }
157:            }
158:
159:            /**
160:             * Called at the end of a request. I advise doing this in a finally block.
161:             */
162:            public void endRequest() {
163:                assertIsStarted();
164:                PerRequestInfo pri = getPerRequest();
165:                Runnable lazarusList = (Runnable) pri.beans
166:                        .locateBean("RSACLazarusList");
167:                GlobalBeanAccessor.endRequest(); // cannot throw
168:
169:                for (int i = 0; i < pri.todestroy.size(); ++i) {
170:                    String todestroyname = pri.todestroy.stringAt(i);
171:                    RSACBeanInfo destroybean = (RSACBeanInfo) rbimap
172:                            .get(todestroyname);
173:                    Object todestroy = null;
174:                    try {
175:                        todestroy = getBean(pri, todestroyname, false);
176:                        if (todestroy instanceof  DisposableBean) {
177:                            ((DisposableBean) todestroy).destroy();
178:                        } else {
179:                            reflectivecache.invokeMethod(todestroy,
180:                                    destroybean.destroymethod);
181:                        }
182:                    }
183:                    // must try to destroy as many beans as possible, cannot propagate
184:                    // exception in a finally block in any case.
185:                    catch (Throwable e) { // must NOT propagate any exceptions through a finally block
186:                        Logger.log.error("Error destroying bean " + todestroy
187:                                + " with name " + todestroyname, e);
188:                    }
189:                }
190:                // System.out.println(pri.cbeans + " beans were created");
191:                // Give the garbage collector a head start
192:                pri.clear();
193:                if (lazarusList != null) {
194:                    lazarusList.run();
195:                }
196:            }
197:
198:            // this is a map of bean names to RSACBeanInfo
199:            private Map rbimap;
200:            // this is a list of the beans of type RSACLazyTargetSources
201:            private StringList lazysources;
202:            // this is a list of "fallback" beans that have already been queried
203:            private StringList fallbacks;
204:            // this is a map of alias names to "canonical" bean names
205:            private Map aliasMap;
206:
207:            public void init() {
208:                // at this point we actually expect that the "Dead" factory is FULLY
209:                // CREATED. This checks that all dependencies are resolvable (if this
210:                // has not already been checked by the IDE).
211:                String[] beanNames = blankcontext.getBeanDefinitionNames();
212:                ConfigurableListableBeanFactory factory = blankcontext
213:                        .getBeanFactory();
214:                // prepare our list of dependencies.
215:                rbimap = new HashMap();
216:                lazysources = new StringList();
217:                fallbacks = new StringList();
218:                aliasMap = new HashMap();
219:
220:                RBIBeanDefConverter converter = new RBIBeanDefConverter(
221:                        factory, smc);
222:
223:                for (int i = 0; i < beanNames.length; i++) {
224:                    String beanname = beanNames[i];
225:                    BeanDefinition beandef = factory
226:                            .getBeanDefinition(beanname);
227:                    try {
228:                        converter.convertBeanDef(beandef, beanname, false);
229:                    } catch (Exception e) {
230:                        Logger.log.error("Error loading definition for bean "
231:                                + beanname, e);
232:                    }
233:                }
234:                for (int i = 0; i < converter.rbilist.size(); ++i) {
235:                    RSACBeanInfo rbi = (RSACBeanInfo) converter.rbilist.get(i);
236:                    String beanname = rbi.beanname;
237:                    rbimap.put(beanname, rbi);
238:                    for (int j = 0; j < rbi.aliases.length; ++j) {
239:                        aliasMap.put(rbi.aliases[j], beanname);
240:                    }
241:                }
242:
243:                // Make a last-ditch attempt to infer bean types.
244:                for (int i = 0; i < converter.rbilist.size(); ++i) {
245:                    RSACBeanInfo rbi = (RSACBeanInfo) converter.rbilist.get(i);
246:                    String beanname = rbi.beanname;
247:                    if (rbi.beanclass == null) {
248:                        rbi.beanclass = getBeanClass(beanname);
249:                    }
250:                    if (rbi.beanclass != null) {
251:                        if (rbi.islazyinit) {
252:                            lazysources.add(beanname);
253:                        }
254:                        if (FallbackBeanLocator.class
255:                                .isAssignableFrom(rbi.beanclass)
256:                                && !rbi.isabstract) {
257:                            fallbacks.add(beanname);
258:                        }
259:                        rbi.isfactorybean = FactoryBean.class
260:                                .isAssignableFrom(rbi.beanclass);
261:                    }
262:                }
263:                BracketerPopulator.populateBracketers(parentcontext, rbimap);
264:
265:                // we must add this manually because it expects a DIFFERENT applicationContext
266:                // to the real one. Also the lifecycle is somewhat different.
267:                tlabpp = new TLABPostProcessor();
268:                tlabpp.setMappingContext(smc);
269:                tlabpp.setApplicationContext(blankcontext);
270:            }
271:
272:            /**
273:             * Returns a list of bean names which are known to correspond to beans
274:             * implementing or derived from the supplied class. RSAC has tried slightly
275:             * harder to resolve bean classes than Spring generally does, through walking
276:             * chains of factory-methods.
277:             * 
278:             * @param clazz A class or interface class to be searched for.
279:             * @return A list of derived bean names.
280:             */
281:            public String[] beanNamesForClass(Class clazz) {
282:                StringList togo = new StringList();
283:                String[] beanNames = blankcontext.getBeanDefinitionNames();
284:                for (int i = 0; i < beanNames.length; i++) {
285:                    String beanname = beanNames[i];
286:                    RSACBeanInfo rbi = (RSACBeanInfo) rbimap.get(beanname);
287:                    if (rbi.beanclass != null && !rbi.isabstract
288:                            && clazz.isAssignableFrom(rbi.beanclass)) {
289:                        togo.add(beanname);
290:                    }
291:                }
292:                return togo.toStringArray();
293:            }
294:
295:            /**
296:             * Returns the class of this bean, if it can be statically determined,
297:             * <code>null</code> if it cannot (i.e. this bean is the product of a
298:             * factory-method of a class which is not yet known)
299:             * 
300:             * @param beanname
301:             * @return
302:             */
303:            public Class getBeanClass(String beanname) {
304:                RSACBeanInfo rbi = (RSACBeanInfo) rbimap.get(beanname);
305:                if (rbi == null) {
306:                    return parentcontext.getType(beanname);
307:                } else if (rbi.beanclass != null) {
308:                    return rbi.beanclass;
309:                } else if (rbi.factorymethod != null && rbi.factorybean != null) {
310:                    try {
311:                        Class factoryclass = getBeanClass(rbi.factorybean);
312:                        Method m = ReflectiveCache.getMethod(factoryclass,
313:                                rbi.factorymethod);
314:                        if (m != null) {
315:                            rbi.beanclass = m.getReturnType();
316:                        }
317:                    } catch (Exception e) {
318:                        Logger.log
319:                                .info("Error reflecting for factory method "
320:                                        + rbi.factorymethod
321:                                        + " in bean "
322:                                        + rbi.factorybean
323:                                        + " however, it may be present in the concrete bean type");
324:                    }
325:                }
326:                // Noone could possibly say we didn't do our best to work out the type of
327:                // this bean.
328:                return rbi.beanclass;
329:            }
330:
331:            public void addPostProcessor(BeanPostProcessor beanpp) {
332:                getPerRequest().postprocessors.add(beanpp);
333:            }
334:
335:            private String getTransformedBeanName(String beanname) {
336:                String alias = (String) aliasMap.get(beanname);
337:                return alias == null ? beanname : alias;
338:            }
339:
340:            private Object getLocalBean(PerRequestInfo pri, String beanname,
341:                    boolean nolazy) {
342:                beanname = getTransformedBeanName(beanname);
343:                Object bean = pri.beans.locateBean(beanname);
344:                if (bean instanceof  CreationMarker) {
345:                    throw new BeanCurrentlyInCreationException(beanname);
346:                } else if (bean == null) {
347:                    FactoryBean pfb = (FactoryBean) pri.lazysources
348:                            .get(beanname);
349:                    if (pfb != null && !nolazy) {
350:                        try {
351:                            return pfb.getObject();
352:                        } catch (Exception e) {
353:                            throw UniversalRuntimeException.accumulate(e,
354:                                    "Error getting proxied bean");
355:                        }
356:                    } else {
357:                        bean = createBean(pri, beanname,
358:                                BEAN_IN_CREATION_OBJECT);
359:                    }
360:                }
361:                return bean;
362:            }
363:
364:            // package access ensures visibility from RSACLazarusList
365:            Map getSeedMap() {
366:                return getPerRequest().seedbeans;
367:            }
368:
369:            // package access ensures visibility from RSACBeanFactory
370:            Map getRBIMap() {
371:                return rbimap;
372:            }
373:
374:            ConfigurableApplicationContext getBlankContext() {
375:                return blankcontext;
376:            }
377:
378:            // package access ensures visibility from RSACLazyTargetSource
379:            Object getBean(PerRequestInfo pri, String beanname, boolean nolazy) {
380:                Object bean = null;
381:                // NOTES on parentage: We actually WOULD like to make the "blank" context
382:                // a child context of the parent, so that we could resolve parents across
383:                // the gap - the problem is the line below, where we distinguish local beans
384:                // from parent ones. Revisit this when we have a sensible idea about parent
385:                // contexts.
386:                // NB - we check the container since some fiend might have thrown it in
387:                // manually on inchuck - but actually this is faster than Spring anyway.
388:                if (pri.beans.locateBean(beanname) != null
389:                        || rbimap.containsKey(beanname)) {
390:                    bean = getLocalBean(pri, beanname, nolazy);
391:                } else {
392:                    if (bean == null
393:                            && this .parentcontext.containsBean(beanname)) {
394:                        bean = this .parentcontext.getBean(beanname);
395:                    }
396:                }
397:                return bean;
398:            }
399:
400:            /** Return a list of names of beans of type FallbackBeanLocator **/
401:            public StringList getFallbackBeans() {
402:                return fallbacks;
403:            }
404:
405:            private Object assembleVectorProperty(PerRequestInfo pri,
406:                    StringList beannames, Class declaredType) {
407:                Object deliver = ReflectUtils.instantiateContainer(
408:                        declaredType, beannames.size(), reflectivecache);
409:                Denumeration den = EnumerationConverter.getDenumeration(
410:                        deliver, reflectivecache);
411:                for (int i = 0; i < beannames.size(); ++i) {
412:                    String this beanname = beannames.stringAt(i);
413:                    Object bean = getBean(pri, this beanname, false);
414:                    den.add(bean);
415:                }
416:                return deliver;
417:            }
418:
419:            private Object createBean(final PerRequestInfo pri,
420:                    final String beanname, CreationMarker marker) {
421:                boolean success = false;
422:                try {
423:                    RSACBeanInfo rbi = (RSACBeanInfo) rbimap.get(beanname);
424:                    if (rbi == null) {
425:                        throw new NoSuchBeanDefinitionException(beanname,
426:                                "Bean definition not found");
427:                    }
428:                    if (rbi.isabstract) {
429:                        throw new BeanInstantiationException(rbi.beanclass,
430:                                "Abstract bean " + rbi.beanname
431:                                        + " cannot be instantiated");
432:                    }
433:
434:                    if (marker == null) {
435:                        marker = BEAN_IN_CREATION_OBJECT;
436:                        if (rbi.issingleton) {
437:                            pri.beans.set(beanname, marker);
438:                        }
439:                    }
440:
441:                    // implement fetch wrappers in such a way that doesn't slow normal
442:                    // creation.
443:                    if (rbi.fetchwrappers != null
444:                            && marker.wrapperindex < rbi.fetchwrappers.length) {
445:                        Object wrappero = rbi.fetchwrappers[marker.wrapperindex];
446:                        if (marker.wrapperindex == 0) {
447:                            marker = new CreationMarker(1);
448:                            if (rbi.issingleton) {
449:                                pri.beans.set(beanname, marker);
450:                            }
451:                        } else {
452:                            ++marker.wrapperindex;
453:                        }
454:                        RunnableInvoker wrapper = (RunnableInvoker) (wrappero instanceof  RunnableInvoker ? wrappero
455:                                : getBean(pri, (String) wrappero, true));
456:                        final Object[] togo = new Object[1];
457:                        final CreationMarker nextmarker = marker;
458:                        wrapper.invokeRunnable(new Runnable() {
459:                            public void run() {
460:                                togo[0] = createBean(pri, beanname, nextmarker);
461:                            }
462:
463:                        });
464:                        return togo[0];
465:                    }
466:                    if (rbi.issingleton) {
467:                        ++pri.cbeans;
468:                    }
469:
470:                    Object newbean;
471:                    // NB - isn't this odd, and in fact generally undocumented - properties
472:                    // defined for factory-method beans are set on the PRODUCT, whereas those
473:                    // set on FactoryBeans are set on the FACTORY!!
474:                    if (rbi.factorybean != null) {
475:
476:                        Object factorybean = null;
477:                        try {
478:                            factorybean = getBean(pri, rbi.factorybean, false);
479:                        } catch (Exception e) {
480:                            throw UniversalRuntimeException
481:                                    .accumulate(e,
482:                                            "Error fetching factory bean "
483:                                                    + rbi.factorybean
484:                                                    + " to initialise bean "
485:                                                    + beanname);
486:                        }
487:
488:                        try {
489:                            newbean = reflectivecache.invokeMethod(factorybean,
490:                                    rbi.factorymethod);
491:                        } catch (Exception e) {
492:                            throw UniversalRuntimeException.accumulate(e,
493:                                    "Error fetching bean " + beanname
494:                                            + " from factory method "
495:                                            + rbi.factorymethod
496:                                            + " of factory bean "
497:                                            + rbi.factorybean);
498:                        }
499:                        if (newbean == null) {
500:                            throw new IllegalArgumentException(
501:                                    "Error: null returned from factory method "
502:                                            + rbi.factorymethod + " of bean "
503:                                            + rbi.factorybean);
504:                        }
505:                        // rbi.beanclass = newbean.getClass();
506:                    } else {
507:                        // Locate the "dead" bean from the genuine Spring context, and clone it
508:                        // as quick as we can - bytecodes might do faster but in the meantime
509:                        // observe that a clone typically costs 1.6 reflective calls so in
510:                        // general this method will win over a reflective solution.
511:                        // NB - all Copiables simply copy dependencies manually for now, no
512:                        // cost.
513:                        // Copiable deadbean = (Copiable) livecontext.getBean(rbi.isfactorybean?
514:                        // "&" +beanname : beanname);
515:                        // All the same, the following line will cost us close to 1us - unless
516:                        // it invokes manual code!
517:                        if (rbi.constructorargvals == null) {
518:                            newbean = reflectivecache.construct(rbi.beanclass);
519:                        } else {
520:                            newbean = null;
521:                        }
522:                    }
523:                    if (rbi.hasDependencies()) {
524:                        // guard this block since if it is a factory-method bean it may be
525:                        // something
526:                        // extremely undesirable (like an inner class) that we should not even
527:                        // dream of reflecting over. If on the other hand the user has specified
528:                        // some dependencies they doubtless know what they are doing.
529:                        MethodAnalyser ma = smc.getAnalyser(newbean.getClass());
530:                        // Object clonebean = deadbean.copy();
531:                        // iterate over each LOCAL dependency of the bean with given name.
532:                        for (Iterator depit = rbi.dependencies(); depit
533:                                .hasNext();) {
534:                            String propertyname = (String) depit.next();
535:
536:                            try {
537:                                AccessMethod setter = ma
538:                                        .getAccessMethod(propertyname);
539:                                if (setter == null) {
540:                                    throw new IllegalArgumentException(
541:                                            newbean.getClass()
542:                                                    + " has no writeable property named "
543:                                                    + propertyname);
544:                                }
545:                                Object beanref = rbi.beanref(propertyname);
546:                                Class targetclazz = setter.getAccessedType();
547:                                Object depbean = resolveDependent(beanref, pri,
548:                                        targetclazz, setter.getDeclaredType());
549:
550:                                // Lose another 500ns here, until we bring on FastClass.
551:                                setter.setChildObject(newbean, depbean);
552:                            } catch (Exception e) {
553:                                throw UniversalRuntimeException.accumulate(e,
554:                                        "Error setting dependency "
555:                                                + propertyname + " of bean "
556:                                                + beanname);
557:                            }
558:                        }
559:                    }
560:                    if (rbi.dependson != null) {
561:                        for (int i = 0; i < rbi.dependson.length; ++i) {
562:                            getBean(pri, rbi.dependson[i], false);
563:                        }
564:                    }
565:                    // process it FIRST since it will be the factory that is expecting the
566:                    // dependencies set!
567:                    newbean = processNewBean(pri, beanname, newbean);
568:                    // now the bean is initialised, attempt to call any init-method or
569:                    // InitBean.
570:                    if (rbi.initmethod != null) {
571:                        try {
572:                            reflectivecache.invokeMethod(newbean,
573:                                    rbi.initmethod);
574:                        } catch (Exception e) {
575:                            throw UniversalRuntimeException.accumulate(e,
576:                                    "Error invoking init method "
577:                                            + rbi.initmethod + " on bean "
578:                                            + beanname);
579:                        }
580:                    }
581:                    if (newbean instanceof  InitializingBean) {
582:                        try {
583:                            ((InitializingBean) newbean).afterPropertiesSet();
584:                        } catch (Exception e) {
585:                            throw UniversalRuntimeException.accumulate(e);
586:                        }
587:                    }
588:                    if (rbi.destroymethod != null
589:                            || (newbean instanceof  DisposableBean)) {
590:                        pri.todestroy.add(beanname);
591:                    }
592:
593:                    if (newbean instanceof  FactoryBean) {
594:                        FactoryBean factorybean = (FactoryBean) newbean;
595:                        try {
596:                            newbean = factorybean.getObject();
597:                        } catch (Exception e) {
598:                            throw UniversalRuntimeException.accumulate(e);
599:                        }
600:                    }
601:                    // enter the bean into the req-specific map.
602:                    if (rbi.issingleton) {
603:                        pri.beans.set(beanname, newbean);
604:                    }
605:                    success = true;
606:                    return newbean;
607:                } finally {
608:                    if (marker.wrapperindex > 0) {
609:                        --marker.wrapperindex;
610:                        if (marker.wrapperindex == 0 && !success) {
611:                            pri.beans.remove(beanname);
612:                        }
613:                    }
614:                }
615:
616:            }
617:
618:            private Object resolveDependent(Object beanref, PerRequestInfo pri,
619:                    Class accessedType, Class declaredType) {
620:                Object depbean = null;
621:                if (beanref instanceof  String) {
622:                    String depbeanname = (String) beanref;
623:                    depbean = fetchDependent(pri, depbeanname, accessedType);
624:                    BeanUtil.censorNullBean(depbeanname, depbean);
625:                } else if (beanref instanceof  ValueHolder) {
626:                    String value = ((ValueHolder) beanref).value;
627:                    if (smc.saxleafparser.isLeafType(accessedType)) {
628:                        depbean = smc.saxleafparser.parse(accessedType, value);
629:                    } else {
630:                        // exception def copied from the beast BeanWrapperImpl!
631:                        throw new TypeMismatchException(
632:                                new PropertyChangeEvent(
633:                                //newbean, propertyname,
634:                                        null, null, null, value), accessedType,
635:                                null);
636:                    }
637:                } else {
638:                    // Really need generalised conversion of vector values here.
639:                    // The code to do this is actually WITHIN the grotty
640:                    // BeanWrapperImpl
641:                    // itself in a protected method with 5 arguments!!
642:                    // This is a sort of 50% solution. It will deal with all 1-d array
643:                    // types and collections, and values of parseable types.
644:                    depbean = assembleVectorProperty(pri, (StringList) beanref,
645:                            declaredType);
646:                }
647:                return depbean;
648:            }
649:
650:            private Object fetchDependent(final PerRequestInfo pri,
651:                    final String beanname, Class targetclazz) {
652:
653:                if (ObjectFactory.class.isAssignableFrom(targetclazz)) {
654:                    return new ObjectFactory() {
655:                        public Object getObject() {
656:                            return getBean(pri, beanname, false);
657:                        }
658:                    };
659:                } else if (org.springframework.beans.factory.ObjectFactory.class
660:                        .isAssignableFrom(targetclazz)) {
661:                    return new org.springframework.beans.factory.ObjectFactory() {
662:                        public Object getObject() throws BeansException {
663:                            return getBean(pri, beanname, false);
664:                        }
665:                    };
666:                } else
667:                    return getBean(pri, beanname, false);
668:            }
669:
670:            private Object processNewBean(PerRequestInfo pri, String beanname,
671:                    Object newbean) {
672:                pri.tlabpp.postProcessBeforeInitialization(newbean, beanname);
673:                for (int i = 0; i < pri.postprocessors.size(); ++i) {
674:                    BeanPostProcessor beanpp = (BeanPostProcessor) pri.postprocessors
675:                            .get(i);
676:                    try {
677:                        newbean = beanpp.postProcessBeforeInitialization(
678:                                newbean, beanname);
679:                        // TODO: Timing of this next line is incorrect - should occur after
680:                        // initialisation in caller.
681:                        // beanpp.postProcessAfterInitialization(newbean, beanname);
682:                    } catch (Exception e) {
683:                        Logger.log.log(Level.ERROR,
684:                                "Exception processing bean "
685:                                        + newbean.getClass().getName(), e);
686:                    }
687:                }
688:                if (newbean instanceof  BeanFactoryAware) {
689:                    ((BeanFactoryAware) newbean).setBeanFactory(pri.blfactory);
690:                }
691:                if (newbean instanceof  BeanNameAware) {
692:                    ((BeanNameAware) newbean).setBeanName(beanname);
693:                }
694:                if (newbean instanceof  ApplicationContextAware) {
695:                    ((ApplicationContextAware) newbean)
696:                            .setApplicationContext(parentcontext);
697:                }
698:                return newbean;
699:            }
700:
701:            /**
702:             * This method gets a BeanLocator which is good just for the current request
703:             * scope. The ThreadLocal barrier has already been breached in the returned
704:             * object, and evaluation will proceed quickly.
705:             */
706:            public WriteableBeanLocator getBeanLocator() {
707:                assertIsStarted();
708:                PerRequestInfo pri = getPerRequest();
709:                return pri.requestwbl;
710:            }
711:
712:            /**
713:             * Scope of this BeanLocator is the same as previous, but it will NOT
714:             * auto-create beans that are not present.
715:             */
716:            public WriteableBeanLocator getDeadBeanLocator() {
717:                assertIsStarted();
718:                PerRequestInfo pri = getPerRequest();
719:                return pri.beans;
720:            }
721:
722:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.