EMMA Coverage Report (generated Tue Jan 19 17:53:40 UTC 2010)
[all classes][org.jomc.ri]

COVERAGE SUMMARY FOR SOURCE FILE [DefaultObjectManager.java]

nameclass, %method, %block, %line, %
DefaultObjectManager.java100% (5/5)82%  (50/61)69%  (2895/4224)72%  (591.6/821)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class DefaultObjectManager$1100% (1/1)50%  (1/2)24%  (4/17)50%  (1/2)
toString (): String 0%   (0/1)0%   (0/13)0%   (0/1)
DefaultObjectManager$1 (ClassLoader): void 100% (1/1)100% (4/4)100% (1/1)
     
class DefaultObjectManager100% (1/1)81%  (43/53)68%  (2823/4139)72%  (580.6/809)
getArtifactNameMessage (): String 0%   (0/1)0%   (0/5)0%   (0/1)
getDefaultLocatorInfoMessage (String, ClassLoader): String 0%   (0/1)0%   (0/15)0%   (0/1)
getDependencyCycleMessage (String): String 0%   (0/1)0%   (0/10)0%   (0/1)
getMissingInstanceMessage (String, String): String 0%   (0/1)0%   (0/14)0%   (0/1)
getMissingObjectInstanceMessage (Object): String 0%   (0/1)0%   (0/11)0%   (0/1)
getMissingSpecificationClassMessage (Specification): String 0%   (0/1)0%   (0/11)0%   (0/1)
getUnsupportedMultiplicityMessage (Multiplicity): String 0%   (0/1)0%   (0/10)0%   (0/1)
setBootstrapClassLoaderClassName (String): void 0%   (0/1)0%   (0/5)0%   (0/3)
setDefaultLogLevel (Level): void 0%   (0/1)0%   (0/3)0%   (0/2)
setLogLevel (Level): void 0%   (0/1)0%   (0/4)0%   (0/2)
getDependency (Object, String): Object 100% (1/1)39%  (246/635)46%  (55.3/121)
getInvocation (Object, Instance, Method, Object []): Invocation 100% (1/1)44%  (74/170)56%  (19.6/35)
getInvoker (ClassLoader): Invoker 100% (1/1)55%  (104/190)65%  (22.1/34)
initialize (): void 100% (1/1)57%  (188/328)64%  (45/70)
getObject (Class, String): Object 100% (1/1)57%  (139/242)62%  (34/55)
getObject (Class): Object 100% (1/1)62%  (239/387)65%  (51.8/80)
isLoggable (Level): boolean 100% (1/1)65%  (11/17)63%  (1.9/3)
getObject (Scope, Instance, ClassLoader): Object 100% (1/1)67%  (81/121)84%  (19.4/23)
getLocator (ClassLoader, URI): Locator 100% (1/1)73%  (145/199)79%  (33/42)
getMessage (Object, String, Locale, Object []): String 100% (1/1)76%  (89/117)75%  (18/24)
getProperty (Object, String): Object 100% (1/1)76%  (89/117)78%  (21/27)
getModules (ClassLoader): Modules 100% (1/1)77%  (129/167)84%  (29.5/35)
createProxy (Instance, Object): Object 100% (1/1)80%  (66/82)70%  (11.9/17)
getScope (ClassLoader, String): Scope 100% (1/1)82%  (157/192)87%  (34/39)
log (Level, String, Throwable): void 100% (1/1)83%  (24/29)83%  (5/6)
getObjectManager (ClassLoader): ObjectManager 100% (1/1)85%  (29/34)88%  (7/8)
getClassLoader (ClassLoader): ClassLoader 100% (1/1)90%  (18/20)80%  (4/5)
getDefaultLocator (URI): Locator 100% (1/1)90%  (19/21)86%  (6/7)
logModulesReport (Modules, ClassLoader): void 100% (1/1)99%  (498/505)98%  (80/82)
<static initializer> 100% (1/1)100% (12/12)100% (3/3)
DefaultObjectManager (): void 100% (1/1)100% (28/28)100% (7/7)
appendImplementationInfo (Implementation, StringBuilder): StringBuilder 100% (1/1)100% (69/69)100% (10/10)
appendSpecificationInfo (Specification, StringBuilder): StringBuilder 100% (1/1)100% (56/56)100% (9/9)
getBootstrapClassLoaderClassName (): String 100% (1/1)100% (11/11)100% (4/4)
getClassLoader (Class): ClassLoader 100% (1/1)100% (16/16)100% (6/6)
getDefaultLogLevel (): Level 100% (1/1)100% (10/10)100% (3/3)
getDefaultScope (String): Scope 100% (1/1)100% (22/22)100% (6/6)
getDefaultScopeInfoMessage (String, ClassLoader): String 100% (1/1)100% (15/15)100% (1/1)
getImplementationInfoMessage (Long): String 100% (1/1)100% (10/10)100% (1/1)
getListeners (): List 100% (1/1)100% (11/11)100% (3/3)
getLogLevel (): Level 100% (1/1)100% (30/30)100% (4/4)
getMessage (String, Object): String 100% (1/1)100% (16/16)100% (2/2)
getMissingDependencyMessage (String, String): String 100% (1/1)100% (14/14)100% (1/1)
getMissingImplementationMessage (String, String): String 100% (1/1)100% (14/14)100% (1/1)
getMissingImplementationsMessage (String): String 100% (1/1)100% (10/10)100% (1/1)
getMissingLocatorMessage (URI): String 100% (1/1)100% (11/11)100% (1/1)
getMissingMessageMessage (String, String): String 100% (1/1)100% (14/14)100% (1/1)
getMissingObjectMessage (String, String): String 100% (1/1)100% (14/14)100% (1/1)
getMissingPropertyMessage (String, String): String 100% (1/1)100% (14/14)100% (1/1)
getMissingScopeMessage (String): String 100% (1/1)100% (10/10)100% (1/1)
getMissingSpecificationMessage (String): String 100% (1/1)100% (10/10)100% (1/1)
getObject (Class, URI, ClassLoader): Object 100% (1/1)100% (51/51)100% (13/13)
getRegisteredListenerMessage (String): String 100% (1/1)100% (10/10)100% (1/1)
     
class DefaultObjectManager$2100% (1/1)100% (2/2)100% (13/13)100% (3/3)
DefaultObjectManager$2 (DefaultObjectManager): void 100% (1/1)100% (6/6)100% (1/1)
onLog (Level, String, Throwable): void 100% (1/1)100% (7/7)100% (2/2)
     
class DefaultObjectManager$3100% (1/1)100% (2/2)100% (24/24)100% (5/5)
DefaultObjectManager$3 (DefaultObjectManager, List): void 100% (1/1)100% (9/9)100% (1/1)
onLog (Level, String, Throwable): void 100% (1/1)100% (15/15)100% (4/4)
     
class DefaultObjectManager$4100% (1/1)100% (2/2)100% (31/31)100% (2/2)
DefaultObjectManager$4 (DefaultObjectManager, ClassLoader, Object, Instance):... 100% (1/1)100% (15/15)100% (1/1)
invoke (Object, Method, Object []): Object 100% (1/1)100% (16/16)100% (1/1)

1// SECTION-START[License Header]
2// <editor-fold defaultstate="collapsed" desc=" Generated License ">
3/*
4 *   Copyright (c) 2010 The JOMC Project
5 *   Copyright (c) 2005 Christian Schulte <cs@jomc.org>
6 *   All rights reserved.
7 *
8 *   Redistribution and use in source and binary forms, with or without
9 *   modification, are permitted provided that the following conditions
10 *   are met:
11 *
12 *     o Redistributions of source code must retain the above copyright
13 *       notice, this list of conditions and the following disclaimer.
14 *
15 *     o Redistributions in binary form must reproduce the above copyright
16 *       notice, this list of conditions and the following disclaimer in
17 *       the documentation and/or other materials provided with the
18 *       distribution.
19 *
20 *   THIS SOFTWARE IS PROVIDED BY THE JOMC PROJECT AND CONTRIBUTORS "AS IS"
21 *   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 *   THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 *   PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE JOMC PROJECT OR
24 *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 *   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 *   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 *   OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 *   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 *   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *   $Id: DefaultObjectManager.java 1346 2010-01-19 12:16:43Z schulte2005 $
33 *
34 */
35// </editor-fold>
36// SECTION-END
37package org.jomc.ri;
38 
39import java.io.IOException;
40import java.lang.reflect.Array;
41import java.lang.reflect.Method;
42import java.lang.reflect.Proxy;
43import java.net.URI;
44import java.text.MessageFormat;
45import java.util.ArrayList;
46import java.util.HashMap;
47import java.util.HashSet;
48import java.util.LinkedList;
49import java.util.List;
50import java.util.Locale;
51import java.util.Map;
52import java.util.ResourceBundle;
53import java.util.Set;
54import java.util.logging.Level;
55import java.util.logging.LogRecord;
56import org.jomc.ObjectManagementException;
57import org.jomc.ObjectManager;
58import org.jomc.ObjectManagerFactory;
59import org.jomc.model.Dependency;
60import org.jomc.model.Implementation;
61import org.jomc.model.ImplementationReference;
62import org.jomc.model.Implementations;
63import org.jomc.model.Instance;
64import org.jomc.model.Message;
65import org.jomc.model.ModelContext;
66import org.jomc.model.ModelException;
67import org.jomc.model.ModelValidationReport;
68import org.jomc.model.Module;
69import org.jomc.model.Modules;
70import org.jomc.model.Multiplicity;
71import org.jomc.model.Property;
72import org.jomc.model.Specification;
73import org.jomc.model.SpecificationReference;
74import org.jomc.spi.Invocation;
75import org.jomc.spi.Invoker;
76import org.jomc.spi.Listener;
77import org.jomc.spi.Locator;
78import org.jomc.spi.Scope;
79import org.jomc.util.WeakIdentityHashMap;
80 
81// SECTION-START[Documentation]
82// <editor-fold defaultstate="collapsed" desc=" Generated Documentation ">
83/**
84 * Object management and configuration reference implementation.
85 * <p><b>Specifications</b><ul>
86 * <li>{@code org.jomc.ObjectManager} {@code 1.0} {@code Singleton}</li>
87 * </ul></p>
88 *
89 * @author <a href="mailto:cs@jomc.org">Christian Schulte</a> 1.0
90 * @version $Id: DefaultObjectManager.java 1346 2010-01-19 12:16:43Z schulte2005 $
91 */
92// </editor-fold>
93// SECTION-END
94// SECTION-START[Annotations]
95// <editor-fold defaultstate="collapsed" desc=" Generated Annotations ">
96@javax.annotation.Generated( value = "org.jomc.tools.JavaSources",
97                             comments = "See http://jomc.sourceforge.net/jomc/1.0-alpha-15/jomc-tools" )
98// </editor-fold>
99// SECTION-END
100public class DefaultObjectManager implements ObjectManager
101{
102    // SECTION-START[Constructors]
103    // <editor-fold defaultstate="collapsed" desc=" Generated Constructors ">
104 
105    /** Creates a new {@code DefaultObjectManager} instance. */
106    @javax.annotation.Generated( value = "org.jomc.tools.JavaSources",
107                                 comments = "See http://jomc.sourceforge.net/jomc/1.0-alpha-15/jomc-tools" )
108    public DefaultObjectManager()
109    {
110        // SECTION-START[Default Constructor]
111        super();
112        // SECTION-END
113    }
114    // </editor-fold>
115    // SECTION-END
116    // SECTION-START[ObjectManager]
117 
118    public Object getObject( final Class specification )
119    {
120        if ( specification == null )
121        {
122            throw new NullPointerException( "specification" );
123        }
124 
125        try
126        {
127            this.initialize();
128 
129            final ClassLoader classLoader = getClassLoader( specification );
130            final Modules model = this.getModules( classLoader );
131            final Specification s = model.getSpecification( specification );
132 
133            if ( s == null )
134            {
135                if ( this.isLoggable( Level.WARNING ) )
136                {
137                    this.log( Level.WARNING, this.getMissingSpecificationMessage(
138                        specification.getName() ), new Exception() );
139 
140                }
141 
142                return null;
143            }
144 
145            Scope scope = null;
146            if ( s.getScope() != null )
147            {
148                scope = this.getScope( classLoader, s.getScope() );
149 
150                if ( scope == null )
151                {
152                    if ( this.isLoggable( Level.WARNING ) )
153                    {
154                        this.log( Level.WARNING, this.getMissingScopeMessage( s.getScope() ), null );
155                    }
156 
157                    return null;
158                }
159            }
160 
161            final Implementations available = model.getImplementations( s.getIdentifier() );
162            if ( available == null || available.getImplementation().isEmpty() )
163            {
164                if ( this.isLoggable( Level.WARNING ) )
165                {
166                    this.log( Level.WARNING, this.getMissingImplementationsMessage(
167                        specification.getName() ), new Exception() );
168 
169                }
170 
171                return null;
172            }
173 
174            if ( s.getMultiplicity() == Multiplicity.ONE )
175            {
176                final Implementation i = available.getImplementation().get( 0 );
177 
178                if ( i.getLocation() != null )
179                {
180                    if ( s.getClazz() == null )
181                    {
182                        if ( this.isLoggable( Level.WARNING ) )
183                        {
184                            this.log( Level.WARNING, this.getMissingSpecificationClassMessage( s ), new Exception() );
185                        }
186 
187                        return null;
188                    }
189 
190                    final Object object = this.getObject(
191                        Class.forName( s.getClazz(), true, classLoader ), i.getLocationUri(), classLoader );
192 
193                    if ( object == null )
194                    {
195                        if ( this.isLoggable( Level.WARNING ) )
196                        {
197                            this.log( Level.WARNING, this.getMissingObjectMessage(
198                                i.getIdentifier(), i.getName() ), new Exception() );
199 
200                        }
201 
202                        return null;
203                    }
204 
205                    return object;
206                }
207                else if ( !i.isAbstract() )
208                {
209                    final Instance instance = model.getInstance( i.getIdentifier() );
210                    if ( instance == null )
211                    {
212                        if ( this.isLoggable( Level.WARNING ) )
213                        {
214                            this.log( Level.WARNING, this.getMissingInstanceMessage(
215                                i.getIdentifier(), i.getName() ), new Exception() );
216 
217                        }
218 
219                        return null;
220                    }
221 
222                    final Object object = this.getObject( scope, instance, classLoader );
223                    if ( object == null )
224                    {
225                        if ( this.isLoggable( Level.WARNING ) )
226                        {
227                            this.log( Level.WARNING, this.getMissingObjectMessage(
228                                i.getIdentifier(), i.getName() ), new Exception() );
229 
230                        }
231 
232                        return null;
233                    }
234 
235                    return object;
236                }
237            }
238            else if ( s.getMultiplicity() == Multiplicity.MANY )
239            {
240                final List<Object> list = new ArrayList<Object>( available.getImplementation().size() );
241 
242                for ( Implementation i : available.getImplementation() )
243                {
244                    if ( i.getLocation() != null )
245                    {
246                        if ( s.getClazz() == null )
247                        {
248                            if ( this.isLoggable( Level.WARNING ) )
249                            {
250                                this.log( Level.WARNING, this.getMissingSpecificationClassMessage( s ),
251                                          new Exception() );
252 
253                            }
254 
255                            return null;
256                        }
257 
258                        final Object o = this.getObject(
259                            Class.forName( s.getClazz(), true, classLoader ), i.getLocationUri(), classLoader );
260 
261                        if ( o == null )
262                        {
263                            if ( this.isLoggable( Level.WARNING ) )
264                            {
265                                this.log( Level.WARNING, this.getMissingObjectMessage(
266                                    i.getIdentifier(), i.getName() ), new Exception() );
267 
268                            }
269                        }
270                        else
271                        {
272                            list.add( o );
273                        }
274                    }
275                    else if ( !i.isAbstract() )
276                    {
277                        final Instance instance = model.getInstance( i.getIdentifier() );
278                        if ( instance == null )
279                        {
280                            if ( this.isLoggable( Level.WARNING ) )
281                            {
282                                this.log( Level.WARNING, this.getMissingInstanceMessage(
283                                    i.getIdentifier(), i.getName() ), new Exception() );
284 
285                            }
286 
287                            return null;
288                        }
289 
290                        final Object o = this.getObject( scope, instance, classLoader );
291                        if ( o == null )
292                        {
293                            if ( this.isLoggable( Level.WARNING ) )
294                            {
295                                this.log( Level.WARNING, this.getMissingObjectMessage(
296                                    i.getIdentifier(), i.getName() ), new Exception() );
297 
298                            }
299                        }
300                        else
301                        {
302                            list.add( o );
303                        }
304                    }
305                }
306 
307                return list.isEmpty()
308                       ? null : list.toArray( (Object[]) Array.newInstance( specification, list.size() ) );
309 
310            }
311            else if ( this.isLoggable( Level.WARNING ) )
312            {
313                this.log( Level.WARNING, this.getUnsupportedMultiplicityMessage(
314                    s.getMultiplicity() ), new Exception() );
315 
316            }
317 
318            return null;
319        }
320        catch ( final Exception e )
321        {
322            throw new ObjectManagementException( e.getMessage(), e );
323        }
324    }
325 
326    public Object getObject( final Class specification, final String implementationName )
327    {
328        if ( specification == null )
329        {
330            throw new NullPointerException( "specification" );
331        }
332        if ( implementationName == null )
333        {
334            throw new NullPointerException( "implementationName" );
335        }
336 
337        try
338        {
339            this.initialize();
340 
341            final ClassLoader classLoader = getClassLoader( specification );
342            final Modules model = this.getModules( classLoader );
343            final Specification s = model.getSpecification( specification );
344 
345            if ( s == null )
346            {
347                if ( this.isLoggable( Level.WARNING ) )
348                {
349                    this.log( Level.WARNING, this.getMissingSpecificationMessage(
350                        specification.getName() ), new Exception() );
351 
352                }
353 
354                return null;
355            }
356 
357            Scope scope = null;
358            if ( s.getScope() != null )
359            {
360                scope = this.getScope( classLoader, s.getScope() );
361 
362                if ( scope == null )
363                {
364                    if ( this.isLoggable( Level.WARNING ) )
365                    {
366                        this.log( Level.WARNING, this.getMissingScopeMessage( s.getScope() ), null );
367                    }
368 
369                    return null;
370                }
371            }
372 
373            final Implementations available = model.getImplementations( s.getIdentifier() );
374            if ( available == null || available.getImplementation().isEmpty() )
375            {
376                if ( this.isLoggable( Level.WARNING ) )
377                {
378                    this.log( Level.WARNING, this.getMissingImplementationsMessage(
379                        specification.getName() ), new Exception() );
380 
381                }
382 
383                return null;
384            }
385 
386            final Implementation i = available.getImplementationByName( implementationName );
387            if ( i == null )
388            {
389                if ( this.isLoggable( Level.WARNING ) )
390                {
391                    this.log( Level.WARNING, this.getMissingImplementationMessage(
392                        implementationName, s.getIdentifier() ), new Exception() );
393 
394                }
395 
396                return null;
397            }
398 
399            if ( i.getLocation() != null )
400            {
401                if ( s.getClazz() == null )
402                {
403                    if ( this.isLoggable( Level.WARNING ) )
404                    {
405                        this.log( Level.WARNING, this.getMissingSpecificationClassMessage( s ), new Exception() );
406                    }
407 
408                    return null;
409                }
410 
411                final Object object = this.getObject(
412                    Class.forName( s.getClazz(), true, classLoader ), i.getLocationUri(), classLoader );
413 
414                if ( object == null )
415                {
416                    if ( this.isLoggable( Level.WARNING ) )
417                    {
418                        this.log( Level.WARNING, this.getMissingObjectMessage(
419                            i.getIdentifier(), i.getName() ), new Exception() );
420 
421                    }
422 
423                    return null;
424                }
425 
426                return object;
427            }
428            else if ( !i.isAbstract() )
429            {
430                final Instance instance = model.getInstance( i.getIdentifier() );
431                if ( instance == null )
432                {
433                    if ( this.isLoggable( Level.WARNING ) )
434                    {
435                        this.log( Level.WARNING, this.getMissingInstanceMessage(
436                            i.getIdentifier(), i.getName() ), new Exception() );
437 
438                    }
439 
440                    return null;
441                }
442 
443                final Object object = this.getObject( scope, instance, classLoader );
444                if ( object == null )
445                {
446                    if ( this.isLoggable( Level.WARNING ) )
447                    {
448                        this.log( Level.WARNING, this.getMissingObjectMessage(
449                            i.getIdentifier(), i.getName() ), new Exception() );
450 
451                    }
452 
453                    return null;
454                }
455 
456                return object;
457            }
458 
459            return null;
460        }
461        catch ( final Exception e )
462        {
463            throw new ObjectManagementException( e.getMessage(), e );
464        }
465    }
466 
467    public Object getDependency( final Object object, final String dependencyName )
468    {
469        if ( object == null )
470        {
471            throw new NullPointerException( "object" );
472        }
473        if ( dependencyName == null )
474        {
475            throw new NullPointerException( "dependencyName" );
476        }
477 
478        try
479        {
480            this.initialize();
481 
482            final ClassLoader classLoader = getClassLoader( object.getClass() );
483            final Modules model = this.getModules( classLoader );
484            final Instance instance = model.getInstance( object );
485 
486            if ( instance == null )
487            {
488                if ( this.isLoggable( Level.WARNING ) )
489                {
490                    this.log( Level.WARNING, this.getMissingObjectInstanceMessage( object ), new Exception() );
491                }
492 
493                return null;
494            }
495 
496            synchronized ( instance )
497            {
498                final Dependency dependency = instance.getDependencies() != null
499                                              ? instance.getDependencies().getDependency( dependencyName ) : null;
500 
501                if ( dependency == null )
502                {
503                    if ( this.isLoggable( Level.WARNING ) )
504                    {
505                        this.log( Level.WARNING, this.getMissingDependencyMessage(
506                            dependencyName, instance.getIdentifier() ), new Exception() );
507 
508                    }
509 
510                    return null;
511                }
512 
513                Object o = instance.getDependencyObjects().get( dependencyName );
514                if ( o == null )
515                {
516                    final Specification ds = model.getSpecification( dependency.getIdentifier() );
517                    if ( ds == null )
518                    {
519                        if ( this.isLoggable( Level.WARNING ) )
520                        {
521                            this.log( Level.WARNING, this.getMissingSpecificationMessage(
522                                dependency.getIdentifier() ), new Exception() );
523 
524                        }
525 
526                        return null;
527                    }
528 
529                    Scope scope = null;
530                    if ( ds.getScope() != null )
531                    {
532                        scope = this.getScope( classLoader, ds.getScope() );
533 
534                        if ( scope == null )
535                        {
536                            if ( this.isLoggable( Level.WARNING ) )
537                            {
538                                this.log( Level.WARNING, this.getMissingScopeMessage( ds.getScope() ), null );
539                            }
540 
541                            return null;
542                        }
543                    }
544 
545                    final Implementations available = model.getImplementations( ds.getIdentifier() );
546                    if ( available == null || available.getImplementation().isEmpty() )
547                    {
548                        if ( !dependency.isOptional() && this.isLoggable( Level.WARNING ) )
549                        {
550                            this.log( Level.WARNING, this.getMissingImplementationsMessage(
551                                dependency.getIdentifier() ), new Exception() );
552 
553                        }
554 
555                        return null;
556                    }
557 
558                    if ( dependency.getImplementationName() != null )
559                    {
560                        final Implementation i =
561                            available.getImplementationByName( dependency.getImplementationName() );
562 
563                        if ( i == null )
564                        {
565                            if ( !dependency.isOptional() && this.isLoggable( Level.WARNING ) )
566                            {
567                                this.log( Level.WARNING, this.getMissingImplementationMessage(
568                                    dependency.getImplementationName(), dependency.getIdentifier() ), new Exception() );
569 
570                            }
571 
572                            return null;
573                        }
574 
575                        if ( i.getLocation() != null )
576                        {
577                            if ( ds.getClazz() == null )
578                            {
579                                if ( this.isLoggable( Level.WARNING ) )
580                                {
581                                    this.log( Level.WARNING, this.getMissingSpecificationClassMessage( ds ),
582                                              new Exception() );
583 
584                                }
585 
586                                return null;
587                            }
588 
589                            o = this.getObject(
590                                Class.forName( ds.getClazz(), true, classLoader ), i.getLocationUri(), classLoader );
591 
592                            if ( o == null )
593                            {
594                                if ( this.isLoggable( Level.WARNING ) )
595                                {
596                                    this.log( Level.WARNING, this.getMissingObjectMessage(
597                                        i.getIdentifier(), i.getName() ), new Exception() );
598 
599                                }
600 
601                                return null;
602                            }
603                        }
604                        else if ( !i.isAbstract() )
605                        {
606                            final Instance di = model.getInstance( i.getIdentifier(), dependency );
607                            if ( di == null )
608                            {
609                                if ( this.isLoggable( Level.WARNING ) )
610                                {
611                                    this.log( Level.WARNING, this.getMissingInstanceMessage(
612                                        i.getIdentifier(), i.getName() ), new Exception() );
613 
614                                }
615 
616                                return null;
617                            }
618 
619                            o = this.getObject( scope, di, classLoader );
620                            if ( o == null )
621                            {
622                                if ( this.isLoggable( Level.WARNING ) )
623                                {
624                                    this.log( Level.WARNING, this.getMissingObjectMessage(
625                                        i.getIdentifier(), i.getName() ), new Exception() );
626 
627                                }
628 
629                                return null;
630                            }
631                        }
632                    }
633                    else if ( ds.getMultiplicity() == Multiplicity.ONE )
634                    {
635                        final Implementation ref = available.getImplementation().get( 0 );
636                        if ( ref.getLocation() != null )
637                        {
638                            if ( ds.getClazz() == null )
639                            {
640                                if ( this.isLoggable( Level.WARNING ) )
641                                {
642                                    this.log( Level.WARNING, this.getMissingSpecificationClassMessage( ds ),
643                                              new Exception() );
644                                }
645 
646                                return null;
647                            }
648 
649                            o = this.getObject(
650                                Class.forName( ds.getClazz(), true, classLoader ), ref.getLocationUri(), classLoader );
651 
652                            if ( o == null )
653                            {
654                                if ( this.isLoggable( Level.WARNING ) )
655                                {
656                                    this.log( Level.WARNING, this.getMissingObjectMessage(
657                                        ref.getIdentifier(), ref.getName() ), new Exception() );
658 
659                                }
660 
661                                return null;
662                            }
663                        }
664                        else if ( !ref.isAbstract() )
665                        {
666                            final Instance di = model.getInstance( ref.getIdentifier(), dependency );
667                            if ( di == null )
668                            {
669                                if ( this.isLoggable( Level.WARNING ) )
670                                {
671                                    this.log( Level.WARNING, this.getMissingInstanceMessage(
672                                        ref.getIdentifier(), ref.getName() ), new Exception() );
673 
674                                }
675 
676                                return null;
677                            }
678 
679                            o = this.getObject( scope, di, classLoader );
680                            if ( o == null )
681                            {
682                                if ( this.isLoggable( Level.WARNING ) )
683                                {
684                                    this.log( Level.WARNING, this.getMissingObjectMessage(
685                                        ref.getIdentifier(), ref.getName() ), new Exception() );
686 
687                                }
688 
689                                return null;
690                            }
691                        }
692                    }
693                    else
694                    {
695                        final List<Object> list = new ArrayList<Object>( available.getImplementation().size() );
696 
697                        if ( !available.getImplementation().isEmpty() && ds.getClazz() == null )
698                        {
699                            if ( this.isLoggable( Level.WARNING ) )
700                            {
701                                this.log( Level.WARNING, this.getMissingSpecificationClassMessage( ds ),
702                                          new Exception() );
703 
704                            }
705 
706                            return null;
707                        }
708 
709                        for ( Implementation a : available.getImplementation() )
710                        {
711                            if ( a.getLocation() != null )
712                            {
713                                final Object o2 = this.getObject( Class.forName( ds.getClazz(), true, classLoader ),
714                                                                  a.getLocationUri(), classLoader );
715 
716                                if ( o2 == null )
717                                {
718                                    if ( this.isLoggable( Level.WARNING ) )
719                                    {
720                                        this.log( Level.WARNING, this.getMissingObjectMessage(
721                                            a.getIdentifier(), a.getName() ), new Exception() );
722 
723                                    }
724                                }
725                                else
726                                {
727                                    list.add( o2 );
728                                }
729                            }
730                            else if ( !a.isAbstract() )
731                            {
732                                final Instance di = model.getInstance( a.getIdentifier(), dependency );
733                                if ( di == null )
734                                {
735                                    if ( this.isLoggable( Level.WARNING ) )
736                                    {
737                                        this.log( Level.WARNING, this.getMissingInstanceMessage(
738                                            a.getIdentifier(), a.getName() ), new Exception() );
739 
740                                    }
741 
742                                    return null;
743                                }
744 
745                                final Object o2 = this.getObject( scope, di, classLoader );
746                                if ( o2 == null )
747                                {
748                                    if ( this.isLoggable( Level.WARNING ) )
749                                    {
750                                        this.log( Level.WARNING, this.getMissingObjectMessage(
751                                            a.getIdentifier(), a.getName() ), new Exception() );
752 
753                                    }
754                                }
755                                else
756                                {
757                                    list.add( o2 );
758                                }
759                            }
760                        }
761 
762                        o = list.isEmpty() ? null : list.toArray( (Object[]) Array.newInstance( Class.forName(
763                            ds.getClazz(), true, classLoader ), list.size() ) );
764 
765                    }
766                }
767 
768                if ( o != null && dependency.isBound() )
769                {
770                    instance.getDependencyObjects().put( dependencyName, o );
771                }
772 
773                return o;
774            }
775        }
776        catch ( final Exception e )
777        {
778            throw new ObjectManagementException( e.getMessage(), e );
779        }
780    }
781 
782    public Object getProperty( final Object object, final String propertyName )
783    {
784        if ( object == null )
785        {
786            throw new NullPointerException( "object" );
787        }
788        if ( propertyName == null )
789        {
790            throw new NullPointerException( "propertyName" );
791        }
792 
793        try
794        {
795            this.initialize();
796 
797            final ClassLoader classLoader = getClassLoader( object.getClass() );
798            final Modules model = this.getModules( classLoader );
799            final Instance instance = model.getInstance( object );
800 
801            if ( instance == null )
802            {
803                if ( this.isLoggable( Level.WARNING ) )
804                {
805                    this.log( Level.WARNING, this.getMissingObjectInstanceMessage( object ), new Exception() );
806                }
807 
808                return null;
809            }
810 
811            synchronized ( instance )
812            {
813                Object value = instance.getPropertyObjects().get( propertyName );
814                if ( value == null )
815                {
816                    final Property property =
817                        instance.getProperties() != null ? instance.getProperties().getProperty( propertyName ) : null;
818 
819                    if ( property == null )
820                    {
821                        if ( this.isLoggable( Level.WARNING ) )
822                        {
823                            this.log( Level.WARNING, this.getMissingPropertyMessage(
824                                propertyName, object.getClass().getName() ), new Exception() );
825 
826                        }
827 
828                        return null;
829                    }
830 
831                    value = property.getJavaValue( classLoader );
832                    if ( value != null )
833                    {
834                        instance.getPropertyObjects().put( propertyName, value );
835                    }
836                }
837 
838                return value;
839            }
840        }
841        catch ( final Exception e )
842        {
843            throw new ObjectManagementException( e.getMessage(), e );
844        }
845    }
846 
847    public String getMessage( final Object object, final String messageName, final Locale locale,
848                              final Object... arguments )
849    {
850        if ( object == null )
851        {
852            throw new NullPointerException( "object" );
853        }
854        if ( messageName == null )
855        {
856            throw new NullPointerException( "messageName" );
857        }
858        if ( locale == null )
859        {
860            throw new NullPointerException( "locale" );
861        }
862 
863        try
864        {
865            this.initialize();
866 
867            final ClassLoader classLoader = getClassLoader( object.getClass() );
868            final Modules model = this.getModules( classLoader );
869            final Instance instance = model.getInstance( object );
870 
871            if ( instance == null )
872            {
873                if ( this.isLoggable( Level.WARNING ) )
874                {
875                    this.log( Level.WARNING, this.getMissingObjectInstanceMessage( object ), new Exception() );
876                }
877 
878                return null;
879            }
880 
881            synchronized ( instance )
882            {
883                final Message message =
884                    instance.getMessages() != null ? instance.getMessages().getMessage( messageName ) : null;
885 
886                if ( message == null || message.getTemplate() == null )
887                {
888                    if ( this.isLoggable( Level.WARNING ) )
889                    {
890                        this.log( Level.WARNING, this.getMissingMessageMessage(
891                            messageName, object.getClass().getName() ), new Exception() );
892 
893                    }
894 
895                    return null;
896                }
897 
898                return MessageFormat.format( message.getTemplate().getText(
899                    locale.getLanguage().toLowerCase( Locale.ENGLISH ) ).getValue(), arguments );
900 
901            }
902        }
903        catch ( final Exception e )
904        {
905            throw new ObjectManagementException( e.getMessage(), e );
906        }
907    }
908 
909    // SECTION-END
910    // SECTION-START[DefaultObjectManager]
911    /** Constant for the {@code Singleton} scope identifier. */
912    protected static final String SINGLETON_SCOPE_IDENTIFIER = "Singleton";
913 
914    /**
915     * Log level events are logged at by default.
916     * @see #getDefaultLogLevel()
917     */
918    private static final Level DEFAULT_LOG_LEVEL = Level.WARNING;
919 
920    /** Default log level. */
921    private static volatile Level defaultLogLevel;
922 
923    /** Name of the platform's bootstrap class loader class. */
924    private static volatile String bootstrapClassLoaderClassName;
925 
926    private static volatile boolean bootstrapClassLoaderClassNameInitialized;
927 
928    /** {@code ClassLoader} instance representing the bootstrap class loader. */
929    private static final ClassLoader BOOTSTRAP_CLASSLOADER = new ClassLoader( null )
930    {
931 
932        @Override
933        public String toString()
934        {
935            return DefaultObjectManager.class.getName() + ".BootstrapClassLoader@" + System.identityHashCode( this );
936        }
937 
938    };
939 
940    /** Listeners of the instance. */
941    private List<Listener> listeners;
942 
943    /** Flag indicating that initialization has been performed. */
944    private boolean initialized;
945 
946    /** Log level of the instance. */
947    private Level logLevel;
948 
949    /** Modules of the instance. */
950    private final Map<ClassLoader, Modules> modules = new WeakIdentityHashMap();
951 
952    /** Invokers of the instance. */
953    private final Map<ClassLoader, Invoker> invokers = new WeakIdentityHashMap();
954 
955    /** Scopes of the instance. */
956    private final Map<ClassLoader, Map<String, Scope>> scopes = new WeakIdentityHashMap();
957 
958    /** Locators of the instance. */
959    private final Map<ClassLoader, Map<String, Locator>> locators = new WeakIdentityHashMap();
960 
961    /** Objects of the instance. */
962    private final Map<ClassLoader, Map<Object, Instance>> objects = new WeakIdentityHashMap();
963 
964    /** {@code ObjectManager} singletons. */
965    private static final Map<ClassLoader, ObjectManager> singletons = new WeakIdentityHashMap();
966 
967    /**
968     * Default {@link ObjectManagerFactory#getObjectManager(ClassLoader)} implementation.
969     *
970     * @param classLoader The class loader to use for getting the singleton instance; {@code null} to use the platform's
971     * bootstrap class loader.
972     *
973     * @return The default {@code ObjectManager} singleton instance.
974     *
975     * @see ObjectManagerFactory#getObjectManager(ClassLoader)
976     */
977    public static ObjectManager getObjectManager( final ClassLoader classLoader )
978    {
979        synchronized ( singletons )
980        {
981            final ClassLoader singletonsLoader = getClassLoader( classLoader );
982            ObjectManager manager = singletons.get( singletonsLoader );
983            if ( manager == null )
984            {
985                manager = ObjectManagerFactory.newObjectManager( classLoader );
986                singletons.put( singletonsLoader, manager );
987            }
988 
989            return (ObjectManager) manager.getObject( ObjectManager.class );
990        }
991    }
992 
993    /**
994     * Gets the list of registered listeners.
995     * <p>This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make
996     * to the returned list will be present inside the object. This is why there is no {@code set} method for the
997     * listeners property.</p>
998     *
999     * @return The list of registered listeners.
1000     */
1001    public List<Listener> getListeners()
1002    {
1003        if ( this.listeners == null )
1004        {
1005            this.listeners = new LinkedList<Listener>();
1006        }
1007 
1008        return this.listeners;
1009    }
1010 
1011    /**
1012     * Gets the default log level events are logged at.
1013     * <p>The default log level is controlled by system property
1014     * {@code org.jomc.ri.DefaultObjectManager.defaultLogLevel} holding the log level to log events at by default.
1015     * If that property is not set, the {@code WARNING} default is returned.</p>
1016     *
1017     * @return The log level events are logged at by default.
1018     *
1019     * @see #getLogLevel()
1020     * @see Level#parse(java.lang.String)
1021     */
1022    public static Level getDefaultLogLevel()
1023    {
1024        if ( defaultLogLevel == null )
1025        {
1026            defaultLogLevel = Level.parse( System.getProperty( "org.jomc.ri.DefaultObjectManager.defaultLogLevel",
1027                                                               DEFAULT_LOG_LEVEL.getName() ) );
1028 
1029        }
1030 
1031        return defaultLogLevel;
1032    }
1033 
1034    /**
1035     * Sets the default log level events are logged at.
1036     *
1037     * @param value The new default level events are logged at or {@code null}.
1038     *
1039     * @see #getDefaultLogLevel()
1040     */
1041    public static void setDefaultLogLevel( final Level value )
1042    {
1043        defaultLogLevel = value;
1044    }
1045 
1046    /**
1047     * Gets the log level of the instance.
1048     *
1049     * @return The log level of the instance.
1050     *
1051     * @see #getDefaultLogLevel()
1052     * @see #setLogLevel(java.util.logging.Level)
1053     * @see #isLoggable(java.util.logging.Level)
1054     */
1055    public Level getLogLevel()
1056    {
1057        if ( this.logLevel == null )
1058        {
1059            this.logLevel = getDefaultLogLevel();
1060            this.log( Level.CONFIG, this.getMessage( "defaultLogLevelInfo", new Object[]
1061                {
1062                    this.getClass().getCanonicalName(), this.logLevel.getLocalizedName()
1063                } ), null );
1064 
1065        }
1066 
1067        return this.logLevel;
1068    }
1069 
1070    /**
1071     * Sets the log level of the instance.
1072     *
1073     * @param value The new log level of the instance or {@code null}.
1074     *
1075     * @see #getLogLevel()
1076     * @see #isLoggable(java.util.logging.Level)
1077     */
1078    public void setLogLevel( final Level value )
1079    {
1080        this.logLevel = value;
1081    }
1082 
1083    /**
1084     * Checks if a message at a given level is provided to the listeners of the instance.
1085     *
1086     * @param level The level to test.
1087     *
1088     * @return {@code true} if messages at {@code level} are provided to the listeners of the instance;
1089     * {@code false} if messages at {@code level} are not provided to the listeners of the instance.
1090     *
1091     * @throws NullPointerException if {@code level} is {@code null}.
1092     *
1093     * @see #getLogLevel()
1094     * @see #setLogLevel(java.util.logging.Level)
1095     * @see #log(java.util.logging.Level, java.lang.String, java.lang.Throwable)
1096     */
1097    public boolean isLoggable( final Level level )
1098    {
1099        if ( level == null )
1100        {
1101            throw new NullPointerException( "level" );
1102        }
1103 
1104        return level.intValue() >= this.getLogLevel().intValue();
1105    }
1106 
1107    /**
1108     * Gets the name of the platform's bootstrap class loader class.
1109     * <p>The name of the platform's bootstrap class loader class is controlled by system property
1110     * {@code org.jomc.ri.DefaultObjectManager.bootstrapClassLoaderClassName} holding the name of the platform's
1111     * bootstrap class loader class. If that property is not set, the bootstrap class loader is assumed to be
1112     * represented by a {@code null} parent class loader.</p>
1113     *
1114     * @return The name of the platform's bootstrap class loader class or {@code null}.
1115     *
1116     * @see #getClassLoader(java.lang.ClassLoader)
1117     */
1118    public static String getBootstrapClassLoaderClassName()
1119    {
1120        if ( bootstrapClassLoaderClassName == null && !bootstrapClassLoaderClassNameInitialized )
1121        {
1122            bootstrapClassLoaderClassName =
1123                System.getProperty( "org.jomc.ri.DefaultObjectManager.bootstrapClassLoaderClassName" );
1124 
1125            bootstrapClassLoaderClassNameInitialized = true;
1126        }
1127 
1128        return bootstrapClassLoaderClassName;
1129    }
1130 
1131    /**
1132     * Sets the name of the platform's bootstrap class loader class.
1133     *
1134     * @param value The new name of the platform's bootstrap class loader class or {@code null}.
1135     *
1136     * @see #getBootstrapClassLoaderClassName()
1137     */
1138    public static void setBootstrapClassLoaderClassName( final String value )
1139    {
1140        bootstrapClassLoaderClassName = value;
1141        bootstrapClassLoaderClassNameInitialized = false;
1142    }
1143 
1144    /**
1145     * Gets the modules of a given class loader.
1146     *
1147     * @param classLoader The class loader to get the modules of.
1148     *
1149     * @return The modules of the given class loader.
1150     *
1151     * @throws NullPointerException if {@code classLoader} is {@code null},
1152     */
1153    public Modules getModules( final ClassLoader classLoader )
1154    {
1155        if ( classLoader == null )
1156        {
1157            throw new NullPointerException( "classLoader" );
1158        }
1159 
1160        synchronized ( this.modules )
1161        {
1162            Modules cachedModules = this.modules.get( classLoader );
1163 
1164            if ( cachedModules == null )
1165            {
1166                try
1167                {
1168                    final ModelContext modelContext = ModelContext.createModelContext( classLoader );
1169                    modelContext.setLogLevel( this.getLogLevel() );
1170                    modelContext.getListeners().add( new ModelContext.Listener()
1171                    {
1172 
1173                        public void onLog( final Level level, final String message, final Throwable t )
1174                        {
1175                            log( level, message, t );
1176                        }
1177 
1178                    } );
1179 
1180                    cachedModules = modelContext.findModules();
1181                    Module classpathModule =
1182                        cachedModules.getClasspathModule( Modules.getDefaultClasspathModuleName(), classLoader );
1183 
1184                    if ( classpathModule != null )
1185                    {
1186                        cachedModules.getModule().add( classpathModule );
1187                    }
1188 
1189                    cachedModules = modelContext.processModules( cachedModules );
1190 
1191                    final ModelValidationReport validationReport = modelContext.validateModel( cachedModules );
1192 
1193                    for ( ModelValidationReport.Detail d : validationReport.getDetails() )
1194                    {
1195                        this.log( d.getLevel(), d.getMessage(), null );
1196                    }
1197 
1198                    if ( validationReport.isModelValid() )
1199                    {
1200                        final ClassLoader objectsLoader = getClassLoader( classLoader );
1201                        Map<Object, Instance> objectMap = this.objects.get( objectsLoader );
1202                        if ( objectMap == null )
1203                        {
1204                            objectMap = new WeakIdentityHashMap();
1205                            this.objects.put( objectsLoader, objectMap );
1206                        }
1207 
1208                        this.modules.put( classLoader, new Modules( cachedModules, objectMap ) );
1209 
1210                        if ( this.isLoggable( Level.FINEST ) )
1211                        {
1212                            this.logModulesReport( cachedModules, classLoader );
1213                        }
1214                    }
1215                    else
1216                    {
1217                        cachedModules = null;
1218                    }
1219                }
1220                catch ( final ModelException e )
1221                {
1222                    if ( this.isLoggable( Level.SEVERE ) )
1223                    {
1224                        this.log( Level.SEVERE, e.getMessage(), e );
1225                    }
1226 
1227                    cachedModules = null;
1228                }
1229                finally
1230                {
1231                    if ( cachedModules == null )
1232                    {
1233                        cachedModules = new Modules();
1234                    }
1235                }
1236            }
1237 
1238            return cachedModules;
1239        }
1240    }
1241 
1242    /**
1243     * Gets the class loader of a given class.
1244     *
1245     * @param clazz The class whose class loader to return.
1246     *
1247     * @return The class loader of {@code clazz}.
1248     *
1249     * @throws NullPointerException if {@code clazz} is {@code null}.
1250     */
1251    public static ClassLoader getClassLoader( final Class clazz )
1252    {
1253        if ( clazz == null )
1254        {
1255            throw new NullPointerException( "clazz" );
1256        }
1257 
1258        ClassLoader cl = clazz.getClassLoader();
1259        if ( cl == null )
1260        {
1261            cl = BOOTSTRAP_CLASSLOADER;
1262        }
1263 
1264        return cl;
1265    }
1266 
1267    /**
1268     * Gets the parent class loader of a given class loader recursively.
1269     * <p>This method recursively finds the parent class loader of the given class loader. Recursion stops at the
1270     * platform's bootstrap class loader. That class loader is detected when either the current class loader has no
1271     * parent (a call to the {@code getParent()} method returns {@code null}) or when the class name of the
1272     * current class loader's parent class loader is equal to the name returned by method
1273     * {@code getBootstrapClassLoaderClassName()}. Configuration of the name of the platform's bootstrap class loader
1274     * class is needed when the platform's {@code getParent()} method of the {@code ClassLoader} class does not return
1275     * {@code null} to indicate the bootstrap class loader but instead returns an instance of {@code ClassLoader}.</p>
1276     *
1277     * @param classLoader The class loader whose parent class loader to return or {@code null} to return a
1278     * {@code ClassLoader} instance representing the platform's bootstrap class loader.
1279     *
1280     * @return The parent class loader of {@code classLoader}.
1281     *
1282     * @throws NullPointerException if {@code classLoader} is {@code null}.
1283     *
1284     * @see #getBootstrapClassLoaderClassName()
1285     * @see ClassLoader#getParent()
1286     */
1287    public static ClassLoader getClassLoader( final ClassLoader classLoader )
1288    {
1289        if ( classLoader == null )
1290        {
1291            return BOOTSTRAP_CLASSLOADER;
1292        }
1293 
1294        if ( classLoader.getParent() != null &&
1295             !classLoader.getParent().getClass().getName().equals( getBootstrapClassLoaderClassName() ) )
1296        {
1297            return getClassLoader( classLoader.getParent() );
1298        }
1299 
1300        return classLoader;
1301    }
1302 
1303    /**
1304     * Gets an object of a given instance from a given scope.
1305     *
1306     * @param scope The scope to get the object from or {@code null}.
1307     * @param instance The instance of the object to get.
1308     * @param classLoader The class loader to use for creating the object.
1309     *
1310     * @return An object of {@code instance} from {@code scope} or {@code null} if no such object is found.
1311     *
1312     * @throws NullPointerException if {@code instance} or {@code classLoader} is {@code null}.
1313     * @throws InstantiationException if creating an object fails.
1314     */
1315    public Object getObject( final Scope scope, final Instance instance, final ClassLoader classLoader )
1316        throws InstantiationException
1317    {
1318        if ( instance == null )
1319        {
1320            throw new NullPointerException( "instance" );
1321        }
1322        if ( classLoader == null )
1323        {
1324            throw new NullPointerException( "classLoader" );
1325        }
1326 
1327        Object object = null;
1328        final Modules model = this.getModules( classLoader );
1329 
1330        if ( scope != null )
1331        {
1332            synchronized ( scope )
1333            {
1334                object = scope.getObject( instance.getIdentifier() );
1335 
1336                if ( object == null )
1337                {
1338                    scope.putObject( instance.getIdentifier(), instance );
1339 
1340                    try
1341                    {
1342                        object = model.createObject( instance, classLoader );
1343                    }
1344                    finally
1345                    {
1346                        if ( object != null )
1347                        {
1348                            object = this.createProxy( instance, object );
1349                        }
1350 
1351                        scope.putObject( instance.getIdentifier(), object );
1352                    }
1353                }
1354                else if ( object instanceof Instance )
1355                {
1356                    throw new ObjectManagementException( this.getDependencyCycleMessage(
1357                        ( (Instance) object ).getIdentifier() ) );
1358 
1359                }
1360            }
1361        }
1362        else
1363        {
1364            try
1365            {
1366                object = model.createObject( instance, classLoader );
1367            }
1368            finally
1369            {
1370                if ( object != null )
1371                {
1372                    object = this.createProxy( instance, object );
1373                }
1374            }
1375        }
1376 
1377        return object;
1378    }
1379 
1380    /**
1381     * Gets an object for a given location URI.
1382     *
1383     * @param specification The specification class of the object to locate.
1384     * @param location The location URI of the object to locate.
1385     * @param classLoader The class loader to use for loading locator classes.
1386     * @param <T> The type of the object.
1387     *
1388     * @return An object located at {@code location} or {@code null} if no such object is found.
1389     *
1390     * @throws NullPointerException if {@code specification}, {@code location} or {@code classLoader} is {@code null}.
1391     * @throws InstantiationException if instantiating a locator fails.
1392     * @throws ClassNotFoundException if the class of {@code specification} is not found.
1393     * @throws IOException if locating the object fails.
1394     */
1395    public <T> T getObject( final Class<T> specification, final URI location, final ClassLoader classLoader )
1396        throws InstantiationException, ClassNotFoundException, IOException
1397    {
1398        if ( specification == null )
1399        {
1400            throw new NullPointerException( "specification" );
1401        }
1402        if ( location == null )
1403        {
1404            throw new NullPointerException( "location" );
1405        }
1406        if ( classLoader == null )
1407        {
1408            throw new NullPointerException( "classLoader" );
1409        }
1410 
1411        T object = null;
1412        final Locator locator = this.getLocator( classLoader, location );
1413 
1414        if ( locator != null )
1415        {
1416            object = locator.getObject( specification, location );
1417        }
1418        else if ( this.isLoggable( Level.WARNING ) )
1419        {
1420            this.log( Level.WARNING, this.getMissingLocatorMessage( location ), new Exception() );
1421        }
1422 
1423        return object;
1424    }
1425 
1426    /**
1427     * Gets the scope implementation for a given scope identifier.
1428     *
1429     * @param classLoader The class loader to use for loading scope implementations.
1430     * @param identifier The identifier of the scope to get an implementation of.
1431     *
1432     * @return The implementation of the scope identified by {@code identifier} or {@code null} if no such
1433     * scope implementation is found.
1434     *
1435     * @throws NullPointerException if {@code classLoader} or {@code identifier} is {@code null}.
1436     * @throws InstantiationException if instantiating a scope fails.
1437     *
1438     * @see #getDefaultScope(java.lang.String)
1439     */
1440    public Scope getScope( final ClassLoader classLoader, final String identifier ) throws InstantiationException
1441    {
1442        if ( classLoader == null )
1443        {
1444            throw new NullPointerException( "classLoader" );
1445        }
1446        if ( identifier == null )
1447        {
1448            throw new NullPointerException( "identifier" );
1449        }
1450 
1451        final Modules model = this.getModules( classLoader );
1452        final ClassLoader scopesLoader = getClassLoader( classLoader );
1453 
1454        synchronized ( this.scopes )
1455        {
1456            Map<String, Scope> cachedScopes = this.scopes.get( scopesLoader );
1457            if ( cachedScopes == null )
1458            {
1459                cachedScopes = new HashMap();
1460                this.scopes.put( scopesLoader, cachedScopes );
1461            }
1462 
1463            Scope scope = cachedScopes.get( identifier );
1464 
1465            if ( scope == null )
1466            {
1467                // Bootstrap scope loading.
1468                final Specification scopeSpecification = model.getSpecification( Scope.class );
1469 
1470                if ( scopeSpecification != null )
1471                {
1472                    final Implementations implementations =
1473                        model.getImplementations( scopeSpecification.getIdentifier() );
1474 
1475                    if ( implementations != null )
1476                    {
1477                        for ( Implementation i : implementations.getImplementation() )
1478                        {
1479                            if ( identifier.equals( i.getName() ) )
1480                            {
1481                                final Instance instance = model.getInstance( i.getIdentifier() );
1482 
1483                                if ( instance != null )
1484                                {
1485                                    scope = (Scope) model.createObject( instance, classLoader );
1486                                    cachedScopes.put( identifier, scope );
1487                                    if ( this.isLoggable( Level.CONFIG ) )
1488                                    {
1489                                        this.log( Level.CONFIG, this.getMessage( "scopeInfo", new Object[]
1490                                            {
1491                                                i.getIdentifier(), identifier, scopesLoader.toString()
1492                                            } ), null );
1493 
1494                                    }
1495                                    break;
1496                                }
1497                                else if ( this.isLoggable( Level.WARNING ) )
1498                                {
1499                                    this.log( Level.WARNING, this.getMissingInstanceMessage(
1500                                        i.getIdentifier(), i.getName() ), new Exception() );
1501 
1502                                }
1503                            }
1504                        }
1505                    }
1506                }
1507                else if ( this.isLoggable( Level.WARNING ) )
1508                {
1509                    this.log( Level.WARNING, this.getMissingSpecificationMessage( Scope.class.getName() ),
1510                              new Exception() );
1511 
1512                }
1513            }
1514 
1515            if ( scope == null )
1516            {
1517                scope = this.getDefaultScope( identifier );
1518                if ( scope != null )
1519                {
1520                    cachedScopes.put( identifier, scope );
1521                    if ( this.isLoggable( Level.CONFIG ) )
1522                    {
1523                        this.log( Level.CONFIG, this.getDefaultScopeInfoMessage( identifier, scopesLoader ), null );
1524                    }
1525                }
1526            }
1527 
1528            return scope;
1529        }
1530    }
1531 
1532    /**
1533     * Gets the default scope implementation for a given identifier.
1534     *
1535     * @param identifier The identifier of the scope to get a default implementation of.
1536     *
1537     * @return The default implementation of the scope identified by {@code identifier} or {@code null} if no such
1538     * default implementation is available.
1539     *
1540     * @throws NullPointerException if {@code identifier} is {@code null}.
1541     *
1542     * @see #getScope(java.lang.ClassLoader, java.lang.String)
1543     */
1544    public Scope getDefaultScope( final String identifier )
1545    {
1546        if ( identifier == null )
1547        {
1548            throw new NullPointerException( "identifier" );
1549        }
1550 
1551        DefaultScope defaultScope = null;
1552 
1553        if ( identifier.equals( SINGLETON_SCOPE_IDENTIFIER ) )
1554        {
1555            defaultScope = new DefaultScope( new HashMap<String, Object>() );
1556        }
1557 
1558        return defaultScope;
1559    }
1560 
1561    /**
1562     * Gets a locator to use with a given location URI.
1563     *
1564     * @param classLoader The class loader to use for loading locator implementations.
1565     * @param location The location URI to get a locator for.
1566     *
1567     * @return The locator to use for locating objects at {@code location} or {@code null} if no such locator is
1568     * available.
1569     *
1570     * @throws NullPointerException if {@code classLoader} or {@code location} is {@code null}.
1571     * @throws InstantiationException if instantiating a locator fails.
1572     *
1573     * @see #getDefaultLocator(java.net.URI)
1574     */
1575    public Locator getLocator( final ClassLoader classLoader, final URI location ) throws InstantiationException
1576    {
1577        if ( classLoader == null )
1578        {
1579            throw new NullPointerException( "classLoader" );
1580        }
1581        if ( location == null )
1582        {
1583            throw new NullPointerException( "location" );
1584        }
1585 
1586        final String scheme = location.getScheme();
1587 
1588        if ( scheme != null )
1589        {
1590            final Modules model = this.getModules( classLoader );
1591            final ClassLoader locatorsLoader = getClassLoader( classLoader );
1592 
1593            synchronized ( this.locators )
1594            {
1595                Map<String, Locator> cachedLocators = this.locators.get( locatorsLoader );
1596                if ( cachedLocators == null )
1597                {
1598                    cachedLocators = new HashMap();
1599                    this.locators.put( locatorsLoader, cachedLocators );
1600                }
1601 
1602                Locator locator = cachedLocators.get( scheme );
1603 
1604                if ( locator == null )
1605                {
1606                    // Bootstrap locator loading.
1607                    final Specification locatorSpecification = model.getSpecification( Locator.class );
1608 
1609                    if ( locatorSpecification != null )
1610                    {
1611                        final Implementations implementations =
1612                            model.getImplementations( locatorSpecification.getIdentifier() );
1613 
1614                        if ( implementations != null )
1615                        {
1616                            for ( Implementation i : implementations.getImplementation() )
1617                            {
1618                                if ( scheme.equals( i.getName() ) )
1619                                {
1620                                    final Instance instance = model.getInstance( i.getIdentifier() );
1621 
1622                                    if ( instance != null )
1623                                    {
1624                                        locator = (Locator) model.createObject( instance, classLoader );
1625                                        cachedLocators.put( scheme, locator );
1626 
1627                                        if ( this.isLoggable( Level.CONFIG ) )
1628                                        {
1629                                            this.log( Level.CONFIG, this.getMessage( "locatorInfo", new Object[]
1630                                                {
1631                                                    i.getIdentifier(), scheme, locatorsLoader.toString()
1632                                                } ), null );
1633 
1634                                        }
1635 
1636                                        break;
1637                                    }
1638                                    else if ( this.isLoggable( Level.WARNING ) )
1639                                    {
1640                                        this.log( Level.WARNING, this.getMissingInstanceMessage(
1641                                            i.getIdentifier(), i.getName() ), new Exception() );
1642 
1643                                    }
1644                                }
1645                            }
1646                        }
1647                    }
1648                    else if ( this.isLoggable( Level.WARNING ) )
1649                    {
1650                        this.log( Level.WARNING, this.getMissingSpecificationMessage( Locator.class.getName() ),
1651                                  new Exception() );
1652 
1653                    }
1654                }
1655 
1656                if ( locator == null )
1657                {
1658                    locator = this.getDefaultLocator( location );
1659                    if ( locator != null )
1660                    {
1661                        cachedLocators.put( scheme, locator );
1662                        if ( this.isLoggable( Level.CONFIG ) )
1663                        {
1664                            this.log( Level.CONFIG, this.getDefaultLocatorInfoMessage( scheme, locatorsLoader ), null );
1665                        }
1666                    }
1667                }
1668 
1669                return locator;
1670            }
1671        }
1672 
1673        return null;
1674    }
1675 
1676    /**
1677     * Gets the default locator implementation for a given location URI.
1678     *
1679     * @param location The location URI to get a default locator implementation for.
1680     *
1681     * @return The default locator implementation for {@code location} or {@code null} if no default implementation is
1682     * available for {@code location}.
1683     *
1684     * @throws NullPointerException if {@code location} is {@code null}.
1685     *
1686     * @see #getLocator(java.lang.ClassLoader, java.net.URI)
1687     */
1688    public Locator getDefaultLocator( final URI location )
1689    {
1690        if ( location == null )
1691        {
1692            throw new NullPointerException( "location" );
1693        }
1694 
1695        Locator locator = null;
1696        final DefaultLocator defaultLocator = new DefaultLocator();
1697 
1698        if ( defaultLocator.isLocationSupported( location ) )
1699        {
1700            locator = defaultLocator;
1701        }
1702 
1703        return locator;
1704    }
1705 
1706    /**
1707     * Gets the invoker of the given class loader.
1708     *
1709     * @param classLoader The class loader to use for loading invoker implementations.
1710     *
1711     * @return The invoker of the given class loader.
1712     *
1713     * @throws NullPointerException if {@code classLoader} is {@code null}.
1714     * @throws InstantiationException if instantiating a new invoker fails.
1715     */
1716    public Invoker getInvoker( final ClassLoader classLoader ) throws InstantiationException
1717    {
1718        if ( classLoader == null )
1719        {
1720            throw new NullPointerException( "classLoader" );
1721        }
1722 
1723        final Modules model = this.getModules( classLoader );
1724        final ClassLoader invokersLoader = getClassLoader( classLoader );
1725 
1726        synchronized ( this.invokers )
1727        {
1728            Invoker invoker = this.invokers.get( invokersLoader );
1729 
1730            if ( invoker == null )
1731            {
1732                final Specification invokerSpecification = model.getSpecification( Invoker.class );
1733 
1734                if ( invokerSpecification != null )
1735                {
1736                    final Implementations implementations =
1737                        model.getImplementations( invokerSpecification.getIdentifier() );
1738 
1739                    if ( implementations != null && !implementations.getImplementation().isEmpty() )
1740                    {
1741                        for ( Implementation i : implementations.getImplementation() )
1742                        {
1743                            if ( invoker == null )
1744                            {
1745                                final Instance invokerInstance = model.getInstance( i.getIdentifier() );
1746 
1747                                if ( invokerInstance != null )
1748                                {
1749                                    invoker = (Invoker) model.createObject( invokerInstance, classLoader );
1750                                    this.invokers.put( invokersLoader, invoker );
1751 
1752                                    if ( this.isLoggable( Level.CONFIG ) )
1753                                    {
1754                                        this.log( Level.CONFIG, this.getMessage( "invokerInfo", new Object[]
1755                                            {
1756                                                i.getIdentifier(), invokersLoader.toString()
1757                                            } ), null );
1758 
1759                                    }
1760                                }
1761                                else if ( this.isLoggable( Level.WARNING ) )
1762                                {
1763                                    this.log( Level.WARNING, this.getMissingInstanceMessage(
1764                                        i.getIdentifier(), i.getName() ), new Exception() );
1765 
1766                                }
1767                            }
1768                            else if ( this.isLoggable( Level.CONFIG ) )
1769                            {
1770                                this.log( Level.CONFIG, this.getMessage( "ignoredInvoker", new Object[]
1771                                    {
1772                                        i.getIdentifier()
1773                                    } ), null );
1774 
1775                            }
1776                        }
1777                    }
1778                }
1779                else if ( this.isLoggable( Level.WARNING ) )
1780                {
1781                    this.log( Level.WARNING, this.getMissingSpecificationMessage( Invoker.class.getName() ),
1782                              new Exception() );
1783 
1784                }
1785 
1786                if ( invoker == null )
1787                {
1788                    invoker = new DefaultInvoker();
1789                    this.invokers.put( invokersLoader, invoker );
1790                    if ( this.isLoggable( Level.CONFIG ) )
1791                    {
1792                        this.log( Level.CONFIG, this.getMessage( "defaultInvokerInfo", new Object[]
1793                            {
1794                                invokersLoader.toString()
1795                            } ), null );
1796 
1797                    }
1798                }
1799            }
1800 
1801            return invoker;
1802        }
1803    }
1804 
1805    /**
1806     * Gets an invocation for a given object, instance, method and arguments.
1807     *
1808     * @param object The object to invoke.
1809     * @param instance The instance of the object to invoke.
1810     * @param method The method to invoke on {@code object}.
1811     * @param arguments The arguments of the invocation or {@code null}.
1812     *
1813     * @return An invocation with {@code object}, {@code instance}, {@code method} and {@code arguments}.
1814     *
1815     * @throws NullPointerException if {@code object}, {@code instance} or {@code method} is {@code null}.
1816     * @throws InstantiationException if instantiating a new invocation fails.
1817     */
1818    public Invocation getInvocation( final Object object, final Instance instance, final Method method,
1819                                     final Object[] arguments ) throws InstantiationException
1820    {
1821        if ( object == null )
1822        {
1823            throw new NullPointerException( "object" );
1824        }
1825        if ( instance == null )
1826        {
1827            throw new NullPointerException( "instance" );
1828        }
1829        if ( method == null )
1830        {
1831            throw new NullPointerException( "method" );
1832        }
1833 
1834        Invocation invocation = null;
1835        final ClassLoader classLoader = getClassLoader( object.getClass() );
1836        final Modules model = this.getModules( classLoader );
1837        final Specification invocationSpecification = model.getSpecification( Invocation.class );
1838 
1839        if ( invocationSpecification != null )
1840        {
1841            final Implementations implementations =
1842                model.getImplementations( invocationSpecification.getIdentifier() );
1843 
1844            if ( implementations != null && !implementations.getImplementation().isEmpty() )
1845            {
1846                for ( Implementation i : implementations.getImplementation() )
1847                {
1848                    if ( invocation == null )
1849                    {
1850                        final Instance invocationInstance = model.getInstance( i.getIdentifier() );
1851 
1852                        if ( invocationInstance != null )
1853                        {
1854                            invocation = (Invocation) model.createObject( invocationInstance, classLoader );
1855                        }
1856                        else if ( this.isLoggable( Level.WARNING ) )
1857                        {
1858                            this.log( Level.WARNING, this.getMissingInstanceMessage(
1859                                i.getIdentifier(), i.getName() ), new Exception() );
1860 
1861                        }
1862                    }
1863                    else if ( this.isLoggable( Level.CONFIG ) )
1864                    {
1865                        this.log( Level.CONFIG, this.getMessage( "ignoredInvocation", new Object[]
1866                            {
1867                                i.getIdentifier()
1868                            } ), null );
1869 
1870                    }
1871                }
1872            }
1873        }
1874        else if ( this.isLoggable( Level.WARNING ) )
1875        {
1876            this.log( Level.WARNING, this.getMissingSpecificationMessage( Invocation.class.getName() ),
1877                      new Exception() );
1878 
1879        }
1880 
1881        if ( invocation == null )
1882        {
1883            invocation = new DefaultInvocation();
1884        }
1885 
1886        invocation.getContext().put( DefaultInvocation.OBJECT_KEY, object );
1887        invocation.getContext().put( DefaultInvocation.METHOD_KEY, method );
1888        invocation.getContext().put( DefaultInvocation.ARGUMENTS_KEY, arguments );
1889        invocation.getContext().put( DefaultInvocation.INSTANCE_KEY, instance );
1890        invocation.getContext().put( DefaultInvocation.MODULES_KEY, model );
1891        invocation.getContext().put( DefaultInvocation.CLASSLOADER_KEY, classLoader );
1892        return invocation;
1893    }
1894 
1895    /**
1896     * Initializes the instance.
1897     * <p>This method is called once on first usage of a new instance.</p>
1898     *
1899     * @throws InstantiationException if initialization fails.
1900     */
1901    public synchronized void initialize() throws InstantiationException
1902    {
1903        if ( !this.initialized )
1904        {
1905            final List<LogRecord> bootstrapLogRecords = new LinkedList<LogRecord>();
1906            final List<Listener> providedListeners = new LinkedList<Listener>();
1907 
1908            try
1909            {
1910                final long t0 = System.currentTimeMillis();
1911                this.initialized = true;
1912 
1913                this.listeners = null;
1914                this.modules.clear();
1915                this.invokers.clear();
1916                this.locators.clear();
1917                this.scopes.clear();
1918 
1919                Listener bootstrapListener = new Listener()
1920                {
1921 
1922                    public void onLog( final Level level, final String message, final Throwable throwable )
1923                    {
1924                        final LogRecord record = new LogRecord( level, message );
1925                        record.setThrown( throwable );
1926                        bootstrapLogRecords.add( record );
1927                    }
1928 
1929                };
1930                this.getListeners().add( bootstrapListener );
1931 
1932                final ClassLoader classLoader = getClassLoader( this.getClass() );
1933                final Modules model = this.getModules( classLoader );
1934                final Specification objectManager = model.getSpecification( ObjectManager.class );
1935                if ( objectManager == null )
1936                {
1937                    throw new InstantiationException( this.getMissingSpecificationMessage(
1938                        ObjectManager.class.getName() ) );
1939 
1940                }
1941 
1942                final Instance thisInstance = model.getInstance( this );
1943                if ( thisInstance == null )
1944                {
1945                    throw new InstantiationException( this.getMissingInstanceMessage(
1946                        this.getClass().getName(), this.getArtifactNameMessage() ) );
1947 
1948                }
1949 
1950                if ( objectManager.getScope() != null )
1951                {
1952                    final Scope scope = this.getScope( classLoader, objectManager.getScope() );
1953                    if ( scope == null )
1954                    {
1955                        throw new InstantiationException( this.getMissingScopeMessage( objectManager.getScope() ) );
1956                    }
1957 
1958                    scope.putObject( thisInstance.getIdentifier(), this );
1959                }
1960 
1961                // Bootstrap listener loading.
1962                final Specification listenerSpecification = model.getSpecification( Listener.class );
1963 
1964                if ( listenerSpecification != null )
1965                {
1966                    final Implementations implementations =
1967                        model.getImplementations( listenerSpecification.getIdentifier() );
1968 
1969                    if ( implementations != null && !implementations.getImplementation().isEmpty() )
1970                    {
1971                        for ( Implementation i : implementations.getImplementation() )
1972                        {
1973                            final Instance listenerInstance = model.getInstance( i.getIdentifier() );
1974                            if ( listenerInstance != null )
1975                            {
1976                                final Listener l = (Listener) model.createObject( listenerInstance, classLoader );
1977                                providedListeners.add( l );
1978                                this.log( Level.CONFIG, this.getRegisteredListenerMessage(
1979                                    l.getClass().getName() ), null );
1980 
1981                            }
1982                            else if ( this.isLoggable( Level.WARNING ) )
1983                            {
1984                                this.log( Level.WARNING, this.getMissingInstanceMessage(
1985                                    i.getIdentifier(), i.getName() ), null );
1986 
1987                            }
1988                        }
1989                    }
1990                    else if ( this.isLoggable( Level.WARNING ) )
1991                    {
1992                        this.log( Level.WARNING, this.getMissingImplementationsMessage(
1993                            listenerSpecification.getIdentifier() ), new Exception() );
1994 
1995                    }
1996                }
1997                else if ( this.isLoggable( Level.WARNING ) )
1998                {
1999                    this.log( Level.WARNING, this.getMissingSpecificationMessage(
2000                        Listener.class.getName() ), new Exception() );
2001 
2002                }
2003 
2004                if ( this.isLoggable( Level.FINE ) )
2005                {
2006                    this.log( Level.FINE, this.getImplementationInfoMessage(
2007                        Long.valueOf( System.currentTimeMillis() - t0 ) ), null );
2008 
2009                }
2010 
2011                this.getListeners().addAll( providedListeners );
2012                this.getListeners().remove( bootstrapListener );
2013                bootstrapListener = null;
2014 
2015                if ( !this.getListeners().isEmpty() )
2016                {
2017                    for ( LogRecord logRecord : bootstrapLogRecords )
2018                    {
2019                        this.log( logRecord.getLevel(), logRecord.getMessage(), logRecord.getThrown() );
2020                    }
2021                }
2022            }
2023            catch ( final InstantiationException e )
2024            {
2025                Throwable cause = e;
2026                if ( !bootstrapLogRecords.isEmpty() )
2027                {
2028                    for ( LogRecord r : bootstrapLogRecords )
2029                    {
2030                        if ( r.getLevel().intValue() > Level.WARNING.intValue() )
2031                        {
2032                            if ( r.getMessage() != null )
2033                            {
2034                                cause = new ObjectManagementException( r.getMessage(), cause );
2035                            }
2036                            if ( r.getThrown() != null )
2037                            {
2038                                cause = new ObjectManagementException( r.getThrown().getMessage(), cause );
2039                            }
2040                        }
2041                    }
2042                }
2043 
2044                this.listeners = null;
2045                this.modules.clear();
2046                this.invokers.clear();
2047                this.locators.clear();
2048                this.scopes.clear();
2049                this.initialized = false;
2050 
2051                throw (InstantiationException) new InstantiationException( cause.getMessage() ).initCause( cause );
2052            }
2053        }
2054    }
2055 
2056    /**
2057     * Notifies registered listeners.
2058     *
2059     * @param level The level of the event.
2060     * @param message The message of the event or {@code null}.
2061     * @param throwable The throwable of the event or {@code null}.
2062     *
2063     * @throws NullPointerException if {@code level} is {@code null}.
2064     */
2065    protected void log( final Level level, final String message, final Throwable throwable )
2066    {
2067        if ( level == null )
2068        {
2069            throw new NullPointerException( "level" );
2070        }
2071 
2072        if ( this.isLoggable( level ) )
2073        {
2074            for ( Listener l : this.getListeners() )
2075            {
2076                l.onLog( level, message, throwable );
2077            }
2078        }
2079    }
2080 
2081    /**
2082     * Creates a proxy for a given object.
2083     *
2084     * @param instance The instance of {@code object}.
2085     * @param object The object to create a proxy for.
2086     *
2087     * @return A proxy for {@code object}.
2088     *
2089     * @throws InstantiationException if creating a proxy fails.
2090     */
2091    private Object createProxy( final Instance instance, final Object object ) throws InstantiationException
2092    {
2093        try
2094        {
2095            final ClassLoader classLoader = getClassLoader( object.getClass() );
2096            final Set<Class> interfaces = new HashSet<Class>();
2097            boolean canProxy = instance.getSpecifications() != null;
2098 
2099            if ( canProxy )
2100            {
2101                for ( Specification s : instance.getSpecifications().getSpecification() )
2102                {
2103                    if ( s.getClazz() != null )
2104                    {
2105                        final Class clazz = Class.forName( s.getClazz(), true, classLoader );
2106 
2107                        if ( !clazz.isInterface() )
2108                        {
2109                            canProxy = false;
2110                            break;
2111                        }
2112 
2113                        interfaces.add( clazz );
2114                    }
2115                }
2116            }
2117 
2118            if ( canProxy && !interfaces.isEmpty() )
2119            {
2120                return Proxy.newProxyInstance( classLoader, interfaces.toArray( new Class[ interfaces.size() ] ),
2121                                               new java.lang.reflect.InvocationHandler()
2122                {
2123 
2124                    public Object invoke( final Object proxy, final Method method, final Object[] args )
2125                        throws Throwable
2126                    {
2127                        return getInvoker( classLoader ).invoke( getInvocation( object, instance, method, args ) );
2128                    }
2129 
2130                } );
2131 
2132            }
2133 
2134            return object;
2135        }
2136        catch ( final ClassNotFoundException e )
2137        {
2138            throw (InstantiationException) new InstantiationException( e.getMessage() ).initCause( e );
2139        }
2140    }
2141 
2142    private String getMessage( final String key, final Object arguments )
2143    {
2144        final ResourceBundle bundle =
2145            ResourceBundle.getBundle( DefaultObjectManager.class.getName().replace( '.', '/' ) );
2146 
2147        return new MessageFormat( bundle.getString( key ) ).format( arguments );
2148    }
2149 
2150    private String getArtifactNameMessage()
2151    {
2152        return this.getMessage( "artifactName", null );
2153    }
2154 
2155    private String getMissingSpecificationMessage( final String specification )
2156    {
2157        return this.getMessage( "missingSpecification", new Object[]
2158            {
2159                specification
2160            } );
2161 
2162    }
2163 
2164    private String getMissingImplementationsMessage( final String specification )
2165    {
2166        return this.getMessage( "missingImplementations", new Object[]
2167            {
2168                specification
2169            } );
2170 
2171    }
2172 
2173    private String getMissingImplementationMessage( final String implementationName, final String specification )
2174    {
2175        return this.getMessage( "missingImplementation", new Object[]
2176            {
2177                implementationName, specification
2178            } );
2179 
2180    }
2181 
2182    private String getMissingObjectInstanceMessage( final Object object )
2183    {
2184        return this.getMessage( "missingObjectInstance", new Object[]
2185            {
2186                object.toString()
2187            } );
2188 
2189    }
2190 
2191    private String getMissingDependencyMessage( final String dependency, final String implementation )
2192    {
2193        return this.getMessage( "missingDependency", new Object[]
2194            {
2195                dependency, implementation
2196            } );
2197    }
2198 
2199    private String getMissingPropertyMessage( final String property, final String implementation )
2200    {
2201        return this.getMessage( "missingProperty", new Object[]
2202            {
2203                property, implementation
2204            } );
2205 
2206    }
2207 
2208    private String getMissingMessageMessage( final String message, final String implementation )
2209    {
2210        return this.getMessage( "missingMessage", new Object[]
2211            {
2212                message, implementation
2213            } );
2214 
2215    }
2216 
2217    private String getMissingInstanceMessage( final String implementation, final String implementationName )
2218    {
2219        return this.getMessage( "missingInstance", new Object[]
2220            {
2221                implementation, implementationName
2222            } );
2223 
2224    }
2225 
2226    private String getMissingObjectMessage( final String implementation, final String implementationName )
2227    {
2228        return this.getMessage( "missingObject", new Object[]
2229            {
2230                implementation, implementationName
2231            } );
2232 
2233    }
2234 
2235    private String getDependencyCycleMessage( final String implementation )
2236    {
2237        return this.getMessage( "dependencyCycle", new Object[]
2238            {
2239                implementation
2240            } );
2241 
2242    }
2243 
2244    private String getImplementationInfoMessage( final Long startMillis )
2245    {
2246        return this.getMessage( "implementationInfo", new Object[]
2247            {
2248                startMillis
2249            } );
2250 
2251    }
2252 
2253    private String getDefaultScopeInfoMessage( final String modelScope, final ClassLoader classLoader )
2254    {
2255        return this.getMessage( "defaultScopeInfo", new Object[]
2256            {
2257                modelScope, classLoader.toString()
2258            } );
2259 
2260    }
2261 
2262    private String getMissingScopeMessage( final String modelScope )
2263    {
2264        return this.getMessage( "missingScope", new Object[]
2265            {
2266                modelScope
2267            } );
2268 
2269    }
2270 
2271    private String getRegisteredListenerMessage( final String listener )
2272    {
2273        return this.getMessage( "listenerInfo", new Object[]
2274            {
2275                listener
2276            } );
2277 
2278    }
2279 
2280    private String getUnsupportedMultiplicityMessage( final Multiplicity multiplicity )
2281    {
2282        return this.getMessage( "unsupportedMultiplicity", new Object[]
2283            {
2284                multiplicity
2285            } );
2286    }
2287 
2288    private String getDefaultLocatorInfoMessage( final String scheme, final ClassLoader classLoader )
2289    {
2290        return this.getMessage( "defaultLocatorInfo", new Object[]
2291            {
2292                scheme, classLoader.toString()
2293            } );
2294 
2295    }
2296 
2297    private String getMissingLocatorMessage( final URI location )
2298    {
2299        return this.getMessage( "missingLocator", new Object[]
2300            {
2301                location.toString()
2302            } );
2303 
2304    }
2305 
2306    private String getMissingSpecificationClassMessage( final Specification specification )
2307    {
2308        return this.getMessage( "missingSpecificationClass", new Object[]
2309            {
2310                specification.getIdentifier()
2311            } );
2312 
2313    }
2314 
2315    private void logModulesReport( final Modules mods, final ClassLoader classLoader )
2316    {
2317        final StringBuilder modulesInfo = new StringBuilder();
2318 
2319        this.log( Level.FINEST, this.getMessage( "modulesReport", null ), null );
2320 
2321        modulesInfo.append( "\tClassLoader:" ).append( classLoader );
2322 
2323        if ( mods.getDocumentation() != null )
2324        {
2325            modulesInfo.append( "|Documentation:" ).append( mods.getDocumentation().getText(
2326                Locale.getDefault().getLanguage() ).getValue() );
2327 
2328        }
2329 
2330        this.log( Level.FINEST, modulesInfo.toString(), null );
2331 
2332        for ( Module m : mods.getModule() )
2333        {
2334            modulesInfo.setLength( 0 );
2335            modulesInfo.append( "\tM:" ).append( m.getName() );
2336 
2337            if ( m.getVersion() != null )
2338            {
2339                modulesInfo.append( "|Version:" ).append( m.getVersion() );
2340            }
2341            if ( m.getVendor() != null )
2342            {
2343                modulesInfo.append( "|Vendor:" ).append( m.getVendor() );
2344            }
2345 
2346            this.log( Level.FINEST, modulesInfo.toString(), null );
2347            modulesInfo.setLength( 0 );
2348 
2349            if ( m.getSpecifications() != null )
2350            {
2351                for ( Specification s : m.getSpecifications().getSpecification() )
2352                {
2353                    modulesInfo.append( "\t\t" );
2354                    this.appendSpecificationInfo( s, modulesInfo );
2355                    this.log( Level.FINEST, modulesInfo.toString(), null );
2356                    modulesInfo.setLength( 0 );
2357 
2358                    final Implementations available = mods.getImplementations( s.getIdentifier() );
2359 
2360                    if ( available != null )
2361                    {
2362                        for ( Implementation i : available.getImplementation() )
2363                        {
2364                            modulesInfo.append( "\t\t\t" );
2365                            this.appendImplementationInfo( i, modulesInfo ).append( "|Module:" ).
2366                                append( mods.getModuleOfImplementation( i.getIdentifier() ).getName() );
2367 
2368                            this.log( Level.FINEST, modulesInfo.toString(), null );
2369                            modulesInfo.setLength( 0 );
2370                        }
2371                    }
2372                }
2373            }
2374 
2375            if ( m.getImplementations() != null )
2376            {
2377                for ( Implementation i : m.getImplementations().getImplementation() )
2378                {
2379                    modulesInfo.append( "\t\t" );
2380                    this.appendImplementationInfo( i, modulesInfo );
2381                    this.log( Level.FINEST, modulesInfo.toString(), null );
2382                    modulesInfo.setLength( 0 );
2383 
2384                    if ( i.getImplementations() != null )
2385                    {
2386                        modulesInfo.append( "\t\t\t" );
2387                        for ( ImplementationReference r : i.getImplementations().getReference() )
2388                        {
2389                            this.appendImplementationInfo(
2390                                mods.getImplementation( r.getIdentifier() ), modulesInfo ).append( "|Module:" ).
2391                                append( mods.getModuleOfImplementation( r.getIdentifier() ).getName() );
2392 
2393                            this.log( Level.FINEST, modulesInfo.toString(), null );
2394                            modulesInfo.setLength( 0 );
2395                        }
2396                    }
2397                    if ( i.getSpecifications() != null )
2398                    {
2399                        for ( SpecificationReference s : i.getSpecifications().getReference() )
2400                        {
2401                            modulesInfo.append( "\t\t\tS:" ).append( s.getIdentifier() );
2402 
2403                            if ( s.getVersion() != null )
2404                            {
2405                                modulesInfo.append( "|Version:" ).append( s.getVersion() );
2406                            }
2407 
2408                            modulesInfo.append( "|Module:" ).append( mods.getModuleOfSpecification(
2409                                s.getIdentifier() ).getName() );
2410 
2411                            this.log( Level.FINEST, modulesInfo.toString(), null );
2412                            modulesInfo.setLength( 0 );
2413                        }
2414                    }
2415 
2416                    if ( i.getDependencies() != null )
2417                    {
2418                        for ( Dependency d : i.getDependencies().getDependency() )
2419                        {
2420                            modulesInfo.append( "\t\t\tD:" ).append( d.getName() ).append( "|Identifier:" ).
2421                                append( d.getIdentifier() );
2422 
2423                            if ( d.getImplementationName() != null )
2424                            {
2425                                modulesInfo.append( "|Name:" ).append( d.getImplementationName() );
2426                            }
2427 
2428                            modulesInfo.append( "|Module:" ).append( mods.getModuleOfSpecification(
2429                                d.getIdentifier() ).getName() );
2430 
2431                            this.log( Level.FINEST, modulesInfo.toString(), null );
2432                            modulesInfo.setLength( 0 );
2433 
2434                            final Implementations available = mods.getImplementations( d.getIdentifier() );
2435 
2436                            if ( available != null )
2437                            {
2438                                for ( Implementation di : available.getImplementation() )
2439                                {
2440                                    modulesInfo.append( "\t\t\t\t" );
2441                                    this.appendImplementationInfo( di, modulesInfo ).append( "|Module:" ).
2442                                        append( mods.getModuleOfImplementation( di.getIdentifier() ).getName() );
2443 
2444                                    this.log( Level.FINEST, modulesInfo.toString(), null );
2445                                    modulesInfo.setLength( 0 );
2446                                }
2447                            }
2448                        }
2449                    }
2450 
2451                    if ( i.getMessages() != null )
2452                    {
2453                        for ( Message msg : i.getMessages().getMessage() )
2454                        {
2455                            modulesInfo.append( "\t\t\tM:" ).append( msg.getName() ).append( "|Text:" ).
2456                                append( msg.getTemplate().getText( Locale.getDefault().getLanguage() ).getValue() );
2457 
2458                            this.log( Level.FINEST, modulesInfo.toString(), null );
2459                            modulesInfo.setLength( 0 );
2460                        }
2461                    }
2462 
2463                    if ( i.getProperties() != null )
2464                    {
2465                        for ( Property p : i.getProperties().getProperty() )
2466                        {
2467                            modulesInfo.append( "\t\t\tP:" ).append( p.getName() );
2468                            modulesInfo.append( "|Type:" ).append( p.getType() );
2469                            modulesInfo.append( "|Value:" ).append( p.getValue() );
2470 
2471                            try
2472                            {
2473                                modulesInfo.append( "|JavaValue:" ).append( p.getJavaValue( classLoader ) );
2474                            }
2475                            catch ( final ModelException e )
2476                            {
2477                                modulesInfo.append( "|JavaValue:" ).append( e );
2478                            }
2479 
2480                            this.log( Level.FINEST, modulesInfo.toString(), null );
2481                            modulesInfo.setLength( 0 );
2482                        }
2483                    }
2484                }
2485            }
2486        }
2487    }
2488 
2489    private StringBuilder appendSpecificationInfo( final Specification s, final StringBuilder b )
2490    {
2491        b.append( "S:" ).append( s.getIdentifier() );
2492        if ( s.getVersion() != null )
2493        {
2494            b.append( "|Version:" ).append( s.getVersion() );
2495        }
2496        if ( s.getVendor() != null )
2497        {
2498            b.append( "|Vendor:" ).append( s.getVendor() );
2499        }
2500 
2501        b.append( "|Multiplicity:" ).append( s.getMultiplicity() ).append( "|Scope:" ).
2502            append( s.getScope() == null ? "Multiton" : s.getScope() );
2503 
2504        if ( s.getClazz() != null )
2505        {
2506            b.append( "|Class:" ).append( s.getClazz() );
2507        }
2508 
2509        return b;
2510    }
2511 
2512    private StringBuilder appendImplementationInfo( final Implementation i, final StringBuilder b )
2513    {
2514        b.append( "I:" ).append( i.getIdentifier() ).append( "|Name:" ).append( i.getName() ).append( "|Abstract:" ).
2515            append( i.isAbstract() ).append( "|Final:" ).append( i.isFinal() ).append( "|Stateless:" ).
2516            append( i.isStateless() );
2517 
2518        if ( i.getVersion() != null )
2519        {
2520            b.append( "|Version:" ).append( i.getVersion() );
2521        }
2522        if ( i.getVendor() != null )
2523        {
2524            b.append( "|Vendor:" ).append( i.getVendor() );
2525        }
2526        if ( i.getClazz() != null )
2527        {
2528            b.append( "|Class:" ).append( i.getClazz() );
2529        }
2530        if ( i.getLocation() != null )
2531        {
2532            b.append( "|Location:" ).append( i.getLocation() );
2533        }
2534 
2535        return b;
2536    }
2537 
2538    // SECTION-END
2539    // SECTION-START[Dependencies]
2540    // SECTION-END
2541    // SECTION-START[Properties]
2542    // SECTION-END
2543    // SECTION-START[Messages]
2544    // SECTION-END
2545}

[all classes][org.jomc.ri]
EMMA 2.0.5312 (C) Vladimir Roubtsov