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$
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$
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-4/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-4/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 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() ), 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 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() ), 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 if ( !i.isAbstract() )
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 if ( !i.isAbstract() )
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 if ( !ref.isAbstract() )
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 if ( !a.isAbstract() )
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 t0 = 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 Long.valueOf( System.currentTimeMillis() - t0 ) ), 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 Long startMillis )
1635 {
1636 return this.getMessage( "implementationInfo", new Object[]
1637 {
1638 startMillis
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.getImplementations() != null )
1748 {
1749 modulesInfo.append( "\t\t\t" );
1750 for ( ImplementationReference r : i.getImplementations().getReference() )
1751 {
1752 this.appendImplementationInfo(
1753 mods.getImplementation( r.getIdentifier() ), modulesInfo ).append( '@' ).
1754 append( mods.getModuleOfImplementation( r.getIdentifier() ).getName() ).
1755 append( lineSeparator );
1756
1757 }
1758 }
1759 if ( i.getSpecifications() != null )
1760 {
1761 for ( SpecificationReference s : i.getSpecifications().getReference() )
1762 {
1763 modulesInfo.append( "\t\t\tS:" ).append( s.getIdentifier() ).append( ':' ).
1764 append( s.getVersion() ).append( '@' ).append( mods.getModuleOfSpecification(
1765 s.getIdentifier() ).getName() ).append( lineSeparator );
1766
1767 }
1768 }
1769
1770 if ( i.getDependencies() != null )
1771 {
1772 for ( Dependency d : i.getDependencies().getDependency() )
1773 {
1774 modulesInfo.append( "\t\t\tD:" ).append( d.getName() ).append( ':' ).
1775 append( d.getIdentifier() );
1776
1777 if ( d.getImplementationName() != null )
1778 {
1779 modulesInfo.append( ":" ).append( d.getImplementationName() );
1780 }
1781
1782 modulesInfo.append( '@' ).append( mods.getModuleOfSpecification(
1783 d.getIdentifier() ).getName() ).append( lineSeparator );
1784
1785 final Implementations available = mods.getImplementations( d.getIdentifier() );
1786
1787 if ( available != null )
1788 {
1789 for ( Implementation di : available.getImplementation() )
1790 {
1791 modulesInfo.append( "\t\t\t\t" );
1792 this.appendImplementationInfo( di, modulesInfo ).append( "@" ).
1793 append( mods.getModuleOfImplementation( di.getIdentifier() ).getName() ).
1794 append( lineSeparator );
1795
1796 }
1797 }
1798 }
1799 }
1800
1801 if ( i.getMessages() != null )
1802 {
1803 for ( Message msg : i.getMessages().getMessage() )
1804 {
1805 modulesInfo.append( "\t\t\tM:" ).append( msg.getName() ).append( ':' ).
1806 append( msg.getTemplate().getText( Locale.getDefault().getLanguage() ).getValue() ).
1807 append( lineSeparator );
1808
1809 }
1810 }
1811
1812 if ( i.getProperties() != null )
1813 {
1814 for ( Property p : i.getProperties().getProperty() )
1815 {
1816 modulesInfo.append( "\t\t\tP:" ).append( p.getName() ).append( ':' ).
1817 append( p.getType() ).append( ':' );
1818
1819 try
1820 {
1821 modulesInfo.append( p.getJavaValue( this.getClassLoader( this.getClass() ) ) );
1822 }
1823 catch ( final ClassNotFoundException e )
1824 {
1825 modulesInfo.append( Level.WARNING.getLocalizedName() ).append( " " ).append( e );
1826 }
1827 catch ( final InstantiationException e )
1828 {
1829 modulesInfo.append( Level.WARNING.getLocalizedName() ).append( " " ).append( e );
1830 }
1831
1832 modulesInfo.append( lineSeparator );
1833 }
1834 }
1835 }
1836 }
1837 }
1838
1839 return modulesInfo.toString();
1840 }
1841
1842 private StringBuilder appendSpecificationInfo( final Specification s, final StringBuilder b )
1843 {
1844 b.append( "S:" ).append( s.getIdentifier() ).append( ':' ).append( s.getVersion() ).append( ':' ).
1845 append( s.getMultiplicity() ).append( ":Scope:" ).
1846 append( s.getScope() == null ? "Multiton" : s.getScope() ).append( ":Class:" ).append( s.getClazz() );
1847
1848 return b;
1849 }
1850
1851 private StringBuilder appendImplementationInfo( final Implementation i, final StringBuilder b )
1852 {
1853 b.append( "I:" ).append( i.getIdentifier() ).append( ':' ).append( i.getName() ).append( ':' ).
1854 append( i.getVersion() );
1855
1856 if ( i.getClazz() != null )
1857 {
1858 b.append( ":Class:" ).append( i.getClazz() );
1859 }
1860 if ( i.getLocation() != null )
1861 {
1862 b.append( ":Location:" ).append( i.getLocation() );
1863 }
1864
1865 return b;
1866 }
1867
1868 // SECTION-END
1869 // SECTION-START[Dependencies]
1870 // SECTION-END
1871 // SECTION-START[Properties]
1872 // SECTION-END
1873 // SECTION-START[Messages]
1874 // SECTION-END
1875 }