Skip to content

Commit

Permalink
feat(jans-auth-server): added JIT compiler support under jvm 17 (#5954)
Browse files Browse the repository at this point in the history
#5837

Signed-off-by: YuriyZ <yzabrovarniy@gmail.com>
  • Loading branch information
yuriyz authored Sep 5, 2023
1 parent 06a8bcd commit 3760380
Show file tree
Hide file tree
Showing 8 changed files with 949 additions and 50 deletions.
5 changes: 0 additions & 5 deletions jans-core/script/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,6 @@
<artifactId>testng</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>net.openhft</groupId>
<artifactId>compiler</artifactId>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,30 @@
import io.jans.model.custom.script.model.ScriptError;
import io.jans.model.custom.script.type.BaseExternalType;
import io.jans.service.PythonService;
import io.jans.service.custom.script.jit.SimpleJavaCompiler;
import io.jans.util.StringHelper;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import net.openhft.compiler.CompilerUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.io.IoBuilder;
import org.python.core.PyLong;
import org.python.core.PyObject;
import org.slf4j.Logger;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

/**
* @author Yuriy Zabrovarnyy
*/
@ApplicationScoped
public class ExternalTypeCreator {

private static final AtomicBoolean classPathInitialized = new AtomicBoolean(false);

@Inject
protected Logger log;

Expand All @@ -49,22 +41,6 @@ public class ExternalTypeCreator {
@Inject
protected AbstractCustomScriptService customScriptService;

private void initJavaCompilerClasspathIfNeeded() {
if (classPathInitialized.get()) {
return;
}
try {
classPathInitialized.set(true);

URL[] urls = ((URLClassLoader) this.getClass().getClassLoader()).getURLs();
for (URL url : urls) {
CompilerUtils.addClassPath(url.getFile());
}
} catch (Throwable e) {
log.error("FAILED to output class loader urls", e);
}
}

public BaseExternalType createExternalType(CustomScript customScript,
Map<String, SimpleCustomProperty> configurationAttributes) {
String customScriptInum = customScript.getInum();
Expand All @@ -81,6 +57,7 @@ public BaseExternalType createExternalType(CustomScript customScript,
loadException = ex;
log.error("Failed to prepare external type '{}', exception: '{}'", customScriptInum, ExceptionUtils.getStackTrace(ex));
log.error("Script '{}'", customScript.getScript());
log.error("Classpath '{}'", SimpleJavaCompiler.getClasspath());
}

externalType = initExternalType(externalType, customScript, configurationAttributes);
Expand Down Expand Up @@ -132,12 +109,8 @@ private BaseExternalType initExternalType(BaseExternalType externalType, CustomS
return null;
}

private BaseExternalType createExternalTypeWithJava(CustomScript customScript) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
initJavaCompilerClasspathIfNeeded();
CustomScriptType customScriptType = customScript.getScriptType();

PrintWriter printWriter = IoBuilder.forLogger(getClass()).setLevel(Level.DEBUG).buildPrintWriter();
Class<?> aClass = CompilerUtils.CACHED_COMPILER.loadFromJava(getClass().getClassLoader(), customScriptType.getClassName(), customScript.getScript(), printWriter);
private BaseExternalType createExternalTypeWithJava(CustomScript customScript) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class<?> aClass = SimpleJavaCompiler.compile(BaseExternalType.class, customScript.getScript());
return (BaseExternalType) aClass.getDeclaredConstructor().newInstance();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.jans.service.custom.script.jit;


public class DiscardableClassLoader {
public static <T> Class<? extends T> classFromBytes(final Class<T> baseClass, final String name, final byte[] bytecode) {
return new ClassLoader(baseClass.getClassLoader()) {
Class<? extends T> c = defineClass(name, bytecode, 0, bytecode.length).asSubclass(baseClass);
}.c;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package io.jans.service.custom.script.jit;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;


public class IndentedPrintWriter extends PrintWriter {

/**
* Creates a new IndentedPrintWriter, without automatic line flushing.
*
* @param out A character-output stream
*/
public IndentedPrintWriter(Writer out) {
super(new IndentedWriter(out));
}

/**
* Creates a new IndentedPrintWriter.
*
* @param out A character-output stream
* @param autoFlush A boolean; if true, the <tt>println</tt>,
* <tt>printf</tt>, or <tt>format</tt> methods will
* flush the output buffer
*/
public IndentedPrintWriter(Writer out, boolean autoFlush) {
super(new IndentedWriter(out), autoFlush);
}

/**
* Increases the indentation level
*/
public void indent() {
((IndentedWriter) out).indent();
}

/**
* Decreases the indentation level
*/
public void dedent() {
((IndentedWriter) out).dedent();
}

/**
* A writer that supports indentation of the output
*/
@SuppressWarnings("WeakerAccess")
private static class IndentedWriter extends Writer {
/**
* Characters used for one indentation level
*/
private static final char[] INDENT = "\t".toCharArray();
/**
* The underlying {@link Writer}
*/
private final Writer out;
/**
* Indentation level
*/
private int level;
/**
* true if must indent the next char
*/
private boolean mustIndent;

/**
* Constructor based on a {@link Writer}
*/
public IndentedWriter(Writer out) {
this.out = out;
}

/**
* Increases the indentation level
*/
public void indent() {
++level;
}

/**
* Decreases the indentation level
*/
public void dedent() {
--level;
}

@Override
public void write(char[] cbuf, int off, int len) throws IOException {
int last = off;
for (int i = off; i < off + len; i++) {
if (mustIndent) {
mustIndent = false;
// Do not indent empty lines
if (cbuf[i] != '\n')
writeIndent();
}
if (cbuf[i] == '\n') {
mustIndent = true;
out.write(cbuf, last, i - last + 1);
last = i + 1;
}
}
final int remaining = off + len - last;
if (remaining > 0)
out.write(cbuf, last, remaining);
}

private void writeIndent() throws IOException {
for (int i = 0; i < level; i++) {
out.write(INDENT);
}
}

@Override
public void flush() throws IOException {
out.flush();
}

@Override
public void close() throws IOException {
out.close();
}
}

/**
* Wraps the given writer in a indenting one if it isn't one already.
* Otherwise, returns the same one (casted).
*/
public static IndentedPrintWriter of(PrintWriter writer) {
if (writer instanceof IndentedPrintWriter)
return (IndentedPrintWriter) writer;
else
return new IndentedPrintWriter(writer);
}
}
Loading

0 comments on commit 3760380

Please # to comment.