Skip to content

Commit ea9c259

Browse files
author
Muhammad Hammad
committed
System Class Loader to Thread ClassLoader
1 parent 24933be commit ea9c259

File tree

5 files changed

+94
-34
lines changed

5 files changed

+94
-34
lines changed

README.md

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,46 @@
11
# Dynamic Loader [![Build Status](https://travis-ci.org/dvare/DynamicLoader.svg?branch=master)](https://travis-ci.org/dvare/DynamicLoader)
2-
Library for Loading java code and dependencies at runtime.
2+
Dynamic Loader is In Memory Java Compiler and classpath loader which enables to compile both java file and code string in memory and also provide support to load supportive jars in classpath which need to compile the dynamic code.
3+
4+
## Example
5+
6+
##### In Memory Compilation..
7+
8+
```java
9+
public class SourceTest {
10+
11+
@Test
12+
public void sourceCodeTest() throws Exception {
13+
14+
StringBuilder sourceCode = new StringBuilder();
15+
sourceCode.append("package org.dvare.dynamic;\n");
16+
sourceCode.append("public class SourceTestClass {\n");
17+
sourceCode.append(" public String testMethod() { return \"inside test method\"; }");
18+
sourceCode.append("}");
19+
20+
DynamicCompiler dynamicCompiler = new DynamicCompiler();
21+
dynamicCompiler.addSource("org.dvare.dynamic.SourceTestClass", sourceCode.toString());
22+
Map<String, Class<?>> compiled = dynamicCompiler.build();
23+
Class<?> aClass = compiled.get("org.dvare.dynamic.SourceTestClass");
24+
Assert.assertNotNull(aClass);
25+
Assert.assertEquals(1, aClass.getDeclaredMethods().length);
26+
}
27+
}
28+
```
29+
330

431
## Current version
532

6-
* The current version is `1.0`
33+
* The current stable version is `1.1` : [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.dvare/dynamic-loader/badge.svg?style=flat)](http://search.maven.org/#artifactdetails|org.dvare|dynamic-loader|1.1|)
734

8-
you need to add the following maven repository in your `pom.xml`:
35+
Maven dependency:
936

1037
```xml
1138

1239
<dependencies>
1340
<dependency>
1441
<groupId>org.dvare</groupId>
1542
<artifactId>dynamic-loader</artifactId>
16-
<version>1.0</version>
43+
<version>1.1</version>
1744
</dependency>
1845
<dependencies>
1946
```

pom.xml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44

55
<groupId>org.dvare</groupId>
66
<artifactId>dynamic-loader</artifactId>
7-
<version>1.0</version>
7+
<version>1.1</version>
88

9-
<description>Library for Loading java code and dependencies at runtime.</description>
9+
<description>Dynamic Loader is in memory java compiler and classpath loader which enables to compile both java file
10+
and code string in memory and also provide support to load supportive jars in classpath which need
11+
to compile the dynamic code.
12+
</description>
1013
<packaging>jar</packaging>
1114

1215
<name>Dynamic Loader</name>
@@ -16,7 +19,7 @@
1619
<developer>
1720
<id>hammadirshad</id>
1821
<name>Muhammad Hammad</name>
19-
<url></url>
22+
<url>https://github.com/hammadirshad</url>
2023
<email>hammadirshad046@gmail.com</email>
2124
<roles>
2225
<role>Developer</role>
@@ -92,6 +95,7 @@
9295
<groupId>junit</groupId>
9396
<artifactId>junit</artifactId>
9497
<version>4.11</version>
98+
<scope>test</scope>
9599
</dependency>
96100

97101
<dependency>
@@ -105,11 +109,7 @@
105109
<artifactId>slf4j-log4j12</artifactId>
106110
<version>1.7.7</version>
107111
</dependency>
108-
<dependency>
109-
<groupId>org.apache.commons</groupId>
110-
<artifactId>commons-lang3</artifactId>
111-
<version>3.4</version>
112-
</dependency>
112+
113113

114114
</dependencies>
115115

src/main/java/org/dvare/dynamic/compiler/DynamicCompiler.java

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ of this software and associated documentation files (the "Software"), to deal
2929
import org.dvare.dynamic.resources.DynamicClassLoader;
3030
import org.dvare.dynamic.resources.DynamicJavaFileManager;
3131
import org.dvare.dynamic.resources.SourceCode;
32+
import org.slf4j.Logger;
33+
import org.slf4j.LoggerFactory;
3234

3335
import javax.tools.*;
3436
import java.io.File;
@@ -39,19 +41,22 @@ of this software and associated documentation files (the "Software"), to deal
3941

4042
public class DynamicCompiler {
4143
private static final List<String> options = new ArrayList<>(Arrays.asList("-Xlint:unchecked"));
44+
private static Logger logger = LoggerFactory.getLogger(DynamicCompiler.class);
4245
private static javax.tools.JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
4346
private StandardJavaFileManager standardFileManager =
4447
javac.getStandardFileManager(null, null, null);
4548
private DynamicClassLoader dynamicClassLoader;
4649
private Map<String, JavaFileObject> sourceCodes = new HashMap<>();
4750
private List<URL> jars = new ArrayList<>();
51+
private String classpath = "";
4852
private boolean separateContext = false;
4953
private boolean updateContextClassLoader = false;
5054

5155
public void addSource(String className, String testSourceCode) {
5256
sourceCodes.put(className, new SourceCode(className, testSourceCode));
5357
}
5458

59+
5560
public void addSource(String className, File sourceFile) {
5661
Iterable<? extends JavaFileObject> compilationUnits = standardFileManager.getJavaFileObjectsFromFiles(Arrays.asList(sourceFile));
5762
for (JavaFileObject javaFileObject : compilationUnits) {
@@ -67,45 +72,63 @@ public void addJar(URL url) {
6772

6873
public Map<String, Class<?>> build() throws DynamicCompilerException {
6974

70-
//ClassLoader classLoader = ClassLoader.getSystemClassLoader();
7175
ClassLoader classLoader = Thread.currentThread()
7276
.getContextClassLoader();
7377
if (separateContext) {
7478
classLoader = new CustomClassLoader().getCustomURLClassLoader();
7579
}
7680

77-
URLClassLoader urlClassLoader = (URLClassLoader) classLoader;
7881

79-
try {
80-
if (!jars.isEmpty()) {
82+
if (!(classLoader instanceof URLClassLoader)) {
83+
classLoader = this.getClass().getClassLoader();
84+
}
85+
86+
87+
if (classLoader instanceof URLClassLoader) {
88+
89+
URLClassLoader urlClassLoader = (URLClassLoader) classLoader;
8190

82-
for (URL url : jars) {
83-
Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
84-
method.setAccessible(true);
85-
method.invoke(urlClassLoader, new Object[]{url});
91+
try {
92+
if (!jars.isEmpty()) {
93+
94+
for (URL url : jars) {
95+
Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
96+
method.setAccessible(true);
97+
method.invoke(urlClassLoader, new Object[]{url});
98+
}
8699
}
87-
}
88100

89-
Method method2 = URLClassLoader.class.getDeclaredMethod("getURLs");
90-
method2.setAccessible(true);
91-
URL[] urls = (URL[]) method2.invoke((URLClassLoader) classLoader);
92-
String classpath = "";
93-
for (URL url : urls) {
94-
classpath += url + File.pathSeparator;
95-
}
101+
Method method2 = URLClassLoader.class.getDeclaredMethod("getURLs");
102+
method2.setAccessible(true);
103+
URL[] urls = (URL[]) method2.invoke((URLClassLoader) classLoader);
96104

97-
options.addAll(Arrays.asList("-classpath", classpath));
105+
if (urls.length == 0) {
106+
107+
urls = (URL[]) method2.invoke((URLClassLoader) getClass().getClassLoader());
108+
}
109+
for (URL url : urls) {
110+
File file = new File(url.getFile());
111+
112+
classpath += file.getAbsolutePath() + File.pathSeparator;
113+
logger.debug(file.getAbsolutePath() + File.pathSeparator);
114+
}
115+
116+
if (!classpath.trim().isEmpty()) {
117+
options.addAll(Arrays.asList("-classpath", classpath));
118+
}
119+
120+
121+
} catch (Exception e) {
122+
e.printStackTrace();
123+
}
98124

99125

100-
} catch (Exception e) {
101-
e.printStackTrace();
102126
}
103127

128+
dynamicClassLoader = new DynamicClassLoader(classLoader);
104129
Collection<JavaFileObject> compilationUnits = sourceCodes.values();
105130
List<CompiledCode> compiledCodes = new ArrayList<>();
106131

107-
108-
dynamicClassLoader = new DynamicClassLoader(urlClassLoader);
109132
DynamicJavaFileManager fileManager = new DynamicJavaFileManager(standardFileManager, compiledCodes, dynamicClassLoader);
110133

111134

@@ -159,5 +182,11 @@ public void setUpdateContextClassLoader(boolean updateContextClassLoader) {
159182
this.updateContextClassLoader = updateContextClassLoader;
160183
}
161184

185+
public String getClasspath() {
186+
return classpath;
187+
}
162188

189+
public void setClasspath(String classpath) {
190+
this.classpath = classpath;
191+
}
163192
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
log4j.rootLogger=DEBUG, stdout
2+
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
3+
log4j.appender.stdout.Target=System.out
4+
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
5+
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd'T'HH:mm:ss.SSS} %-5p [%c] - %m%n

src/test/org/dvare/dynamic/SourceTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ public class SourceTest {
3535
@Test
3636
public void compile_whenTypical() throws Exception {
3737
StringBuilder sourceCode = new StringBuilder();
38-
3938
sourceCode.append("package org.dvare.dynamic;\n");
4039
sourceCode.append("public class SourceClass {\n");
4140
sourceCode.append(" public String test() { return \"inside test method\"; }");

0 commit comments

Comments
 (0)