/*
 * Copyright 2015 the original author or authors.
 *
 * 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.springframework.boot.loader;

import java.lang.reflect.Method;
import java.net.URL;
import java.util.List;

import org.springframework.boot.loader.archive.Archive;
import org.springframework.boot.loader.util.AsciiBytes;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;

/**
 * A (possibly temporary) alternative to {@link JarLauncher} that provides a public
 * {@link #launch(String[])} method.
 *
 * Also, it restricts the classloader of the launched application to the contents of the uber-jar and the
 * extension classloader of the JVM.
 *
 * @author Mark Fisher
 * @author Marius Bogoevici
 */
public class ModuleJarLauncher extends ExecutableArchiveLauncher {

	private static final AsciiBytes LIB = new AsciiBytes("lib/");

	public ModuleJarLauncher(Archive archive) {
		super(archive);
	}

	@Override
	protected boolean isNestedArchive(Archive.Entry entry) {
		return !entry.isDirectory() && entry.getName().startsWith(LIB);
	}

	@Override
	protected void postProcessClassPathArchives(List<Archive> archives) throws Exception {
		archives.add(0, getArchive());
	}

	@Override
	// TODO: this method is protected in Spring Boot but we need it to be public here
	public void launch(String[] args) {
		super.launch(args);
	}

	@Override
	protected void launch(String[] args, String mainClass, ClassLoader classLoader)
			throws Exception {
		if (ClassUtils.isPresent(
				"org.apache.catalina.webresources.TomcatURLStreamHandlerFactory",
				classLoader)) {
			// Ensure the method is invoked on a class that is loaded by the provided
			// class loader (not the current context class loader):
			Method method = ReflectionUtils
					.findMethod(
							classLoader
							.loadClass("org.apache.catalina.webresources.TomcatURLStreamHandlerFactory"),
							"disable");
			ReflectionUtils.invokeMethod(method, null);
		}
		super.launch(args, mainClass, classLoader);
	}

	@Override
	protected ClassLoader createClassLoader(URL[] urls) throws Exception {
		ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
		// try to retrieve the extension classloader
		ClassLoader extensionClassLoader = systemClassLoader != null ? systemClassLoader.getParent() : null;
		// set the classloader for the module as the extension classloader if available
		// fall back to the system classloader (which can also be null) if not available
		ClassLoader classLoaderForModule = extensionClassLoader != null ? extensionClassLoader : systemClassLoader;
		return new LaunchedURLClassLoader(urls, classLoaderForModule);
	}

}

@@ -706,16 +706,48 @@
 et.URL;%0A
+import java.net.URLClassLoader;%0A
 import j
@@ -2732,55 +2732,65 @@
 ;%0A%09%09
-// try to retrieve the extension c
+if (systemClassLoader instanceof URLC
 lass
-l
+L
 oader
-%0A%09%09
+) %7B%0A%09%09%09URL
 Clas
@@ -2797,26 +2797,17 @@
 sLoader 
-extensionC
+c
 lassLoad
@@ -2811,22 +2811,20 @@
 oader = 
-system
+(URL
 ClassLoa
@@ -2826,26 +2826,17 @@
 ssLoader
- != null ?
+)
  systemC
@@ -2849,304 +2849,293 @@
 ader
-.getParent() : null;%0A%09%09// set the
+;%0A%09%09%09URL%5B%5D toUse = new URL%5Burls.length +
  class
-l
+L
 oader
- for the module as the extension classloader if available%0A%09%09// fall back to the system 
+.getURLs().length%5D;%0A%09%09%09System.arraycopy(urls, 0, toUse, 0, urls.length);%0A%09%09%09System.arraycopy(
 class
-l
+L
 oader
- (which can also be null) if not available%0A%09%09ClassLoader classLoaderForModule = extensionClassLoader != null ? extensionClassLoader : systemClassLoader;%0A
+.getURLs(), 0, toUse, urls.length, classLoader.getURLs().length);%0A%09%09%09return new LaunchedURLClassLoader(toUse, null);%0A%09%09%7D else %7B%0A%09
 %09%09re
@@ -3172,17 +3172,23 @@
 r(urls, 
-c
+systemC
 lassLoad
@@ -3193,19 +3193,14 @@
 ader
-ForModule);
+);%0A%09%09%7D
 %0A%09%7D%0A

Copy parent URLs when creating CL