Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SocraticPhoenix/ca0583f057baafcbaf09a2d0183cef89 to your computer and use it in GitHub Desktop.
Save SocraticPhoenix/ca0583f057baafcbaf09a2d0183cef89 to your computer and use it in GitHub Desktop.
/*
* The MIT License (MIT)
*
* Copyright (c) 2015 socraticphoenix@gmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* @author Socratic_Phoenix (socraticphoenix@gmail.com)
*/
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Pattern;
public class JarClassLoader {
private File file;
private URLClassLoader loader;
private List<String> urls;
public JarClassLoader(String filePath) {
this(new File(filePath));
}
public JarClassLoader(File jarFile) {
this.file = jarFile;
this.urls = new ArrayList<>();
}
public List<Class> loadClasses() {
try {
this.ensureNotNull();
List<Class> classes = new ArrayList<>();
for (String str : this.urls) {
if (this.classCanBeFoundBySystem(str)) {
classes.add(JarClassLoader.resolveClass(str));
} else {
Class clazz = JarClassLoader.resolveClass(str, true, this.loader);
classes.add(clazz);
}
}
return classes;
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
}
public void clearCache() {
this.loader = null;
this.urls.clear();
}
private void cachePaths() {
try {
JarFile jarFile = new JarFile(this.file);
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String name = entry.getName();
if (name.endsWith(".class")) {
String clazz = JarClassLoader.reverseString(JarClassLoader.reverseString(
name.replaceAll(Pattern.quote(File.separator), ".")
.replaceAll(Pattern.quote("/"), ".")).replaceFirst(
Pattern.quote("ssalc."), ""));
this.urls.add(clazz);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private boolean classCanBeFoundBySystem(String name) {
try {
JarClassLoader.resolveClass(name);
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
private void ensureNotNull() {
try {
if (this.loader == null) {
if(this.getClass().getClassLoader() instanceof URLClassLoader) {
URLClassLoader localLoader = (URLClassLoader) this.getClass().getClassLoader();
try {
Method method = localLoader.getClass().getDeclaredMethod("addURL", URL.class);
boolean access = method.isAccessible();
method.setAccessible(true);
method.invoke(localLoader, this.file.toURI().toURL());
method.setAccessible(access);
this.loader = localLoader;
} catch (Throwable e) {
this.loader = new URLClassLoader(new URL[]{this.file.toURI().toURL()},
this.getClass().getClassLoader());
}
} else {
this.loader = new URLClassLoader(new URL[]{this.file.toURI().toURL()},
this.getClass().getClassLoader());
}
}
if (this.urls.isEmpty()) {
this.cachePaths();
}
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
}
private static Map<String, Class> primitives;
static {
primitives = new HashMap<>();
primitives.put("int", int.class);
primitives.put("long", long.class);
primitives.put("byte", byte.class);
primitives.put("short", short.class);
primitives.put("double", double.class);
primitives.put("float", float.class);
primitives.put("boolean", boolean.class);
}
/**
* Resolves the given class name by first checking the local primitive mappings, and second invoking {@link Class#forName(String)}
*
* @param name The name of the target class
*
* @return The class with the given name
*
* @throws ClassNotFoundException If the class wasn't found
*/
public static Class resolveClass(String name) throws ClassNotFoundException {
if (primitives.containsKey(name)) {
return primitives.get(name);
} else {
return Class.forName(name);
}
}
/**
* Resolves the given class name by first checking the local primitive mappings, and second invoking {@link Class#forName(String, boolean, ClassLoader)}
*
* @param name The name of the target class
* @param initialize See {@link Class#forName(String, boolean, ClassLoader)}
* @param loader See {@link Class#forName(String, boolean, ClassLoader)}
*
* @return The class with the given name
*
* @throws ClassNotFoundException If the class wasn't found
*/
public static Class resolveClass(String name, boolean initialize, ClassLoader loader) throws ClassNotFoundException {
if (primitives.containsKey(name)) {
return primitives.get(name);
} else {
return Class.forName(name, initialize, loader);
}
}
public static String reverseString(String input) {
char[] arr = input.toCharArray();
String backward = "";
for (int i = arr.length - 1; i >= 0; i--) {
backward = backward + String.valueOf(arr[i]);
}
return backward;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment