View Javadoc

1   /*
2    *  jDTAUS Core RI Client Container
3    *  Copyright (C) 2005 Christian Schulte
4    *  <cs@schulte.it>
5    *
6    *  This library is free software; you can redistribute it and/or
7    *  modify it under the terms of the GNU Lesser General Public
8    *  License as published by the Free Software Foundation; either
9    *  version 2.1 of the License, or any later version.
10   *
11   *  This library is distributed in the hope that it will be useful,
12   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   *  Lesser General Public License for more details.
15   *
16   *  You should have received a copy of the GNU Lesser General Public
17   *  License along with this library; if not, write to the Free Software
18   *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19   *
20   */
21  package org.jdtaus.core.container.ri.client;
22  
23  import java.lang.reflect.Array;
24  import java.lang.reflect.Constructor;
25  import java.lang.reflect.InvocationTargetException;
26  import java.lang.reflect.Method;
27  import java.text.MessageFormat;
28  import java.util.ArrayList;
29  import java.util.List;
30  import java.util.Locale;
31  import java.util.Map;
32  import java.util.logging.Level;
33  import java.util.logging.Logger;
34  import org.jdtaus.core.container.Container;
35  import org.jdtaus.core.container.ContainerError;
36  import org.jdtaus.core.container.ContainerInitializer;
37  import org.jdtaus.core.container.ContextFactory;
38  import org.jdtaus.core.container.ContextInitializer;
39  import org.jdtaus.core.container.Dependency;
40  import org.jdtaus.core.container.DependencyCycleException;
41  import org.jdtaus.core.container.Implementation;
42  import org.jdtaus.core.container.MissingImplementationException;
43  import org.jdtaus.core.container.Model;
44  import org.jdtaus.core.container.ModelFactory;
45  import org.jdtaus.core.container.MultiplicityConstraintException;
46  import org.jdtaus.core.container.Specification;
47  import org.jdtaus.core.container.ri.client.versioning.VersionParser;
48  
49  /**
50   * {@code Container} reference implementation.
51   *
52   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
53   * @version $JDTAUS: DefaultContainer.java 8743 2012-10-07 03:06:20Z schulte $
54   *
55   * @see org.jdtaus.core.container.ContainerFactory
56   */
57  public class DefaultContainer implements Container
58  {
59      //--Constants---------------------------------------------------------------
60  
61      /** Empty Class-Array. */
62      private static final Class[] EMPTY =
63      {
64      };
65  
66      /** Implementation Class-Array. */
67      private static final Class[] IMPL_CTOR =
68      {
69          Implementation.class
70      };
71  
72      /** Dependency Class-Array. */
73      private static final Class[] DEP_CTOR =
74      {
75          Dependency.class
76      };
77  
78      /** Array of scope implementations. */
79      private static final Scope[] SCOPES =
80      {
81          null, new ContextScope(), new SingletonScope()
82      };
83  
84      //---------------------------------------------------------------Constants--
85      //--Container---------------------------------------------------------------
86  
87      /** Mutex used to detect cyclic instantiations. */
88      private final Object cycle = new Object();
89  
90      /** Maps objects to model object. */
91      private final Map objects = new WeakIdentityHashMap( 1024 );
92  
93      public Object getObject( final Class specification )
94      {
95          if ( specification == null )
96          {
97              throw new NullPointerException( "specification" );
98          }
99  
100         return this.getObjectInternal( this.getClassLoader( specification ),
101                                        specification.getName(), null, false );
102 
103     }
104 
105     public Object getObject( final Class specification,
106                              final String implementationName )
107     {
108         if ( specification == null )
109         {
110             throw new NullPointerException( "specification" );
111         }
112         if ( implementationName == null )
113         {
114             throw new NullPointerException( "implementationName" );
115         }
116 
117         return this.getObjectInternal( this.getClassLoader( specification ),
118                                        specification.getName(),
119                                        implementationName, true );
120 
121     }
122 
123     public Object getDependency( final Object object,
124                                  final String dependencyName )
125     {
126         if ( object == null )
127         {
128             throw new NullPointerException( "object" );
129         }
130         if ( dependencyName == null )
131         {
132             throw new NullPointerException( "dependencyName" );
133         }
134 
135         try
136         {
137             final Implementation impl = this.getImplementation( object );
138             final Instance instance = this.getInstance( object, impl );
139 
140             synchronized ( instance )
141             {
142                 return this.getDependency(
143                     instance.getClassLoader(), instance,
144                     impl.getDependencies().getDependency( dependencyName ) );
145 
146             }
147         }
148         catch ( final ClassNotFoundException e )
149         {
150             throw new ContainerError( e );
151         }
152         catch ( final NoSuchMethodException e )
153         {
154             throw new ContainerError( e );
155         }
156         catch ( final IllegalAccessException e )
157         {
158             throw new ContainerError( e );
159         }
160         catch ( final InvocationTargetException e )
161         {
162             throw new ContainerError( e );
163         }
164     }
165 
166     public Object getProperty( final Object object,
167                                final String propertyName )
168     {
169         if ( object == null )
170         {
171             throw new NullPointerException( "object" );
172         }
173         if ( propertyName == null )
174         {
175             throw new NullPointerException( "propertyName" );
176         }
177 
178         return this.getInstance( object, this.getImplementation( object ) ).
179             getProperties().getProperty( propertyName ).getValue();
180 
181     }
182 
183     public String getMessage( final Object object, final String messageName,
184                               final Locale locale, final Object arguments )
185     {
186         if ( object == null )
187         {
188             throw new NullPointerException( "object" );
189         }
190         if ( locale == null )
191         {
192             throw new NullPointerException( "locale" );
193         }
194         if ( messageName == null )
195         {
196             throw new NullPointerException( "messageName" );
197         }
198 
199         return new MessageFormat(
200             this.getInstance( object, this.getImplementation( object ) ).
201             getMessages().getMessage( messageName ).getTemplate().
202             getValue( locale ), locale ).format( arguments );
203 
204     }
205 
206     public final Object getObject( final String specificationIdentifier )
207     {
208         return this.getObjectInternal( this.getClassLoader( this.getClass() ),
209                                        specificationIdentifier, null,
210                                        false );
211 
212     }
213 
214     public final Object getObject( final String specificationIdentifier,
215                                    final String implementationName )
216     {
217         return this.getObjectInternal( this.getClassLoader( this.getClass() ),
218                                        specificationIdentifier,
219                                        implementationName, true );
220 
221     }
222 
223     public final String getMessage( final Object object,
224                                     final String messageName,
225                                     final Object arguments )
226     {
227         if ( object == null )
228         {
229             throw new NullPointerException( "object" );
230         }
231         if ( messageName == null )
232         {
233             throw new NullPointerException( "messageName" );
234         }
235 
236         return this.getMessage( object, messageName, Locale.getDefault(),
237                                 arguments );
238 
239     }
240 
241     public final Object getImplementation(
242         final Class specification, final String implementationName )
243     {
244         if ( specification == null )
245         {
246             throw new NullPointerException( "specification" );
247         }
248         if ( implementationName == null )
249         {
250             throw new NullPointerException( "implementationName" );
251         }
252 
253         return this.getObject( specification, implementationName );
254     }
255 
256     public final Object getDependency(
257         final Class implementation, final String dependencyName )
258     {
259         if ( implementation == null )
260         {
261             throw new NullPointerException( "implementation" );
262         }
263         if ( dependencyName == null )
264         {
265             throw new NullPointerException( "dependencyName" );
266         }
267 
268         try
269         {
270             final Object dependencyObject = this.getDependency(
271                 this.getClassLoader( implementation ), null,
272                 ModelFactory.getModel().getModules().
273                 getImplementation( implementation.getName() ).
274                 getDependencies().getDependency( dependencyName ) );
275 
276             this.initializeContext( dependencyObject );
277             return dependencyObject;
278         }
279         catch ( final ClassNotFoundException e )
280         {
281             throw new ContainerError( e );
282         }
283         catch ( final NoSuchMethodException e )
284         {
285             throw new ContainerError( e );
286         }
287         catch ( final IllegalAccessException e )
288         {
289             throw new ContainerError( e );
290         }
291         catch ( final InvocationTargetException e )
292         {
293             throw new ContainerError( e );
294         }
295     }
296 
297     //---------------------------------------------------------------Container--
298     //--DefaultContainer--------------------------------------------------------
299 
300     /** Creates a new {@code DefaultContainer} instance. */
301     public DefaultContainer()
302     {
303         super();
304     }
305 
306     /**
307      * Creates a new instance of an implementation.
308      * <p>The reference implementation loads the class corresponding to the
309      * implementation and creates a new instance of that class by calling the
310      * constructor taking an {@code Implementation} as an argument.</p>
311      *
312      * @param classLoader The classloader to use for loading classes.
313      * @param impl the implementation to return a new instance for.
314      *
315      * @return a new instance of the class corresponding to {@code impl}.
316      *
317      * @throws NullPointerException if {@code classLoader} or {@code impl} is
318      * {@code null}.
319      * @throws org.jdtaus.core.container.InstantiationException
320      * if no instance can be created.
321      * @deprecated Replaced by {@link #instantiateObject(org.jdtaus.core.container.ri.client.Instance)
322      */
323     private Object instantiateImplementation( final ClassLoader classLoader,
324                                               final Implementation impl )
325     {
326         if ( classLoader == null )
327         {
328             throw new NullPointerException( "classLoader" );
329         }
330         if ( impl == null )
331         {
332             throw new NullPointerException( "impl" );
333         }
334 
335         Constructor ctor = null;
336 
337         try
338         {
339             final Class clazz = Class.forName( impl.getIdentifier(), true,
340                                                classLoader );
341 
342             ctor = clazz.getDeclaredConstructor( IMPL_CTOR );
343             ctor.setAccessible( true );
344 
345             final Object object = ctor.newInstance( new Object[]
346                 {
347                     impl
348                 } );
349 
350             return object;
351         }
352         catch ( final Throwable e )
353         {
354             throw new org.jdtaus.core.container.InstantiationException(
355                 impl.getIdentifier(), e );
356 
357         }
358         finally
359         {
360             if ( ctor != null )
361             {
362                 ctor.setAccessible( false );
363             }
364         }
365     }
366 
367     /**
368      * Creates a new instance of a dependency.
369      * <p>The reference implementation loads the class corresponding to the
370      * dependency and creates a new instance of that class by calling the
371      * constructor taking a {@code Dependency} as an argument.</p>
372      *
373      * @param classLoader The classloader to use for loading classes.
374      * @param dep the dependency to return a new instance for.
375      *
376      * @return a new instance of the class corresponding to {@code dep}.
377      *
378      * @throws NullPointerException if {@code classLoader} or {@code dep} is
379      * {@code null}.
380      * @throws org.jdtaus.core.container.InstantiationException
381      * if no instance can be created.
382      * @deprecated Replaced by {@link #instantiateObject(org.jdtaus.core.container.ri.client.Instance)
383      */
384     private Object instantiateDependency( final ClassLoader classLoader,
385                                           final Dependency dep )
386     {
387         if ( classLoader == null )
388         {
389             throw new NullPointerException( "classLoader" );
390         }
391         if ( dep == null )
392         {
393             throw new NullPointerException( "dep" );
394         }
395 
396         Constructor ctor = null;
397 
398         try
399         {
400             final Class clazz = Class.forName( dep.getImplementation().
401                 getIdentifier(), true, classLoader );
402 
403             ctor = clazz.getDeclaredConstructor( DEP_CTOR );
404             ctor.setAccessible( true );
405 
406             final Object object = ctor.newInstance( new Object[]
407                 {
408                     dep
409                 } );
410 
411             return object;
412         }
413         catch ( final Throwable e )
414         {
415             throw new org.jdtaus.core.container.InstantiationException(
416                 dep.getImplementation().getIdentifier(), e );
417 
418         }
419         finally
420         {
421             if ( ctor != null )
422             {
423                 ctor.setAccessible( false );
424             }
425         }
426     }
427 
428     /**
429      * Performs initialization of an object.
430      *
431      * @param object The object to initialize.
432      *
433      * @throws NullPointerException if {@code object} is {@code null}.
434      * @throws Exception if initialization fails.
435      */
436     private void initializeObject( final Object object ) throws Exception
437     {
438         if ( object == null )
439         {
440             throw new NullPointerException( "object" );
441         }
442 
443         if ( object instanceof ContainerInitializer )
444         {
445             ( (ContainerInitializer) object ).initialize();
446         }
447     }
448 
449     /**
450      * Performs context initialization of an object.
451      *
452      * @param object The object to perform context initialization with.
453      *
454      * @throws NullPointerException if {@code object} is {@code null}.
455      * @throws org.jdtaus.core.container.ContextError for unrecoverable context
456      * errors.
457      */
458     private void initializeContext( final Object object )
459     {
460         if ( object == null )
461         {
462             throw new NullPointerException( "object" );
463         }
464 
465         if ( object instanceof ContextInitializer &&
466              !( (ContextInitializer) object ).isInitialized(
467             ContextFactory.getContext() ) )
468         {
469             ( (ContextInitializer) object ).initialize(
470                 ContextFactory.getContext() );
471 
472         }
473     }
474 
475     private Object getObjectInternal( final ClassLoader classLoader,
476                                       final String specificationIdentifier,
477                                       final String implementationName,
478                                       final boolean implementationNameWarning )
479     {
480         if ( classLoader == null )
481         {
482             throw new NullPointerException( "classLoader" );
483         }
484         if ( specificationIdentifier == null )
485         {
486             throw new NullPointerException( "specificationIdentifier" );
487         }
488 
489         try
490         {
491             final Object object;
492             final Specification specification = ModelFactory.getModel().
493                 getModules().getSpecification( specificationIdentifier );
494 
495             if ( implementationName != null )
496             {
497                 final Class specClass =
498                     Class.forName( specification.getIdentifier(), true,
499                                    classLoader );
500 
501                 final Implementation implementation =
502                     specification.getImplementation( implementationName );
503 
504                 final Instance instance = new Instance(
505                     classLoader, specification.getScope(),
506                     implementation.getIdentifier(),
507                     implementation.getModelVersion(),
508                     implementation.getModuleName() );
509 
510                 instance.setImplementation( implementation );
511                 object = this.requestImplementation(
512                     specClass, specification, this.getObject( instance ) );
513 
514             }
515             else
516             {
517                 if ( implementationNameWarning )
518                 {
519                     final Throwable x = new Throwable();
520                     final StackTraceElement[] elements = x.getStackTrace();
521 
522                     String cname = "unknown";
523                     String method = "unknown";
524                     StackTraceElement caller = null;
525 
526                     if ( elements != null && elements.length > 2 )
527                     {
528                         caller = elements[2];
529                         cname = caller.getClassName();
530                         method = caller.getMethodName();
531                     }
532 
533                     Logger.getLogger( DefaultContainer.class.getName() ).
534                         log( Level.SEVERE, DefaultContainerBundle.getInstance().
535                         getNullImplementationNameWarningMessage(
536                         Locale.getDefault(), specificationIdentifier, cname,
537                         method ), x );
538 
539                 }
540 
541                 object = this.resolveImplementation( classLoader,
542                                                      specification );
543 
544             }
545 
546             return object;
547         }
548         catch ( final IllegalAccessException e )
549         {
550             // Cannot happen - method got set accessible.
551             throw new AssertionError( e );
552         }
553         catch ( final InvocationTargetException e )
554         {
555             throw new ContainerError( e );
556         }
557         catch ( final NoSuchMethodException e )
558         {
559             throw new ContainerError( e );
560         }
561         catch ( final ClassNotFoundException e )
562         {
563             throw new ContainerError( e );
564         }
565     }
566 
567     private Object getObject( final Instance instance )
568     {
569         return this.getScopedObject(
570             SCOPES[instance.getScope() - Specification.SCOPE_MULTITON],
571             instance );
572 
573     }
574 
575     private Object instantiateObject( final Instance instance )
576     {
577         try
578         {
579             Object object = null;
580 
581             if ( VersionParser.compare( instance.getModelVersion(),
582                                         "1.3" ) < 0 )
583             {
584                 if ( instance.getImplementation() != null )
585                 {
586                     object = this.instantiateImplementation(
587                         instance.getClassLoader(),
588                         instance.getImplementation() );
589 
590                 }
591                 else if ( instance.getDependency() != null )
592                 {
593                     object = this.instantiateDependency(
594                         instance.getClassLoader(),
595                         instance.getDependency() );
596 
597                 }
598                 else
599                 {
600                     throw new AssertionError();
601                 }
602             }
603             else
604             {
605                 final Class clazz = Class.forName(
606                     instance.getClassName(), true, instance.getClassLoader() );
607 
608                 if ( Model.class.getName().equals( instance.getModuleName() ) )
609                 {
610                     // Automatically discovered default implementations must use
611                     // the static getDefault method.
612                     final Method accessor =
613                         clazz.getMethod( "getDefault", EMPTY );
614 
615                     object = accessor.invoke( null, EMPTY );
616                 }
617                 else
618                 {
619                     object = clazz.newInstance();
620                 }
621             }
622 
623             synchronized ( this.objects )
624             {
625                 this.objects.put( object, instance );
626             }
627 
628             this.initializeObject( object );
629             return object;
630         }
631         catch ( final Throwable t )
632         {
633             if ( t instanceof Error )
634             {
635                 throw (Error) t;
636             }
637             else if ( t instanceof RuntimeException )
638             {
639                 throw (RuntimeException) t;
640             }
641             else
642             {
643                 throw new org.jdtaus.core.container.InstantiationException(
644                     instance.getClassName(), t );
645 
646             }
647         }
648     }
649 
650     private Implementation getImplementation( final Object object )
651     {
652         MissingImplementationException exception = null;
653         Implementation implementation = null;
654         Class clazz = object.getClass();
655 
656         do
657         {
658             try
659             {
660                 implementation = ModelFactory.getModel().getModules().
661                     getImplementation( clazz.getName() );
662 
663                 break;
664             }
665             catch ( final MissingImplementationException e )
666             {
667                 if ( exception == null )
668                 {
669                     exception = e;
670                 }
671             }
672         }
673         while ( ( clazz = clazz.getSuperclass() ) != null );
674 
675         if ( implementation == null )
676         {
677             throw exception;
678         }
679 
680         return implementation;
681     }
682 
683     private Instance getInstance( final Object object,
684                                   final Implementation impl )
685     {
686         synchronized ( this.objects )
687         {
688             Instance instance = (Instance) this.objects.get( object );
689 
690             if ( instance == null )
691             {
692                 instance =
693                     new Instance( this.getClassLoader( object.getClass() ),
694                                   Specification.SCOPE_MULTITON,
695                                   impl.getIdentifier(),
696                                   impl.getModelVersion(),
697                                   impl.getModuleName() );
698 
699                 instance.setImplementation( impl );
700                 this.objects.put( object, instance );
701             }
702 
703             return instance;
704         }
705     }
706 
707     private Object getDependency( final ClassLoader classLoader,
708                                   final Instance instance,
709                                   final Dependency dependency )
710         throws ClassNotFoundException, NoSuchMethodException,
711                IllegalAccessException, InvocationTargetException
712     {
713         Object dependencyObject =
714             instance != null
715             ? instance.getDependencyObject( dependency.getName() )
716             : null;
717 
718         if ( dependencyObject == null )
719         {
720             if ( dependency.getImplementation() != null )
721             {
722                 final Class specClass =
723                     Class.forName( dependency.getSpecification().getIdentifier(),
724                                    true, classLoader );
725 
726                 final Instance dependencyInstance = new Instance(
727                     classLoader, dependency.getSpecification().getScope(),
728                     dependency.getImplementation().getIdentifier(),
729                     dependency.getImplementation().getModelVersion(),
730                     dependency.getImplementation().getModuleName() );
731 
732                 dependencyInstance.setDependency( dependency );
733                 dependencyObject = this.requestImplementation(
734                     specClass, dependency.getSpecification(),
735                     this.getObject( dependencyInstance ) );
736 
737             }
738             else
739             {
740                 dependencyObject = this.resolveDependency( classLoader,
741                                                            dependency );
742 
743             }
744         }
745 
746         if ( instance != null && dependency.isBound() )
747         {
748             instance.setDependencyObject( dependency.getName(),
749                                           dependencyObject );
750 
751         }
752 
753         return dependencyObject;
754     }
755 
756     private Object resolveDependency( final ClassLoader classLoader,
757                                       final Dependency dependency )
758         throws ClassNotFoundException, NoSuchMethodException,
759                IllegalAccessException, InvocationTargetException
760     {
761         Implementation impl;
762         Instance dependencyInstance;
763         Dependency clone;
764         final Object resolved;
765 
766         final Class specClass =
767             Class.forName( dependency.getSpecification().getIdentifier(),
768                            true, classLoader );
769 
770         switch ( dependency.getSpecification().getMultiplicity() )
771         {
772             case Specification.MULTIPLICITY_ONE:
773                 if ( dependency.getSpecification().
774                     getImplementations().size() != 1 )
775                 {
776                     throw new MultiplicityConstraintException(
777                         dependency.getSpecification().
778                         getIdentifier() );
779 
780                 }
781 
782                 impl = dependency.getSpecification().getImplementations().
783                     getImplementation( 0 );
784 
785                 dependencyInstance = new Instance(
786                     classLoader, dependency.getSpecification().getScope(),
787                     impl.getIdentifier(), impl.getModelVersion(),
788                     impl.getModuleName() );
789 
790                 clone = (Dependency) dependency.clone();
791                 clone.setImplementation( impl );
792                 dependencyInstance.setDependency( clone );
793                 resolved = this.requestImplementation( specClass, dependency.
794                     getSpecification(), this.getObject( dependencyInstance ) );
795 
796                 break;
797 
798             case Specification.MULTIPLICITY_MANY:
799                 final List list = new ArrayList( dependency.getSpecification().
800                     getImplementations().size() );
801 
802                 for ( int i = dependency.getSpecification().
803                     getImplementations().size() - 1; i >= 0; i-- )
804                 {
805                     impl = dependency.getSpecification().getImplementations().
806                         getImplementation( i );
807 
808                     dependencyInstance = new Instance(
809                         classLoader, dependency.getSpecification().getScope(),
810                         impl.getIdentifier(), impl.getModelVersion(),
811                         impl.getModuleName() );
812 
813                     clone = (Dependency) dependency.clone();
814                     clone.setImplementation( impl );
815                     dependencyInstance.setDependency( clone );
816                     list.add( this.requestImplementation(
817                         specClass, dependency.getSpecification(),
818                         this.getObject( dependencyInstance ) ) );
819 
820                 }
821 
822                 final Object[] implementations =
823                     (Object[]) Array.newInstance( specClass,
824                                                   list.size() );
825 
826                 resolved = list.toArray( implementations );
827                 break;
828 
829             default:
830                 throw new AssertionError( Integer.toString(
831                     dependency.getSpecification().getMultiplicity() ) );
832 
833         }
834 
835         return resolved;
836     }
837 
838     private Object resolveImplementation( final ClassLoader classLoader,
839                                           final Specification spec )
840         throws ClassNotFoundException, NoSuchMethodException,
841                IllegalAccessException, InvocationTargetException
842     {
843         Instance instance;
844         Implementation impl;
845 
846         final Object resolved;
847         final Class specClass = Class.forName(
848             spec.getIdentifier(), true, classLoader );
849 
850         switch ( spec.getMultiplicity() )
851         {
852             case Specification.MULTIPLICITY_ONE:
853                 if ( spec.getImplementations().size() != 1 )
854                 {
855                     throw new MultiplicityConstraintException(
856                         spec.getIdentifier() );
857 
858                 }
859 
860                 impl = spec.getImplementations().getImplementation( 0 );
861                 instance = new Instance( classLoader,
862                                          spec.getScope(),
863                                          impl.getIdentifier(),
864                                          impl.getModelVersion(),
865                                          impl.getModuleName() );
866 
867                 instance.setImplementation( impl );
868                 resolved = this.requestImplementation(
869                     specClass, spec, this.getObject( instance ) );
870 
871                 break;
872 
873             case Specification.MULTIPLICITY_MANY:
874                 final List list = new ArrayList(
875                     spec.getImplementations().size() );
876 
877                 for ( int i = spec.getImplementations().size() - 1; i >= 0;
878                       i-- )
879                 {
880                     impl = spec.getImplementations().getImplementation( i );
881                     instance = new Instance( classLoader,
882                                              spec.getScope(),
883                                              impl.getIdentifier(),
884                                              impl.getModelVersion(),
885                                              impl.getModuleName() );
886 
887                     instance.setImplementation( impl );
888                     list.add( this.requestImplementation(
889                         specClass, spec, this.getObject( instance ) ) );
890 
891                 }
892 
893                 final Object[] implementations =
894                     (Object[]) Array.newInstance( specClass,
895                                                   list.size() );
896 
897                 resolved = list.toArray( implementations );
898                 break;
899 
900             default:
901                 throw new AssertionError( Integer.toString(
902                     spec.getMultiplicity() ) );
903 
904         }
905 
906         return resolved;
907     }
908 
909     private Object getScopedObject( final Scope scope, final Instance instance )
910     {
911         Object object;
912 
913         if ( scope != null )
914         {
915             object = scope.getObject( instance.getClassName() );
916 
917             if ( object == null || object instanceof Instance )
918             {
919                 synchronized ( this.cycle )
920                 {
921                     object = scope.getObject( instance.getClassName() );
922 
923                     if ( object == null )
924                     {
925                         scope.putObject( instance.getClassName(), instance );
926 
927                         try
928                         {
929                             object = this.instantiateObject( instance );
930                         }
931                         catch ( final Throwable t )
932                         {
933                             scope.removeObject( instance.getClassName() );
934                             if ( t instanceof Error )
935                             {
936                                 throw (Error) t;
937                             }
938                             else if ( t instanceof RuntimeException )
939                             {
940                                 throw (RuntimeException) t;
941                             }
942                             else
943                             {
944                                 throw new org.jdtaus.core.container.InstantiationException(
945                                     instance.getClassName(), t );
946 
947                             }
948                         }
949 
950                         scope.putObject( instance.getClassName(), object );
951                     }
952                     else if ( object instanceof Instance )
953                     {
954                         throw new DependencyCycleException(
955                             ( (Instance) object ).getClassName(),
956                             instance.getClassName() );
957 
958                     }
959                 }
960             }
961         }
962         else
963         {
964             object = this.instantiateObject( instance );
965         }
966 
967         return object;
968     }
969 
970     private ClassLoader getClassLoader( final Class clazz )
971     {
972         ClassLoader classLoader = clazz.getClassLoader();
973         if ( classLoader == null )
974         {
975             classLoader = ClassLoader.getSystemClassLoader();
976         }
977 
978         return classLoader;
979     }
980 
981     private Object requestImplementation( final Class specClass,
982                                           final Specification spec,
983                                           final Object object )
984         throws NoSuchMethodException, IllegalAccessException,
985                InvocationTargetException
986     {
987         Object resolved = object;
988         Method accessor = null;
989 
990         try
991         {
992             if ( !specClass.isAssignableFrom( object.getClass() ) )
993             {
994                 accessor = object.getClass().getDeclaredMethod(
995                     spec.getIdentifier().replace( '.', '_' ), EMPTY );
996 
997                 accessor.setAccessible( true );
998                 resolved = accessor.invoke( object, EMPTY );
999             }
1000 
1001             return resolved;
1002         }
1003         finally
1004         {
1005             if ( accessor != null )
1006             {
1007                 accessor.setAccessible( false );
1008             }
1009         }
1010     }
1011 
1012     //--------------------------------------------------------DefaultContainer--
1013 }