001    /*
002     * Copyright 2006 Stephen J. McConnell.
003     *
004     * Licensed  under the  Apache License,  Version 2.0  (the "License");
005     * you may not use  this file  except in  compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *   http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed  under the  License is distributed on an "AS IS" BASIS,
012     * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
013     * implied.
014     *
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    
019    package net.dpml.lang;
020    
021    import java.util.ServiceLoader;
022    
023    /**
024     * Default service registry implementation that resolves services via 
025     * services resolvable using <tt>java.util.ServiceLoader</tt>.
026     *
027     * @author <a href="http://www.dpml.net">Digital Product Management Laboratory</a>
028     * @version 2.0.1
029     */
030    public class StandardServiceRegistry implements ServiceRegistry
031    {
032        private final ServiceRegistry m_parent;
033        
034       /**
035        * Creation of a new service registry with no parent.
036        */
037        public StandardServiceRegistry()
038        {
039            this( null );
040        }
041        
042       /**
043        * Creation of a new service registry with fallback delegation to
044        * a parent registry.
045        *
046        * @param parent an optional parent registry
047        */
048        public StandardServiceRegistry( ServiceRegistry parent )
049        {
050            m_parent = parent;
051        }
052        
053       /**
054        * Matches a service in the registry with the supplied type.  If no
055        * match is found and a parent registry has been delclared, the lookup
056        * request is passed onto the parent registry, otherwise null is 
057        * returned.
058        */
059        public <T>T lookup( Class<T> type )
060        {
061            ServiceLoader<T> loaders = ServiceLoader.load( type );
062            for( T service : loaders )
063            {
064                return service; // the first available
065            }
066            if( null != m_parent )
067            {
068                return m_parent.lookup( type );
069            }
070            return null;
071        }
072    }
073