EMMA Coverage Report (generated Wed Feb 03 01:24:19 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%  (2937/4272)72%  (601.5/832)

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

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