Source Code Cross Referenced for BlockingRepository.java in  » Web-Framework » rife-1.6.1 » com » uwyn » rife » rep » 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 » rife 1.6.1 » com.uwyn.rife.rep 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
003:         * Distributed under the terms of either:
004:         * - the common development and distribution license (CDDL), v1.0; or
005:         * - the GNU Lesser General Public License, v2.1 or later
006:         * $Id: BlockingRepository.java 3634 2007-01-08 21:42:24Z gbevin $
007:         */
008:        package com.uwyn.rife.rep;
009:
010:        import com.uwyn.rife.ioc.HierarchicalProperties;
011:        import com.uwyn.rife.rep.exceptions.BlockingParticipantExpectedException;
012:        import com.uwyn.rife.rep.exceptions.InitializationErrorException;
013:        import com.uwyn.rife.rep.exceptions.RepException;
014:        import com.uwyn.rife.resources.ResourceFinder;
015:        import com.uwyn.rife.resources.ResourceFinderClasspath;
016:        import com.uwyn.rife.tools.ExceptionUtils;
017:        import com.uwyn.rife.xml.exceptions.XmlErrorException;
018:        import java.util.ArrayList;
019:        import java.util.Collection;
020:        import java.util.HashMap;
021:        import java.util.HashSet;
022:        import java.util.logging.Logger;
023:
024:        /**
025:         * The <code>BlockingRepository</code> class provides a
026:         * <code>Repository</code> implementation that loads the participants from an
027:         * XML file.
028:         * <p>This file defaults to <code>rep/participants.xml</code>, but it can be
029:         * overridden by providing another filename to the <code>{@link
030:         * #initialize(String, ResourceFinder) initialize}</code> method. The
031:         * participants are initialized according to their listed order.
032:         * <p>Following is an example of such an XML file :
033:         * <pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
034:         *&lt;!DOCTYPE rep SYSTEM "/dtd/rep.dtd"&gt;
035:         *&lt;rep&gt;
036:         *&lt;participant blocking="true" parameter="rep/config.xml"&gt;ParticipantConfig&lt;/participant&gt;
037:         *&lt;participant blocking="false" parameter="graphics/buttons/"&gt;ParticipantImages&lt;/participant&gt;
038:         *&lt;participant name="my cursors" blocking="false" parameter="graphics/cursors/"&gt;ParticipantCursors&lt;/participant&gt;
039:         *&lt;/rep&gt;</pre>
040:         * <p>Each participant has a <code>blocking</code> attribute that determines
041:         * whether the repository should wait for the end of the participant's
042:         * initialization before progressing to the next participant or not. Using
043:         * this intelligently, it's possible to dramatically increase the perceived
044:         * startup time of an application.
045:         * <p>Optionally a participant can have a <code>name</code> attribute which
046:         * makes it possible to declare multiple participants of the same class. If no
047:         * name is provided, the participant's class name will be used to identify the
048:         * declared participant.
049:         * <p>Optionally a participant can also have a <code>parameter</code>
050:         * attribute which is merely a <code>String</code> that is provided to the
051:         * participant object for configuration purposes.
052:         * <p>Listeners can be added to the repository to receive notifications about
053:         * the initialization advancement of the participants and to know when the
054:         * initialization has completely finished. These notifications can, for
055:         * example, be used to display a progress bar in a splash window and to switch
056:         * to the real application window when the initialization has finished.
057:         * <p>The JDK's logging facility is used to output informative text during the
058:         * advancement of the initialization. Each participant has to provide an
059:         * initialization message that will be output.
060:         *
061:         * @author Geert Bevin (gbevin[remove] at uwyn dot com)
062:         * @version $Revision: 3634 $
063:         * @see RepositoryListener
064:         * @see BlockingParticipant
065:         * @since 1.0
066:         */
067:        public class BlockingRepository extends ThreadGroup implements 
068:                Repository {
069:            /**
070:             * The default path of the repository participant XML file is
071:             * <code>rep/participants.xml</code>. It can be overridden by setting the
072:             * <code>rep.path</code> system property.
073:             */
074:            private static final String DEFAULT_REP_PATH = "rep/participants.xml";
075:
076:            /**
077:             * A map of the registered participants, indexed according to their name.
078:             */
079:            private HashMap<String, BlockingParticipant> mRepParticipants = new HashMap<String, BlockingParticipant>();
080:            /**
081:             * A map of the registered participants class name with all the registered
082:             * participants.
083:             */
084:            private HashMap<String, ArrayList<BlockingParticipant>> mRepParticipantClassnames = new HashMap<String, ArrayList<BlockingParticipant>>();
085:            /**
086:             * A list of the participant names, ordered according to their
087:             * registration moment. This will be used as the order of execution.
088:             */
089:            private ArrayList<String> mRepParticipantsOrder = new ArrayList<String>();
090:            /**
091:             * The list of participant names that will be use to determine which
092:             * participant's initialization end the repository has to wait for.
093:             */
094:            private ArrayList<String> mRepParticipantsToWaitFor = new ArrayList<String>();
095:            /**
096:             * The list of all registered <code>RepListener</code> objects.
097:             */
098:            private HashSet<RepositoryListener> mRepListeners = new HashSet<RepositoryListener>();
099:            /**
100:             * Indicates whether the initialization is finished.
101:             */
102:            private boolean mFinished = false;
103:            /**
104:             * Object that is used for thread synchronization of the finish.
105:             */
106:            private final Object mFinishedThreadMonitor = new Object();
107:            /**
108:             * Indicates whether the repository has been cleaned up.
109:             */
110:            private boolean mCleanedUp = false;
111:            /**
112:             * Contains a handle to the registered shutdown hook.
113:             */
114:            private BlockingRepositoryCleanup mCleanupShutdownHook = null;
115:            /**
116:             * Object that is used for thread synchronization of the cleanup.
117:             */
118:            private final Object mCleanupThreadMonitor = new Object();
119:            /**
120:             * Exception that is thrown by a participant.
121:             */
122:            private Throwable mParticipantException = null;
123:            /**
124:             * The repository's properties.
125:             */
126:            private HierarchicalProperties mProperties;
127:            /**
128:             * The repository's context.
129:             */
130:            private Object mContext;
131:
132:            /**
133:             * Default constructor without a repository context.
134:             */
135:            public BlockingRepository() {
136:                this (null);
137:            }
138:
139:            /**
140:             * Constructor which sets up a the context in which the repository is initialized.
141:             */
142:            public BlockingRepository(Object context) {
143:                super ("BlockingRepository");
144:
145:                HierarchicalProperties system_properties = new HierarchicalProperties()
146:                        .putAll(System.getProperties());
147:                mProperties = new HierarchicalProperties()
148:                        .parent(system_properties);
149:                mContext = context;
150:            }
151:
152:            /**
153:             * Adds a <code>BlockingParticipant</code> to the repository, using the
154:             * class name for the name of the participant.
155:             * <p>The participant will not be blocking and have no parameter.
156:             *
157:             * @param className The fully resolved name of the participant's class, or
158:             * only the class name if the participant resides in the
159:             * <code>com.uwyn.rife.rep.participants</code> package.
160:             * @return <code>true</code> if the participants was added successfully;
161:             * or
162:             * <p><code>false</code> if errors occurred
163:             * @see BlockingParticipant
164:             * @see Participant
165:             * @see #addParticipant(Class, String, boolean, String)
166:             * @since 1.5
167:             */
168:            public boolean addParticipant(String className) throws RepException {
169:                return addParticipant(className, null, false, null);
170:            }
171:
172:            /**
173:             * Adds a <code>BlockingParticipant</code> to the repository, using the
174:             * class name for the name of the participant.
175:             * <p>The participant will have no parameter.
176:             *
177:             * @param className The fully resolved name of the participant's class, or
178:             * only the class name if the participant resides in the
179:             * <code>com.uwyn.rife.rep.participants</code> package.
180:             * @param blocking Indicates if this a blocking participant or not.
181:             * @return <code>true</code> if the participants was added successfully;
182:             * or
183:             * <p><code>false</code> if errors occurred
184:             * @see BlockingParticipant
185:             * @see Participant
186:             * @see #addParticipant(Class, String, boolean, String)
187:             * @since 1.5
188:             */
189:            public boolean addParticipant(String className, boolean blocking)
190:                    throws RepException {
191:                return addParticipant(className, null, blocking, null);
192:            }
193:
194:            /**
195:             * Adds a <code>BlockingParticipant</code> to the repository, using the
196:             * class name for the name of the participant.
197:             * <p>The participant will not be blocking.
198:             *
199:             * @param className The fully resolved name of the participant's class, or
200:             * only the class name if the participant resides in the
201:             * <code>com.uwyn.rife.rep.participants</code> package.
202:             * @param parameter An optional string that contains the parameter for
203:             * this participant.
204:             * @return <code>true</code> if the participants was added successfully;
205:             * or
206:             * <p><code>false</code> if errors occurred
207:             * @see BlockingParticipant
208:             * @see Participant
209:             * @see #addParticipant(Class, String, boolean, String)
210:             * @since 1.5
211:             */
212:            public boolean addParticipant(String className, String parameter)
213:                    throws RepException {
214:                return addParticipant(className, null, false, parameter);
215:            }
216:
217:            /**
218:             * Adds a <code>BlockingParticipant</code> to the repository, using the
219:             * class name for the name of the participant.
220:             *
221:             * @param className The fully resolved name of the participant's class, or
222:             * only the class name if the participant resides in the
223:             * <code>com.uwyn.rife.rep.participants</code> package.
224:             * @param blocking Indicates if this a blocking participant or not.
225:             * @param parameter An optional string that contains the parameter for
226:             * this participant.
227:             * @return <code>true</code> if the participants was added successfully;
228:             * or
229:             * <p><code>false</code> if errors occurred
230:             * @see BlockingParticipant
231:             * @see Participant
232:             * @see #addParticipant(Class, String, boolean, String)
233:             * @since 1.5
234:             */
235:            public boolean addParticipant(String className, boolean blocking,
236:                    String parameter) throws RepException {
237:                return addParticipant(className, null, blocking, parameter);
238:            }
239:
240:            /**
241:             * Adds a <code>BlockingParticipant</code> to the repository.
242:             *
243:             * @param className The fully resolved name of the participant's class, or
244:             * only the class name if the participant resides in the
245:             * <code>com.uwyn.rife.rep.participants</code> package.
246:             * @param name The name under which the participant will be registered, if
247:             * the name is <code>null</code> the class name will be used
248:             * @param blocking Indicates if this a blocking participant or not.
249:             * @param parameter An optional string that contains the parameter for
250:             * this participant.
251:             * @return <code>true</code> if the participants was added successfully;
252:             * or
253:             * <p><code>false</code> if errors occurred
254:             * @see BlockingParticipant
255:             * @see Participant
256:             * @see #addParticipant(Class, String, boolean, String)
257:             * @since 1.0
258:             */
259:            public boolean addParticipant(String className, String name,
260:                    boolean blocking, String parameter) throws RepException {
261:                // Try to resolve the participant's classname to ensure that an
262:                // object can be instantiated.
263:                Class klass = null;
264:                try {
265:                    klass = Class.forName(className);
266:                } catch (ClassNotFoundException e1) {
267:                    className = "com.uwyn.rife.rep.participants." + className;
268:                    try {
269:                        klass = Class.forName(className);
270:                    } catch (ClassNotFoundException e2) {
271:                        return false;
272:                    }
273:                }
274:
275:                return addParticipant(klass, name, blocking, parameter);
276:            }
277:
278:            /**
279:             * Adds a <code>BlockingParticipant</code> to the repository, using the
280:             * class name as the name of the participant.
281:             *
282:             * @param klass The class of the participant.
283:             * @param blocking Indicates if this a blocking participant or not.
284:             * @param parameter An optional string that contains the parameter for
285:             * this participant.
286:             * @return <code>true</code> if the participants was added successfully;
287:             * or
288:             * <p><code>false</code> if errors occurred
289:             * @see BlockingParticipant
290:             * @see Participant
291:             * @see #addParticipant(Class, String, boolean, String)
292:             * @since 1.5
293:             */
294:            public boolean addParticipant(Class klass, boolean blocking,
295:                    String parameter) throws RepException {
296:                return addParticipant(klass, null, blocking, parameter);
297:            }
298:
299:            /**
300:             * Adds a <code>BlockingParticipant</code> to the repository, using the
301:             * class name as the name of the participant.
302:             * <p>The participant will not be blocking and have no parameter.
303:             *
304:             * @param klass The class of the participant.
305:             * this participant.
306:             * @return <code>true</code> if the participants was added successfully;
307:             * or
308:             * <p><code>false</code> if errors occurred
309:             * @see BlockingParticipant
310:             * @see Participant
311:             * @see #addParticipant(Class, String, boolean, String)
312:             * @since 1.5
313:             */
314:            public boolean addParticipant(Class klass) throws RepException {
315:                return addParticipant(klass, null, false, null);
316:            }
317:
318:            /**
319:             * Adds a <code>BlockingParticipant</code> to the repository, using the
320:             * class name as the name of the participant.
321:             * <p>The participant will have no parameter.
322:             *
323:             * @param klass The class of the participant.
324:             * @param blocking Indicates if this a blocking participant or not.
325:             * @return <code>true</code> if the participants was added successfully;
326:             * or
327:             * <p><code>false</code> if errors occurred
328:             * @see BlockingParticipant
329:             * @see Participant
330:             * @see #addParticipant(Class, String, boolean, String)
331:             * @since 1.5
332:             */
333:            public boolean addParticipant(Class klass, boolean blocking)
334:                    throws RepException {
335:                return addParticipant(klass, null, blocking, null);
336:            }
337:
338:            /**
339:             * Adds a <code>BlockingParticipant</code> to the repository, using the
340:             * class name as the name of the participant.
341:             * <p>The participant will not be blocking.
342:             *
343:             * @param klass The class of the participant.
344:             * @param parameter An optional string that contains the parameter for
345:             * this participant.
346:             * @return <code>true</code> if the participants was added successfully;
347:             * or
348:             * <p><code>false</code> if errors occurred
349:             * @see BlockingParticipant
350:             * @see Participant
351:             * @see #addParticipant(Class, String, boolean, String)
352:             * @since 1.5
353:             */
354:            public boolean addParticipant(Class klass, String parameter)
355:                    throws RepException {
356:                return addParticipant(klass, null, false, parameter);
357:            }
358:
359:            /**
360:             * Adds a <code>BlockingParticipant</code> to the repository.
361:             *
362:             * @param klass The class of the participant.
363:             * @param name The name under which the participant will be registered, if
364:             * the name is <code>null</code> the class name will be used
365:             * @param blocking Indicates if this a blocking participant or not.
366:             * @param parameter An optional string that contains the parameter for
367:             * this participant.
368:             * @return <code>true</code> if the participants was added successfully;
369:             * or
370:             * <p><code>false</code> if errors occurred
371:             * @see BlockingParticipant
372:             * @see Participant
373:             * @since 1.0
374:             */
375:            public boolean addParticipant(Class klass, String name,
376:                    boolean blocking, String parameter) throws RepException {
377:                boolean generated_name = false;
378:
379:                if (null == name || 0 == name.length()) {
380:                    name = klass.getName();
381:                    generated_name = true;
382:                }
383:
384:                // Check if the participant isn't already present in the repository.
385:                if (mRepParticipants.containsKey(name)) {
386:                    if (!generated_name) {
387:                        return false;
388:                    }
389:
390:                    String new_name = null;
391:                    int counter = 2;
392:                    do {
393:                        new_name = name + counter;
394:                        counter++;
395:                    } while (mRepParticipants.containsKey(new_name));
396:
397:                    name = new_name;
398:                }
399:
400:                try {
401:                    // Try to create an instance of the participant.
402:                    BlockingParticipant participant_instance = null;
403:                    if (!BlockingParticipant.class.isAssignableFrom(klass)) {
404:                        if (Participant.class.isAssignableFrom(klass)) {
405:                            participant_instance = new BlockingParticipantDelegate(
406:                                    klass);
407:                        } else {
408:                            throw new BlockingParticipantExpectedException(
409:                                    klass.getName());
410:                        }
411:                    } else {
412:                        participant_instance = (BlockingParticipant) klass
413:                                .newInstance();
414:                    }
415:
416:                    // Sets the name of the blocking participant thread to the one
417:                    // it will be registered with
418:                    participant_instance.setName(name);
419:
420:                    // Setup the thread
421:                    Thread thread = new Thread(this , participant_instance);
422:                    participant_instance.setThread(thread);
423:
424:                    // Store the participant and its name, remember it's execution order
425:                    // according to other participants and remember whether this
426:                    // participant's initialization should be finished before
427:                    // continuing the repository initialization.
428:                    // Regardless of their names, all the participants are already
429:                    // registered with their class name.
430:                    // Store its optional parameter.
431:                    participant_instance.setRepository(this );
432:                    mRepParticipants.put(name, participant_instance);
433:                    ArrayList<BlockingParticipant> participants = mRepParticipantClassnames
434:                            .get(klass.getName());
435:                    if (null == participants) {
436:                        participants = new ArrayList<BlockingParticipant>();
437:                        mRepParticipantClassnames.put(klass.getName(),
438:                                participants);
439:                    }
440:                    participants.add(participant_instance);
441:                    mRepParticipantsOrder.add(name);
442:                    if (blocking) {
443:                        mRepParticipantsToWaitFor.add(name);
444:                    }
445:                    if (null != parameter) {
446:                        participant_instance.setParameter(parameter);
447:                    }
448:                    return true;
449:                } catch (IllegalAccessException e) {
450:                    return false;
451:                } catch (InstantiationException e) {
452:                    return false;
453:                }
454:            }
455:
456:            /**
457:             * Verifies if a participant that corresponds to a given name is present.
458:             *
459:             * @param name The name of the participant object that you wish to
460:             * retrieve from the repository. See the {@link #getParticipant(String)
461:             * getParticipant} method for detailed information about how the
462:             * participant's name is resolved.
463:             * @return <code>true</code> if the provided class name could be found, or
464:             * <p><code>false</code> otherwise
465:             * @see BlockingParticipant
466:             * @see #getParticipant(String)
467:             * @since 1.0
468:             */
469:            public boolean hasParticipant(String name) {
470:                BlockingParticipant participant = getParticipant(name);
471:                if (null == participant) {
472:                    return false;
473:                }
474:
475:                if (participant.hadInitializationError()) {
476:                    return false;
477:                }
478:
479:                return true;
480:            }
481:
482:            /**
483:             * Looks for the participant that corresponds to a given name and returns
484:             * it when found.
485:             *
486:             * @param name The name of the participant instance that you wish to
487:             * retrieve from the repository.
488:             * <p>If no name was provided during the XML specification, the
489:             * participant will have been registered with its class name. If the
490:             * participant's class is not part of the
491:             * <code>com.uwyn.rife.rep.participants</code> package, its full class
492:             * name has to be provided, otherwise just the name of the class itself is
493:             * sufficient.
494:             * <p>Also, even though a participant has been registered with a name,
495:             * it'll still be known under its class name. When a class name is
496:             * provided as the argument, the first known participant of that class
497:             * will be returned. This can be seen as the default participant for the
498:             * specified type.
499:             * @return A <code>BlockingParticipant</code> instance if the provided
500:             * name could be found amongst the registered participants in the
501:             * repository; or
502:             * <p><code>null</code> if the participant couldn't be found
503:             * @see BlockingParticipant
504:             * @see #hasParticipant(String)
505:             * @since 1.0
506:             */
507:            public BlockingParticipant getParticipant(String name) {
508:                // check if the provided participant name is present in the repository
509:                if (mRepParticipants.containsKey(name)) {
510:                    return mRepParticipants.get(name);
511:                }
512:
513:                // check if the provided participant name can be expanded to a name that
514:                // is known by the repository
515:                String prefixed_name = "com.uwyn.rife.rep.participants." + name;
516:                if (mRepParticipants.containsKey(prefixed_name)) {
517:                    return mRepParticipants.get(prefixed_name);
518:                }
519:
520:                // check if the provided participant name has been remembered as the
521:                // first participant of a certain class
522:                if (mRepParticipantClassnames.containsKey(name)) {
523:                    ArrayList<BlockingParticipant> participants = mRepParticipantClassnames
524:                            .get(name);
525:                    if (participants.size() > 0) {
526:                        return participants.get(0);
527:                    }
528:                }
529:                if (mRepParticipantClassnames.containsKey(prefixed_name)) {
530:                    ArrayList<BlockingParticipant> participants = mRepParticipantClassnames
531:                            .get(prefixed_name);
532:                    if (participants.size() > 0) {
533:                        return participants.get(0);
534:                    }
535:                }
536:
537:                return null;
538:            }
539:
540:            /**
541:             * Returns all the participants with a given class name
542:             *
543:             * @param className The class name of the participants that you wish to
544:             * retrieve from the repository.
545:             * <p>If the participant's class is not part of the
546:             * <code>com.uwyn.rife.rep.participants</code> package, its full class
547:             * name has to be provided, otherwise just the name of the class itself is
548:             * sufficient.
549:             * @return A <code>Collection</code> of <code>BlockingParticipant</code>
550:             * instances of the provided class name; or
551:             * <p><code>null</code> if no participants with the provided class name
552:             * could be found
553:             * @see BlockingParticipant
554:             * @see #getParticipant(String)
555:             * @since 1.0
556:             */
557:            public Collection<BlockingParticipant> getParticipants(
558:                    String className) {
559:                // check if the provided participant name has been remembered as the
560:                // first participant of a certain class
561:                if (mRepParticipantClassnames.containsKey(className)) {
562:                    ArrayList<BlockingParticipant> participants = mRepParticipantClassnames
563:                            .get(className);
564:                    if (participants.size() > 0) {
565:                        return participants;
566:                    }
567:                }
568:                // check if the provided participant class name can be expanded to a
569:                // name that is known by the repository
570:                String prefixed_name = "com.uwyn.rife.rep.participants."
571:                        + className;
572:                if (mRepParticipantClassnames.containsKey(prefixed_name)) {
573:                    ArrayList<BlockingParticipant> participants = mRepParticipantClassnames
574:                            .get(prefixed_name);
575:                    if (participants.size() > 0) {
576:                        return participants;
577:                    }
578:                }
579:
580:                return null;
581:            }
582:
583:            /**
584:             * Sequentially execute the participants according to their registration
585:             * order. If the participant has already been run or is still running, it
586:             * is not executed anymore. The repository waits for the participant's
587:             * execution to finish if this has been indicated by registering with the
588:             * <code>blocking</code> attribute.
589:             * <p>The resource finder that will be used is an instance of {@link ResourceFinderClasspath}.
590:             *
591:             * @see ResourceFinderClasspath
592:             * @see #runParticipants(ResourceFinder)
593:             * @since 1.5
594:             */
595:            public void runParticipants() {
596:                runParticipants(ResourceFinderClasspath.getInstance());
597:            }
598:
599:            /**
600:             * Sequentially execute the participants according to their registration
601:             * order. If the participant has already been run or is still running, it
602:             * is not executed anymore. The repository waits for the participant's
603:             * execution to finish if this has been indicated by registering with the
604:             * <code>blocking</code> attribute.
605:             *
606:             * @param resourceFinder The resource finder that is used during the
607:             * initialization.
608:             * @since 1.0
609:             */
610:            public void runParticipants(ResourceFinder resourceFinder) {
611:                // Iterate over the participants according to their registration order.
612:                for (String name : mRepParticipantsOrder) {
613:                    BlockingParticipant participant = mRepParticipants
614:                            .get(name);
615:                    try {
616:                        // Only start the participant's initialization if it hasn't run
617:                        // before.
618:                        if (!participant.getThread().isAlive()
619:                                && !participant.isFinished()) {
620:                            Logger
621:                                    .getLogger("com.uwyn.rife.rep")
622:                                    .info(
623:                                            "INITIALIZATION : "
624:                                                    + participant
625:                                                            .getInitializationMessage());
626:                            // Initialize the participant
627:                            participant.setResourceFinder(resourceFinder);
628:                            participant.getThread().start();
629:                            // Wait for the initialization to finish if this has been
630:                            // specified.
631:                            if (mRepParticipantsToWaitFor.contains(name)) {
632:                                participant.waitUntilFinished();
633:                            }
634:                        }
635:                    } finally {
636:                        detectParticipantException();
637:                    }
638:                }
639:
640:                synchronized (mFinishedThreadMonitor) {
641:                    if (!mFinished) {
642:                        mCleanupShutdownHook = new BlockingRepositoryCleanup(
643:                                this );
644:                        Runtime.getRuntime().addShutdownHook(
645:                                mCleanupShutdownHook);
646:                        mFinished = true;
647:                        fireInitFinished();
648:                    }
649:                }
650:            }
651:
652:            private void detectParticipantException() {
653:                if (mParticipantException != null) {
654:                    if (mParticipantException instanceof  RuntimeException) {
655:                        throw (RuntimeException) mParticipantException;
656:                    }
657:                    throw new RuntimeException(mParticipantException);
658:                }
659:            }
660:
661:            /**
662:             * If participants call an exception, clean up correctly and rethrow the
663:             * exception afterwards.
664:             *
665:             * @since 1.0
666:             */
667:            public void uncaughtException(Thread thread, Throwable e) {
668:                if (e instanceof  ThreadDeath) {
669:                    super .uncaughtException(thread, e);
670:                }
671:
672:                if (null == mParticipantException) {
673:                    mParticipantException = e;
674:                }
675:
676:                synchronized (mFinishedThreadMonitor) {
677:                    if (!mFinished) {
678:                        mFinished = true;
679:                        fireInitFinished();
680:                        cleanup();
681:                    }
682:                    // the repository has finished so log the exception
683:                    else {
684:                        if (mParticipantException != null) {
685:                            Logger
686:                                    .getLogger("com.uwyn.rife.rep")
687:                                    .severe(
688:                                            ExceptionUtils
689:                                                    .getExceptionStackTrace(mParticipantException));
690:                        }
691:                    }
692:                }
693:            }
694:
695:            /**
696:             * Parses the XML file to determine what the participants are. Then, one
697:             * by one, initializes each participant with the {@link
698:             * #runParticipants(ResourceFinder) runParticipants} method, waiting for
699:             * it to finish if its <code>blocking</code> attribute was set to
700:             * <code>true</code>.
701:             *
702:             * @param repXmlPath The path of the XML file.
703:             * <p>If this is <code>null</code>, <code>rep/participants.xml</code> will
704:             * be used.
705:             * @param resourcefinder The resource finder that will be used to look up
706:             * resources such as XML files and DTDs. It will also be used by other
707:             * classes after initialization through the
708:             * <code>getResourceFinder()</code> method.
709:             * <p>If this is <code>null</code>, an instance of <code>{@link
710:             * ResourceFinderClasspath}</code> will be used.
711:             * @exception RepException when an error occurs during the initialization.
712:             * @since 1.0
713:             */
714:            public void initialize(String repXmlPath,
715:                    ResourceFinder resourcefinder) throws RepException {
716:                mFinished = false;
717:
718:                if (null == resourcefinder) {
719:                    resourcefinder = ResourceFinderClasspath.getInstance();
720:                }
721:                if (null == repXmlPath) {
722:                    repXmlPath = DEFAULT_REP_PATH;
723:                }
724:
725:                // Parse the repository configuration file.
726:                Xml2BlockingRepository xml2rep = new Xml2BlockingRepository(
727:                        this );
728:                try {
729:                    // Add the participants that have been specified in the
730:                    // configuration file to the repository.
731:                    xml2rep.addRepParticipants(repXmlPath, resourcefinder);
732:                }
733:                // If errors occured during the parsing of the repository configuration
734:                // file, output a message and throw a runtime error.
735:                catch (XmlErrorException e) {
736:                    throw new InitializationErrorException(e);
737:                }
738:
739:                // Initialize the participants.
740:                runParticipants(resourcefinder);
741:            }
742:
743:            /**
744:             * Obtains the finished status of the initialization.
745:             *
746:             * @return <code>false</code> if the initialization is still busy; or
747:             * <p><code>true</code> if the initialization is finished
748:             * @since 1.0
749:             */
750:            public boolean isFinished() {
751:                return mFinished;
752:            }
753:
754:            /**
755:             * Cleans up the participants in the order in which they have been
756:             * declared. Every participant's <code>cleanup()</code> method is
757:             * successively called.
758:             *
759:             * @exception RepException when an error occurs during the cleanup.
760:             * @since 1.0
761:             */
762:            public void cleanup() throws RepException {
763:                if (!mFinished) {
764:                    return;
765:                }
766:
767:                synchronized (mCleanupThreadMonitor) {
768:                    if (mCleanedUp) {
769:                        return;
770:                    }
771:
772:                    // iterate over all the registered participants in their reverse
773:                    // registration order
774:                    String name = null;
775:                    BlockingParticipant participant = null;
776:                    for (int i = mRepParticipantsOrder.size() - 1; i >= 0; i--) {
777:                        name = mRepParticipantsOrder.get(i);
778:
779:                        // obtain each participant by its name and clean it up
780:                        participant = getParticipant(name);
781:                        if (participant != null) {
782:                            Logger.getLogger("com.uwyn.rife.rep").info(
783:                                    "CLEANUP : "
784:                                            + participant.getCleanupMessage());
785:                            participant.cleanup();
786:                        }
787:                    }
788:
789:                    mCleanedUp = true;
790:                }
791:            }
792:
793:            public HierarchicalProperties getProperties() {
794:                return mProperties;
795:            }
796:
797:            public Object getContext() {
798:                return mContext;
799:            }
800:
801:            /**
802:             * Adds the specified repository listener to receive repository
803:             * initialization events. If <code>repListener</code> is null, no
804:             * exception is thrown and no action is performed.
805:             *
806:             * @param repListener The repository listener that will be added.
807:             * @see RepositoryListener
808:             * @see #removeRepListener(RepositoryListener)
809:             * @since 1.0
810:             */
811:            public void addRepListener(RepositoryListener repListener) {
812:                if (null == repListener)
813:                    return;
814:
815:                mRepListeners.add(repListener);
816:            }
817:
818:            /**
819:             * Removes the repository listener so that it no longer receives
820:             * repository initialization events. This method performs no function, nor
821:             * does it throw an exception, if the listener specified by the argument
822:             * was not previously added to this component. If <code>repListener</code>
823:             * is <code>null</code>, no exception is thrown and no action is
824:             * performed.
825:             *
826:             * @param repListener The repository listener that will be removed.
827:             * @see RepositoryListener
828:             * @see #addRepListener(RepositoryListener)
829:             * @since 1.0
830:             */
831:            public void removeRepListener(RepositoryListener repListener) {
832:                mRepListeners.remove(repListener);
833:            }
834:
835:            /**
836:             * Notifies the registered listeners that a new initialization action has
837:             * been performed.
838:             * <p>This is always triggered when a participant's initialization has
839:             * finished. Each participant however has the possibility to call this
840:             * method directly, allowed for finer-grained notification of the
841:             * advancement of the initialization.
842:             *
843:             * @param participant The participant that triggered the action.
844:             * @see RepositoryListener
845:             * @since 1.0
846:             */
847:            public void fireInitActionPerformed(BlockingParticipant participant) {
848:                if (mRepListeners.size() > 0) {
849:                    for (RepositoryListener listener : mRepListeners) {
850:                        listener.initActionPerformed(participant);
851:                    }
852:                }
853:            }
854:
855:            /**
856:             * Notifies the registered listeners that the repository initialization
857:             * has finished.
858:             *
859:             * @see RepositoryListener
860:             * @since 1.0
861:             */
862:            public void fireInitFinished() {
863:                if (mRepListeners.size() > 0) {
864:                    for (RepositoryListener listener : mRepListeners) {
865:                        listener.initFinished();
866:                    }
867:                }
868:            }
869:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.