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