/**
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* 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 org.mapstruct.ap.testutil.runner;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* A parallel capable class loader for which additional URLs can be added after construction, and that will force
* classes from org.mapstruct.at.test.** packages to be loaded with this instance
*
* @author Andreas Gudian
*/
final class ModifiableURLClassLoader extends URLClassLoader {
private static final String ORG_MAPSTRUCT_AP_TEST = "org.mapstruct.ap.test.";
private static final FilteringParentClassLoader DEFAULT_PARENT_CLASS_LOADER = new FilteringParentClassLoader(
ORG_MAPSTRUCT_AP_TEST );
static {
tryRegisterAsParallelCapable();
}
private final ConcurrentMap<URL, URL> addedURLs = new ConcurrentHashMap<URL, URL>();
ModifiableURLClassLoader(ClassLoader parent) {
super( new URL[] { }, parent );
}
ModifiableURLClassLoader() {
this( DEFAULT_PARENT_CLASS_LOADER );
}
@Override
protected void addURL(URL url) {
if ( addedURLs.putIfAbsent( url, url ) == null ) {
super.addURL( url );
}
}
ModifiableURLClassLoader withOriginsOf(Collection<Class<?>> classes) {
for ( Class<?> c : classes ) {
withOriginOf( c );
}
return this;
}
ModifiableURLClassLoader withOriginOf(Class<?> clazz) {
String classFileName = clazz.getName().replace( ".", "/" ) + ".class";
URL classResource = clazz.getClassLoader().getResource( classFileName );
String fullyQualifiedUrl = classResource.toExternalForm();
String basePath = fullyQualifiedUrl.substring( 0, fullyQualifiedUrl.length() - classFileName.length() );
return withURL( basePath );
}
ModifiableURLClassLoader withPaths(Collection<String> baseUrls) {
for ( String url : baseUrls ) {
withPath( url );
}
return this;
}
ModifiableURLClassLoader withURL(String baseUrl) {
try {
addURL( new URL( baseUrl ) );
}
catch ( MalformedURLException e ) {
throw new RuntimeException( e );
}
return this;
}
ModifiableURLClassLoader withPath(String path) {
try {
addURL( new File( path ).toURI().toURL() );
}
catch ( MalformedURLException e ) {
throw new RuntimeException( e );
}
return this;
}
private static void tryRegisterAsParallelCapable() {
try {
ClassLoader.class.getMethod( "registerAsParallelCapable" ).invoke( null );
}
catch ( NoSuchMethodException e ) {
return; // ignore
}
catch ( SecurityException e ) {
return; // ignore
}
catch ( IllegalAccessException e ) {
return; // ignore
}
catch ( IllegalArgumentException e ) {
return; // ignore
}
catch ( InvocationTargetException e ) {
return; // ignore
}
}
}