001/*
002 * Copyright (c) 2007-2015 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  }