001/*
002 *  jDTAUS Core RI Client Container
003 *  Copyright (C) 2005 Christian Schulte
004 *  <cs@schulte.it>
005 *
006 *  This library is free software; you can redistribute it and/or
007 *  modify it under the terms of the GNU Lesser General Public
008 *  License as published by the Free Software Foundation; either
009 *  version 2.1 of the License, or any later version.
010 *
011 *  This library is distributed in the hope that it will be useful,
012 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
013 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014 *  Lesser General Public License for more details.
015 *
016 *  You should have received a copy of the GNU Lesser General Public
017 *  License along with this library; if not, write to the Free Software
018 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
019 *
020 */
021package org.jdtaus.core.container.ri.client;
022
023import java.lang.reflect.Array;
024import java.lang.reflect.Constructor;
025import java.lang.reflect.InvocationTargetException;
026import java.lang.reflect.Method;
027import java.text.MessageFormat;
028import java.util.ArrayList;
029import java.util.List;
030import java.util.Locale;
031import java.util.Map;
032import java.util.logging.Level;
033import java.util.logging.Logger;
034import org.jdtaus.core.container.Container;
035import org.jdtaus.core.container.ContainerError;
036import org.jdtaus.core.container.ContainerInitializer;
037import org.jdtaus.core.container.ContextFactory;
038import org.jdtaus.core.container.ContextInitializer;
039import org.jdtaus.core.container.Dependency;
040import org.jdtaus.core.container.DependencyCycleException;
041import org.jdtaus.core.container.Implementation;
042import org.jdtaus.core.container.MissingImplementationException;
043import org.jdtaus.core.container.Model;
044import org.jdtaus.core.container.ModelFactory;
045import org.jdtaus.core.container.MultiplicityConstraintException;
046import org.jdtaus.core.container.Specification;
047import org.jdtaus.core.container.ri.client.versioning.VersionParser;
048
049/**
050 * {@code Container} reference implementation.
051 *
052 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
053 * @version $JDTAUS: DefaultContainer.java 8743 2012-10-07 03:06:20Z schulte $
054 *
055 * @see org.jdtaus.core.container.ContainerFactory
056 */
057public class DefaultContainer implements Container
058{
059    //--Constants---------------------------------------------------------------
060
061    /** Empty Class-Array. */
062    private static final Class[] EMPTY =
063    {
064    };
065
066    /** Implementation Class-Array. */
067    private static final Class[] IMPL_CTOR =
068    {
069        Implementation.class
070    };
071
072    /** Dependency Class-Array. */
073    private static final Class[] DEP_CTOR =
074    {
075        Dependency.class
076    };
077
078    /** Array of scope implementations. */
079    private static final Scope[] SCOPES =
080    {
081        null, new ContextScope(), new SingletonScope()
082    };
083
084    //---------------------------------------------------------------Constants--
085    //--Container---------------------------------------------------------------
086
087    /** Mutex used to detect cyclic instantiations. */
088    private final Object cycle = new Object();
089
090    /** Maps objects to model object. */
091    private final Map objects = new WeakIdentityHashMap( 1024 );
092
093    public Object getObject( final Class specification )
094    {
095        if ( specification == null )
096        {
097            throw new NullPointerException( "specification" );
098        }
099
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}