    001    /*
    002     * Copyright (c) 2007-2014 Concurrent, Inc. All Rights Reserved.
    003     *
    004     * Project and contact information: http://www.cascading.org/
    005     *
    006     * This file is part of the Cascading project.
    007     *
    008     * Licensed under the Apache License, Version 2.0 (the "License");
    009     * you may not use this file except in compliance with the License.
    010     * You may obtain a copy of the License at
    011     *
    012     *     http://www.apache.org/licenses/LICENSE-2.0
    013     *
    014     * Unless required by applicable law or agreed to in writing, software
    015     * distributed under the License is distributed on an "AS IS" BASIS,
    016     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    017     * See the License for the specific language governing permissions and
    018     * limitations under the License.
    019     */
    020
    021    package cascading.provider;
    022
    023    import java.net.URL;
    024
    025    import org.slf4j.Logger;
    026    import org.slf4j.LoggerFactory;
    027
    028    /**
    029     * Class ProviderLoader is the base class for loading various "provider" types.
    030     * <p/>
    031     * This loader can optinally load a provider implementation within its own ClassLoader using the
    032     * {@link ChildFirstURLClassLoader}.
    033     *
    034     * @see FactoryLoader
    035     * @see ServiceLoader
    036     */
    037    public class ProviderLoader<Provider>
    038      {
    039      private static final Logger LOG = LoggerFactory.getLogger( ServiceLoader.class );
    040      URL libraryURL;
    041      String[] exclusions;
    042
    043      ClassLoader classLoader;
    044
    045      public ProviderLoader()
    046        {
    047        }
    048
    049      public ProviderLoader( String[] exclusions, URL libraryURL )
    050        {
    051        this.exclusions = exclusions;
    052        this.libraryURL = libraryURL;
    053        }
    054
    055      public Provider createProvider( String className )
    056        {
    057        // test for ant style token escapes
    058        if( className == null || className.isEmpty() )
    059          return null;
    060
    061        if( className.startsWith( "@" ) && className.endsWith( "@" ) )
    062          {
    063          LOG.warn( "invalid classname: {}", className );
    064          return null;
    065          }
    066
    067        try
    068          {
    069          Class<Provider> type = (Class<Provider>) getClassLoader().loadClass( className );
    070
    071          return type.newInstance();
    072          }
    073        catch( ClassNotFoundException exception )
    074          {
    075          LOG.error( "unable to find service class: {}, with exception: {}", className, exception );
    076          }
    077        catch( IllegalAccessException exception )
    078          {
    079          LOG.error( "unable to instantiate service class: {}, with exception: {}", className, exception );
    080          }
    081        catch( InstantiationException exception )
    082          {
    083          LOG.error( "unable to instantiate service class: {}, with exception: {}", className, exception );
    084          }
    085
    086        return null;
    087        }
    088
    089      private synchronized ClassLoader getClassLoader()
    090        {
    091        if( classLoader != null )
    092          return classLoader;
    093
    094        if( libraryURL == null )
    095          {
    096          classLoader = Thread.currentThread().getContextClassLoader();
    097          }
    098        else
    099          {
    100          LOG.info( "loading services from library: {}", libraryURL );
    101
    102          classLoader = new ChildFirstURLClassLoader( exclusions, libraryURL );
    103          }
    104
    105        return classLoader;
    106        }
    107      }