From 6e4e66c759e2a2329ab698a02863d060c83f838b Mon Sep 17 00:00:00 2001 From: konsoletyper Date: Sun, 23 Feb 2014 19:39:25 +0400 Subject: [PATCH] Adds partial implementation of JCL logger framework --- .../org/teavm/classlib/java/lang/TThread.java | 4 + .../util/logging/LoggerNativeGenerator.java | 36 ++++ .../classlib/java/util/logging/TLevel.java | 59 ++++++ .../java/util/logging/TLogRecord.java | 125 ++++++++++++ .../classlib/java/util/logging/TLogger.java | 181 ++++++++++++++++++ 5 files changed, 405 insertions(+) create mode 100644 teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/LoggerNativeGenerator.java create mode 100644 teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/TLevel.java create mode 100644 teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/TLogRecord.java create mode 100644 teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/TLogger.java diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThread.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThread.java index b3ff73690..165d25c75 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThread.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThread.java @@ -73,4 +73,8 @@ public class TThread extends TObject implements TRunnable { public static int activeCount() { return 1; } + + public long getId() { + return 1; + } } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/LoggerNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/LoggerNativeGenerator.java new file mode 100644 index 000000000..177cc9b24 --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/LoggerNativeGenerator.java @@ -0,0 +1,36 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.logging; + +import java.io.IOException; +import org.teavm.codegen.SourceWriter; +import org.teavm.javascript.ni.Generator; +import org.teavm.javascript.ni.GeneratorContext; +import org.teavm.model.MethodReference; + +/** + * + * @author Alexey Andreev + */ +public class LoggerNativeGenerator implements Generator { + @Override + public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { + writer.append("if (console) {").indent().softNewLine(); + writer.append("console.").append(methodRef.getName()).append("(").append(context.getParameterName(1)) + .append(");").softNewLine(); + writer.outdent().append("}").softNewLine(); + } +} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/TLevel.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/TLevel.java new file mode 100644 index 000000000..31bbfd34e --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/TLevel.java @@ -0,0 +1,59 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.logging; + +import org.teavm.classlib.java.io.TSerializable; +import org.teavm.classlib.java.lang.TInteger; +import org.teavm.classlib.java.lang.TObject; +import org.teavm.classlib.java.lang.TString; +import org.teavm.javascript.ni.Rename; + +/** + * + * @author Alexey Andreev + */ +public class TLevel extends TObject implements TSerializable { + public static final TLevel OFF = new TLevel(TString.wrap("OFF"), TInteger.MAX_VALUE); + public static final TLevel SEVERE = new TLevel(TString.wrap("SEVERE"), 1000); + public static final TLevel WARNING = new TLevel(TString.wrap("WARNING"), 900); + public static final TLevel INFO = new TLevel(TString.wrap("INFO"), 800); + public static final TLevel CONFIG = new TLevel(TString.wrap("CONFIG"), 700); + public static final TLevel FINE = new TLevel(TString.wrap("FINE"), 500); + public static final TLevel FINER = new TLevel(TString.wrap("FINER"), 400); + public static final TLevel FINEST = new TLevel(TString.wrap("FINEST"), 300); + public static final TLevel ALL = new TLevel(TString.wrap("FINEST"), TInteger.MIN_VALUE); + private TString name; + private int value; + + protected TLevel(TString name, int value) { + this.name = name; + this.value = value; + } + + public TString getName() { + return name; + } + + @Override + @Rename("toString") + public final TString toString0() { + return name; + } + + public final int intValue() { + return value; + } +} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/TLogRecord.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/TLogRecord.java new file mode 100644 index 000000000..6563b0053 --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/TLogRecord.java @@ -0,0 +1,125 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.logging; + +import org.teavm.classlib.java.io.TSerializable; +import org.teavm.classlib.java.lang.*; + +/** + * + * @author Alexey Andreev + */ +public class TLogRecord extends TObject implements TSerializable { + private static long sequenceNumberGenerator; + private TLevel level; + private TString loggerName; + private TString message; + private long millis; + private Object[] parameters; + private long sequenceNumber; + private TString sourceClassName; + private TString sourceMethodName; + private long threadID; + private TThrowable thrown; + + public TLogRecord(TLevel level, TString msg) { + this.level = level; + this.message = msg; + this.millis = TSystem.currentTimeMillis(); + this.sequenceNumber = sequenceNumberGenerator++; + this.threadID = TThread.currentThread().getId(); + } + + public TLevel getLevel() { + return level; + } + + public void setLevel(TLevel level) { + this.level = level; + } + + public TString getLoggerName() { + return loggerName; + } + + public void setLoggerName(TString loggerName) { + this.loggerName = loggerName; + } + + public TString getMessage() { + return message; + } + + public void setMessage(TString message) { + this.message = message; + } + + public long getMillis() { + return millis; + } + + public void setMillis(long millis) { + this.millis = millis; + } + + public Object[] getParameters() { + return parameters; + } + + public void setParameters(Object[] parameters) { + this.parameters = parameters; + } + + public long getSequenceNumber() { + return sequenceNumber; + } + + public void setSequenceNumber(long sequenceNumber) { + this.sequenceNumber = sequenceNumber; + } + + public TString getSourceClassName() { + return sourceClassName; + } + + public void setSourceClassName(TString sourceClassName) { + this.sourceClassName = sourceClassName; + } + + public TString getSourceMethodName() { + return sourceMethodName; + } + + public void setSourceMethodName(TString sourceMethodName) { + this.sourceMethodName = sourceMethodName; + } + + public long getThreadID() { + return threadID; + } + + public void setThreadID(long threadID) { + this.threadID = threadID; + } + + public TThrowable getThrown() { + return thrown; + } + + public void setThrown(TThrowable thrown) { + this.thrown = thrown; + } +} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/TLogger.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/TLogger.java new file mode 100644 index 000000000..60cd62901 --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/TLogger.java @@ -0,0 +1,181 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.logging; + +import org.teavm.classlib.java.lang.*; +import org.teavm.classlib.java.util.THashMap; +import org.teavm.classlib.java.util.TMap; +import org.teavm.javascript.ni.GeneratedBy; + +/** + * + * @author Alexey Andreev + */ +public class TLogger { + public static final TString GLOBAL_LOGGER_NAME = TString.wrap("global"); + private static TMap loggerCache = new THashMap<>(); + private TString name; + private TLogger parent; + + TLogger(TString name) { + this.name = name; + } + + public static TLogger getLogger(TString name) { + TLogger logger = loggerCache.get(name); + if (logger == null) { + logger = new TLogger(name); + int dotIndex = name.lastIndexOf('.'); + if (dotIndex >= 0) { + TString parentName = name.substring(0, dotIndex); + logger.parent = getLogger(parentName); + } else if (!name.isEmpty()) { + logger.parent = getLogger(TString.wrap("")); + } + loggerCache.put(name, logger); + } + return logger; + } + + public static TLogger getAnonymousLogger() { + return new TLogger(null); + } + + public void log(TLogRecord record) { + TString message = format(record.getMessage(), record.getParameters()); + if (record.getLevel().intValue() >= TLevel.SEVERE.intValue()) { + error(message); + } else if (record.getLevel().intValue() >= TLevel.WARNING.intValue()) { + warn(message); + } else { + info(message); + } + } + + private TString format(TString message, Object[] params) { + if (params == null) { + return message; + } + TStringBuilder sb = new TStringBuilder(); + int index = 0; + while (index < message.length()) { + int next = message.indexOf('{', index); + if (next < 0) { + break; + } + int paramStart = next + 1; + next = digits(paramStart, message); + if (next < 0) { + break; + } + if (message.charAt(next) != '}') { + sb.append(message.substring(index, next)); + index = next; + continue; + } + int paramIndex = TInteger.parseInt(message.substring(index, next - 1)); + if (paramIndex >= params.length) { + sb.append(message.substring(index, next)); + index = next; + continue; + } + sb.append(TObject.wrap(params[paramIndex])); + index = next + 1; + } + return TString.wrap(sb.toString()); + } + + private static int digits(int from, TString message) { + while (from < message.length()) { + int c = message.charAt(from++); + if (c <= '0' || c >= '9') { + return from; + } + } + return -1; + } + + public void log(TLevel level, TString msg, Object[] params) { + TLogRecord record = new TLogRecord(level, msg); + record.setParameters(params); + log(record); + } + + public void log(TLevel level, TString msg) { + log(new TLogRecord(level, msg)); + } + + public void log(TLevel level, TString msg, TObject param1) { + TLogRecord record = new TLogRecord(level, msg); + record.setParameters(new Object[] { param1 }); + log(record); + } + + public void log(TLevel level, TString msg, TThrowable thrown) { + TLogRecord record = new TLogRecord(level, msg); + record.setThrown(thrown); + log(record); + } + + public void severe(TString msg) { + log(TLevel.SEVERE, msg); + } + + public void warning(TString msg) { + log(TLevel.WARNING, msg); + } + + public void config(TString msg) { + log(TLevel.CONFIG, msg); + } + + public void fine(TString msg) { + log(TLevel.FINE, msg); + } + + public void finer(TString msg) { + log(TLevel.FINER, msg); + } + + public void finest(TString msg) { + log(TLevel.FINEST, msg); + } + + public boolean isLoggable(@SuppressWarnings("unused") TLevel level) { + return true; + } + + public TString getName() { + return name; + } + + public TLogger getParent() { + return parent; + } + + public void setParent(TLogger parent) { + this.parent = parent; + } + + @GeneratedBy(LoggerNativeGenerator.class) + public native void info(TString message); + + @GeneratedBy(LoggerNativeGenerator.class) + private native void warn(TString message); + + @GeneratedBy(LoggerNativeGenerator.class) + private native void error(TString message); +}