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