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