/* * Copyright 2017 TNG Technology Consulting GmbH * * 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 com.tngtech.archunit.core.importer; import java.io.IOException; import java.net.URL; import java.net.URLClassLoader; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import com.google.common.collect.ImmutableSet; import com.tngtech.archunit.PublicAPI; import com.tngtech.archunit.base.ArchUnitException.LocationException; import static com.tngtech.archunit.PublicAPI.Usage.ACCESS; public final class Locations { private Locations() { } @PublicAPI(usage = ACCESS) public static Collection<Location> of(Collection<URL> urls) { Set<Location> result = new HashSet<>(); for (URL url : urls) { result.add(Location.of(url)); } return result; } /** * All locations in the classpath that match the supplied package.<br> * NOTE: Only works, if the used ClassLoader extends {@link URLClassLoader} (which is true for normal settings) * * @param pkg the package to look for within the classpath * @return Locations of all paths that match the supplied package */ @PublicAPI(usage = ACCESS) public static Set<Location> ofPackage(String pkg) { ImmutableSet.Builder<Location> result = ImmutableSet.builder(); for (Location location : getLocationsOf(asResourceName(pkg))) { result.add(location); } return result.build(); } @PublicAPI(usage = ACCESS) public static Set<Location> ofClass(Class<?> clazz) { return getLocationsOf(asResourceName(clazz.getName()) + ".class"); } @PublicAPI(usage = ACCESS) public static Set<Location> inClassPath() { Set<Location> result = new HashSet<>(); for (URLClassLoader loader : findAllUrlClassLoadersInContext()) { for (URL url : loader.getURLs()) { result.add(Location.of(url)); } } return result; } private static String asResourceName(String qualifiedName) { return qualifiedName.replace('.', '/'); } private static Set<Location> getLocationsOf(String resourceName) { ImmutableSet.Builder<Location> result = ImmutableSet.builder(); for (URLClassLoader loader : findAllUrlClassLoadersInContext()) { for (URL url : getResources(loader, resourceName)) { result.add(Location.of(url)); } } return result.build(); } private static List<URL> getResources(URLClassLoader loader, String resourceName) { try { return Collections.list(loader.getResources(resourceName)); } catch (IOException e) { throw new LocationException(e); } } private static Set<URLClassLoader> findAllUrlClassLoadersInContext() { return ImmutableSet.<URLClassLoader>builder() .addAll(findUrlClassLoadersInHierarchy(Thread.currentThread().getContextClassLoader())) .addAll(findUrlClassLoadersInHierarchy(Locations.class.getClassLoader())) .build(); } private static Set<URLClassLoader> findUrlClassLoadersInHierarchy(ClassLoader loader) { Set<URLClassLoader> result = new HashSet<>(); while (loader != null) { if (loader instanceof URLClassLoader) { result.add((URLClassLoader) loader); } loader = loader.getParent(); } return result; } }