    001/*
    002 * Copyright (c) 2007-2016 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
    021package cascading.provider;
    022
    023import java.net.URL;
    024
    025import org.slf4j.Logger;
    026import 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 */
    037public 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  }