解决动态生成类依赖jar in jar编译报找不到类的问题.
This commit is contained in:
+2
@@ -21,6 +21,8 @@
|
||||
*/
|
||||
package fun.asgc.neutrino.core.aop.compiler;
|
||||
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.SpringBootJarParser;
|
||||
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.NestingKind;
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
package fun.asgc.neutrino.core.aop.compiler;
|
||||
|
||||
import org.springframework.boot.loader.jar.JarFile;
|
||||
import org.springframework.boot.loader.jar.JarURLConnection;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* @author: aoshiguchen
|
||||
* @date: 2023/2/23
|
||||
*/
|
||||
public class SpringBootJarParser {
|
||||
|
||||
/**
|
||||
* 根据一个URI从SpringBoot jar包中解析出输入流
|
||||
* 1、先尝试直接获取流,若能获取则到此结束
|
||||
* 2、若不能获取,且URI标识定位的是一个jar包,则进行处理(只处理SpringBoot情况的jar)
|
||||
* @param uri
|
||||
* @return
|
||||
*/
|
||||
public static InputStream getInputStream(URI uri) {
|
||||
try {
|
||||
return uri.toURL().openStream();
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
if (e instanceof FileNotFoundException && uri.getScheme().equals("jar")) {
|
||||
URL url = uri.toURL();
|
||||
String path = url.getPath();
|
||||
int index = path.indexOf("!");
|
||||
if (index >= 0) {
|
||||
path = path.substring(0, index);
|
||||
}
|
||||
if (path.startsWith("file:")) {
|
||||
path = path.substring(5);
|
||||
}
|
||||
JarFile jarFile = new JarFile(new File(path));
|
||||
return JarURLConnection.get(url, jarFile).getInputStream();
|
||||
}
|
||||
} catch (Exception e1) {
|
||||
// ignore
|
||||
System.out.println("1");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+1
-17
@@ -1,20 +1,4 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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
|
||||
*
|
||||
* https://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;
|
||||
package fun.asgc.neutrino.core.aop.compiler.internal;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.MalformedURLException;
|
||||
+3
-19
@@ -1,23 +1,7 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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
|
||||
*
|
||||
* https://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 fun.asgc.neutrino.core.aop.compiler.internal;
|
||||
|
||||
package org.springframework.boot.loader;
|
||||
|
||||
import org.springframework.boot.loader.archive.Archive;
|
||||
import org.springframework.boot.loader.archive.ExplodedArchive;
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.archive.Archive;
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.archive.ExplodedArchive;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
+8
-29
@@ -1,25 +1,8 @@
|
||||
/*
|
||||
* Copyright 2012-2021 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
|
||||
*
|
||||
* https://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 fun.asgc.neutrino.core.aop.compiler.internal;
|
||||
|
||||
package org.springframework.boot.loader;
|
||||
|
||||
import org.springframework.boot.loader.archive.Archive;
|
||||
import org.springframework.boot.loader.archive.Archive.EntryFilter;
|
||||
import org.springframework.boot.loader.archive.ExplodedArchive;
|
||||
import org.springframework.boot.loader.archive.JarFileArchive;
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.archive.Archive;
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.archive.ExplodedArchive;
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.archive.JarFileArchive;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -34,18 +17,18 @@ import java.io.File;
|
||||
* @author Scott Frederick
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class MyJarLauncher extends ExecutableArchiveLauncher {
|
||||
public class JarLauncher extends ExecutableArchiveLauncher {
|
||||
|
||||
private String path;
|
||||
|
||||
static final EntryFilter NESTED_ARCHIVE_ENTRY_FILTER = (entry) -> {
|
||||
static final Archive.EntryFilter NESTED_ARCHIVE_ENTRY_FILTER = (entry) -> {
|
||||
if (entry.isDirectory()) {
|
||||
return entry.getName().equals("BOOT-INF/classes/");
|
||||
}
|
||||
return entry.getName().startsWith("BOOT-INF/lib/");
|
||||
};
|
||||
|
||||
public MyJarLauncher(String path) {
|
||||
public JarLauncher(String path) {
|
||||
this.path = path;
|
||||
try {
|
||||
this.setArchive(createArchive(this.path));
|
||||
@@ -71,7 +54,7 @@ public class MyJarLauncher extends ExecutableArchiveLauncher {
|
||||
return (root.isDirectory() ? new ExplodedArchive(root) : new JarFileArchive(root));
|
||||
}
|
||||
|
||||
protected MyJarLauncher(Archive archive) {
|
||||
protected JarLauncher(Archive archive) {
|
||||
super(archive);
|
||||
}
|
||||
|
||||
@@ -90,8 +73,4 @@ public class MyJarLauncher extends ExecutableArchiveLauncher {
|
||||
return "BOOT-INF/";
|
||||
}
|
||||
|
||||
// public static void main(String[] args) throws Exception {
|
||||
// new MyJarLauncher().launch(args);
|
||||
// }
|
||||
|
||||
}
|
||||
+5
-21
@@ -1,23 +1,7 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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
|
||||
*
|
||||
* https://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 fun.asgc.neutrino.core.aop.compiler.internal;
|
||||
|
||||
package org.springframework.boot.loader;
|
||||
|
||||
import org.springframework.boot.loader.archive.Archive;
|
||||
import org.springframework.boot.loader.jar.Handler;
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.archive.Archive;
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.jar.Handler;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -307,8 +291,8 @@ public class LaunchedURLClassLoader extends URLClassLoader {
|
||||
|
||||
private void clearCache(URLConnection connection) throws IOException {
|
||||
Object jarFile = ((JarURLConnection) connection).getJarFile();
|
||||
if (jarFile instanceof org.springframework.boot.loader.jar.JarFile) {
|
||||
((org.springframework.boot.loader.jar.JarFile) jarFile).clearCache();
|
||||
if (jarFile instanceof fun.asgc.neutrino.core.aop.compiler.internal.jar.JarFile) {
|
||||
((fun.asgc.neutrino.core.aop.compiler.internal.jar.JarFile) jarFile).clearCache();
|
||||
}
|
||||
}
|
||||
|
||||
+4
-62
@@ -1,25 +1,8 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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
|
||||
*
|
||||
* https://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 fun.asgc.neutrino.core.aop.compiler.internal;
|
||||
|
||||
package org.springframework.boot.loader;
|
||||
|
||||
import org.springframework.boot.loader.archive.Archive;
|
||||
import org.springframework.boot.loader.archive.ExplodedArchive;
|
||||
import org.springframework.boot.loader.archive.JarFileArchive;
|
||||
import org.springframework.boot.loader.jar.JarFile;
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.archive.Archive;
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.archive.ExplodedArchive;
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.archive.JarFileArchive;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
@@ -40,24 +23,6 @@ import java.util.List;
|
||||
*/
|
||||
public abstract class Launcher {
|
||||
|
||||
private static final String JAR_MODE_LAUNCHER = "org.springframework.boot.loader.jarmode.JarModeLauncher";
|
||||
|
||||
/**
|
||||
* Launch the application. This method is the initial entry point that should be
|
||||
* called by a subclass {@code public static void main(String[] args)} method.
|
||||
* @param args the incoming arguments
|
||||
* @throws Exception if the application fails to launch
|
||||
*/
|
||||
protected void launch(String[] args) throws Exception {
|
||||
if (!isExploded()) {
|
||||
JarFile.registerUrlProtocolHandler();
|
||||
}
|
||||
ClassLoader classLoader = createClassLoader(getClassPathArchivesIterator());
|
||||
String jarMode = System.getProperty("jarmode");
|
||||
String launchClass = (jarMode != null && !jarMode.isEmpty()) ? JAR_MODE_LAUNCHER : getMainClass();
|
||||
launch(args, launchClass, classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a classloader for the specified archives.
|
||||
* @param archives the archives
|
||||
@@ -83,29 +48,6 @@ public abstract class Launcher {
|
||||
return new LaunchedURLClassLoader(isExploded(), getArchive(), urls, getClass().getClassLoader());
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch the application given the archive file and a fully configured classloader.
|
||||
* @param args the incoming arguments
|
||||
* @param launchClass the launch class to run
|
||||
* @param classLoader the classloader
|
||||
* @throws Exception if the launch fails
|
||||
*/
|
||||
protected void launch(String[] args, String launchClass, ClassLoader classLoader) throws Exception {
|
||||
Thread.currentThread().setContextClassLoader(classLoader);
|
||||
createMainMethodRunner(launchClass, args, classLoader).run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the {@code MainMethodRunner} used to launch the application.
|
||||
* @param mainClass the main class
|
||||
* @param args the incoming arguments
|
||||
* @param classLoader the classloader
|
||||
* @return the main method runner
|
||||
*/
|
||||
protected MainMethodRunner createMainMethodRunner(String mainClass, String[] args, ClassLoader classLoader) {
|
||||
return new MainMethodRunner(mainClass, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the main class that should be launched.
|
||||
* @return the name of the main class
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package fun.asgc.neutrino.core.aop.compiler.internal;
|
||||
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.jar.JarFile;
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.jar.JarURLConnection;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* @author: aoshiguchen
|
||||
* @date: 2023/2/23
|
||||
*/
|
||||
public final class SpringBootJarParser {
|
||||
|
||||
/**
|
||||
* 根据一个URI从SpringBoot jar包中解析出输入流
|
||||
* 1、先尝试直接获取流,若能获取则到此结束
|
||||
* 2、若不能获取,且URI标识定位的是一个jar包,则进行处理(只处理SpringBoot情况的jar)
|
||||
* @param uri
|
||||
* @return
|
||||
*/
|
||||
public static InputStream getInputStream(URI uri) {
|
||||
try {
|
||||
if (uri.getScheme().equals("jar")) {
|
||||
URL url = uri.toURL();
|
||||
String path = url.getPath();
|
||||
int index = path.indexOf("!");
|
||||
if (index >= 0) {
|
||||
path = path.substring(0, index);
|
||||
}
|
||||
if (path.startsWith("file:")) {
|
||||
path = path.substring(5);
|
||||
}
|
||||
JarFile jarFile = new JarFile(new File(path));
|
||||
return JarURLConnection.get(url, jarFile).getInputStream();
|
||||
}
|
||||
} catch (Exception e1) {
|
||||
// ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+1
-17
@@ -1,20 +1,4 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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
|
||||
*
|
||||
* https://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.util;
|
||||
package fun.asgc.neutrino.core.aop.compiler.internal;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
+2
-18
@@ -1,22 +1,6 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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
|
||||
*
|
||||
* https://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 fun.asgc.neutrino.core.aop.compiler.internal.archive;
|
||||
|
||||
package org.springframework.boot.loader.archive;
|
||||
|
||||
import org.springframework.boot.loader.Launcher;
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.Launcher;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
+1
-17
@@ -1,20 +1,4 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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
|
||||
*
|
||||
* https://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.archive;
|
||||
package fun.asgc.neutrino.core.aop.compiler.internal.archive;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
+2
-18
@@ -1,22 +1,6 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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
|
||||
*
|
||||
* https://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 fun.asgc.neutrino.core.aop.compiler.internal.archive;
|
||||
|
||||
package org.springframework.boot.loader.archive;
|
||||
|
||||
import org.springframework.boot.loader.jar.JarFile;
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.jar.JarFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
+1
-17
@@ -1,20 +1,4 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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
|
||||
*
|
||||
* https://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.data;
|
||||
package fun.asgc.neutrino.core.aop.compiler.internal.data;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
+1
-17
@@ -1,20 +1,4 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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
|
||||
*
|
||||
* https://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.data;
|
||||
package fun.asgc.neutrino.core.aop.compiler.internal.data;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
+1
-17
@@ -1,20 +1,4 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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
|
||||
*
|
||||
* https://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.jar;
|
||||
package fun.asgc.neutrino.core.aop.compiler.internal.jar;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
+1
-17
@@ -1,20 +1,4 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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
|
||||
*
|
||||
* https://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.jar;
|
||||
package fun.asgc.neutrino.core.aop.compiler.internal.jar;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package fun.asgc.neutrino.core.aop.compiler.internal.jar;
|
||||
|
||||
/**
|
||||
* Utilities for dealing with bytes from ZIP files.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
final class Bytes {
|
||||
|
||||
private Bytes() {
|
||||
}
|
||||
|
||||
static long littleEndianValue(byte[] bytes, int offset, int length) {
|
||||
long value = 0;
|
||||
for (int i = length - 1; i >= 0; i--) {
|
||||
value = ((value << 8) | (bytes[offset + i] & 0xFF));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
+2
-18
@@ -1,22 +1,6 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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
|
||||
*
|
||||
* https://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 fun.asgc.neutrino.core.aop.compiler.internal.jar;
|
||||
|
||||
package org.springframework.boot.loader.jar;
|
||||
|
||||
import org.springframework.boot.loader.data.RandomAccessData;
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.data.RandomAccessData;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
+2
-18
@@ -1,22 +1,6 @@
|
||||
/*
|
||||
* Copyright 2012-2023 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
|
||||
*
|
||||
* https://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 fun.asgc.neutrino.core.aop.compiler.internal.jar;
|
||||
|
||||
package org.springframework.boot.loader.jar;
|
||||
|
||||
import org.springframework.boot.loader.data.RandomAccessData;
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.data.RandomAccessData;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.ZoneId;
|
||||
+2
-18
@@ -1,22 +1,6 @@
|
||||
/*
|
||||
* Copyright 2012-2021 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
|
||||
*
|
||||
* https://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 fun.asgc.neutrino.core.aop.compiler.internal.jar;
|
||||
|
||||
package org.springframework.boot.loader.jar;
|
||||
|
||||
import org.springframework.boot.loader.data.RandomAccessData;
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.data.RandomAccessData;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package fun.asgc.neutrino.core.aop.compiler.internal.jar;
|
||||
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.data.RandomAccessData;
|
||||
|
||||
/**
|
||||
* Callback visitor triggered by {@link CentralDirectoryParser}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
interface CentralDirectoryVisitor {
|
||||
|
||||
void visitStart(CentralDirectoryEndRecord endRecord, RandomAccessData centralDirectoryData);
|
||||
|
||||
void visitFileHeader(CentralDirectoryFileHeader fileHeader, long dataOffset);
|
||||
|
||||
void visitEnd();
|
||||
|
||||
}
|
||||
+1
-17
@@ -1,20 +1,4 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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
|
||||
*
|
||||
* https://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.jar;
|
||||
package fun.asgc.neutrino.core.aop.compiler.internal.jar;
|
||||
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
+4
-20
@@ -1,20 +1,4 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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
|
||||
*
|
||||
* https://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.jar;
|
||||
package fun.asgc.neutrino.core.aop.compiler.internal.jar;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -82,10 +66,10 @@ public class Handler extends URLStreamHandler {
|
||||
@Override
|
||||
protected URLConnection openConnection(URL url) throws IOException {
|
||||
if (this.jarFile != null && isUrlInJarFile(url, this.jarFile)) {
|
||||
return JarURLConnection.get(url, this.jarFile);
|
||||
return fun.asgc.neutrino.core.aop.compiler.internal.jar.JarURLConnection.get(url, this.jarFile);
|
||||
}
|
||||
try {
|
||||
return JarURLConnection.get(url, getRootJarFileFromUrl(url));
|
||||
return fun.asgc.neutrino.core.aop.compiler.internal.jar.JarURLConnection.get(url, getRootJarFileFromUrl(url));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
return openFallbackConnection(url, ex);
|
||||
@@ -418,7 +402,7 @@ public class Handler extends URLStreamHandler {
|
||||
resetCachedUrlHandlers();
|
||||
jarContextUrl = new URL("jar:file:context.jar!/");
|
||||
URLConnection connection = jarContextUrl.openConnection();
|
||||
if (connection instanceof JarURLConnection) {
|
||||
if (connection instanceof fun.asgc.neutrino.core.aop.compiler.internal.jar.JarURLConnection) {
|
||||
jarContextUrl = null;
|
||||
}
|
||||
}
|
||||
+1
-17
@@ -1,20 +1,4 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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
|
||||
*
|
||||
* https://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.jar;
|
||||
package fun.asgc.neutrino.core.aop.compiler.internal.jar;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
+1
-17
@@ -1,20 +1,4 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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
|
||||
*
|
||||
* https://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.jar;
|
||||
package fun.asgc.neutrino.core.aop.compiler.internal.jar;
|
||||
|
||||
import java.security.CodeSigner;
|
||||
import java.security.cert.Certificate;
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package fun.asgc.neutrino.core.aop.compiler.internal.jar;
|
||||
|
||||
/**
|
||||
* Interface that can be used to filter and optionally rename jar entries.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
interface JarEntryFilter {
|
||||
|
||||
/**
|
||||
* Apply the jar entry filter.
|
||||
* @param name the current entry name. This may be different that the original entry
|
||||
* name if a previous filter has been applied
|
||||
* @return the new name of the entry or {@code null} if the entry should not be
|
||||
* included.
|
||||
*/
|
||||
AsciiBytes apply(AsciiBytes name);
|
||||
|
||||
}
|
||||
+3
-19
@@ -1,23 +1,7 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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
|
||||
*
|
||||
* https://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 fun.asgc.neutrino.core.aop.compiler.internal.jar;
|
||||
|
||||
package org.springframework.boot.loader.jar;
|
||||
|
||||
import org.springframework.boot.loader.data.RandomAccessData;
|
||||
import org.springframework.boot.loader.data.RandomAccessDataFile;
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.data.RandomAccessData;
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.data.RandomAccessDataFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilePermission;
|
||||
+2
-18
@@ -1,22 +1,6 @@
|
||||
/*
|
||||
* Copyright 2012-2023 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
|
||||
*
|
||||
* https://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 fun.asgc.neutrino.core.aop.compiler.internal.jar;
|
||||
|
||||
package org.springframework.boot.loader.jar;
|
||||
|
||||
import org.springframework.boot.loader.data.RandomAccessData;
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.data.RandomAccessData;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
+1
-17
@@ -1,20 +1,4 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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
|
||||
*
|
||||
* https://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.jar;
|
||||
package fun.asgc.neutrino.core.aop.compiler.internal.jar;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
+1
-17
@@ -1,20 +1,4 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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
|
||||
*
|
||||
* https://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.jar;
|
||||
package fun.asgc.neutrino.core.aop.compiler.internal.jar;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
+1
-17
@@ -1,20 +1,4 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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
|
||||
*
|
||||
* https://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.jar;
|
||||
package fun.asgc.neutrino.core.aop.compiler.internal.jar;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
+1
-17
@@ -1,20 +1,4 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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
|
||||
*
|
||||
* https://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.jar;
|
||||
package fun.asgc.neutrino.core.aop.compiler.internal.jar;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2021 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
|
||||
*
|
||||
* https://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 org.springframework.boot.loader.archive.Archive;
|
||||
import org.springframework.boot.loader.archive.Archive.EntryFilter;
|
||||
|
||||
/**
|
||||
* {@link Launcher} for JAR based archives. This launcher assumes that dependency jars are
|
||||
* included inside a {@code /BOOT-INF/lib} directory and that application classes are
|
||||
* included inside a {@code /BOOT-INF/classes} directory.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
* @author Madhura Bhave
|
||||
* @author Scott Frederick
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class JarLauncher extends ExecutableArchiveLauncher {
|
||||
|
||||
static final EntryFilter NESTED_ARCHIVE_ENTRY_FILTER = (entry) -> {
|
||||
if (entry.isDirectory()) {
|
||||
return entry.getName().equals("BOOT-INF/classes/");
|
||||
}
|
||||
return entry.getName().startsWith("BOOT-INF/lib/");
|
||||
};
|
||||
|
||||
public JarLauncher() {
|
||||
}
|
||||
|
||||
protected JarLauncher(Archive archive) {
|
||||
super(archive);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPostProcessingClassPathArchives() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isNestedArchive(Archive.Entry entry) {
|
||||
return NESTED_ARCHIVE_ENTRY_FILTER.matches(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getArchiveEntryPathPrefix() {
|
||||
return "BOOT-INF/";
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new JarLauncher().launch(args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
/**
|
||||
* Utility class that is used by {@link Launcher}s to call a main method. The class
|
||||
* containing the main method is loaded using the thread context class loader.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class MainMethodRunner {
|
||||
|
||||
private final String mainClassName;
|
||||
|
||||
private final String[] args;
|
||||
|
||||
/**
|
||||
* Create a new {@link MainMethodRunner} instance.
|
||||
* @param mainClass the main class
|
||||
* @param args incoming arguments
|
||||
*/
|
||||
public MainMethodRunner(String mainClass, String[] args) {
|
||||
this.mainClassName = mainClass;
|
||||
this.args = (args != null) ? args.clone() : null;
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
Class<?> mainClass = Class.forName(this.mainClassName, false, Thread.currentThread().getContextClassLoader());
|
||||
Method mainMethod = mainClass.getDeclaredMethod("main", String[].class);
|
||||
mainMethod.setAccessible(true);
|
||||
mainMethod.invoke(null, new Object[] { this.args });
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,716 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2023 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
|
||||
*
|
||||
* https://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 org.springframework.boot.loader.archive.Archive;
|
||||
import org.springframework.boot.loader.archive.Archive.Entry;
|
||||
import org.springframework.boot.loader.archive.Archive.EntryFilter;
|
||||
import org.springframework.boot.loader.archive.ExplodedArchive;
|
||||
import org.springframework.boot.loader.archive.JarFileArchive;
|
||||
import org.springframework.boot.loader.util.SystemPropertyUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.*;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* {@link Launcher} for archives with user-configured classpath and main class through a
|
||||
* properties file. This model is often more flexible and more amenable to creating
|
||||
* well-behaved OS-level services than a model based on executable jars.
|
||||
* <p>
|
||||
* Looks in various places for a properties file to extract loader settings, defaulting to
|
||||
* {@code loader.properties} either on the current classpath or in the current working
|
||||
* directory. The name of the properties file can be changed by setting a System property
|
||||
* {@code loader.config.name} (e.g. {@code -Dloader.config.name=foo} will look for
|
||||
* {@code foo.properties}. If that file doesn't exist then tries
|
||||
* {@code loader.config.location} (with allowed prefixes {@code classpath:} and
|
||||
* {@code file:} or any valid URL). Once that file is located turns it into Properties and
|
||||
* extracts optional values (which can also be provided overridden as System properties in
|
||||
* case the file doesn't exist):
|
||||
* <ul>
|
||||
* <li>{@code loader.path}: a comma-separated list of directories (containing file
|
||||
* resources and/or nested archives in *.jar or *.zip or archives) or archives to append
|
||||
* to the classpath. {@code BOOT-INF/classes,BOOT-INF/lib} in the application archive are
|
||||
* always used</li>
|
||||
* <li>{@code loader.main}: the main method to delegate execution to once the class loader
|
||||
* is set up. No default, but will fall back to looking for a {@code Start-Class} in a
|
||||
* {@code MANIFEST.MF}, if there is one in <code>${loader.home}/META-INF</code>.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Janne Valkealahti
|
||||
* @author Andy Wilkinson
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class PropertiesLauncher extends Launcher {
|
||||
|
||||
private static final Class<?>[] PARENT_ONLY_PARAMS = new Class<?>[] { ClassLoader.class };
|
||||
|
||||
private static final Class<?>[] URLS_AND_PARENT_PARAMS = new Class<?>[] { URL[].class, ClassLoader.class };
|
||||
|
||||
private static final Class<?>[] NO_PARAMS = new Class<?>[] {};
|
||||
|
||||
private static final URL[] NO_URLS = new URL[0];
|
||||
|
||||
private static final String DEBUG = "loader.debug";
|
||||
|
||||
/**
|
||||
* Properties key for main class. As a manifest entry can also be specified as
|
||||
* {@code Start-Class}.
|
||||
*/
|
||||
public static final String MAIN = "loader.main";
|
||||
|
||||
/**
|
||||
* Properties key for classpath entries (directories possibly containing jars or
|
||||
* jars). Multiple entries can be specified using a comma-separated list. {@code
|
||||
* BOOT-INF/classes,BOOT-INF/lib} in the application archive are always used.
|
||||
*/
|
||||
public static final String PATH = "loader.path";
|
||||
|
||||
/**
|
||||
* Properties key for home directory. This is the location of external configuration
|
||||
* if not on classpath, and also the base path for any relative paths in the
|
||||
* {@link #PATH loader path}. Defaults to current working directory (
|
||||
* <code>${user.dir}</code>).
|
||||
*/
|
||||
public static final String HOME = "loader.home";
|
||||
|
||||
/**
|
||||
* Properties key for default command line arguments. These arguments (if present) are
|
||||
* prepended to the main method arguments before launching.
|
||||
*/
|
||||
public static final String ARGS = "loader.args";
|
||||
|
||||
/**
|
||||
* Properties key for name of external configuration file (excluding suffix). Defaults
|
||||
* to "application". Ignored if {@link #CONFIG_LOCATION loader config location} is
|
||||
* provided instead.
|
||||
*/
|
||||
public static final String CONFIG_NAME = "loader.config.name";
|
||||
|
||||
/**
|
||||
* Properties key for config file location (including optional classpath:, file: or
|
||||
* URL prefix).
|
||||
*/
|
||||
public static final String CONFIG_LOCATION = "loader.config.location";
|
||||
|
||||
/**
|
||||
* Properties key for boolean flag (default false) which, if set, will cause the
|
||||
* external configuration properties to be copied to System properties (assuming that
|
||||
* is allowed by Java security).
|
||||
*/
|
||||
public static final String SET_SYSTEM_PROPERTIES = "loader.system";
|
||||
|
||||
private static final Pattern WORD_SEPARATOR = Pattern.compile("\\W+");
|
||||
|
||||
private static final String NESTED_ARCHIVE_SEPARATOR = "!" + File.separator;
|
||||
|
||||
private final File home;
|
||||
|
||||
private List<String> paths = new ArrayList<>();
|
||||
|
||||
private final Properties properties = new Properties();
|
||||
|
||||
private final Archive parent;
|
||||
|
||||
private volatile ClassPathArchives classPathArchives;
|
||||
|
||||
public PropertiesLauncher() {
|
||||
try {
|
||||
this.home = getHomeDirectory();
|
||||
initializeProperties();
|
||||
initializePaths();
|
||||
this.parent = createArchive();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected File getHomeDirectory() {
|
||||
try {
|
||||
return new File(getPropertyWithDefault(HOME, "${user.dir}"));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeProperties() throws Exception {
|
||||
List<String> configs = new ArrayList<>();
|
||||
if (getProperty(CONFIG_LOCATION) != null) {
|
||||
configs.add(getProperty(CONFIG_LOCATION));
|
||||
}
|
||||
else {
|
||||
String[] names = getPropertyWithDefault(CONFIG_NAME, "loader").split(",");
|
||||
for (String name : names) {
|
||||
configs.add("file:" + getHomeDirectory() + "/" + name + ".properties");
|
||||
configs.add("classpath:" + name + ".properties");
|
||||
configs.add("classpath:BOOT-INF/classes/" + name + ".properties");
|
||||
}
|
||||
}
|
||||
for (String config : configs) {
|
||||
try (InputStream resource = getResource(config)) {
|
||||
if (resource != null) {
|
||||
debug("Found: " + config);
|
||||
loadResource(resource);
|
||||
// Load the first one we find
|
||||
return;
|
||||
}
|
||||
else {
|
||||
debug("Not found: " + config);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadResource(InputStream resource) throws Exception {
|
||||
this.properties.load(resource);
|
||||
for (Object key : Collections.list(this.properties.propertyNames())) {
|
||||
String text = this.properties.getProperty((String) key);
|
||||
String value = SystemPropertyUtils.resolvePlaceholders(this.properties, text);
|
||||
if (value != null) {
|
||||
this.properties.put(key, value);
|
||||
}
|
||||
}
|
||||
if ("true".equals(getProperty(SET_SYSTEM_PROPERTIES))) {
|
||||
debug("Adding resolved properties to System properties");
|
||||
for (Object key : Collections.list(this.properties.propertyNames())) {
|
||||
String value = this.properties.getProperty((String) key);
|
||||
System.setProperty((String) key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private InputStream getResource(String config) throws Exception {
|
||||
if (config.startsWith("classpath:")) {
|
||||
return getClasspathResource(config.substring("classpath:".length()));
|
||||
}
|
||||
config = handleUrl(config);
|
||||
if (isUrl(config)) {
|
||||
return getURLResource(config);
|
||||
}
|
||||
return getFileResource(config);
|
||||
}
|
||||
|
||||
private String handleUrl(String path) throws UnsupportedEncodingException {
|
||||
if (path.startsWith("jar:file:") || path.startsWith("file:")) {
|
||||
path = URLDecoder.decode(path, "UTF-8");
|
||||
if (path.startsWith("file:")) {
|
||||
path = path.substring("file:".length());
|
||||
if (path.startsWith("//")) {
|
||||
path = path.substring(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
private boolean isUrl(String config) {
|
||||
return config.contains("://");
|
||||
}
|
||||
|
||||
private InputStream getClasspathResource(String config) {
|
||||
while (config.startsWith("/")) {
|
||||
config = config.substring(1);
|
||||
}
|
||||
config = "/" + config;
|
||||
debug("Trying classpath: " + config);
|
||||
return getClass().getResourceAsStream(config);
|
||||
}
|
||||
|
||||
private InputStream getFileResource(String config) throws Exception {
|
||||
File file = new File(config);
|
||||
debug("Trying file: " + config);
|
||||
if (file.canRead()) {
|
||||
return new FileInputStream(file);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private InputStream getURLResource(String config) throws Exception {
|
||||
URL url = new URL(config);
|
||||
if (exists(url)) {
|
||||
URLConnection con = url.openConnection();
|
||||
try {
|
||||
return con.getInputStream();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// Close the HTTP connection (if applicable).
|
||||
if (con instanceof HttpURLConnection) {
|
||||
((HttpURLConnection)con).disconnect();
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean exists(URL url) throws IOException {
|
||||
// Try a URL connection content-length header...
|
||||
URLConnection connection = url.openConnection();
|
||||
try {
|
||||
connection.setUseCaches(connection.getClass().getSimpleName().startsWith("JNLP"));
|
||||
if (connection instanceof HttpURLConnection) {
|
||||
HttpURLConnection httpConnection = (HttpURLConnection)connection;
|
||||
httpConnection.setRequestMethod("HEAD");
|
||||
int responseCode = httpConnection.getResponseCode();
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
return true;
|
||||
}
|
||||
else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return (connection.getContentLength() >= 0);
|
||||
}
|
||||
finally {
|
||||
if (connection instanceof HttpURLConnection) {
|
||||
((HttpURLConnection)connection).disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initializePaths() throws Exception {
|
||||
String path = getProperty(PATH);
|
||||
if (path != null) {
|
||||
this.paths = parsePathsProperty(path);
|
||||
}
|
||||
debug("Nested archive paths: " + this.paths);
|
||||
}
|
||||
|
||||
private List<String> parsePathsProperty(String commaSeparatedPaths) {
|
||||
List<String> paths = new ArrayList<>();
|
||||
for (String path : commaSeparatedPaths.split(",")) {
|
||||
path = cleanupPath(path);
|
||||
// "" means the user wants root of archive but not current directory
|
||||
path = (path == null || path.isEmpty()) ? "/" : path;
|
||||
paths.add(path);
|
||||
}
|
||||
if (paths.isEmpty()) {
|
||||
paths.add("lib");
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
protected String[] getArgs(String... args) throws Exception {
|
||||
String loaderArgs = getProperty(ARGS);
|
||||
if (loaderArgs != null) {
|
||||
String[] defaultArgs = loaderArgs.split("\\s+");
|
||||
String[] additionalArgs = args;
|
||||
args = new String[defaultArgs.length + additionalArgs.length];
|
||||
System.arraycopy(defaultArgs, 0, args, 0, defaultArgs.length);
|
||||
System.arraycopy(additionalArgs, 0, args, defaultArgs.length, additionalArgs.length);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getMainClass() throws Exception {
|
||||
String mainClass = getProperty(MAIN, "Start-Class");
|
||||
if (mainClass == null) {
|
||||
throw new IllegalStateException("No '" + MAIN + "' or 'Start-Class' specified");
|
||||
}
|
||||
return mainClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClassLoader createClassLoader(Iterator<Archive> archives) throws Exception {
|
||||
String customLoaderClassName = getProperty("loader.classLoader");
|
||||
if (customLoaderClassName == null) {
|
||||
return super.createClassLoader(archives);
|
||||
}
|
||||
Set<URL> urls = new LinkedHashSet<>();
|
||||
while (archives.hasNext()) {
|
||||
urls.add(archives.next().getUrl());
|
||||
}
|
||||
ClassLoader loader = new LaunchedURLClassLoader(urls.toArray(NO_URLS), getClass().getClassLoader());
|
||||
debug("Classpath for custom loader: " + urls);
|
||||
loader = wrapWithCustomClassLoader(loader, customLoaderClassName);
|
||||
debug("Using custom class loader: " + customLoaderClassName);
|
||||
return loader;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private ClassLoader wrapWithCustomClassLoader(ClassLoader parent, String className) throws Exception {
|
||||
Class<ClassLoader> type = (Class<ClassLoader>) Class.forName(className, true, parent);
|
||||
ClassLoader classLoader = newClassLoader(type, PARENT_ONLY_PARAMS, parent);
|
||||
if (classLoader == null) {
|
||||
classLoader = newClassLoader(type, URLS_AND_PARENT_PARAMS, NO_URLS, parent);
|
||||
}
|
||||
if (classLoader == null) {
|
||||
classLoader = newClassLoader(type, NO_PARAMS);
|
||||
}
|
||||
if (classLoader == null) {
|
||||
throw new IllegalArgumentException("Unable to create class loader for " + className);
|
||||
}
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
private ClassLoader newClassLoader(Class<ClassLoader> loaderClass, Class<?>[] parameterTypes, Object... initargs)
|
||||
throws Exception {
|
||||
try {
|
||||
Constructor<ClassLoader> constructor = loaderClass.getDeclaredConstructor(parameterTypes);
|
||||
constructor.setAccessible(true);
|
||||
return constructor.newInstance(initargs);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String getProperty(String propertyKey) throws Exception {
|
||||
return getProperty(propertyKey, null, null);
|
||||
}
|
||||
|
||||
private String getProperty(String propertyKey, String manifestKey) throws Exception {
|
||||
return getProperty(propertyKey, manifestKey, null);
|
||||
}
|
||||
|
||||
private String getPropertyWithDefault(String propertyKey, String defaultValue) throws Exception {
|
||||
return getProperty(propertyKey, null, defaultValue);
|
||||
}
|
||||
|
||||
private String getProperty(String propertyKey, String manifestKey, String defaultValue) throws Exception {
|
||||
if (manifestKey == null) {
|
||||
manifestKey = propertyKey.replace('.', '-');
|
||||
manifestKey = toCamelCase(manifestKey);
|
||||
}
|
||||
String property = SystemPropertyUtils.getProperty(propertyKey);
|
||||
if (property != null) {
|
||||
String value = SystemPropertyUtils.resolvePlaceholders(this.properties, property);
|
||||
debug("Property '" + propertyKey + "' from environment: " + value);
|
||||
return value;
|
||||
}
|
||||
if (this.properties.containsKey(propertyKey)) {
|
||||
String value = SystemPropertyUtils.resolvePlaceholders(this.properties,
|
||||
this.properties.getProperty(propertyKey));
|
||||
debug("Property '" + propertyKey + "' from properties: " + value);
|
||||
return value;
|
||||
}
|
||||
try {
|
||||
if (this.home != null) {
|
||||
// Prefer home dir for MANIFEST if there is one
|
||||
try (ExplodedArchive archive = new ExplodedArchive(this.home, false)) {
|
||||
Manifest manifest = archive.getManifest();
|
||||
if (manifest != null) {
|
||||
String value = manifest.getMainAttributes().getValue(manifestKey);
|
||||
if (value != null) {
|
||||
debug("Property '" + manifestKey + "' from home directory manifest: " + value);
|
||||
return SystemPropertyUtils.resolvePlaceholders(this.properties, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
// Ignore
|
||||
}
|
||||
// Otherwise try the parent archive
|
||||
Manifest manifest = createArchive().getManifest();
|
||||
if (manifest != null) {
|
||||
String value = manifest.getMainAttributes().getValue(manifestKey);
|
||||
if (value != null) {
|
||||
debug("Property '" + manifestKey + "' from archive manifest: " + value);
|
||||
return SystemPropertyUtils.resolvePlaceholders(this.properties, value);
|
||||
}
|
||||
}
|
||||
return (defaultValue != null) ? SystemPropertyUtils.resolvePlaceholders(this.properties, defaultValue)
|
||||
: defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterator<Archive> getClassPathArchivesIterator() throws Exception {
|
||||
ClassPathArchives classPathArchives = this.classPathArchives;
|
||||
if (classPathArchives == null) {
|
||||
classPathArchives = new ClassPathArchives();
|
||||
this.classPathArchives = classPathArchives;
|
||||
}
|
||||
return classPathArchives.iterator();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
PropertiesLauncher launcher = new PropertiesLauncher();
|
||||
args = launcher.getArgs(args);
|
||||
launcher.launch(args);
|
||||
}
|
||||
|
||||
public static String toCamelCase(CharSequence string) {
|
||||
if (string == null) {
|
||||
return null;
|
||||
}
|
||||
StringBuilder builder = new StringBuilder();
|
||||
Matcher matcher = WORD_SEPARATOR.matcher(string);
|
||||
int pos = 0;
|
||||
while (matcher.find()) {
|
||||
builder.append(capitalize(string.subSequence(pos, matcher.end()).toString()));
|
||||
pos = matcher.end();
|
||||
}
|
||||
builder.append(capitalize(string.subSequence(pos, string.length()).toString()));
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static String capitalize(String str) {
|
||||
return Character.toUpperCase(str.charAt(0)) + str.substring(1);
|
||||
}
|
||||
|
||||
private void debug(String message) {
|
||||
if (Boolean.getBoolean(DEBUG)) {
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
|
||||
private String cleanupPath(String path) {
|
||||
path = path.trim();
|
||||
// No need for current dir path
|
||||
if (path.startsWith("./")) {
|
||||
path = path.substring(2);
|
||||
}
|
||||
String lowerCasePath = path.toLowerCase(Locale.ENGLISH);
|
||||
if (lowerCasePath.endsWith(".jar") || lowerCasePath.endsWith(".zip")) {
|
||||
return path;
|
||||
}
|
||||
if (path.endsWith("/*")) {
|
||||
path = path.substring(0, path.length() - 1);
|
||||
}
|
||||
else {
|
||||
// It's a directory
|
||||
if (!path.endsWith("/") && !path.equals(".")) {
|
||||
path = path + "/";
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
void close() throws Exception {
|
||||
if (this.classPathArchives != null) {
|
||||
this.classPathArchives.close();
|
||||
}
|
||||
if (this.parent != null) {
|
||||
this.parent.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An iterable collection of the classpath archives.
|
||||
*/
|
||||
private class ClassPathArchives implements Iterable<Archive> {
|
||||
|
||||
private final List<Archive> classPathArchives;
|
||||
|
||||
private final List<JarFileArchive> jarFileArchives = new ArrayList<>();
|
||||
|
||||
ClassPathArchives() throws Exception {
|
||||
this.classPathArchives = new ArrayList<>();
|
||||
for (String path : PropertiesLauncher.this.paths) {
|
||||
for (Archive archive : getClassPathArchives(path)) {
|
||||
addClassPathArchive(archive);
|
||||
}
|
||||
}
|
||||
addNestedEntries();
|
||||
}
|
||||
|
||||
private void addClassPathArchive(Archive archive) throws IOException {
|
||||
if (!(archive instanceof ExplodedArchive)) {
|
||||
this.classPathArchives.add(archive);
|
||||
return;
|
||||
}
|
||||
this.classPathArchives.add(archive);
|
||||
this.classPathArchives.addAll(asList(archive.getNestedArchives(null, new ArchiveEntryFilter())));
|
||||
}
|
||||
|
||||
private List<Archive> getClassPathArchives(String path) throws Exception {
|
||||
String root = cleanupPath(handleUrl(path));
|
||||
List<Archive> lib = new ArrayList<>();
|
||||
File file = new File(root);
|
||||
if (!"/".equals(root)) {
|
||||
if (!isAbsolutePath(root)) {
|
||||
file = new File(PropertiesLauncher.this.home, root);
|
||||
}
|
||||
if (file.isDirectory()) {
|
||||
debug("Adding classpath entries from " + file);
|
||||
Archive archive = new ExplodedArchive(file, false);
|
||||
lib.add(archive);
|
||||
}
|
||||
}
|
||||
Archive archive = getArchive(file);
|
||||
if (archive != null) {
|
||||
debug("Adding classpath entries from archive " + archive.getUrl() + root);
|
||||
lib.add(archive);
|
||||
}
|
||||
List<Archive> nestedArchives = getNestedArchives(root);
|
||||
if (nestedArchives != null) {
|
||||
debug("Adding classpath entries from nested " + root);
|
||||
lib.addAll(nestedArchives);
|
||||
}
|
||||
return lib;
|
||||
}
|
||||
|
||||
private boolean isAbsolutePath(String root) {
|
||||
// Windows contains ":" others start with "/"
|
||||
return root.contains(":") || root.startsWith("/");
|
||||
}
|
||||
|
||||
private Archive getArchive(File file) throws IOException {
|
||||
if (isNestedArchivePath(file)) {
|
||||
return null;
|
||||
}
|
||||
String name = file.getName().toLowerCase(Locale.ENGLISH);
|
||||
if (name.endsWith(".jar") || name.endsWith(".zip")) {
|
||||
return getJarFileArchive(file);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isNestedArchivePath(File file) {
|
||||
return file.getPath().contains(NESTED_ARCHIVE_SEPARATOR);
|
||||
}
|
||||
|
||||
private List<Archive> getNestedArchives(String path) throws Exception {
|
||||
Archive parent = PropertiesLauncher.this.parent;
|
||||
String root = path;
|
||||
if (!root.equals("/") && root.startsWith("/")
|
||||
|| parent.getUrl().toURI().equals(PropertiesLauncher.this.home.toURI())) {
|
||||
// If home dir is same as parent archive, no need to add it twice.
|
||||
return null;
|
||||
}
|
||||
int index = root.indexOf('!');
|
||||
if (index != -1) {
|
||||
File file = new File(PropertiesLauncher.this.home, root.substring(0, index));
|
||||
if (root.startsWith("jar:file:")) {
|
||||
file = new File(root.substring("jar:file:".length(), index));
|
||||
}
|
||||
parent = getJarFileArchive(file);
|
||||
root = root.substring(index + 1);
|
||||
while (root.startsWith("/")) {
|
||||
root = root.substring(1);
|
||||
}
|
||||
}
|
||||
if (root.endsWith(".jar")) {
|
||||
File file = new File(PropertiesLauncher.this.home, root);
|
||||
if (file.exists()) {
|
||||
parent = getJarFileArchive(file);
|
||||
root = "";
|
||||
}
|
||||
}
|
||||
if (root.equals("/") || root.equals("./") || root.equals(".")) {
|
||||
// The prefix for nested jars is actually empty if it's at the root
|
||||
root = "";
|
||||
}
|
||||
EntryFilter filter = new PrefixMatchingArchiveFilter(root);
|
||||
List<Archive> archives = asList(parent.getNestedArchives(null, filter));
|
||||
if ((root == null || root.isEmpty() || ".".equals(root)) && !path.endsWith(".jar")
|
||||
&& parent != PropertiesLauncher.this.parent) {
|
||||
// You can't find the root with an entry filter so it has to be added
|
||||
// explicitly. But don't add the root of the parent archive.
|
||||
archives.add(parent);
|
||||
}
|
||||
return archives;
|
||||
}
|
||||
|
||||
private void addNestedEntries() {
|
||||
// The parent archive might have "BOOT-INF/lib/" and "BOOT-INF/classes/"
|
||||
// directories, meaning we are running from an executable JAR. We add nested
|
||||
// entries from there with low priority (i.e. at end).
|
||||
try {
|
||||
Iterator<Archive> archives = PropertiesLauncher.this.parent.getNestedArchives(null,
|
||||
JarLauncher.NESTED_ARCHIVE_ENTRY_FILTER);
|
||||
while (archives.hasNext()) {
|
||||
this.classPathArchives.add(archives.next());
|
||||
}
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
private List<Archive> asList(Iterator<Archive> iterator) {
|
||||
List<Archive> list = new ArrayList<>();
|
||||
while (iterator.hasNext()) {
|
||||
list.add(iterator.next());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private JarFileArchive getJarFileArchive(File file) throws IOException {
|
||||
JarFileArchive archive = new JarFileArchive(file);
|
||||
this.jarFileArchives.add(archive);
|
||||
return archive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Archive> iterator() {
|
||||
return this.classPathArchives.iterator();
|
||||
}
|
||||
|
||||
void close() throws IOException {
|
||||
for (JarFileArchive archive : this.jarFileArchives) {
|
||||
archive.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience class for finding nested archives that have a prefix in their file path
|
||||
* (e.g. "lib/").
|
||||
*/
|
||||
private static final class PrefixMatchingArchiveFilter implements EntryFilter {
|
||||
|
||||
private final String prefix;
|
||||
|
||||
private final ArchiveEntryFilter filter = new ArchiveEntryFilter();
|
||||
|
||||
private PrefixMatchingArchiveFilter(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Entry entry) {
|
||||
if (entry.isDirectory()) {
|
||||
return entry.getName().equals(this.prefix);
|
||||
}
|
||||
return entry.getName().startsWith(this.prefix) && this.filter.matches(entry);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience class for finding nested archives (archive entries that can be
|
||||
* classpath entries).
|
||||
*/
|
||||
private static final class ArchiveEntryFilter implements EntryFilter {
|
||||
|
||||
private static final String DOT_JAR = ".jar";
|
||||
|
||||
private static final String DOT_ZIP = ".zip";
|
||||
|
||||
@Override
|
||||
public boolean matches(Entry entry) {
|
||||
return entry.getName().endsWith(DOT_JAR) || entry.getName().endsWith(DOT_ZIP);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2021 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
|
||||
*
|
||||
* https://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 org.springframework.boot.loader.archive.Archive;
|
||||
|
||||
/**
|
||||
* {@link Launcher} for WAR based archives. This launcher for standard WAR archives.
|
||||
* Supports dependencies in {@code WEB-INF/lib} as well as {@code WEB-INF/lib-provided},
|
||||
* classes are loaded from {@code WEB-INF/classes}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
* @author Scott Frederick
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class WarLauncher extends ExecutableArchiveLauncher {
|
||||
|
||||
public WarLauncher() {
|
||||
}
|
||||
|
||||
protected WarLauncher(Archive archive) {
|
||||
super(archive);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPostProcessingClassPathArchives() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNestedArchive(Archive.Entry entry) {
|
||||
if (entry.isDirectory()) {
|
||||
return entry.getName().equals("WEB-INF/classes/");
|
||||
}
|
||||
return entry.getName().startsWith("WEB-INF/lib/") || entry.getName().startsWith("WEB-INF/lib-provided/");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getArchiveEntryPathPrefix() {
|
||||
return "WEB-INF/";
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new WarLauncher().launch(args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Abstraction over logical Archives be they backed by a JAR file or unpacked into a
|
||||
* directory.
|
||||
*
|
||||
* @see org.springframework.boot.loader.archive.Archive
|
||||
*/
|
||||
package org.springframework.boot.loader.archive;
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2021 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Classes and interfaces to allow random access to a block of data.
|
||||
*
|
||||
* @see org.springframework.boot.loader.data.RandomAccessData
|
||||
*/
|
||||
package org.springframework.boot.loader.data;
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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
|
||||
*
|
||||
* https://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.jar;
|
||||
|
||||
/**
|
||||
* Utilities for dealing with bytes from ZIP files.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
final class Bytes {
|
||||
|
||||
private Bytes() {
|
||||
}
|
||||
|
||||
static long littleEndianValue(byte[] bytes, int offset, int length) {
|
||||
long value = 0;
|
||||
for (int i = length - 1; i >= 0; i--) {
|
||||
value = ((value << 8) | (bytes[offset + i] & 0xFF));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2021 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
|
||||
*
|
||||
* https://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.jar;
|
||||
|
||||
import org.springframework.boot.loader.data.RandomAccessData;
|
||||
|
||||
/**
|
||||
* Callback visitor triggered by {@link CentralDirectoryParser}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
interface CentralDirectoryVisitor {
|
||||
|
||||
void visitStart(CentralDirectoryEndRecord endRecord, RandomAccessData centralDirectoryData);
|
||||
|
||||
void visitFileHeader(CentralDirectoryFileHeader fileHeader, long dataOffset);
|
||||
|
||||
void visitEnd();
|
||||
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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
|
||||
*
|
||||
* https://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.jar;
|
||||
|
||||
/**
|
||||
* Interface that can be used to filter and optionally rename jar entries.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
interface JarEntryFilter {
|
||||
|
||||
/**
|
||||
* Apply the jar entry filter.
|
||||
* @param name the current entry name. This may be different that the original entry
|
||||
* name if a previous filter has been applied
|
||||
* @return the new name of the entry or {@code null} if the entry should not be
|
||||
* included.
|
||||
*/
|
||||
AsciiBytes apply(AsciiBytes name);
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Support for loading and manipulating JAR/WAR files.
|
||||
*/
|
||||
package org.springframework.boot.loader.jar;
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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
|
||||
*
|
||||
* https://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.jarmode;
|
||||
|
||||
/**
|
||||
* Interface registered in {@code spring.factories} to provides extended 'jarmode'
|
||||
* support.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public interface JarMode {
|
||||
|
||||
/**
|
||||
* Returns if this accepts and can run the given mode.
|
||||
* @param mode the mode to check
|
||||
* @return if this instance accepts the mode
|
||||
*/
|
||||
boolean accepts(String mode);
|
||||
|
||||
/**
|
||||
* Run the jar in the given mode.
|
||||
* @param mode the mode to use
|
||||
* @param args any program arguments
|
||||
*/
|
||||
void run(String mode, String[] args);
|
||||
|
||||
}
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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
|
||||
*
|
||||
* https://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.jarmode;
|
||||
|
||||
//import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
//import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Delegate class used to launch the fat jar in a specific mode.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public final class JarModeLauncher {
|
||||
|
||||
static final String DISABLE_SYSTEM_EXIT = JarModeLauncher.class.getName() + ".DISABLE_SYSTEM_EXIT";
|
||||
|
||||
private JarModeLauncher() {
|
||||
}
|
||||
|
||||
// public static void main(String[] args) {
|
||||
// String mode = System.getProperty("jarmode");
|
||||
// List<JarMode> candidates = SpringFactoriesLoader.loadFactories(JarMode.class,
|
||||
// ClassUtils.getDefaultClassLoader());
|
||||
// for (JarMode candidate : candidates) {
|
||||
// if (candidate.accepts(mode)) {
|
||||
// candidate.run(mode, args);
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// System.err.println("Unsupported jarmode '" + mode + "'");
|
||||
// if (!Boolean.getBoolean(DISABLE_SYSTEM_EXIT)) {
|
||||
// System.exit(1);
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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
|
||||
*
|
||||
* https://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.jarmode;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* {@link JarMode} for testing.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class TestJarMode implements JarMode {
|
||||
|
||||
@Override
|
||||
public boolean accepts(String mode) {
|
||||
return "test".equals(mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(String mode, String[] args) {
|
||||
System.out.println("running in " + mode + " jar mode " + Arrays.asList(args));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Support for launching the JAR using jarmode.
|
||||
*
|
||||
* @see org.springframework.boot.loader.jarmode.JarModeLauncher
|
||||
*/
|
||||
package org.springframework.boot.loader.jarmode;
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* System that allows self-contained JAR/WAR archives to be launched using
|
||||
* {@code java -jar}. Archives can include nested packaged dependency JARs (there is no
|
||||
* need to create shade style jars) and are executed without unpacking. The only
|
||||
* constraint is that nested JARs must be stored in the archive uncompressed.
|
||||
*
|
||||
* @see org.springframework.boot.loader.JarLauncher
|
||||
* @see org.springframework.boot.loader.WarLauncher
|
||||
*/
|
||||
package org.springframework.boot.loader;
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Utilities used by Spring Boot's JAR loading.
|
||||
*/
|
||||
package org.springframework.boot.loader.util;
|
||||
+2
-2
@@ -23,7 +23,7 @@ package fun.asgc.neutrino.core.aop.compiler;
|
||||
|
||||
import fun.asgc.neutrino.core.util.ReflectUtil;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.loader.MyJarLauncher;
|
||||
import fun.asgc.neutrino.core.aop.compiler.internal.JarLauncher;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
@@ -122,7 +122,7 @@ public class AsgcCompilerTest {
|
||||
*/
|
||||
@Test
|
||||
public void compileAndLoadClass5() throws Exception {
|
||||
MyJarLauncher jarLauncher = new MyJarLauncher("/Users/yangwen/my/tmp/java/asgc-package-lab2.jar");
|
||||
JarLauncher jarLauncher = new JarLauncher("/Users/yangwen/my/tmp/java/asgc-package-lab2.jar");
|
||||
AsgcCompiler compiler = new AsgcCompiler(jarLauncher.createClassLoader());
|
||||
String code = "package a.b;\n" +
|
||||
"import fun.asgc.lab.pkg.lab2.Console;\n" +
|
||||
|
||||
Reference in New Issue
Block a user