Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

fix(jans-auth-server): added JIT compiler support under jvm 17 #5954

Merged
merged 1 commit into from
Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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