001    // SECTION-START[License Header]
002    /*
003     *   Copyright (c) 2009 The JOMC Project
004     *   Copyright (c) 2005 Christian Schulte <cs@jomc.org>
005     *   All rights reserved.
006     *
007     *   Redistribution and use in source and binary forms, with or without
008     *   modification, are permitted provided that the following conditions
009     *   are met:
010     *
011     *     o Redistributions of source code must retain the above copyright
012     *       notice, this list of conditions and the following disclaimer.
013     *
014     *     o Redistributions in binary form must reproduce the above copyright
015     *       notice, this list of conditions and the following disclaimer in
016     *       the documentation and/or other materials provided with the
017     *       distribution.
018     *
019     *   THIS SOFTWARE IS PROVIDED BY THE JOMC PROJECT AND CONTRIBUTORS "AS IS"
020     *   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
021     *   THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
022     *   PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE JOMC PROJECT OR
023     *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
024     *   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
025     *   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
026     *   OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
027     *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
028     *   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
029     *   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
030     *
031     *   $Id: DefaultObjectManager.java 751 2009-10-06 06:32:50Z schulte2005 $
032     *
033     */
034    // SECTION-END
035    package org.jomc.ri;
036    
037    import java.io.IOException;
038    import java.lang.reflect.Array;
039    import java.lang.reflect.InvocationHandler;
040    import java.lang.reflect.InvocationTargetException;
041    import java.lang.reflect.Method;
042    import java.lang.reflect.Proxy;
043    import java.net.URI;
044    import java.net.URL;
045    import java.net.URLClassLoader;
046    import java.text.MessageFormat;
047    import java.util.ArrayList;
048    import java.util.HashMap;
049    import java.util.HashSet;
050    import java.util.LinkedList;
051    import java.util.List;
052    import java.util.Locale;
053    import java.util.Map;
054    import java.util.ResourceBundle;
055    import java.util.Set;
056    import java.util.logging.Level;
057    import java.util.logging.LogRecord;
058    import java.util.logging.Logger;
059    import javax.xml.bind.JAXBException;
060    import javax.xml.transform.Transformer;
061    import javax.xml.transform.TransformerException;
062    import org.jomc.ObjectManagementException;
063    import org.jomc.ObjectManager;
064    import org.jomc.ObjectManagerFactory;
065    import org.jomc.model.DefaultModelManager;
066    import org.jomc.model.Dependency;
067    import org.jomc.model.Implementation;
068    import org.jomc.model.ImplementationReference;
069    import org.jomc.model.Implementations;
070    import org.jomc.model.Instance;
071    import org.jomc.model.Message;
072    import org.jomc.model.ModelException;
073    import org.jomc.model.ModelManager;
074    import org.jomc.model.Module;
075    import org.jomc.model.Modules;
076    import org.jomc.model.Multiplicity;
077    import org.jomc.model.Property;
078    import org.jomc.model.Specification;
079    import org.jomc.model.SpecificationReference;
080    import org.jomc.spi.Listener;
081    import org.jomc.spi.Locator;
082    import org.jomc.spi.Scope;
083    import org.xml.sax.SAXException;
084    
085    // SECTION-START[Documentation]
086    /**
087     * Object management and configuration reference implementation.
088     * <p><b>Specifications</b><ul>
089     * <li>{@code org.jomc.ObjectManager} {@code 1.0} {@code Singleton}</li>
090     * </ul></p>
091     *
092     * @author <a href="mailto:cs@jomc.org">Christian Schulte</a> 1.0
093     * @version $Id: DefaultObjectManager.java 751 2009-10-06 06:32:50Z schulte2005 $
094     */
095    // SECTION-END
096    // SECTION-START[Annotations]
097    @javax.annotation.Generated( value = "org.jomc.tools.JavaSources",
098                                 comments = "See http://jomc.sourceforge.net/jomc/1.0-alpha-5/jomc-tools" )
099    // SECTION-END
100    public class DefaultObjectManager implements ObjectManager
101    {
102        // SECTION-START[Constructors]
103    
104        /** Creates a new {@code DefaultObjectManager} instance. */
105        @javax.annotation.Generated( value = "org.jomc.tools.JavaSources",
106                                     comments = "See http://jomc.sourceforge.net/jomc/1.0-alpha-5/jomc-tools" )
107        public DefaultObjectManager()
108        {
109            // SECTION-START[Default Constructor]
110            super();
111            // SECTION-END
112        }
113        // SECTION-END
114        // SECTION-START[ObjectManager]
115    
116        public Object getObject( final Class specification )
117        {
118            if ( specification == null )
119            {
120                throw new NullPointerException( "specification" );
121            }
122    
123            Object object = null;
124    
125            try
126            {
127                this.initialize();
128    
129                final Specification s = this.getModules().getSpecification( specification );
130    
131                if ( s != null )
132                {
133                    final Implementations available = this.getModules().getImplementations( s.getIdentifier() );
134    
135                    if ( available != null && !available.getImplementation().isEmpty() )
136                    {
137                        if ( s.getMultiplicity() == Multiplicity.ONE )
138                        {
139                            final Implementation i = available.getImplementation().get( 0 );
140    
141                            if ( i.getLocation() != null )
142                            {
143                                object = this.getObject( s, i.getLocationUri(), this.getClassLoader( specification ) );
144                                if ( object == null )
145                                {
146                                    this.log( Level.WARNING, this.getMissingObjectMessage(
147                                        i.getIdentifier(), i.getName() ), new Exception() );
148    
149                                }
150                            }
151                            else if ( !i.isAbstract() )
152                            {
153                                final Instance instance = this.getModelManager().getInstance(
154                                    this.getModules(), i, this.getClassLoader( specification ) );
155    
156                                if ( instance != null )
157                                {
158                                    object = this.getObject( s, instance );
159                                    if ( object == null )
160                                    {
161                                        this.log( Level.WARNING, this.getMissingObjectMessage(
162                                            i.getIdentifier(), i.getName() ), new Exception() );
163    
164                                    }
165                                }
166                                else
167                                {
168                                    this.log( Level.WARNING, this.getMissingInstanceMessage(
169                                        i.getIdentifier(), i.getName() ), new Exception() );
170    
171                                }
172                            }
173                        }
174                        else if ( s.getMultiplicity() == Multiplicity.MANY )
175                        {
176                            final List<Object> list = new ArrayList<Object>( available.getImplementation().size() );
177    
178                            for ( Implementation i : available.getImplementation() )
179                            {
180                                if ( i.getLocation() != null )
181                                {
182                                    final Object o =
183                                        this.getObject( s, i.getLocationUri(), this.getClassLoader( specification ) );
184    
185                                    if ( o != null )
186                                    {
187                                        list.add( o );
188                                    }
189                                    else
190                                    {
191                                        this.log( Level.WARNING, this.getMissingObjectMessage(
192                                            i.getIdentifier(), i.getName() ), new Exception() );
193    
194                                    }
195                                }
196                                else if ( !i.isAbstract() )
197                                {
198                                    final Instance instance = this.getModelManager().getInstance(
199                                        this.getModules(), i, this.getClassLoader( specification ) );
200    
201                                    if ( instance != null )
202                                    {
203                                        final Object o = this.getObject( s, instance );
204                                        if ( o != null )
205                                        {
206                                            list.add( o );
207                                        }
208                                        else
209                                        {
210                                            this.log( Level.WARNING, this.getMissingObjectMessage(
211                                                i.getIdentifier(), i.getName() ), new Exception() );
212    
213                                        }
214                                    }
215                                    else
216                                    {
217                                        this.log( Level.WARNING, this.getMissingInstanceMessage(
218                                            i.getIdentifier(), i.getName() ), new Exception() );
219    
220                                    }
221                                }
222                            }
223    
224                            object = list.isEmpty() ? null
225                                     : list.toArray( (Object[]) Array.newInstance( specification, list.size() ) );
226    
227                        }
228                        else
229                        {
230                            this.log( Level.WARNING, this.getUnsupportedMultiplicityMessage( s.getMultiplicity() ),
231                                      new Exception() );
232    
233                        }
234                    }
235                    else
236                    {
237                        this.log( Level.WARNING, this.getMissingImplementationsMessage( specification.getName() ),
238                                  new Exception() );
239    
240                    }
241                }
242                else
243                {
244                    this.log( Level.WARNING, this.getMissingSpecificationMessage( specification.getName() ),
245                              new Exception() );
246    
247                }
248            }
249            catch ( final Exception e )
250            {
251                throw new ObjectManagementException( e.getMessage(), e );
252            }
253    
254            return object;
255        }
256    
257        public Object getObject( final Class specification, final String implementationName )
258        {
259            if ( specification == null )
260            {
261                throw new NullPointerException( "specification" );
262            }
263            if ( implementationName == null )
264            {
265                throw new NullPointerException( "implementationName" );
266            }
267    
268            Object object = null;
269    
270            try
271            {
272                this.initialize();
273    
274                final Specification s = this.getModules().getSpecification( specification );
275    
276                if ( s != null )
277                {
278                    final Implementations available = this.getModules().getImplementations( s.getIdentifier() );
279                    if ( available != null && !available.getImplementation().isEmpty() )
280                    {
281                        final Implementation i = available.getImplementationByName( implementationName );
282    
283                        if ( i != null )
284                        {
285                            if ( i.getLocation() != null )
286                            {
287                                object = this.getObject( s, i.getLocationUri(), this.getClassLoader( specification ) );
288                                if ( object == null )
289                                {
290                                    this.log( Level.WARNING, this.getMissingObjectMessage(
291                                        i.getIdentifier(), i.getName() ), new Exception() );
292    
293                                }
294                            }
295                            else if ( !i.isAbstract() )
296                            {
297                                final Instance instance = this.getModelManager().getInstance(
298                                    this.getModules(), i, this.getClassLoader( specification ) );
299    
300                                if ( instance != null )
301                                {
302                                    object = this.getObject( s, instance );
303                                    if ( object == null )
304                                    {
305                                        this.log( Level.WARNING, this.getMissingObjectMessage(
306                                            i.getIdentifier(), i.getName() ), new Exception() );
307    
308                                    }
309                                }
310                                else
311                                {
312                                    this.log( Level.WARNING, this.getMissingInstanceMessage(
313                                        i.getIdentifier(), i.getName() ), new Exception() );
314    
315                                }
316                            }
317                        }
318                        else
319                        {
320                            this.log( Level.WARNING, this.getMissingImplementationMessage(
321                                implementationName, s.getIdentifier() ), new Exception() );
322    
323                        }
324                    }
325                    else
326                    {
327                        this.log( Level.WARNING, this.getMissingImplementationsMessage(
328                            specification.getName() ), new Exception() );
329    
330                    }
331                }
332                else
333                {
334                    this.log( Level.WARNING, this.getMissingSpecificationMessage( specification.getName() ),
335                              new Exception() );
336    
337                }
338            }
339            catch ( final Exception e )
340            {
341                throw new ObjectManagementException( e.getMessage(), e );
342            }
343    
344            return object;
345        }
346    
347        public Object getDependency( final Object object, final String dependencyName )
348        {
349            if ( object == null )
350            {
351                throw new NullPointerException( "object" );
352            }
353            if ( dependencyName == null )
354            {
355                throw new NullPointerException( "dependencyName" );
356            }
357    
358            Object o = null;
359    
360            try
361            {
362                this.initialize();
363                final Instance instance = this.getModelManager().getInstance( this.getModules(), object );
364    
365                if ( instance != null )
366                {
367                    synchronized ( instance )
368                    {
369                        o = instance.getDependencyObjects().get( dependencyName );
370    
371                        if ( o == null )
372                        {
373                            final Dependency dependency = instance.getDependencies() != null
374                                                          ? instance.getDependencies().getDependency( dependencyName )
375                                                          : null;
376    
377                            if ( dependency != null )
378                            {
379                                final Specification ds = this.getModules().getSpecification( dependency.getIdentifier() );
380    
381                                if ( ds != null )
382                                {
383                                    final Implementations available =
384                                        this.getModules().getImplementations( ds.getIdentifier() );
385    
386                                    if ( available != null && !available.getImplementation().isEmpty() )
387                                    {
388                                        if ( dependency.getImplementationName() != null )
389                                        {
390                                            final Implementation i =
391                                                available.getImplementationByName( dependency.getImplementationName() );
392    
393                                            if ( i != null )
394                                            {
395                                                if ( i.getLocation() != null )
396                                                {
397                                                    o = this.getObject(
398                                                        ds, i.getLocationUri(), this.getClassLoader( object.getClass() ) );
399    
400                                                    if ( o == null )
401                                                    {
402                                                        this.log( Level.WARNING, this.getMissingObjectMessage(
403                                                            i.getIdentifier(), i.getName() ), new Exception() );
404    
405                                                    }
406                                                }
407                                                else if ( !i.isAbstract() )
408                                                {
409                                                    final Instance di = this.getModelManager().getInstance(
410                                                        this.getModules(), i, dependency,
411                                                        this.getClassLoader( object.getClass() ) );
412    
413                                                    if ( di != null )
414                                                    {
415                                                        o = this.getObject( ds, di );
416                                                        if ( o == null )
417                                                        {
418                                                            this.log( Level.WARNING, this.getMissingObjectMessage(
419                                                                i.getIdentifier(), i.getName() ), new Exception() );
420    
421                                                        }
422                                                    }
423                                                    else
424                                                    {
425                                                        this.log( Level.WARNING, this.getMissingInstanceMessage(
426                                                            i.getIdentifier(), i.getName() ), new Exception() );
427    
428                                                    }
429                                                }
430                                            }
431                                            else if ( !dependency.isOptional() )
432                                            {
433                                                this.log( Level.WARNING, this.getMissingImplementationMessage(
434                                                    dependency.getImplementationName(), dependency.getIdentifier() ),
435                                                          new Exception() );
436    
437                                            }
438                                        }
439                                        else if ( ds.getMultiplicity() == Multiplicity.ONE )
440                                        {
441                                            final Implementation ref = available.getImplementation().get( 0 );
442                                            if ( ref.getLocation() != null )
443                                            {
444                                                o = this.getObject(
445                                                    ds, ref.getLocationUri(), this.getClassLoader( object.getClass() ) );
446    
447                                                if ( o == null )
448                                                {
449                                                    this.log( Level.WARNING, this.getMissingObjectMessage(
450                                                        ref.getIdentifier(), ref.getName() ), new Exception() );
451    
452                                                }
453                                            }
454                                            else if ( !ref.isAbstract() )
455                                            {
456                                                final Instance di = this.getModelManager().getInstance(
457                                                    this.getModules(), ref, dependency,
458                                                    this.getClassLoader( object.getClass() ) );
459    
460                                                if ( di != null )
461                                                {
462                                                    o = this.getObject( ds, di );
463                                                    if ( o == null )
464                                                    {
465                                                        this.log( Level.WARNING, this.getMissingObjectMessage(
466                                                            ref.getIdentifier(), ref.getName() ), new Exception() );
467    
468                                                    }
469                                                }
470                                                else
471                                                {
472                                                    this.log( Level.WARNING, this.getMissingInstanceMessage(
473                                                        ref.getIdentifier(), ref.getName() ), new Exception() );
474    
475                                                }
476                                            }
477                                        }
478                                        else
479                                        {
480                                            final List<Object> list =
481                                                new ArrayList<Object>( available.getImplementation().size() );
482    
483                                            for ( Implementation a : available.getImplementation() )
484                                            {
485                                                if ( a.getLocation() != null )
486                                                {
487                                                    final Object o2 = this.getObject(
488                                                        ds, a.getLocationUri(), this.getClassLoader( object.getClass() ) );
489    
490                                                    if ( o2 != null )
491                                                    {
492                                                        list.add( o2 );
493                                                    }
494                                                    else
495                                                    {
496                                                        this.log( Level.WARNING, this.getMissingObjectMessage(
497                                                            a.getIdentifier(), a.getName() ), new Exception() );
498    
499                                                    }
500                                                }
501                                                else if ( !a.isAbstract() )
502                                                {
503                                                    final Instance di = this.getModelManager().getInstance(
504                                                        this.getModules(), a, dependency,
505                                                        this.getClassLoader( object.getClass() ) );
506    
507                                                    if ( di != null )
508                                                    {
509                                                        final Object o2 = this.getObject( ds, di );
510    
511                                                        if ( o2 != null )
512                                                        {
513                                                            list.add( o2 );
514                                                        }
515                                                        else
516                                                        {
517                                                            this.log( Level.WARNING, this.getMissingObjectMessage(
518                                                                a.getIdentifier(), a.getName() ), new Exception() );
519    
520                                                        }
521                                                    }
522                                                    else
523                                                    {
524                                                        this.log( Level.WARNING, this.getMissingInstanceMessage(
525                                                            a.getIdentifier(), a.getName() ), new Exception() );
526    
527                                                    }
528                                                }
529                                            }
530    
531                                            final Class specClass = Class.forName(
532                                                ds.getClazz(), true, this.getClassLoader( object.getClass() ) );
533    
534                                            o = list.isEmpty() ? null : list.toArray( (Object[]) Array.newInstance(
535                                                specClass, list.size() ) );
536    
537                                        }
538    
539                                        if ( o != null && dependency.isBound() )
540                                        {
541                                            instance.getDependencyObjects().put( dependencyName, o );
542                                        }
543                                    }
544                                    else if ( !dependency.isOptional() )
545                                    {
546                                        this.log( Level.WARNING, this.getMissingImplementationsMessage(
547                                            dependency.getIdentifier() ), new Exception() );
548    
549                                    }
550                                }
551                                else
552                                {
553                                    this.log( Level.WARNING, this.getMissingSpecificationMessage(
554                                        dependency.getIdentifier() ), new Exception() );
555    
556                                }
557                            }
558                            else
559                            {
560                                this.log( Level.WARNING, this.getMissingDependencyMessage(
561                                    dependencyName, instance.getIdentifier() ), new Exception() );
562    
563                            }
564                        }
565                    }
566                }
567                else
568                {
569                    this.log( Level.WARNING, this.getMissingObjectInstanceMessage( object ), new Exception() );
570                }
571            }
572            catch ( final Exception e )
573            {
574                throw new ObjectManagementException( e.getMessage(), e );
575            }
576    
577            return o;
578        }
579    
580        public Object getProperty( final Object object, final String propertyName )
581        {
582            if ( object == null )
583            {
584                throw new NullPointerException( "object" );
585            }
586            if ( propertyName == null )
587            {
588                throw new NullPointerException( "propertyName" );
589            }
590    
591            Object value = null;
592    
593            try
594            {
595                this.initialize();
596    
597                final Instance instance = this.getModelManager().getInstance( this.getModules(), object );
598    
599                if ( instance != null )
600                {
601                    synchronized ( instance )
602                    {
603                        value = instance.getPropertyObjects().get( propertyName );
604    
605                        if ( value == null )
606                        {
607                            final Property property = instance.getProperties() != null
608                                                      ? instance.getProperties().getProperty( propertyName )
609                                                      : null;
610    
611                            if ( property != null )
612                            {
613                                value = property.getJavaValue( this.getClassLoader( object.getClass() ) );
614    
615                                if ( value != null )
616                                {
617                                    instance.getPropertyObjects().put( propertyName, value );
618                                }
619                            }
620                            else
621                            {
622                                this.log( Level.WARNING, this.getMissingPropertyMessage(
623                                    propertyName, object.getClass().getName() ), new Exception() );
624    
625                            }
626                        }
627                    }
628                }
629                else
630                {
631                    this.log( Level.WARNING, this.getMissingObjectInstanceMessage( object ), new Exception() );
632                }
633            }
634            catch ( final Exception e )
635            {
636                throw new ObjectManagementException( e.getMessage(), e );
637            }
638    
639            return value;
640        }
641    
642        public String getMessage( final Object object, final String messageName, final Locale locale,
643                                  final Object arguments )
644        {
645            if ( object == null )
646            {
647                throw new NullPointerException( "object" );
648            }
649            if ( messageName == null )
650            {
651                throw new NullPointerException( "messageName" );
652            }
653            if ( locale == null )
654            {
655                throw new NullPointerException( "locale" );
656            }
657    
658            String text = null;
659    
660            try
661            {
662                this.initialize();
663    
664                final Instance instance = this.getModelManager().getInstance( this.getModules(), object );
665    
666                if ( instance != null )
667                {
668                    synchronized ( instance )
669                    {
670                        final Message message = instance.getMessages() != null
671                                                ? instance.getMessages().getMessage( messageName )
672                                                : null;
673    
674                        if ( message != null && message.getTemplate() != null )
675                        {
676                            final MessageFormat fmt = new MessageFormat( message.getTemplate().
677                                getText( locale.getLanguage().toLowerCase( Locale.ENGLISH ) ).getValue(), locale );
678    
679                            text = fmt.format( arguments );
680                        }
681                        else
682                        {
683                            this.log( Level.WARNING, this.getMissingMessageMessage(
684                                messageName, object.getClass().getName() ), new Exception() );
685    
686                        }
687                    }
688                }
689                else
690                {
691                    this.log( Level.WARNING, this.getMissingObjectInstanceMessage( object ), new Exception() );
692                }
693            }
694            catch ( final Exception e )
695            {
696                throw new ObjectManagementException( e.getMessage(), e );
697            }
698    
699            return text;
700        }
701    
702        // SECTION-END
703        // SECTION-START[DefaultObjectManager]
704        /** Constant for the {@code Singleton} scope identifier. */
705        protected static final String SINGLETON_SCOPE_IDENTIFIER = "Singleton";
706    
707        /** Empty {@code URL} array. */
708        private static final URL[] NO_URLS =
709        {
710        };
711    
712        /** Singleton instance. */
713        private static final ObjectManager singleton = ObjectManagerFactory.newObjectManager();
714    
715        /** The modules of the instance. */
716        private Modules modules;
717    
718        /** The model manager of the instance. */
719        private ModelManager modelManager;
720    
721        /** Scopes of the instance. */
722        private final Map<String, Scope> scopes = new HashMap<String, Scope>();
723    
724        /** Locators of the instance. */
725        private final Map<String, Locator> locators = new HashMap<String, Locator>();
726    
727        /** Listeners of the instance. */
728        private List<Listener> listeners;
729    
730        /** Flag indicating that initialization has been performed. */
731        private boolean initialized;
732    
733        /** Flag indicating classpath awareness. */
734        private Boolean classpathAware;
735    
736        /**
737         * Bootstrap {@code LogRecord}s.
738         * @see #initialize()
739         */
740        private final List<LogRecord> bootstrapLogRecords = new LinkedList<LogRecord>();
741    
742        /** {@code DefaultModelManager.Listener} of the instance. */
743        private final DefaultModelManager.Listener defaultModelManagerListener = new DefaultModelManager.Listener()
744        {
745    
746            public void onLog( final Level level, final String message, final Throwable t )
747            {
748                log( level, message, t );
749            }
750    
751        };
752    
753        /** Bootstrap {@code ObjectManagementListener}. */
754        private final Listener bootstrapObjectManagementListener = new Listener()
755        {
756    
757            public void onLog( final Level level, final String message, final Throwable throwable )
758            {
759                final LogRecord record = new LogRecord( level, message );
760                record.setThrown( throwable );
761                bootstrapLogRecords.add( record );
762            }
763    
764        };
765    
766        /**
767         * Default {@link ObjectManagerFactory#getObjectManager()} implementation backed by static field.
768         *
769         * @return The default {@code ObjectManager} singleton instance.
770         */
771        public static ObjectManager getObjectManager()
772        {
773            return (ObjectManager) singleton.getObject( ObjectManager.class );
774        }
775    
776        /**
777         * Gets a flag indicating that classpath resolution is performed.
778         * <p>Classpath resolution is performed by default. It can be disabled by setting the system property
779         * {@code org.jomc.ri.DefaultObjectManager.classpathAware} to {@code false}.</p>
780         *
781         * @return {@code true} if the class loader of the instance is searched for resources; {@code false} if no
782         * classpath resolution is performed.
783         */
784        public boolean isClasspathAware()
785        {
786            if ( this.classpathAware == null )
787            {
788                this.classpathAware = Boolean.valueOf(
789                    System.getProperty( "org.jomc.ri.DefaultObjectManager.classpathAware", Boolean.TRUE.toString() ) );
790    
791            }
792    
793            return this.classpathAware;
794        }
795    
796        /**
797         * Sets the flag indicating that classpath resolution should be performed.
798         *
799         * @param value {@code true} if the class loader of the instance is searched for resources; {@code false} if no
800         * classpath resolution is performed.
801         */
802        public void setClasspathAware( final boolean value )
803        {
804            this.classpathAware = value;
805            this.initialized = false;
806        }
807    
808        /**
809         * Gets the list of registered listeners.
810         *
811         * @return The list of registered listeners.
812         */
813        public List<Listener> getListeners()
814        {
815            if ( this.listeners == null )
816            {
817                this.listeners = new LinkedList<Listener>();
818            }
819    
820            return this.listeners;
821        }
822    
823        /**
824         * Gets the modules of the instance.
825         *
826         * @return The modules of the instance.
827         */
828        public Modules getModules()
829        {
830            if ( this.modules == null )
831            {
832                try
833                {
834                    if ( this.isClasspathAware() && this.getModelManager() instanceof DefaultModelManager )
835                    {
836                        final DefaultModelManager defaultModelManager = (DefaultModelManager) this.getModelManager();
837    
838                        Modules defaultModules = defaultModelManager.getClasspathModules(
839                            defaultModelManager.getDefaultDocumentLocation() );
840    
841                        final Module classpathModule = defaultModelManager.getClasspathModule( defaultModules );
842                        if ( classpathModule != null )
843                        {
844                            defaultModules.getModule().add( classpathModule );
845                        }
846    
847                        final List<Transformer> defaultTransformers = defaultModelManager.getClasspathTransformers(
848                            defaultModelManager.getDefaultStylesheetLocation() );
849    
850                        for ( Transformer t : defaultTransformers )
851                        {
852                            defaultModules = defaultModelManager.transformModelObject(
853                                defaultModelManager.getObjectFactory().createModules( defaultModules ), t );
854    
855                        }
856    
857                        this.getModelManager().validateModules( defaultModules );
858                        this.modules = defaultModules;
859                    }
860                }
861                catch ( final ModelException e )
862                {
863                    this.log( Level.SEVERE, e.getMessage(), e );
864                    for ( ModelException.Detail d : e.getDetails() )
865                    {
866                        this.log( d.getLevel(), d.getMessage(), null );
867                    }
868                }
869                catch ( final TransformerException e )
870                {
871                    this.log( Level.SEVERE, e.getMessage(), e );
872                }
873                catch ( final IOException e )
874                {
875                    this.log( Level.SEVERE, e.getMessage(), e );
876                }
877                catch ( final SAXException e )
878                {
879                    this.log( Level.SEVERE, e.getMessage(), e );
880                }
881                catch ( final JAXBException e )
882                {
883                    this.log( Level.SEVERE, e.getMessage(), e );
884                }
885                finally
886                {
887                    if ( this.modules == null )
888                    {
889                        this.modules = new Modules();
890                    }
891                }
892            }
893    
894            return this.modules;
895        }
896    
897        /**
898         * Sets the modules of the instance.
899         *
900         * @param value The new modules of the instance.
901         */
902        public void setModules( final Modules value )
903        {
904            this.modules = value;
905            this.initialized = false;
906        }
907    
908        /**
909         * Gets the model manager backing the instance.
910         *
911         * @return The model manager backing the instance.
912         */
913        public ModelManager getModelManager()
914        {
915            if ( this.modelManager == null )
916            {
917                final DefaultModelManager defaultManager = new DefaultModelManager();
918                defaultManager.setClassLoader( this.getClassLoader( this.getClass() ) );
919                defaultManager.getListeners().add( this.defaultModelManagerListener );
920                this.modelManager = defaultManager;
921            }
922    
923            return this.modelManager;
924        }
925    
926        /**
927         * Gets the class loader of a given class.
928         *
929         * @param clazz The class whose class loader to return.
930         *
931         * @return The class loader of {@code clazz}.
932         *
933         * @throws NullPointerException if {@code clazz} is {@code null}.
934         */
935        public ClassLoader getClassLoader( final Class clazz )
936        {
937            if ( clazz == null )
938            {
939                throw new NullPointerException( "clazz" );
940            }
941    
942            ClassLoader cl = clazz.getClassLoader();
943            if ( cl == null )
944            {
945                cl = ClassLoader.getSystemClassLoader();
946            }
947    
948            if ( cl == null )
949            {
950                this.log( Level.WARNING, this.getMissingClassLoaderMessage(), new Exception() );
951                cl = new URLClassLoader( NO_URLS );
952            }
953    
954            return cl;
955        }
956    
957        /**
958         * Gets an object of a given instance.
959         *
960         * @param specification The specification specifying the object to return.
961         * @param instance The instance of the object to get.
962         *
963         * @return An object of {@code instance} or {@code null} if nothing could be resolved.
964         *
965         * @throws NullPointerException if {@code specification} or {@code instance} is {@code null}.
966         * @throws InstantiationException if getting an object fails.
967         */
968        public Object getObject( final Specification specification, final Instance instance ) throws InstantiationException
969        {
970            if ( specification == null )
971            {
972                throw new NullPointerException( "specification" );
973            }
974            if ( instance == null )
975            {
976                throw new NullPointerException( "instance" );
977            }
978    
979            Object object = null;
980            if ( specification.getScope() != null )
981            {
982                final Scope scope = this.getScope( specification.getScope() );
983    
984                if ( scope != null )
985                {
986                    synchronized ( scope )
987                    {
988                        object = scope.getObject( instance.getIdentifier() );
989    
990                        if ( object == null )
991                        {
992                            scope.putObject( instance.getIdentifier(), instance );
993    
994                            try
995                            {
996                                object = this.getModelManager().getObject( this.getModules(), specification, instance );
997                            }
998                            finally
999                            {
1000                                if ( object != null )
1001                                {
1002                                    object = this.createProxy( specification, instance, object );
1003                                }
1004    
1005                                scope.putObject( instance.getIdentifier(), object );
1006                            }
1007                        }
1008                        else if ( object instanceof Instance )
1009                        {
1010                            throw new ObjectManagementException( this.getDependencyCycleMessage(
1011                                ( (Instance) object ).getIdentifier() ) );
1012    
1013                        }
1014                    }
1015                }
1016                else
1017                {
1018                    this.log( Level.WARNING, this.getMissingScopeMessage( specification.getScope() ), new Exception() );
1019                }
1020            }
1021            else
1022            {
1023                try
1024                {
1025                    object = this.getModelManager().getObject( this.getModules(), specification, instance );
1026                }
1027                finally
1028                {
1029                    if ( object != null )
1030                    {
1031                        object = this.createProxy( specification, instance, object );
1032                    }
1033                }
1034            }
1035    
1036            return object;
1037        }
1038    
1039        /**
1040         * Gets an object for a given location URI.
1041         *
1042         * @param specification The specification specifying the object to return.
1043         * @param location The location URI of the object to return.
1044         * @param classLoader The class loader of {@code specification}.
1045         *
1046         * @return An object located at {@code location} or {@code null} if nothing could be resolved.
1047         *
1048         * @throws NullPointerException if {@code specification}, {@code location} or {@code classLoader} is {@code null}.
1049         * @throws InstantiationException if instantiating a locator fails.
1050         * @throws ClassNotFoundException if the class of {@code specification} is not found.
1051         * @throws IOException if locating the object fails.
1052         */
1053        public Object getObject( final Specification specification, final URI location, final ClassLoader classLoader )
1054            throws InstantiationException, ClassNotFoundException, IOException
1055        {
1056            if ( specification == null )
1057            {
1058                throw new NullPointerException( "specification" );
1059            }
1060            if ( location == null )
1061            {
1062                throw new NullPointerException( "location" );
1063            }
1064            if ( classLoader == null )
1065            {
1066                throw new NullPointerException( "classLoader" );
1067            }
1068    
1069            Object object = null;
1070            final Locator locator = this.getLocator( location );
1071    
1072            if ( locator != null )
1073            {
1074                object = locator.getObject( Class.forName( specification.getClazz(), true, classLoader ), location );
1075            }
1076            else
1077            {
1078                this.log( Level.WARNING, this.getMissingLocatorMessage( location ), new Exception() );
1079            }
1080    
1081            return object;
1082        }
1083    
1084        /**
1085         * Gets the scope implementation for a given model scope.
1086         *
1087         * @param modelScope The scope to get an implementation of.
1088         *
1089         * @return The implementation of {@code modelScope} or {@code null} if no implementation is available implementing
1090         * {@code modelScope}.
1091         *
1092         * @throws NullPointerException if {@code modelScope} is {@code null}.
1093         * @throws InstantiationException if instantiating a scope fails.
1094         */
1095        public Scope getScope( final String modelScope ) throws InstantiationException
1096        {
1097            if ( modelScope == null )
1098            {
1099                throw new NullPointerException( "modelScope" );
1100            }
1101    
1102            synchronized ( this.scopes )
1103            {
1104                Scope scope = this.scopes.get( modelScope );
1105    
1106                if ( scope == null )
1107                {
1108                    // Bootstrap scope loading.
1109                    final Specification scopeSpecification = this.getModules().getSpecification( Scope.class );
1110    
1111                    if ( scopeSpecification != null )
1112                    {
1113                        final Implementations implementations =
1114                            this.getModules().getImplementations( scopeSpecification.getIdentifier() );
1115    
1116                        if ( implementations != null )
1117                        {
1118                            for ( Implementation i : implementations.getImplementation() )
1119                            {
1120                                if ( modelScope.equals( i.getName() ) )
1121                                {
1122                                    final Instance instance = this.getModelManager().getInstance(
1123                                        this.getModules(), i, this.getClassLoader( Scope.class ) );
1124    
1125                                    scope = (Scope) this.getModelManager().getObject(
1126                                        this.getModules(), scopeSpecification, instance );
1127    
1128                                    this.scopes.put( modelScope, scope );
1129                                    this.log( Level.CONFIG, this.getMessage( "scopeInfo", new Object[]
1130                                        {
1131                                            i.getIdentifier(), modelScope
1132                                        } ), null );
1133    
1134                                    break;
1135                                }
1136                            }
1137                        }
1138                    }
1139                    else
1140                    {
1141                        this.log( Level.WARNING, this.getMissingSpecificationMessage( Scope.class.getName() ),
1142                                  new Exception() );
1143    
1144                    }
1145                }
1146    
1147                if ( scope == null )
1148                {
1149                    scope = this.getDefaultScope( modelScope );
1150                    if ( scope != null )
1151                    {
1152                        this.scopes.put( modelScope, scope );
1153                        this.log( Level.FINE, this.getDefaultScopeInfoMessage( modelScope, scope.getObjects() ), null );
1154                    }
1155                }
1156    
1157                return scope;
1158            }
1159        }
1160    
1161        /**
1162         * Gets the default scope implementation for a given model scope.
1163         *
1164         * @param modelScope The scope to get the default implementation of.
1165         *
1166         * @return The default implementation of {@code modelScope} or {@code null} if no default implementation is
1167         * available implementing {@code modelScope}.
1168         *
1169         * @throws NullPointerException if {@code modelScope} is {@code null}.
1170         */
1171        public Scope getDefaultScope( final String modelScope )
1172        {
1173            if ( modelScope == null )
1174            {
1175                throw new NullPointerException( "modelScope" );
1176            }
1177    
1178            DefaultScope defaultScope = null;
1179    
1180            if ( modelScope.equals( SINGLETON_SCOPE_IDENTIFIER ) )
1181            {
1182                defaultScope = new DefaultScope( new HashMap<String, Object>() );
1183            }
1184    
1185            return defaultScope;
1186        }
1187    
1188        /**
1189         * Gets a locator to use with a given location URI.
1190         *
1191         * @param location The location URI to get a locator for.
1192         *
1193         * @return The locator to use for locating objects at {@code location} or {@code null} if no locator is available.
1194         *
1195         * @throws NullPointerException if {@code location} is {@code null}.
1196         * @throws InstantiationException if instantiating a locator fails.
1197         */
1198        public Locator getLocator( final URI location ) throws InstantiationException
1199        {
1200            if ( location == null )
1201            {
1202                throw new NullPointerException( "location" );
1203            }
1204    
1205            Locator locator = null;
1206            final String scheme = location.getScheme();
1207    
1208            if ( scheme != null )
1209            {
1210                synchronized ( this.locators )
1211                {
1212                    locator = this.locators.get( scheme );
1213    
1214                    if ( locator == null )
1215                    {
1216                        // Bootstrap locator loading.
1217                        final Specification locatorSpecification = this.getModules().getSpecification( Locator.class );
1218    
1219                        if ( locatorSpecification != null )
1220                        {
1221                            final Implementations implementations =
1222                                this.getModules().getImplementations( locatorSpecification.getIdentifier() );
1223    
1224                            if ( implementations != null )
1225                            {
1226                                for ( Implementation i : implementations.getImplementation() )
1227                                {
1228                                    if ( scheme.equals( i.getName() ) )
1229                                    {
1230                                        final Instance instance = this.getModelManager().getInstance(
1231                                            this.getModules(), i, this.getClassLoader( Locator.class ) );
1232    
1233                                        locator = (Locator) this.getModelManager().getObject(
1234                                            this.getModules(), locatorSpecification, instance );
1235    
1236                                        this.locators.put( scheme, locator );
1237                                        this.log( Level.CONFIG, this.getMessage( "locatorInfo", new Object[]
1238                                            {
1239                                                i.getIdentifier(), scheme
1240                                            } ), null );
1241    
1242                                        break;
1243                                    }
1244                                }
1245                            }
1246                        }
1247                        else
1248                        {
1249                            this.log( Level.WARNING, this.getMissingSpecificationMessage( Locator.class.getName() ),
1250                                      new Exception() );
1251    
1252                        }
1253                    }
1254    
1255                    if ( locator == null )
1256                    {
1257                        locator = this.getDefaultLocator( location );
1258                        if ( locator != null )
1259                        {
1260                            this.locators.put( scheme, locator );
1261                            this.log( Level.FINE, this.getDefaultLocatorInfoMessage( scheme ), null );
1262                        }
1263                    }
1264                }
1265            }
1266    
1267            return locator;
1268        }
1269    
1270        /**
1271         * Gets the default locator implementation for a given location URI.
1272         *
1273         * @param location The location URI to get a default locator implementation for.
1274         *
1275         * @return The default locator implementation for {@code location} or {@code null} if no default implementation is
1276         * available for {@code location}.
1277         *
1278         * @throws NullPointerException if {@code location} is {@code null}.
1279         */
1280        public Locator getDefaultLocator( final URI location )
1281        {
1282            if ( location == null )
1283            {
1284                throw new NullPointerException( "location" );
1285            }
1286    
1287            Locator locator = null;
1288            final DefaultLocator defaultLocator = new DefaultLocator();
1289    
1290            if ( defaultLocator.isLocationSupported( location ) )
1291            {
1292                locator = defaultLocator;
1293            }
1294    
1295            return locator;
1296        }
1297    
1298        /**
1299         * Initializes the instance.
1300         * <p>This method is called once on first usage of a new instance.</p>
1301         *
1302         * @throws InstantiationException if initialization fails.
1303         */
1304        public synchronized void initialize() throws InstantiationException
1305        {
1306            try
1307            {
1308                if ( !this.initialized )
1309                {
1310                    final long t0 = System.currentTimeMillis();
1311                    this.initialized = true;
1312    
1313                    this.scopes.clear();
1314                    this.bootstrapLogRecords.clear();
1315    
1316                    if ( this.modelManager instanceof DefaultModelManager )
1317                    {
1318                        ( (DefaultModelManager) this.modelManager ).getListeners().
1319                            remove( this.defaultModelManagerListener );
1320    
1321                    }
1322    
1323                    this.modelManager = null;
1324                    this.listeners = null;
1325                    this.modules = null;
1326    
1327                    this.getListeners().add( this.bootstrapObjectManagementListener );
1328    
1329                    final Specification objectManager = this.getModules().getSpecification( ObjectManager.class );
1330                    if ( objectManager == null )
1331                    {
1332                        throw new InstantiationException( this.getMissingSpecificationMessage(
1333                            ObjectManager.class.getName() ) );
1334    
1335                    }
1336    
1337                    final Instance thisInstance = this.getModelManager().getInstance( this.getModules(), this );
1338                    if ( thisInstance == null )
1339                    {
1340                        throw new InstantiationException( this.getMissingInstanceMessage(
1341                            this.getClass().getName(), this.getArtifactNameMessage() ) );
1342    
1343                    }
1344    
1345                    if ( objectManager.getScope() != null )
1346                    {
1347                        final Scope scope = this.getScope( objectManager.getScope() );
1348                        if ( scope == null )
1349                        {
1350                            throw new InstantiationException( this.getMissingScopeMessage( objectManager.getScope() ) );
1351                        }
1352    
1353                        scope.putObject( thisInstance.getIdentifier(), this );
1354                    }
1355    
1356                    // Bootstrap listener loading.
1357                    final Specification listenerSpecification = this.getModules().getSpecification( Listener.class );
1358    
1359                    if ( listenerSpecification != null )
1360                    {
1361                        final Implementations implementations =
1362                            this.getModules().getImplementations( listenerSpecification.getIdentifier() );
1363    
1364                        if ( implementations != null && !implementations.getImplementation().isEmpty() )
1365                        {
1366                            for ( Implementation i : implementations.getImplementation() )
1367                            {
1368                                final Instance listenerInstance = this.getModelManager().getInstance(
1369                                    this.getModules(), i, this.getClassLoader( Listener.class ) );
1370    
1371                                final Listener l = (Listener) this.getModelManager().getObject(
1372                                    this.getModules(), listenerSpecification, listenerInstance );
1373    
1374                                this.getListeners().add( l );
1375                                this.bootstrapLogRecords.add( new LogRecord(
1376                                    Level.FINE, this.getRegisteredListenerMessage( l.getClass().getName() ) ) );
1377    
1378                            }
1379                        }
1380                        else
1381                        {
1382                            this.log( Level.WARNING, this.getMissingImplementationsMessage(
1383                                listenerSpecification.getIdentifier() ), new Exception() );
1384    
1385                        }
1386                    }
1387                    else
1388                    {
1389                        this.log( Level.WARNING, this.getMissingSpecificationMessage( Listener.class.getName() ),
1390                                  new Exception() );
1391    
1392                    }
1393    
1394                    this.getListeners().remove( this.bootstrapObjectManagementListener );
1395    
1396                    if ( !this.getListeners().isEmpty() )
1397                    {
1398                        for ( LogRecord logRecord : this.bootstrapLogRecords )
1399                        {
1400                            this.log( logRecord.getLevel(), logRecord.getMessage(), logRecord.getThrown() );
1401                        }
1402                    }
1403    
1404                    this.bootstrapLogRecords.clear();
1405                    this.log( Level.FINE, this.getModulesReport( this.getModules() ), null );
1406                    this.log( Level.FINE, this.getImplementationInfoMessage(
1407                        Long.valueOf( System.currentTimeMillis() - t0 ) ), null );
1408    
1409                }
1410            }
1411            catch ( final InstantiationException e )
1412            {
1413                for ( LogRecord r : this.bootstrapLogRecords )
1414                {
1415                    Logger.getLogger( this.getClass().getName() ).log( r );
1416                }
1417    
1418                this.scopes.clear();
1419                this.bootstrapLogRecords.clear();
1420    
1421                if ( this.modelManager instanceof DefaultModelManager )
1422                {
1423                    ( (DefaultModelManager) this.modelManager ).getListeners().remove( this.defaultModelManagerListener );
1424                }
1425    
1426                this.modelManager = null;
1427                this.listeners = null;
1428                this.modules = null;
1429                this.initialized = false;
1430                throw e;
1431            }
1432        }
1433    
1434        /**
1435         * Notifies registered listeners.
1436         *
1437         * @param level The level of the event.
1438         * @param message The message of the event or {@code null}.
1439         * @param throwable The throwable of the event or {@code null}.
1440         */
1441        protected void log( final Level level, final String message, final Throwable throwable )
1442        {
1443            for ( Listener l : this.getListeners() )
1444            {
1445                l.onLog( level, message, throwable );
1446            }
1447        }
1448    
1449        /**
1450         * Creates a proxy for a given object.
1451         *
1452         * @param specification The specification to create a proxy for.
1453         * @param instance The instance of {@code object}.
1454         * @param object The object to create a proxy for.
1455         *
1456         * @return A proxy for {@code object}.
1457         *
1458         * @throws InstantiationException if creating a proxy fails.
1459         */
1460        private Object createProxy( final Specification specification, final Instance instance, final Object object )
1461            throws InstantiationException
1462        {
1463            Object proxy = object;
1464    
1465            try
1466            {
1467                final Class specClass = Class.forName( specification.getClazz(), true, instance.getClassLoader() );
1468                if ( specClass.isInterface() )
1469                {
1470                    final Set<Class> interfaces = new HashSet<Class>();
1471                    interfaces.add( specClass );
1472    
1473                    if ( instance.getSpecifications() != null )
1474                    {
1475                        for ( Specification s : instance.getSpecifications().getSpecification() )
1476                        {
1477                            final Class clazz = Class.forName( s.getClazz(), true, instance.getClassLoader() );
1478                            if ( clazz.isInterface() )
1479                            {
1480                                interfaces.add( clazz );
1481                            }
1482                            else
1483                            {
1484                                this.log( Level.WARNING, this.getCannotProxySpecificationClassMessage(
1485                                    s.getClazz(), instance.getIdentifier() ), null );
1486    
1487                            }
1488                        }
1489                    }
1490    
1491                    proxy = Proxy.newProxyInstance(
1492                        instance.getClassLoader(), interfaces.toArray( new Class[ interfaces.size() ] ),
1493                        new InvocationHandler()
1494                        {
1495    
1496                            public Object invoke( final Object proxy, final Method method, final Object[] args )
1497                                throws Throwable
1498                            {
1499                                try
1500                                {
1501                                    final Method m =
1502                                        object.getClass().getMethod( method.getName(), method.getParameterTypes() );
1503    
1504                                    if ( instance.isStateless() )
1505                                    {
1506                                        return m.invoke( object, args );
1507                                    }
1508                                    else
1509                                    {
1510                                        synchronized ( object )
1511                                        {
1512                                            return m.invoke( object, args );
1513                                        }
1514                                    }
1515                                }
1516                                catch ( final NoSuchMethodException e )
1517                                {
1518                                    log( Level.SEVERE, e.getMessage(), e );
1519                                    throw new ObjectManagementException( e.getMessage(), e );
1520                                }
1521                                catch ( final SecurityException e )
1522                                {
1523                                    log( Level.SEVERE, e.getMessage(), e );
1524                                    throw new ObjectManagementException( e.getMessage(), e );
1525                                }
1526                                catch ( final InvocationTargetException e )
1527                                {
1528                                    if ( e.getTargetException() != null )
1529                                    {
1530                                        throw e.getTargetException();
1531                                    }
1532    
1533                                    log( Level.SEVERE, e.getMessage(), e );
1534                                    throw new ObjectManagementException( e.getMessage(), e );
1535                                }
1536                                catch ( final IllegalAccessException e )
1537                                {
1538                                    log( Level.SEVERE, e.getMessage(), e );
1539                                    throw new ObjectManagementException( e.getMessage(), e );
1540                                }
1541                            }
1542    
1543                        } );
1544    
1545                }
1546    
1547                return proxy;
1548            }
1549            catch ( final ClassNotFoundException e )
1550            {
1551                throw (InstantiationException) new InstantiationException( e.getMessage() ).initCause( e );
1552            }
1553        }
1554    
1555        private String getMessage( final String key, final Object arguments )
1556        {
1557            final ResourceBundle bundle =
1558                ResourceBundle.getBundle( DefaultObjectManager.class.getName().replace( '.', '/' ) );
1559    
1560            return new MessageFormat( bundle.getString( key ) ).format( arguments );
1561        }
1562    
1563        private String getArtifactNameMessage()
1564        {
1565            return this.getMessage( "artifactName", null );
1566        }
1567    
1568        private String getMissingSpecificationMessage( final String specification )
1569        {
1570            return this.getMessage( "missingSpecification", new Object[]
1571                {
1572                    specification
1573                } );
1574    
1575        }
1576    
1577        private String getMissingImplementationsMessage( final String specification )
1578        {
1579            return this.getMessage( "missingImplementations", new Object[]
1580                {
1581                    specification
1582                } );
1583    
1584        }
1585    
1586        private String getMissingImplementationMessage( final String implementationName, final String specification )
1587        {
1588            return this.getMessage( "missingImplementation", new Object[]
1589                {
1590                    implementationName, specification
1591                } );
1592    
1593        }
1594    
1595        private String getMissingObjectInstanceMessage( final Object object )
1596        {
1597            return this.getMessage( "missingObjectInstance", new Object[]
1598                {
1599                    object.toString()
1600                } );
1601    
1602        }
1603    
1604        private String getMissingDependencyMessage( final String dependency, final String implementation )
1605        {
1606            return this.getMessage( "missingDependency", new Object[]
1607                {
1608                    dependency, implementation
1609                } );
1610        }
1611    
1612        private String getMissingPropertyMessage( final String property, final String implementation )
1613        {
1614            return this.getMessage( "missingProperty", new Object[]
1615                {
1616                    property, implementation
1617                } );
1618    
1619        }
1620    
1621        private String getMissingMessageMessage( final String message, final String implementation )
1622        {
1623            return this.getMessage( "missingMessage", new Object[]
1624                {
1625                    message, implementation
1626                } );
1627    
1628        }
1629    
1630        private String getMissingClassLoaderMessage()
1631        {
1632            return this.getMessage( "missingClassloader", null );
1633        }
1634    
1635        private String getMissingInstanceMessage( final String implementation, final String implementationName )
1636        {
1637            return this.getMessage( "missingInstance", new Object[]
1638                {
1639                    implementation, implementationName
1640                } );
1641    
1642        }
1643    
1644        private String getMissingObjectMessage( final String implementation, final String implementationName )
1645        {
1646            return this.getMessage( "missingObject", new Object[]
1647                {
1648                    implementation, implementationName
1649                } );
1650    
1651        }
1652    
1653        private String getDependencyCycleMessage( final String implementation )
1654        {
1655            return this.getMessage( "dependencyCycle", new Object[]
1656                {
1657                    implementation
1658                } );
1659    
1660        }
1661    
1662        private String getImplementationInfoMessage( final Long startMillis )
1663        {
1664            return this.getMessage( "implementationInfo", new Object[]
1665                {
1666                    startMillis
1667                } );
1668    
1669        }
1670    
1671        private String getDefaultScopeInfoMessage( final String modelScope, final Map objects )
1672        {
1673            return this.getMessage( "defaultScopeInfo", new Object[]
1674                {
1675                    modelScope, objects == null ? "" : objects.toString()
1676                } );
1677    
1678        }
1679    
1680        private String getMissingScopeMessage( final String modelScope )
1681        {
1682            return this.getMessage( "missingScope", new Object[]
1683                {
1684                    modelScope
1685                } );
1686    
1687        }
1688    
1689        private String getRegisteredListenerMessage( final String listener )
1690        {
1691            return this.getMessage( "registeredListener", new Object[]
1692                {
1693                    listener
1694                } );
1695    
1696        }
1697    
1698        private String getUnsupportedMultiplicityMessage( final Multiplicity multiplicity )
1699        {
1700            return this.getMessage( "unsupportedMultiplicity", new Object[]
1701                {
1702                    multiplicity
1703                } );
1704        }
1705    
1706        private String getCannotProxySpecificationClassMessage( final String specification, final String instance )
1707        {
1708            return this.getMessage( "cannotProxySpecificationClass", new Object[]
1709                {
1710                    specification, instance
1711                } );
1712    
1713        }
1714    
1715        private String getDefaultLocatorInfoMessage( final String scheme )
1716        {
1717            return this.getMessage( "defaultLocatorInfo", new Object[]
1718                {
1719                    scheme
1720                } );
1721    
1722        }
1723    
1724        private String getMissingLocatorMessage( final URI location )
1725        {
1726            return this.getMessage( "missingLocator", new Object[]
1727                {
1728                    location.toString()
1729                } );
1730    
1731        }
1732    
1733        private String getModulesReport( final Modules mods )
1734        {
1735            final StringBuilder modulesInfo = new StringBuilder();
1736            final String lineSeparator = System.getProperty( "line.separator" );
1737    
1738            if ( mods.getDocumentation() != null )
1739            {
1740                modulesInfo.append( mods.getDocumentation().getText( Locale.getDefault().getLanguage() ).getValue() ).
1741                    append( lineSeparator );
1742    
1743            }
1744            else
1745            {
1746                modulesInfo.append( lineSeparator );
1747            }
1748    
1749            for ( Module m : mods.getModule() )
1750            {
1751                modulesInfo.append( "\tM:" ).append( m.getName() ).append( ':' ).append( m.getVersion() ).
1752                    append( lineSeparator );
1753    
1754                if ( m.getSpecifications() != null )
1755                {
1756                    for ( Specification s : m.getSpecifications().getSpecification() )
1757                    {
1758                        modulesInfo.append( "\t\t" );
1759                        this.appendSpecificationInfo( s, modulesInfo ).append( lineSeparator );
1760    
1761                        final Implementations available = mods.getImplementations( s.getIdentifier() );
1762    
1763                        if ( available != null )
1764                        {
1765                            for ( Implementation i : available.getImplementation() )
1766                            {
1767                                modulesInfo.append( "\t\t\t" );
1768                                this.appendImplementationInfo( i, modulesInfo ).append( "@" ).
1769                                    append( mods.getModuleOfImplementation( i.getIdentifier() ).getName() ).
1770                                    append( lineSeparator );
1771    
1772                            }
1773                        }
1774                    }
1775                }
1776    
1777                if ( m.getImplementations() != null )
1778                {
1779                    for ( Implementation i : m.getImplementations().getImplementation() )
1780                    {
1781                        modulesInfo.append( "\t\t" );
1782                        this.appendImplementationInfo( i, modulesInfo ).append( lineSeparator );
1783    
1784                        if ( i.getImplementations() != null )
1785                        {
1786                            modulesInfo.append( "\t\t\t" );
1787                            for ( ImplementationReference r : i.getImplementations().getReference() )
1788                            {
1789                                this.appendImplementationInfo(
1790                                    mods.getImplementation( r.getIdentifier() ), modulesInfo ).append( '@' ).
1791                                    append( mods.getModuleOfImplementation( r.getIdentifier() ).getName() ).
1792                                    append( lineSeparator );
1793    
1794                            }
1795                        }
1796                        if ( i.getSpecifications() != null )
1797                        {
1798                            for ( SpecificationReference s : i.getSpecifications().getReference() )
1799                            {
1800                                modulesInfo.append( "\t\t\tS:" ).append( s.getIdentifier() ).append( ':' ).
1801                                    append( s.getVersion() ).append( '@' ).append( mods.getModuleOfSpecification(
1802                                    s.getIdentifier() ).getName() ).append( lineSeparator );
1803    
1804                            }
1805                        }
1806    
1807                        if ( i.getDependencies() != null )
1808                        {
1809                            for ( Dependency d : i.getDependencies().getDependency() )
1810                            {
1811                                modulesInfo.append( "\t\t\tD:" ).append( d.getName() ).append( ':' ).
1812                                    append( d.getIdentifier() );
1813    
1814                                if ( d.getImplementationName() != null )
1815                                {
1816                                    modulesInfo.append( ":" ).append( d.getImplementationName() );
1817                                }
1818    
1819                                modulesInfo.append( '@' ).append( mods.getModuleOfSpecification(
1820                                    d.getIdentifier() ).getName() ).append( lineSeparator );
1821    
1822                                final Implementations available = mods.getImplementations( d.getIdentifier() );
1823    
1824                                if ( available != null )
1825                                {
1826                                    for ( Implementation di : available.getImplementation() )
1827                                    {
1828                                        modulesInfo.append( "\t\t\t\t" );
1829                                        this.appendImplementationInfo( di, modulesInfo ).append( "@" ).
1830                                            append( mods.getModuleOfImplementation( di.getIdentifier() ).getName() ).
1831                                            append( lineSeparator );
1832    
1833                                    }
1834                                }
1835                            }
1836                        }
1837    
1838                        if ( i.getMessages() != null )
1839                        {
1840                            for ( Message msg : i.getMessages().getMessage() )
1841                            {
1842                                modulesInfo.append( "\t\t\tM:" ).append( msg.getName() ).append( ':' ).
1843                                    append( msg.getTemplate().getText( Locale.getDefault().getLanguage() ).getValue() ).
1844                                    append( lineSeparator );
1845    
1846                            }
1847                        }
1848    
1849                        if ( i.getProperties() != null )
1850                        {
1851                            for ( Property p : i.getProperties().getProperty() )
1852                            {
1853                                modulesInfo.append( "\t\t\tP:" ).append( p.getName() ).append( ':' ).
1854                                    append( p.getType() ).append( ':' );
1855    
1856                                try
1857                                {
1858                                    modulesInfo.append( p.getJavaValue( this.getClassLoader( this.getClass() ) ) );
1859                                }
1860                                catch ( final ClassNotFoundException e )
1861                                {
1862                                    modulesInfo.append( Level.WARNING.getLocalizedName() ).append( " " ).append( e );
1863                                }
1864                                catch ( final InstantiationException e )
1865                                {
1866                                    modulesInfo.append( Level.WARNING.getLocalizedName() ).append( " " ).append( e );
1867                                }
1868    
1869                                modulesInfo.append( lineSeparator );
1870                            }
1871                        }
1872                    }
1873                }
1874            }
1875    
1876            return modulesInfo.toString();
1877        }
1878    
1879        private StringBuilder appendSpecificationInfo( final Specification s, final StringBuilder b )
1880        {
1881            b.append( "S:" ).append( s.getIdentifier() ).append( ':' ).append( s.getVersion() ).append( ':' ).
1882                append( s.getMultiplicity() ).append( ":Scope:" ).
1883                append( s.getScope() == null ? "Multiton" : s.getScope() ).append( ":Class:" ).append( s.getClazz() );
1884    
1885            return b;
1886        }
1887    
1888        private StringBuilder appendImplementationInfo( final Implementation i, final StringBuilder b )
1889        {
1890            b.append( "I:" ).append( i.getIdentifier() ).append( ':' ).append( i.getName() ).append( ':' ).
1891                append( i.getVersion() );
1892    
1893            if ( i.getClazz() != null )
1894            {
1895                b.append( ":Class:" ).append( i.getClazz() );
1896            }
1897            if ( i.getLocation() != null )
1898            {
1899                b.append( ":Location:" ).append( i.getLocation() );
1900            }
1901    
1902            return b;
1903        }
1904    
1905        // SECTION-END
1906        // SECTION-START[Dependencies]
1907        // SECTION-END
1908        // SECTION-START[Properties]
1909        // SECTION-END
1910        // SECTION-START[Messages]
1911        // SECTION-END
1912    }