Giter Site home page Giter Site logo

janino-compiler / janino Goto Github PK

View Code? Open in Web Editor NEW
1.2K 1.2K 203.0 19.87 MB

Janino is a super-small, super-fast Java™ compiler.

Home Page: http://janino-compiler.github.io/janino

License: Other

Java 99.98% Shell 0.02%
compiler in-memory-java-compiler janino java-compiler

janino's People

Contributors

aunkrig avatar dependabot[bot] avatar geolykt avatar heartsavior avatar kiszk avatar lw-lin avatar maropu avatar nikolayandr avatar oontvoo avatar vvysotskyi avatar zaunerc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

janino's Issues

Script with many "helper" variables

Thanks a lot for creating janino - helps a lot prototyping some cool ideas in the area of route planning :) !

I'm currently seeking for the best approach to make dozens of helper variables available for a dynamic script like
edge.get(helperVariable1) * 0.9

The only parameter that changes per call is edge. But the helperVariable1 is not just a constant, it is an instance of an "accessor" class which is already available at creation (or "cook") time. E.g. we can write edge.get(surface) and an integer value is returned. So basically these helper variables are known up front (and there could be a lot of them), but we can't just replace them with int or double values up front.

Now, when I use createFastEvaluator with 25 parameters I get a nice fast evaluation (in my case 0.06ms/call). (E.g. this is faster compared to "cook&evaluate" with 0.1ms/call, also with 25 params). But the method of the interface gets really lengthy and is not really customizable. (or is there a trick?)

Is there a better and still fast approach like creating a class with all the helper variables (ClassBodyEvaluator?) as local variables and then make only one method scriptable for the end user?

For example something like this:

public class MyClass {
 HelperParam helperVariable1;
 public  MyClass() {
    // init helperParam
 } 

 public double run(OtherParam otherParam) {
   // USER SCRIPT HERE
   // that uses one or more helper variables
 }
}

If this is the way to go. Would I use ClassBodyEvaluator and string manipulation to inject the user script or is there a cleaner method?

I hope this is a bit understandable. Can give more examples if necessary.

Edit: Here is the current working snippet with this approach:

public ScriptWeighting createScriptWeighting(FlexModel model) {
String script = model.getScript();
for (String chars : Arrays.asList("{", "}", "import", "static", "file"))
    if (script.contains(chars))
        throw new IllegalArgumentException("Script contains illegal character " + chars);

if (!script.contains("return"))
    script = "return " + script;
if (!script.endsWith(";"))
    script = script + ";";

try {
    IClassBodyEvaluator cbe = CompilerFactoryFactory.getDefaultCompilerFactory().newClassBodyEvaluator();
    cbe.setNoPermissions();
    cbe.setImplementedInterfaces(new Class[]{ScriptInterface.class});
    cbe.setDefaultImports(new String[]{"com.graphhopper.util.EdgeIteratorState",
            "com.graphhopper.routing.profiles.*"});
    cbe.setClassName("MyRunner");
    cbe.cook("public EnumEncodedValue road_class;\n"
            + "  public EnumEncodedValue road_environment;\n"
            + "  public IntEncodedValue toll;\n"
            + "  public double getMillisFactor(EdgeIteratorState edge, boolean reverse) {\n"
            + script
            + "  }");
    Class<?> c = cbe.getClazz();
    return new ScriptWeighting(model.getBase(), model.getMaxSpeed(), (ScriptInterface) c.newInstance());
} catch (Exception ex) {
    throw new IllegalArgumentException(ex);
}
}

But it looks a bit looks a bit hacky.

UnitCompiler fails with CompileException when parent interface method is overridden in child interface with subtype return type

Hi,
Apache Calcite uses Janino 2.7.6 for compiling code which is used for handling different kinds of query metadata. All was working fine before bumping up Java version in maven-compiler-plugin to 1.8. After this, some tests failed with compile exceptions for generated code. The same issue is observed with Janino 3.0.7.

I have reproduced it on the current Janino master.
When Java version 1.8 is specified in janino-parent/pom.xml maven-compiler-plugin for both source and target, the next test placed into CompilerTest.java is failed:

    public interface A {
        A theFirstMethod();
    }

    public interface B extends A {
        B theFirstMethod();
        Object theSecondMethod();
    }

    @Test
    public void testInterfaceWithOverriddenMethod() throws Exception {
        SimpleCompiler s = new SimpleCompiler();
        s.setDebuggingInformation(true, true, true);
        s.cook("package pkg;\n"
            + "public class D {\n"
            + "    public java.lang.Object one(org.codehaus.janino.tests.CompilerTest.B b) { \n"
            + "       return b.theFirstMethod().theSecondMethod();\n"
            + "    }\n"
            + "}\n");
        s.getClassLoader().loadClass("pkg.D");
    }

Error message and stacktrace:

org.codehaus.commons.compiler.CompileException: Line 4, Column 50: A method named "theSecondMethod" is not declared in any enclosing class nor any supertype, nor through a static import

	at org.codehaus.janino.UnitCompiler.compileError(UnitCompiler.java:12063)
	at org.codehaus.janino.UnitCompiler.findIMethod(UnitCompiler.java:8955)
	at org.codehaus.janino.UnitCompiler.compileGet2(UnitCompiler.java:5018)
	at org.codehaus.janino.UnitCompiler.access$9100(UnitCompiler.java:215)
	at org.codehaus.janino.UnitCompiler$16.visitMethodInvocation(UnitCompiler.java:4378)
	at org.codehaus.janino.UnitCompiler$16.visitMethodInvocation(UnitCompiler.java:4351)
	at org.codehaus.janino.Java$MethodInvocation.accept(Java.java:5051)
	at org.codehaus.janino.UnitCompiler.compileGet(UnitCompiler.java:4351)
	at org.codehaus.janino.UnitCompiler.compileGetValue(UnitCompiler.java:5533)
	at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:2649)
	at org.codehaus.janino.UnitCompiler.access$2800(UnitCompiler.java:215)
	at org.codehaus.janino.UnitCompiler$6.visitReturnStatement(UnitCompiler.java:1504)
	at org.codehaus.janino.UnitCompiler$6.visitReturnStatement(UnitCompiler.java:1487)
	at org.codehaus.janino.Java$ReturnStatement.accept(Java.java:3541)
	at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:1487)
	at org.codehaus.janino.UnitCompiler.compileStatements(UnitCompiler.java:1567)
	at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:3356)
	at org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:1357)
	at org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:1330)
	at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:822)
	at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:432)
	at org.codehaus.janino.UnitCompiler.access$400(UnitCompiler.java:215)
	at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:411)
	at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:406)
	at org.codehaus.janino.Java$PackageMemberClassDeclaration.accept(Java.java:1406)
	at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:406)
	at org.codehaus.janino.UnitCompiler.compileUnit(UnitCompiler.java:378)
	at org.codehaus.janino.SimpleCompiler.cook(SimpleCompiler.java:237)
	at org.codehaus.janino.SimpleCompiler.compileToClassLoader(SimpleCompiler.java:465)
	at org.codehaus.janino.SimpleCompiler.cook(SimpleCompiler.java:216)
	at org.codehaus.janino.SimpleCompiler.cook(SimpleCompiler.java:207)
	at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:80)
	at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:75)
	at org.codehaus.janino.tests.CompilerTest.testInterfaceWithOverriddenMethod(CompilerTest.java:440)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

It looks like the overridden method A theFirstMethod() from the parent interface A was chosen instead of the method from interface B when b.theFirstMethod() was executed.

Also, I have noticed that with Java 8 the next code:

        Method[] declaredMethods = Class.forName("org.codehaus.janino.tests.CompilerTest$B").getDeclaredMethods();
        for (Method m : declaredMethods) {
            System.out.println(m);
        }

returns

public abstract org.codehaus.janino.tests.CompilerTest$B org.codehaus.janino.tests.CompilerTest$B.theFirstMethod()
public default org.codehaus.janino.tests.CompilerTest$A org.codehaus.janino.tests.CompilerTest$B.theFirstMethod()
public abstract java.lang.Object org.codehaus.janino.tests.CompilerTest$B.theSecondMethod()

So perhaps in our case that default method was chosen instead of the correct one.

Java 11 Compatibility check: commons-compiler

Hi,
We are reaching out to you to check Java 11 compatibility of the library commons-compiler.

Could you help us by answering the following questions:

  1. Library Name:
  2. Latest version: <latest 1.1.1="" eg:="" version.="">
  3. Latest version Is the library compatible with Java 11 Compatible? (Y/N)
  4. Is the library supported with Java 11? (Y/N)
  5. (If “N” in compatibility or support) What is the versions that would be compatible and Supported?
  6. Date of support availability?

Appreciate your response by 19.08.2018.

Thanks,
Krzysztof Dragan,
PTC Inc. Contractor

Strings in switch statement

Hello,

In the documentation you say that Janino supports strings in switch statements (Java 7 language features).
However, the following simple test:

    @Test
    public void testSwitch() throws CompileException, InvocationTargetException {
        ScriptEvaluator se = new ScriptEvaluator();
        se.setReturnType(String.class);
        se.cook("switch(\"1\") { case \"1\": return \"42\"; default: return null; }");
        assertEquals("42", se.evaluate(new Object[0]));
    }

throws the following:

org.codehaus.commons.compiler.CompileException: Line 1, Column 7: Assignment conversion not possible from type "java.lang.String" to type "int"
	at org.codehaus.janino.UnitCompiler.compileError(UnitCompiler.java:11523)
	at org.codehaus.janino.UnitCompiler.assignmentConversion(UnitCompiler.java:10379)
	at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:1881)
	at org.codehaus.janino.UnitCompiler.access$2300(UnitCompiler.java:209)
	at org.codehaus.janino.UnitCompiler$6.visitSwitchStatement(UnitCompiler.java:1451)
	at org.codehaus.janino.UnitCompiler$6.visitSwitchStatement(UnitCompiler.java:1438)
	at org.codehaus.janino.Java$SwitchStatement.accept(Java.java:3220)
	at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:1438)
	at org.codehaus.janino.UnitCompiler.compileStatements(UnitCompiler.java:1518)
	at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:2950)
	at org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:1308)
	at org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:1281)
	at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:780)
	at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:431)
	at org.codehaus.janino.UnitCompiler.access$400(UnitCompiler.java:209)
	at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:385)
	at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:380)
	at org.codehaus.janino.Java$PackageMemberClassDeclaration.accept(Java.java:1405)
	at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:380)
	at org.codehaus.janino.UnitCompiler.compileUnit(UnitCompiler.java:354)
	at org.codehaus.janino.SimpleCompiler.compileToClassLoader(SimpleCompiler.java:413)
	at org.codehaus.janino.ClassBodyEvaluator.compileToClass(ClassBodyEvaluator.java:318)
	at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:597)
	at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:489)
	at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:422)
	at org.codehaus.janino.SimpleCompiler.cook(SimpleCompiler.java:200)
	at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:76)
	at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:71)

Whereas it works perfectly with a simple switch on int:

    @Test
    public void testSwitch() throws CompileException, InvocationTargetException {
        ScriptEvaluator se = new ScriptEvaluator();
        se.setReturnType(String.class);
        se.cook("switch(1) { case 1: return \"42\"; default: return null; }");
        assertEquals("42", se.evaluate(new Object[0]));
    }

For information, I'm using the latest version of Janino:

      <dependency>
          <groupId>org.codehaus.janino</groupId>
          <artifactId>janino</artifactId>
          <version>3.0.6</version>
      </dependency>

Am I doing something wrong?

Many thanks for your help!

Laurent

error message should include variable/field names for clarity

When a variable with "default" access modifier is accessed from outside the declaring file, we get this error.

It'd be clearer if the error message include the name of the field.


 Caused by: org.codehaus.commons.compiler.CompileException: File 'Unknown', Line -1, Column -1: Member with "/*default*/" access cannot be accessed from type "com.exampl.MyApp"
         at org.codehaus.janino.UnitCompiler.compileError(UnitCompiler.java:11004)
         at org.codehaus.janino.UnitCompiler.checkAccessible(UnitCompiler.java:6464)
         at org.codehaus.janino.UnitCompiler.checkAccessible(UnitCompiler.java:6440)
         at org.codehaus.janino.UnitCompiler.compileGet2(UnitCompiler.java:3828)
         at org.codehaus.janino.UnitCompiler.access$8800(UnitCompiler.java:206)
         at org.codehaus.janino.UnitCompiler$12.visitFieldAccess(UnitCompiler.java:3793)
         at org.codehaus.janino.UnitCompiler$12.visitFieldAccess(UnitCompiler.java:3762)
         at org.codehaus.janino.Java$FieldAccess.accept(Java.java:3709)
         at org.codehaus.janino.Java$Lvalue.accept(Java.java:3563)
         at org.codehaus.janino.UnitCompiler.compileGet(UnitCompiler.java:3762)
         at org.codehaus.janino.UnitCompiler.compileGet2(UnitCompiler.java:4270)
         at org.codehaus.janino.UnitCompiler.access$8900(UnitCompiler.java:206)
         at org.codehaus.janino.UnitCompiler$12.visitFieldAccessExpression(UnitCompiler.java:3794)
         at org.codehaus.janino.UnitCompiler$12.visitFieldAccessExpression(UnitCompiler.java:3762)
         at org.codehaus.janino.Java$FieldAccessExpression.accept(Java.java:3975)
         at org.codehaus.janino.Java$Lvalue.accept(Java.java:3563)
         at org.codehaus.janino.UnitCompiler.compileGet(UnitCompiler.java:3762)
         at org.codehaus.janino.UnitCompiler.compileGetValue(UnitCompiler.java:4933)
         at org.codehaus.janino.UnitCompiler.compileGet2(UnitCompiler.java:4476)
         at org.codehaus.janino.UnitCompiler.access$7500(UnitCompiler.java:206)
         at org.codehaus.janino.UnitCompiler$12.visitMethodInvocation(UnitCompiler.java:3774)
         at org.codehaus.janino.UnitCompiler$12.visitMethodInvocation(UnitCompiler.java:3762)
         at org.codehaus.janino.Java$MethodInvocation.accept(Java.java:4328)
         at org.codehaus.janino.UnitCompiler.compileGet(UnitCompiler.java:3762)
         at org.codehaus.janino.UnitCompiler.compileGetValue(UnitCompiler.java:4933)
         at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:3180)
         at org.codehaus.janino.UnitCompiler.access$5000(UnitCompiler.java:206)
         at org.codehaus.janino.UnitCompiler$9.visitMethodInvocation(UnitCompiler.java:3151)
         at org.codehaus.janino.UnitCompiler$9.visitMethodInvocation(UnitCompiler.java:3139)
         at org.codehaus.janino.Java$MethodInvocation.accept(Java.java:4328)
         at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:3139)
         at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:2112)
         at org.codehaus.janino.UnitCompiler.access$1700(UnitCompiler.java:206)
         at org.codehaus.janino.UnitCompiler$6.visitExpressionStatement(UnitCompiler.java:1377)
         at org.codehaus.janino.UnitCompiler$6.visitExpressionStatement(UnitCompiler.java:1370)
         at org.codehaus.janino.Java$ExpressionStatement.accept(Java.java:2558)
         at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:1370)
         at org.codehaus.janino.UnitCompiler.compileStatements(UnitCompiler.java:1450)
         at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:1436)
         at org.codehaus.janino.UnitCompiler.access$1600(UnitCompiler.java:206)
         at org.codehaus.janino.UnitCompiler$6.visitBlock(UnitCompiler.java:1376)
         at org.codehaus.janino.UnitCompiler$6.visitBlock(UnitCompiler.java:1370)
         at org.codehaus.janino.Java$Block.accept(Java.java:2471)
         at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:1370)
         at org.codehaus.janino.UnitCompiler.compileStatements(UnitCompiler.java:1450)
         at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:1436)
         at org.codehaus.janino.UnitCompiler.access$1600(UnitCompiler.java:206)
         at org.codehaus.janino.UnitCompiler$6.visitBlock(UnitCompiler.java:1376)
         at org.codehaus.janino.UnitCompiler$6.visitBlock(UnitCompiler.java:1370)
         at org.codehaus.janino.Java$Block.accept(Java.java:2471)
         at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:1370)
         at org.codehaus.janino.UnitCompiler.compileStatements(UnitCompiler.java:1450)
         at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:1436)
         at org.codehaus.janino.UnitCompiler.access$1600(UnitCompiler.java:206)
         at org.codehaus.janino.UnitCompiler$6.visitBlock(UnitCompiler.java:1376)
         at org.codehaus.janino.UnitCompiler$6.visitBlock(UnitCompiler.java:1370)
         at org.codehaus.janino.Java$Block.accept(Java.java:2471)
         at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:1370)
         at org.codehaus.janino.UnitCompiler.compileStatements(UnitCompiler.java:1450)
         at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:2811)
         at org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:1262)
         at org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:1234)
         at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:538)
         at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:420)
         at org.codehaus.janino.UnitCompiler.access$400(UnitCompiler.java:206)
         at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:374)
         at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:369)
         at org.codehaus.janino.Java$AbstractPackageMemberClassDeclaration.accept(Java.java:1309)
         at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:369)
         at org.codehaus.janino.UnitCompiler.compileUnit(UnitCompiler.java:345)
         at com.streambase.sb.codegen.JaninoCompiler.compile(JaninoCompiler.java:88)
         at com.streambase.sb.codegen.CGCompiler.generateBinaryClasses(CGCompiler.java:201)
         at com.streambase.sb.codegen.CompilationUnit.compile(CompilationUnit.java:176)
         ... 7 more

High security mode

Thanks for your library!

Regarding security the documentation says:
JANINO has full access to the JRE, security problems can arise if the expression, script, class body or compilation being compiled and executed contains user input.

I can imagine that the input is very often a user input and then defaults should be something like 'let access only to helper classes', e.g. just allow mathematical operations, Math.* and a list of allowed classes.

The docs says that this can be fixed with de.unkrig.commons.lang.security.Sandboxcode. Wouldn't it make sense to provide this inbuilt maybe as the default option? Or with a simple config call
new ScriptEvaluator(restrictedEnvironment=true)? Or how would I configure the sandbox for this very restricted environment? Is there some more documentation about this than the javadocs?

They reason I ask this is that I'm considering to include this library in a project (due to its simplicity) but have heard that e.g. ElasticSearch had lots of security problems due to its powerful scripting. So they moved from mvel to groovy and then finally moved to some handwritten expression library Painless with 'proper' security.

Issue with scriptEvaluator compilation.

Hi,
I am getting an exception as

_Exception in thread "main" java.lang.ClassFormatError: Too many arguments in method signature in class file SC
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
at org.codehaus.janino.ByteArrayClassLoader.findClass(ByteArrayClassLoader.java:81)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
at org.codehaus.janino.ClassBodyEvaluator.compileToClass(ClassBodyEvaluator.java:319)
at org.codehaus.janino.ScriptEvaluator.cook2(ScriptEvaluator.java:609)
at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:598)
at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:534)
at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:503)
at org.codehaus.janino.SimpleCompiler.cook(SimpleCompiler.java:204)
at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:80)
at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:75)
at org.codehaus.janino.ScriptEvaluator.(ScriptEvaluator.java:165)
at ScriptComplier.main(ScriptComplier.java:23)

I am using scriptEvaluator(block,returntype,parametername,parametertype) to which I am passing two arrays parametername and parametertype both of the size 1000.And script String length 74324.
I have attached the sample code file. Please guide me on this. Is there any other way to achieve this

ScriptComplier.txt

How to use ExpressionEvaluator.cook(String[])?

The javadocs say:

    /**
     * Same as {@link #cook(String)}, but for multiple scripts.
     */

But when I use the latest master and I do:

ExpressionEvaluator ee = new ExpressionEvaluator();
ee.setStaticMethod(false);//without this there is no error
ee.cook("9*3;7+1".split(";"));

I get

! java.lang.IllegalArgumentException: null
! at org.codehaus.janino.ScriptEvaluator.array(ScriptEvaluator.java:775)
! at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:550)
! at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:535)
! at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:500)
! at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:473)
! at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:466)

And how would I define a variable? The following does not work:

ee.cook("int tmp = 3;tmp*7+1".split(";"));

Private Variables in Script Execution Mode

First and foremost, thanks a ton for Janino. I've been using it to run in-class examples for my introductory programming course and it's working brilliantly.

I'm confused, however, as to why the following works:

class Test {
  private int value;
}
Test t = new Test();
t.value = 5;
System.out.println(t.value);

Is there a way to get the visibility modifiers to work in examples like this? Note that I'm currently disabling almost all permissions—with the exception of RuntimePermission("getProtectionDomain") which I needed to enable to get class loading to work at all. Perhaps I'm disabling a permission that is causing this work work incorrectly?

FWIW, the code for Janini (my script runner web service) is available here.

Janino throws runtime excetion for a method with more than 254 of operand stack height

This is the same as issue #6 in the old repository

When we pass the following code piece to Janino, Janino throws the following exception because the max height of Java operand stack for foo() is more than 254.
This issue was revealed by the JIRA entry

Program

double test(double d0, double d1, ..., double d126) { return 1.0D; }

double foo() {
  boolean b = false 
  double d = b ? 0.0D : test(0, 0, .... 0);  // @kiszk corrected this line on July 1, 2016
  return d;
}

Exception

org.codehaus.janino.JaninoRuntimeException: org.apache.spark.sql.catalyst.expressions.GeneratedClass$SpecificSafeProjection.apply(java.lang.Object _i): Operand stack overflow at offset ...

ScriptEvaluator example from website does not work

The example for using the ScriptEvaluator from the website:


ScriptEvaluator se = new ScriptEvaluator();
 
        se.cook(
            ""
            + "static void method1() {\n"
            + "    System.out.println(1);\n"
            + "}\n"
            + "\n"
            + "method1();\n"
            + "method2();\n"
            + "\n"
            + "static void method2() {\n"
            + "    System.out.println(2);\n"
            + "}\n"
        );

fails with the exception:

 org.codehaus.commons.compiler.CompileException: Line 1, Column 7: Unexpected token "static" in primary

StackOverflow when using new Permision system in ClassLoader

Hello,
I'm in the context of a tomcat 6 webapp, using janino 3.0.7
My code is much like the documented code in the security section

What happens is a stackoverflow originated by
SecurityMamanger.checkRead calling the SandBox.checkPermission

In my case here is the loop created

SecurityMamanger.checkRead:888
code : checkPermission(new FilePermission(file,SecurityConstants.FILE_READ_ACTION));

SandBox$1.checkPermission:82
code : acc = Sandbox.CONFINED_CLASS_LOADERS.get(clasS.getClassLoader());

Class.getClassLoader:683
ClassLoader.checkClassLoaderPermission:1528

   who again call :  SandBox$1.checkPermission:82

And so we are from here stuck in a loop which lead to a S.O.

Does not compile my project

Dear Janino developers,

I am developing a free java program for life scientists and would be very interested in a fast java compiler like janino.

Some Java classes are quite big and take several seconds to compile with Oracle javac.
This makes code-editing / recompilation cumbersome. Therefore janino would help a lot.
For final compilation I would probably still trust Oracle Javac but for rapid error fixing and developing
I would prefer janino.

Unfortunately, janino does not compile many of my Java-files. I would need to change too many lines of code
for example explicit casting the results of Map#get and Collection#get.

Is there a chance to get these issues resolved in janino?
I guess, that there are only very few syntactical constructs which are not yet supported in janino.

Many thanks for developing this nice software

Cheers
Christoph

Cooking Multiple Files with SimpleCompiler

Is it possible to cook multiple strings using the Janino SimpleCompiler? I tried something like this:

for (String source : sources) {
    simpleCompiler.cook(new ByteArrayInputStream(source.getBytes(StandardCharsets.UTF_8)));
    simpleCompiler.setParentClassLoader(simpleCompiler.getClassLoader());
}

This works fine as long as the dependencies are in the correct order, but fails if they are not. In contrast, feeding in one string with both class definitions works regardless of in which order the classes are defined.

An obvious approach is to try and concatenate the files together and feed them all in at once, but that fails if there are imports at the top of each class file.

Overall I'd like to be able to take a request containing multiple strings each containing a Java class file with imports, compile them all and then run something. It seems like Janino is really close to being able to do that...

Invalid JavaDoc comment on VariableAccessResource constructor

After the recent addition of try-with-resources support, the newly added VariableAccessResource seems to be suffering from some copy-and-paste error:
(from org.codehaus.janino.Java.TryStatement.VariableAccessResource#VariableAccessResource)

            /**
             * @param modifiers Only {@code final} allowed
             */
            public
            VariableAccessResource(Location location, Rvalue variableAccess) {
                super(location);
                this.variableAccess = variableAccess;
            }

Compiling for heavy task

I'm a newbie, I'd read the tutorial. I need on-memory compiling and run for heavy task.
so the function I need is, load source code as String java heap object, return java.lang.Class on memory.

I wrote the following code. but exception occured. and I don't know this method is suitable for performance. please help.

successException in thread "main"
java.lang.AbstractMethodError: junk.JaninoTest.task()D
at junk.Janino.main(Janino.java:38)


package junk;

import org.codehaus.commons.compiler.*;
import org.codehaus.janino.*;
public class Janino {
	public static void main(String[] args) throws Exception {
		String srcName = "junk.JaninoTest";
		String crlf = System.lineSeparator();
		SimpleCompiler sc = new SimpleCompiler();
		sc.cook("package junk;" + crlf + "import junk.Janino.*;" + crlf
				+ "public class JaninoTest implements TestI{" + crlf
				+ "public double task(){" + "double r = 0;" + crlf
				+ "for(double i=0;i<1000*1000*10;i++){" + crlf
				+ "r += i*(i+r)/r%r*r;" + crlf
				+ "if(Double.isNaN(r)){" + crlf
				+	"r = 38297;" + crlf
				+"}" + crlf
				+ "}" + crlf + "return r;" + crlf
				+ "}" + crlf + "}" + crlf);
		sc.setCompileErrorHandler(new ErrorHandler() {
			@Override
			public void handleError(String message, Location optionalLocation)
					throws CompileException {
				System.out.println(message);
			}
		});
		Class<?> clazz = sc.getClassLoader().loadClass(srcName);
		Object o = clazz.getDeclaredConstructor().newInstance();
		if (o instanceof TestI) {
			System.out.println("success");
			TestI t = (TestI) o;

			//comparison of janino and jdk
			long start = System.currentTimeMillis();
			double d = t.task();
			System.out.println(d);
			System.out.println("by janino "+(System.currentTimeMillis() - start) + "ms");

			start = System.currentTimeMillis();
			d = task();
			System.out.println(d);
			System.out.println("by jdk "+(System.currentTimeMillis() - start) + "ms");
		} else {
			System.out.println("failure");
		}
	}

	public static double task() {
		double r = 0;
		for (double i = 0; i < 1000 * 1000 * 10; i++) {
			r += i * (i + r) / r % r * r;
			if(Double.isNaN(r)){
				r = 38297;
			}
		}
		return r;
	}

	public interface TestI {
		double task();
	}
}

Make Unparser more flexible

Hello,

Apache Drill widely uses Janino for code compilation, rewriting source code of user-defined functions to be able to use it in generated classes and for some other things.

The main modification which we are doing with user-defined functions is wrapping methods code into the block with the label and replacing all return statements in this method by break ones with mentioned above labels.

We use a class, extended from Unparser for this goal, but some of its methods are private, and some of them call visitors.

It would be great if Unparser.unparseMethodDeclarator() and Unparser.unparseStatements() methods became protected and logic from Unparser.blockStatementUnparser.visitReturnStatement() method is moved to protected method in Unparser which will be called from Unparser.blockStatementUnparser.visitReturnStatement(), so inheritors will be able to extend its logic (similar to the Unparser.blockStatementUnparser).

Cannot compile enums

Janino: 3.0.8
Java: 1.8

Currently unable to compile enums.
We're generating Java code and compiling it at runtime. Currently I'm unable to get Janino to compile enums generated. Nothing particularly special about the enums. The one thing I can think of is that we can have the same enum generated in different packages.
Example of actual enums that fail:

public enum Gender {
  MALE,
  FEMALE,
  OTHER,
  RATHER_NOT_SAY;
}

public enum HttpMethod {
  GET,
  PUT,
  POST,
  DELETE,
  PATCH,
  OPTIONS,
  HEAD,
  TRACE,
  CONNECT;
}

For now, I'm going to swap out code gen of enums for ints but I'd like to use enums.
The compiler stacktrace is:

org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.ClassFormatError: Duplicate field name "ENUM$VALUES" with signature "[Lcore.HttpMethod;" in class file core/HttpMethod

	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1006)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:877)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
	at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:71)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
	at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:166)
	at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:133)
	at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:165)
	at hypi.davil.AppSubmissionTest.emptyPostResultsInArror(AppSubmissionTest.java:65)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
	at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.ClassFormatError: Duplicate field name "ENUM$VALUES" with signature "[Lcore.HttpMethod;" in class file core/HttpMethod
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
	at org.codehaus.janino.JavaSourceClassLoader.defineBytecode(JavaSourceClassLoader.java:246)
	at org.codehaus.janino.JavaSourceClassLoader.findClass(JavaSourceClassLoader.java:198)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at hypi.davil.gql.ModelCtx.lambda$compileJava$0(ModelCtx.java:119)
	at java.util.HashMap$KeySet.forEach(HashMap.java:933)
	at hypi.davil.gql.ModelCtx.compileJava(ModelCtx.java:117)
	at hypi.davil.gql.ModelCtx.traverseModel(ModelCtx.java:86)
	at hypi.davil.handlers.GQLHandler.graphql(GQLHandler.java:76)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
	... 42 more

I will try to get some time soon to reproduce this in isolation and attach a a reproducer project if the above isn't enough to go on.
I get the feeling that enums are being shared somehow across the packages.

Permissions - can I black list?

I'm finding the documentation on permissions hard to follow. Is it true that if I don't call setPermissions then all permissions are enabled by default? If I call setPermissions with a permission list, only those permissions are enabled. Is it possible to approach from the other angle and disallow certain permissions?

SIPUSH bytecode is not used for short integer constant

When I compiled the simple program using janinoc with janino 3.0.7, I realized that the compiled java bytecode does not use sipush java bytecode, but it uses ldc java bytecode. While it functionally works correctly, the generated java bytecode consumes an additional constant pool entry.
When I compiled this program using javac in OpenJDK8, the generated java bytecode uses sipush.

public class CP2 {
  static public void main(String[] argv) {
    int i = 32767;
  }
}
Classfile /home/ishizaki/Spark/PR/lsof/spark/CP2.class
  Last modified Nov 24, 2017; size 263 bytes
  MD5 checksum 8759300e8265dce5114c34a53ae853d0
  Compiled from "CP2.java"
public class CP2
  minor version: 0
  major version: 49
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Utf8               CP2
   #2 = Class              #1             // CP2
   #3 = Utf8               java/lang/Object
   #4 = Class              #3             // java/lang/Object
   #5 = Utf8               SourceFile
   #6 = Utf8               CP2.java
   #7 = Utf8               main
   #8 = Utf8               ([Ljava/lang/String;)V
   #9 = Integer            32767
  #10 = Utf8               LineNumberTable
  #11 = Utf8               Code
  #12 = Utf8               <init>
  #13 = Utf8               ()V
  #14 = NameAndType        #12:#13        // "<init>":()V
  #15 = Methodref          #4.#14         // java/lang/Object."<init>":()V
{
  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=2, args_size=1
         0: ldc           #9                  // int 32767
         2: istore_1
         3: return
      LineNumberTable:
        line 3: 0
        line 2: 3

  public CP2();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #15                 // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 1: 0
}

Undeclared runtime dependency on de.unkrig.jdiasm.Disassembler

Digging into this runtime error from a Logback configurator, I discovered that janino has an undeclared runtime dependency on de.unkrig.jdiasm:

java.lang.ClassNotFoundException: de.unkrig.jdisasm.Disassembler
        at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:264)
        at org.codehaus.janino.UnitCompiler.disassembleToStdout(UnitCompiler.java:11913)
        at org.codehaus.janino.UnitCompiler.addClassFile(UnitCompiler.java:847)
        at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:841)
        at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:431)
        at org.codehaus.janino.UnitCompiler.access$400(UnitCompiler.java:209)
        at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:385)
        at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:380)
        at org.codehaus.janino.Java$PackageMemberClassDeclaration.accept(Java.java:1405)
        at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:380)
        at org.codehaus.janino.UnitCompiler.compileUnit(UnitCompiler.java:354)
        at org.codehaus.janino.SimpleCompiler.compileToClassLoader(SimpleCompiler.java:413)
        at org.codehaus.janino.ClassBodyEvaluator.compileToClass(ClassBodyEvaluator.java:318)
        at org.codehaus.janino.ClassBodyEvaluator.cook(ClassBodyEvaluator.java:235)
        at org.codehaus.janino.SimpleCompiler.cook(SimpleCompiler.java:200)
        at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:76)
        at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:71)
        at ch.qos.logback.core.joran.conditional.PropertyEvalScriptBuilder.build(PropertyEvalScriptBuilder.java:47)
        at ch.qos.logback.core.joran.conditional.IfAction.begin(IfAction.java:65)
        at ch.qos.logback.core.joran.spi.Interpreter.callBeginAction(Interpreter.java:269)
        at ch.qos.logback.core.joran.spi.Interpreter.startElement(Interpreter.java:145)
        at ch.qos.logback.core.joran.spi.Interpreter.startElement(Interpreter.java:128)
        at ch.qos.logback.core.joran.spi.EventPlayer.play(EventPlayer.java:50)
        at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:158)
        at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:145)
        at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:103)
        at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:53)
        at play.api.libs.logback.LogbackLoggerConfigurator.configure(LogbackLoggerConfigurator.scala:94)

Which is right there in the code but it's not in the pom:

https://github.com/janino-compiler/janino/blob/master/janino/src/main/java/org/codehaus/janino/UnitCompiler.java#L11952-L11967

Please add a runtime dependency to your pom.xml to make this explicit so that it will show up properly in dependency management tools.

Turning logging off by default

Hi,

The following exception is printed to the console when I execute a simple evaluation:

java.lang.ClassNotFoundException: de.unkrig.jdisasm.Disassembler
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:264)
	at org.codehaus.janino.UnitCompiler.disassembleToStdout(UnitCompiler.java:11913)
	at org.codehaus.janino.UnitCompiler.addClassFile(UnitCompiler.java:847)
	at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:841)
	at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:431)
	at org.codehaus.janino.UnitCompiler.access$400(UnitCompiler.java:209)
	at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:385)
	at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:380)
	at org.codehaus.janino.Java$PackageMemberClassDeclaration.accept(Java.java:1405)
	at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:380)
	at org.codehaus.janino.UnitCompiler.compileUnit(UnitCompiler.java:354)
	at org.codehaus.janino.SimpleCompiler.compileToClassLoader(SimpleCompiler.java:413)
	at org.codehaus.janino.ClassBodyEvaluator.compileToClass(ClassBodyEvaluator.java:318)
	at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:597)
	at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:489)
	at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:422)
	at org.codehaus.janino.SimpleCompiler.cook(SimpleCompiler.java:200)
	at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:76)
	at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:71)
	at com.ohua.engine.flowgraph.elements.operator.CallArrayConstruction$C

The code is not failing but I don't want this log output. It seems that the logger is per-default set to log level FINEST. Is that necessary?

Conversion not possible when generics in play.

org.codehaus.commons.compiler.CompileException: File './target/1473454439101-0/test.java', Line 1078, Column 31: Assignment conversion not possible from type "java.lang.Object" to type "boolean"

the code line looks like:

  this.boolean = method(someObject, someBoolean);

method signature is:

T method(Object obj, T someBool)

This is with janino 3.0.1

For ExpressionEvaluator, doesn't allow null values

I am using Janino library to evaluate expressions fed by user dynamically. Sometimes values passed to expression can be null, while executing expression get following exception:

Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.janino.ScriptEvaluator.evaluate(ScriptEvaluator.java:929) at org.codehaus.janino.ScriptEvaluator.evaluate(ScriptEvaluator.java:349)
..
..
..

Caused by: java.lang.NullPointerException
at SC.eval0(Unknown Source)
... 9 more

Expression: (a != null && a.equals("MATCH"))?true:false

Wile executing sometimes values of a can be null, but expression doesn't get executed since a is null. How could we get this working?

Java 9/10 commons.compiler.jdk Support

I just discovered Janino's ability to use the built-in javax.tools compiler. You have no idea how much time that has saved me—thanks so much for that. (And of course it exposes how much faster Janino is... wow.)

Are there plans to get this working with more recent versions of Java: 9 or 10? Note that I don't mean adding support for these new features to Janino's compiler—I understand how much work that would be. Hopefully supporting the javax.tools compiler would be simpler.

I accidentally experimented with this today as I had my IntelliJ configured to use Java 9. So I can confirm that it does not work. But the problem looked like it was asking the SimpleCompiler class whether a given option was supported which triggered an exception that caused everything to fail. I can reproduce with more details if it's helpful. But I was wondering if just ignoring that option request or returning false would allow things to move forward.

Anyway, thanks again for all of your hard work on this project. I have an unrelated question that I'll open separately.

Can not set final [B field org.codehaus.janino.util.ClassFile$CodeAttribute.code to org.codehaus.janino.util.ClassFile$CodeAttribute

17/04/06 17:04:55 WARN [org.apache.spark.sql.catalyst.expressions.codegen.CodeGenerator(87) -- main]: Error calculating stats of compiled class.
java.lang.IllegalArgumentException: Can not set final [B field org.codehaus.janino.util.ClassFile$CodeAttribute.code to org.codehaus.janino.util.ClassFile$CodeAttribute
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:55)
at sun.reflect.UnsafeQualifiedObjectFieldAccessorImpl.get(UnsafeQualifiedObjectFieldAccessorImpl.java:38)
at java.lang.reflect.Field.get(Field.java:379)
at org.apache.spark.sql.catalyst.expressions.codegen.CodeGenerator$$anonfun$recordCompilationStats$1$$anonfun$apply$4$$anonfun$apply$5.apply(CodeGenerator.scala:997)
at org.apache.spark.sql.catalyst.expressions.codegen.CodeGenerator$$anonfun$recordCompilationStats$1$$anonfun$apply$4$$anonfun$apply$5.apply(CodeGenerator.scala:984)
at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33)
at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:186)
at org.apache.spark.sql.catalyst.expressions.codegen.CodeGenerator$$anonfun$recordCompilationStats$1$$anonfun$apply$4.apply(CodeGenerator.scala:984)
at org.apache.spark.sql.catalyst.expressions.codegen.CodeGenerator$$anonfun$recordCompilationStats$1$$anonfun$apply$4.apply(CodeGenerator.scala:983)
at scala.collection.Iterator$class.foreach(Iterator.scala:893)
at scala.collection.AbstractIterator.foreach(Iterator.scala:1336)
at scala.collection.IterableLike$class.foreach(IterableLike.scala:72)

Caused by: java.lang.NoSuchMethodError: org.codehaus.commons.compiler.Location.getLineNumber()S

Since v3.0.2., using of getLineNumber() ends up in compilation error:
Caused by: java.lang.NoSuchMethodError: org.codehaus.commons.compiler.Location.getLineNumber()S

I think, maybe the error occurs in Location.java:
...

    public static final Location NOWHERE = new Location("<internally generated location>", **(short)** -1, **(short)** -1);

    @Nullable private final String optionalFileName;
    private final int              lineNumber;
    private final int              columnNumber;
...
    public
    Location(@Nullable String optionalFileName, **int** lineNumber, **int** columnNumber) {
        this.optionalFileName = optionalFileName;
        this.lineNumber       = lineNumber;
        this.columnNumber     = columnNumber;
    }

Greetings,
Patrick

Assignment conversion not possible from type \"java.lang.Boolean\" to type \"java.lang.Object\"\n\

I get the below exception very often, I am evaluating using janio for expression evaluation. I have expression like this ((5<=(264+(2.0*0.0)))), that needs to be evaluated, I am using janio within apache storm, where a bolt does the evaluation, I don't get this exception for every message, but it fail for a large number of message.
I don't see these exception when i try to debug with expression it failed for, looks like this happens when there are lot of thread running, like it always does with apache storm.

ee = new ExpressionEvaluator(); ee.cook("((5<=(264+(2.0*0.0))))"); passed = (boolean) ee.evaluate(null);
This is the piece of code with a bolt that does the evaluation, i pass null to evaluate because all the value in the expression are already there.

Any help on this, would be great.

"error": "org.codehaus.commons.compiler.CompileException: Line 1, Column 21: Assignment conversion not possible from type "java.lang.Boolean" to type "java.lang.Object"\n\tat org.codehaus.janino.UnitCompiler.compileError(UnitCompiler.java:10062)\n\tat org.codehaus.janino.UnitCompiler.assignmentConversion(UnitCompiler.java:8988)\n\tat org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:1903)\n\tat org.codehaus.janino.UnitCompiler.access$2100(UnitCompiler.java:182)\n\tat org.codehaus.janino.UnitCompiler$4.visitReturnStatement(UnitCompiler.java:946)\n\tat org.codehaus.janino.Java$ReturnStatement.accept(Java.java:2541)\n\tat org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:958)\n\tat org.codehaus.janino.UnitCompiler.compileStatements(UnitCompiler.java:999)\n\tat org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:2284)\n\tat org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:822)\n\tat org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:794)\n\tat org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:504)\n\tat org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:390)\n\tat org.codehaus.janino.UnitCompiler.access$400(UnitCompiler.java:182)\n\tat org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:344)\n\tat org.codehaus.janino.Java$PackageMemberClassDeclaration.accept(Java.java:1136)\n\tat org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:351)\n\tat org.codehaus.janino.UnitCompiler.compileUnit(UnitCompiler.java:319)\n\tat org.codehaus.janino.SimpleCompiler.compileToClassLoader(SimpleCompiler.java:358)\n\tat org.codehaus.janino.ClassBodyEvaluator.compileToClass(ClassBodyEvaluator.java:315)\n\tat org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:573)\n\tat org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:471)\n\tat org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:383)\n\tat org.codehaus.janino.SimpleCompiler.cook(SimpleCompiler.java:192)\n\tat org.codehaus.commons.compiler.Cookable.cook(Cookable.java:84)\n\tat org.codehaus.commons.compiler.Cookable.cook(Cookable.java:77)\n\tat com.tgt.wlm.workgen.bolts.RuleEvaluatorBolt.evaluateEpressionsFast(RuleEvaluatorBolt.java:75)\n\tat com.tgt.wlm.workgen.bolts.RuleEvaluatorBolt.execute(RuleEvaluatorBolt.java:53)\n\tat org.apache.storm.daemon.executor$fn__7953$tuple_action_fn__7955.invoke(executor.clj:728)\n\tat org.apache.storm.daemon.executor$mk_task_receiver$fn__7874.invoke(executor.clj:461)\n\tat org.apache.storm.disruptor$clojure_handler$reify__7390.onEvent(disruptor.clj:40)\n\tat org.apache.storm.utils.DisruptorQueue.consumeBatchToCursor(DisruptorQueue.java:439)\n\tat org.apache.storm.utils.DisruptorQueue.consumeBatchWhenAvailable(DisruptorQueue.java:418)\n\tat org.apache.storm.disruptor$consume_batch_when_available.invoke(disruptor.clj:73)\n\tat org.apache.storm.daemon.executor$fn__7953$fn__7966$fn__8019.invoke(executor.clj:847)\n\tat org.apache.storm.util$async_loop$fn__625.invoke(util.clj:484)\n\tat clojure.lang.AFn.run(AFn.java:22)\n\tat java.lang.Thread.run(Thread.java:745)\n"

Import silently failing

Not sure of the exact problem and it's difficult to post an example unfortunately, but I can try if this is an unknown issue. I seem to be getting a compile error when trying to reference a class that is full of static items. The import is correct but the compiler says it's an error.

The class being references is like this:

public class MyStaticClass {
    public static final SomeOtherClass ITEM1;

    static {
        ITEM1 = new SomeOtherClass("abc");
    }
}

Then I reference that static item from my code that I am loading with SimpleCompiler:

public void someMethod() {
    SomeOtherClass c1 = MyStaticClass.ITEM1;
}

Error text just points to the line number and position in someMethod().

I apologize for the lack of actual code example but let me know if this is not a known issue and i'll try to provide more information. The actual error is being caused within a Minecraft mod and their code undergoes deobfuscation etc. so a bit hard to provide an example.

java.lang.StackOverflowError when loading some java code

java.lang.StackOverflowError
at org.codehaus.janino.Java$NormalAnnotation.setEnclosingScope(Java.java:389)
at org.codehaus.janino.Java$NormalAnnotation.setEnclosingScope(Java.java:389)
at org.codehaus.janino.Java$NormalAnnotation.setEnclosingScope(Java.java:389)
at org.codehaus.janino.Java$NormalAnnotation.setEnclosingScope(Java.java:389)
at org.codehaus.janino.Java$NormalAnnotation.setEnclosingScope(Java.java:389)

looking at the code, it looks like a infinite loop:

    @Override public void
    setEnclosingScope(Scope enclosingScope) { this.setEnclosingScope(enclosingScope); }

Findbugs would complain about it....

I am using janino 2.7.8

Uninitialized Variables

First and foremost, Janino is really cool. I'm using it for in-class in-browser examples for an intro programming class and it's a lot of fun.

That said, the following doesn't seem to work properly:

int i;
System.out.println(i);

I suppose it is up to the compiler to initialize uninitialized values appropriately, and apparently Janino decides to fail rather than follow the common behavior of setting i to zero. But it would be nice if it matched the behavior of more standard (and slower) compilers.

Add more accessors to ClassFile

In order to analyse user generated code, some additional accessors would be helpful.

I would like to check method usage through ConstantMethodrefInfo but the data I need is not publicly exposed:

  • the class name from index ConstantMethodrefInfo#classIndex
  • the method name from ConstantNameAndTypeInfo#nameIndex

Is this deliberate? Would it be possible to add more getters?

Issue compiling annotations

I'm on 3.0.8. Compiling a small JPA class file with three annotations fails:

	@Id
	@GeneratedValue(strategy=IDENTITY)
	@Column(nullable=false)
	private java.lang.Integer id;

If I remove the @GeneratedValue annotation, everything works fine.

The input code compiles with JDK7-8.

Error:

Exception in thread "main" java.lang.StackOverflowError
	at org.codehaus.janino.UnitCompiler.reclassifyName(UnitCompiler.java:8222)
	at org.codehaus.janino.UnitCompiler.reclassifyName(UnitCompiler.java:8119)
	at org.codehaus.janino.UnitCompiler.reclassify(UnitCompiler.java:7986)
	at org.codehaus.janino.UnitCompiler.access$1000(UnitCompiler.java:212)
	at org.codehaus.janino.UnitCompiler$22$2.visitRvalue(UnitCompiler.java:8058)
	at org.codehaus.janino.Java$Rvalue.accept(Java.java:3855)
	at org.codehaus.janino.UnitCompiler$22.toObject(UnitCompiler.java:8051)
	at org.codehaus.janino.UnitCompiler$22.toIAnnotation(UnitCompiler.java:8027)
	at org.codehaus.janino.UnitCompiler$22.visitNormalAnnotation(UnitCompiler.java:8019)
	at org.codehaus.janino.UnitCompiler$22.visitNormalAnnotation(UnitCompiler.java:8002)
	at org.codehaus.janino.Java$NormalAnnotation.accept(Java.java:477)
	at org.codehaus.janino.UnitCompiler.toIAnnotation(UnitCompiler.java:8001)
	at org.codehaus.janino.UnitCompiler.toIAnnotations(UnitCompiler.java:7993)
	at org.codehaus.janino.UnitCompiler.compileField(UnitCompiler.java:7895)
	at org.codehaus.janino.UnitCompiler.compileFields(UnitCompiler.java:7860)
	at org.codehaus.janino.UnitCompiler.access$17600(UnitCompiler.java:212)
	at org.codehaus.janino.UnitCompiler$30.getDeclaredIFields2(UnitCompiler.java:9532)
	at org.codehaus.janino.IClass.getDeclaredIFieldsCache(IClass.java:345)
	at org.codehaus.janino.IClass.getDeclaredIField(IClass.java:358)
	at org.codehaus.janino.UnitCompiler.findIField(UnitCompiler.java:11725)
	at org.codehaus.janino.UnitCompiler.reclassifyName(UnitCompiler.java:8321)
	at org.codehaus.janino.UnitCompiler.reclassifyName(UnitCompiler.java:8119)
	at org.codehaus.janino.UnitCompiler.reclassify(UnitCompiler.java:7986)
	at org.codehaus.janino.UnitCompiler.access$1000(UnitCompiler.java:212)
	at org.codehaus.janino.UnitCompiler$22$2.visitRvalue(UnitCompiler.java:8058)
	at org.codehaus.janino.Java$Rvalue.accept(Java.java:3855)
	at org.codehaus.janino.UnitCompiler$22.toObject(UnitCompiler.java:8051)
	at org.codehaus.janino.UnitCompiler$22.toIAnnotation(UnitCompiler.java:8027)
	at org.codehaus.janino.UnitCompiler$22.visitNormalAnnotation(UnitCompiler.java:8019)
	at org.codehaus.janino.UnitCompiler$22.visitNormalAnnotation(UnitCompiler.java:8002)
	at org.codehaus.janino.Java$NormalAnnotation.accept(Java.java:477)
 . . .

Another question: Are there any build instructions for Janino and the commons-compiler jars?

Invalid integer literal "9223372036854775808L"

Janino trips over when compiling a negation on minimal values of int and long. e.g. for the following code snippet:

long value = -(-9223372036854775808L);

Janino would throw an exception saying Invalid integer literal "9223372036854775808L", while javac compiles it fine.

Need solution for running in Google App Engine

This code causes an error in Janino v3.0.6 when running on Google AppEngine (although not in their development server):

import java.util.Scanner;
public class T1
{
    public static void main(String[] args)
    {
        Scanner scnr = new Scanner(System.in);
    }
}

The error is this:

Compiling "T1": "findIClass()" returned "Lcom/google/apphosting/runtime/security/shared/stub/java/nio/file/Path;" instead of "Ljava/nio/file/Path;"

The source seems to be this code in org.codehaus.janino.IClassLoader (lines 305-313):

        if (!result.getDescriptor().equalsIgnoreCase(fieldDescriptor)) {
            throw new JaninoRuntimeException(
                "\"findIClass()\" returned \""
                + result.getDescriptor()
                + "\" instead of \""
                + fieldDescriptor
                + "\""
            );
        }

Would it be possible to have some kind of compile-time or run-time switch that would go around this code when compiling for, or running in, Google App Engine?

Thanks,

Jon

Assertion error for public static final field declaration

Here is the scope:
(org.codehaus.janino.Java$FieldDeclaration) public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{"type":"enum","name":"requiredEnum","namespace":"test","symbols":["a","b"]}");

I am not sure what Janino does not like here...

Spurious problems when running in a multi-threaded environment

This problem was originally reported by Matthias Boehm from IBM:

We recently ran into race conditions of multi-threaded
compilation and loading of classes with the same class name. We fixed it
by simply synchronizing the code path for code generation in Spark
executors. However, it might be an indicator of unwanted side effects
because the APIs of isolated SimpleCompilerinstances would suggest
thread-safeness. The intermittent failures we got were puzzling as the
related code works just fine:

  • Operand stack underrun at offset 91
  • No applicable constructor/method found for actual parameters
  • Binary numeric promotion not possible on types "java.lang.Object" and
    "double"

Integer overflow in ClassFile reader

There's a pattern of integer overflow issues in the ClassFile read path.

e.g. https://github.com/janino-compiler/janino/blob/master/janino/src/main/java/org/codehaus/janino/util/ClassFile.java#L708

    /**
     * u2 attributes_count, attributes[attributes_count]
     */
    private List<AttributeInfo>
    loadAttributes(DataInputStream dis) throws IOException {
        short               attributesCount = dis.readShort();
        List<AttributeInfo> attributes      = new ArrayList<AttributeInfo>(attributesCount);
        for (int i = 0; i < attributesCount; ++i) attributes.add(this.loadAttribute(dis));
        return attributes;
    }

The Class file format says the attribute_count is a u2, but it's read here with dis.readShort() so that's reading as a signed short.

In some Class files that Spark generates, various sizes/counts can be really big, above the signed ranges of the corresponding integer types, so when Janino reads in such files, they're subject to weird exceptions like:

java.io.EOFException
        at java.io.DataInputStream.readFully(DataInputStream.java:197)
        at java.io.DataInputStream.readFully(DataInputStream.java:169)
        at org.codehaus.janino.util.ClassFile.loadAttribute(ClassFile.java:1808)
        at org.codehaus.janino.util.ClassFile.loadAttributes(ClassFile.java:698)
        at org.codehaus.janino.util.ClassFile.loadFields(ClassFile.java:673)
        at org.codehaus.janino.util.ClassFile.<init>(ClassFile.java:299)
        at org.apache.spark.sql.catalyst.expressions.codegen.CodeGenerator$$anonfun$29.apply(CodeGenerator.scala:1674)
        ... 

In one such cases, the constant pool had a lot of entries:

...
  #49449 = Utf8               <init> 
  #49450 = Utf8               (Lorg/apache/spark/sql/catalyst/expressions/GeneratedClass$SpecificMutableProjection;)V
  #49451 = Utf8               ()V    
  #49452 = NameAndType        #49449:#49451 // "<init>":()V
  #49453 = Methodref          #4.#49452   // java/lang/Object."<init>":()V
{

(short)49453 interpreted as a signed short is -16083, which probably overflows the following code:
https://github.com/janino-compiler/janino/blob/master/janino/src/main/java/org/codehaus/janino/util/ClassFile.java#L664

short constantPoolCount = dis.readShort(); // constant_pool_count

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.