]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/LoggingModule.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / java / LoggingModule.java
1 package org.simantics.scl.compiler.elaboration.java;
2
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;
25
26 public class LoggingModule extends ConcreteModule {
27
28     private static final String[] LOGGING_METHODS = new String[] {
29             "trace", "debug", "info", "warn", "error" 
30     };
31     
32     public static final TCon Throwable = Types.con("Prelude", "Throwable");
33
34     public LoggingModule() {
35         super("LoggingJava");
36         
37         // Logger
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);
42
43         // Marker
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);
48         
49         // Common types
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);
55
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() {
64                     @Override
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)
69                         });
70                         return apply;
71                     }
72                 });
73                 addValue(value);
74             }
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() {
80                     @Override
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),
85                                 apply.parameters[0]
86                         });
87                         return apply;
88                     }
89                 });
90                 addValue(value);
91             }
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() {
97                     @Override
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),
102                                 apply.parameters[0],
103                                 apply.parameters[1]
104                         });
105                         return apply;
106                     }
107                 });
108                 addValue(value);
109             }
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() {
115                     @Override
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),
120                                 apply.parameters[0],
121                                 apply.parameters[1]
122                         });
123                         return apply;
124                     }
125                 });
126                 addValue(value);
127             }
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() {
133                     @Override
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),
138                                 apply.parameters[0],
139                                 apply.parameters[1],
140                                 apply.parameters[2]
141                         });
142                         return apply;
143                     }
144                 });
145                 addValue(value);
146             }
147         }
148         
149         setParentClassLoader(LoggerFactory.class.getClassLoader());
150     }
151
152     private static String generateIsEnabledName(String level) {
153         return "is" + capitalizeFirstCharacter(level) + "Enabled";
154     }
155     
156     private static String capitalizeFirstCharacter(String input) {
157         return input.substring(0, 1).toUpperCase() + input.substring(1);
158     }
159     
160     private static String resolveModuleIdentifier(CompilationContext context) {
161         ConcreteModule module = context.module;
162         String identifier;
163         if (module != null) {
164             String moduleName = module.getName();
165             if (moduleName.startsWith("http://")) {
166                 moduleName = moduleName.substring("http://".length());
167             }
168             identifier = moduleName.replaceAll("/", ".");
169         } else {
170             identifier = CommandSession.class.getName();
171         }
172         return identifier;
173     }
174 }