1 package org.simantics.scl.compiler.elaboration.java;
3 import org.cojen.classfile.TypeDesc;
4 import org.osgi.service.component.annotations.Component;
5 import org.simantics.scl.compiler.commands.CommandSession;
6 import org.simantics.scl.compiler.common.names.Name;
7 import org.simantics.scl.compiler.compilation.CompilationContext;
8 import org.simantics.scl.compiler.constants.JavaMethod;
9 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
10 import org.simantics.scl.compiler.elaboration.expressions.EApply;
11 import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;
12 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
13 import org.simantics.scl.compiler.elaboration.expressions.Expression;
14 import org.simantics.scl.compiler.elaboration.macros.MacroRule;
15 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
16 import org.simantics.scl.compiler.internal.codegen.types.StandardTypeConstructor;
17 import org.simantics.scl.compiler.module.ConcreteModule;
18 import org.simantics.scl.compiler.types.TCon;
19 import org.simantics.scl.compiler.types.Type;
20 import org.simantics.scl.compiler.types.Types;
21 import org.simantics.scl.compiler.types.kinds.Kinds;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24 import org.slf4j.Marker;
26 public class LoggingModule extends ConcreteModule {
28 private static final String[] LOGGING_METHODS = new String[] {
29 "trace", "debug", "info", "warn", "error"
32 public static final TCon Throwable = Types.con("Prelude", "Throwable");
34 public LoggingModule() {
38 TCon Logger = Types.con(getName(), "Logger");
39 StandardTypeConstructor loggerConstructor = new StandardTypeConstructor(Logger, Kinds.STAR, TypeDesc.forClass(Logger.class));
40 loggerConstructor.external = true;
41 addTypeDescriptor("Logger", loggerConstructor);
44 TCon Marker = Types.con(getName(), "Marker");
45 StandardTypeConstructor markerConstructor = new StandardTypeConstructor(Marker, Kinds.STAR, TypeDesc.forClass(Marker.class));
46 markerConstructor.external = true;
47 addTypeDescriptor("Marker", markerConstructor);
50 Type isEnabledType = Types.functionE(Types.PUNIT, Types.PROC, Types.BOOLEAN);
51 Type loggingType = Types.functionE(Types.STRING, Types.PROC, Types.UNIT);
52 Type loggingTypeWithMarker = Types.functionE(new Type[] { Marker, Types.STRING }, Types.PROC, Types.UNIT);
53 Type loggingTypeWithException = Types.functionE(new Type[] { Types.STRING, Throwable }, Types.PROC, Types.UNIT);
54 Type loggingTypeWithMarkerAndException = Types.functionE(new Type[] { Marker, Types.STRING, Throwable }, Types.PROC, Types.UNIT);
56 // Add logging methods
57 for(String methodName : LOGGING_METHODS) {
58 { // isEnabled :: <Proc> Boolean
59 String completeMethodName = generateIsEnabledName(methodName);
60 JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", completeMethodName, Types.PROC, Types.BOOLEAN, Logger);
61 SCLValue value = new SCLValue(Name.create(getName(), completeMethodName));
62 value.setType(isEnabledType);
63 value.setMacroRule(new MacroRule() {
65 public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
66 String identifier = resolveModuleIdentifier(context.getCompilationContext());
67 apply.set(new ELiteral(javaMethod), new Expression[] {
68 new EExternalConstant(LoggerFactory.getLogger(identifier), Logger)
75 { // logging function with single String-parameter :: String -> <Proc> ()
76 JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", methodName, Types.PROC, Types.UNIT, Logger, Types.STRING);
77 SCLValue value = new SCLValue(Name.create(getName(), methodName));
78 value.setType(loggingType);
79 value.setMacroRule(new MacroRule() {
81 public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
82 String identifier = resolveModuleIdentifier(context.getCompilationContext());
83 apply.set(new ELiteral(javaMethod), new Expression[] {
84 new EExternalConstant(LoggerFactory.getLogger(identifier), Logger),
92 { // logging function with two parameters :: String -> Throwable -> <Proc> ()
93 JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", methodName, Types.PROC, Types.UNIT, Logger, Types.STRING, Throwable);
94 SCLValue value = new SCLValue(Name.create(getName(), methodName + "E"));
95 value.setType(loggingTypeWithException);
96 value.setMacroRule(new MacroRule() {
98 public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
99 String identifier = resolveModuleIdentifier(context.getCompilationContext());
100 apply.set(new ELiteral(javaMethod), new Expression[] {
101 new EExternalConstant(LoggerFactory.getLogger(identifier), Logger),
110 { // logging function with two parameters :: Marker -> String -> <Proc> ()
111 JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", methodName, Types.PROC, Types.UNIT, Logger, Marker, Types.STRING);
112 SCLValue value = new SCLValue(Name.create(getName(), methodName + "M"));
113 value.setType(loggingTypeWithMarker);
114 value.setMacroRule(new MacroRule() {
116 public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
117 String identifier = resolveModuleIdentifier(context.getCompilationContext());
118 apply.set(new ELiteral(javaMethod), new Expression[] {
119 new EExternalConstant(LoggerFactory.getLogger(identifier), Logger),
128 { // logging function with three parameters :: Marker -> String -> Throwable -> <Proc> ()
129 JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", methodName, Types.PROC, Types.UNIT, Logger, Marker, Types.STRING, Throwable);
130 SCLValue value = new SCLValue(Name.create(getName(), methodName + "ME"));
131 value.setType(loggingTypeWithMarkerAndException);
132 value.setMacroRule(new MacroRule() {
134 public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
135 String identifier = resolveModuleIdentifier(context.getCompilationContext());
136 apply.set(new ELiteral(javaMethod), new Expression[] {
137 new EExternalConstant(LoggerFactory.getLogger(identifier), Logger),
149 setParentClassLoader(LoggerFactory.class.getClassLoader());
152 private static String generateIsEnabledName(String level) {
153 return "is" + capitalizeFirstCharacter(level) + "Enabled";
156 private static String capitalizeFirstCharacter(String input) {
157 return input.substring(0, 1).toUpperCase() + input.substring(1);
160 private static String resolveModuleIdentifier(CompilationContext context) {
161 ConcreteModule module = context.module;
163 if (module != null) {
164 String moduleName = module.getName();
165 if (moduleName.startsWith("http://")) {
166 moduleName = moduleName.substring("http://".length());
168 identifier = moduleName.replaceAll("/", ".");
170 identifier = CommandSession.class.getName();