/* * Copyright © 2016 Cask Data, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package co.cask.cdap.security.authorization; import co.cask.cdap.api.app.Application; import co.cask.cdap.common.lang.ClassPathResources; import co.cask.cdap.common.lang.DirectoryClassLoader; import co.cask.cdap.common.lang.FilterClassLoader; import co.cask.cdap.security.spi.authorization.Authorizer; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; import java.util.Set; /** * {@link DirectoryClassLoader} for {@link Authorizer} extensions. */ public class AuthorizerClassLoader extends DirectoryClassLoader { private static final Logger LOG = LoggerFactory.getLogger(AuthorizerClassLoader.class); @VisibleForTesting static ClassLoader createParent() { ClassLoader baseClassLoader = AuthorizerClassLoader.class.getClassLoader(); // Trace dependencies for Authorizer class. This will make classes from cdap-security-spi as well as cdap-proto // and other dependencies of cdap-security-spi available to the authorizer extension. Set<String> authorizerResources; try { authorizerResources = ClassPathResources.getResourcesWithDependencies(baseClassLoader, Authorizer.class); } catch (IOException e) { LOG.error("Failed to determine resources for authorizer class loader while tracing dependencies of " + "Authorizer.", e); authorizerResources = ImmutableSet.of(); } // Trace dependencies of cdap-api and include them as well. This will make classes like slf4j Logger implementation // as well as classes from twill-api and other dependencies required for cdap-api available to the authorizer // extension. Set<String> apiResources; try { apiResources = ClassPathResources.getResourcesWithDependencies(baseClassLoader, Application.class); } catch (IOException e) { LOG.error("Failed to determine resources for authorizer class loader while tracing dependencies of " + "cdap-api.", e); apiResources = ImmutableSet.of(); } final Set<String> finalAuthorizerResources = Sets.union(authorizerResources, apiResources); return new FilterClassLoader(baseClassLoader, new FilterClassLoader.Filter() { @Override public boolean acceptResource(String resource) { return finalAuthorizerResources.contains(resource); } @Override public boolean acceptPackage(String packageName) { return true; } }); } AuthorizerClassLoader(File unpackedJarDir) { super(unpackedJarDir, createParent(), "lib"); } }