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