You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pivot.apache.org by rw...@apache.org on 2018/06/04 15:41:02 UTC
svn commit: r1832859 - in /pivot/trunk:
core/src/org/apache/pivot/util/Console.java
tests/src/org/apache/pivot/tests/TextAreaConsoleTest.java
tests/src/org/apache/pivot/tests/console_test.bxml
wtk/src/org/apache/pivot/wtk/util/TextAreaOutputStream.java
Author: rwhitcomb
Date: Mon Jun 4 15:41:02 2018
New Revision: 1832859
URL: http://svn.apache.org/viewvc?rev=1832859&view=rev
Log:
Improvements to "Console" debugging package:
* Allow override of output streams (defaults to System.out and .err).
* Make Console into a non-static class, but with a default that always
logs to the system console.
* Make a TextAreaOutputStream that can make itself into a PrintStream
for use with Console.
* Make a test program (TextAreaConsoleTest) that uses a small text area
to demonstrate logging using the Console class inside a window.
Added:
pivot/trunk/tests/src/org/apache/pivot/tests/TextAreaConsoleTest.java
pivot/trunk/tests/src/org/apache/pivot/tests/console_test.bxml
pivot/trunk/wtk/src/org/apache/pivot/wtk/util/TextAreaOutputStream.java
Modified:
pivot/trunk/core/src/org/apache/pivot/util/Console.java
Modified: pivot/trunk/core/src/org/apache/pivot/util/Console.java
URL: http://svn.apache.org/viewvc/pivot/trunk/core/src/org/apache/pivot/util/Console.java?rev=1832859&r1=1832858&r2=1832859&view=diff
==============================================================================
--- pivot/trunk/core/src/org/apache/pivot/util/Console.java (original)
+++ pivot/trunk/core/src/org/apache/pivot/util/Console.java Mon Jun 4 15:41:02 2018
@@ -16,34 +16,123 @@
*/
package org.apache.pivot.util;
+import java.io.FileNotFoundException;
+import java.io.PrintStream;
+import java.net.UnknownHostException;
+import java.nio.charset.CharacterCodingException;
+import java.nio.file.NoSuchFileException;
+
/**
* Utility class for a simple log to the console, for example from scripts.
*/
public final class Console {
- private Console() {
+ /** Used to output a null message value, so user knows a null "something" was logged. */
+ private static final String NULL = "<null>";
+
+ /** For static logging, the singleton instance pointing to the system console to use. */
+ private static final Console CONSOLE = new Console();
+
+ /** The print stream to use for "output" logging. Defaults to {@link System#out}. */
+ private PrintStream out = System.out;
+ /** The print stream to use for "error" logging. Defaults to {@link System#err}. */
+ private PrintStream err = System.err;
+
+
+ public Console() {
+ }
+
+ public Console(final PrintStream stream) {
+ setStreams(stream);
+ }
+
+ public Console(final PrintStream output, final PrintStream error) {
+ setOutputStream(output);
+ setErrorStream(error);
+ }
+
+ public static Console getDefault() {
+ return CONSOLE;
+ }
+
+ private void checkNotDefault() {
+ if (this == CONSOLE) {
+ throw new IllegalStateException("Cannot modify default Console object.");
+ }
+ }
+
+ public void setStreams(final PrintStream stream) {
+ checkNotDefault();
+ out = err = stream;
+ }
+
+ public void setOutputStream(final PrintStream output) {
+ checkNotDefault();
+ out = output;
+ }
+
+ public void setErrorStream(final PrintStream error) {
+ checkNotDefault();
+ err = error;
}
- public static final void log(String message) {
+ /**
+ * Log the given message to the "output" stream.
+ *
+ * @param message The message to log.
+ * @see #logOutput
+ */
+ public void log(final String message) {
logOutput(message);
}
- public static final void log(Throwable t) {
+ /**
+ * Log the given exception (basically print the stack trace) to the "error" stream.
+ *
+ * @param t The exception to log.
+ */
+ public void log(final Throwable t) {
if (t != null) {
- t.printStackTrace();
+ t.printStackTrace(err);
}
}
- public static final void logExceptionMessage(Throwable t) {
- logOutput(t.getMessage());
+ /**
+ * Get a user-friendly message from the given exception.
+ *
+ * @param t The throwable (exception) in question.
+ * @return Start with the localized exception message, but use the
+ * simple name of the exception if there is no message, or if the
+ * exception is one of a short list of "funny" exceptions where the
+ * message by itself is ambiguous, prepend the simple name of the
+ * exception to the message.
+ */
+ public static String getExceptionMessage(final Throwable t) {
+ String msg = t.getLocalizedMessage();
+ if (msg == null || msg.isEmpty()) {
+ msg = t.getClass().getSimpleName();
+ } else if ((t instanceof UnknownHostException)
+ || (t instanceof NoClassDefFoundError)
+ || (t instanceof ClassNotFoundException)
+ || (t instanceof NullPointerException)
+ || (t instanceof CharacterCodingException)
+ || (t instanceof FileNotFoundException)
+ || (t instanceof NoSuchFileException)) {
+ msg = String.format("%1$s: %2$s", t.getClass().getSimpleName(), msg);
+ }
+ return msg;
}
- public static final void logOutput(String message) {
- System.out.println(message != null ? message : "");
+ public void logExceptionMessage(final Throwable t) {
+ logOutput(getExceptionMessage(t));
}
- public static final void logError(String message) {
- System.err.println(message != null ? message : "");
+ public void logOutput(final String message) {
+ out.println(message == null ? NULL : message);
+ }
+
+ public void logError(final String message) {
+ err.println(message == null ? NULL : message);
}
/**
@@ -53,9 +142,12 @@ public final class Console {
* or a format string using the remaining args (can be {@code null}).
* @param args The optional arguments used to format the final message.
*/
- public static final void logMethod(String message, Object... args) {
- logOutput(ClassUtils.getCallingMethod(1) + ": " +
- (message == null ? "" : String.format(message, args)));
+ public void logMethod(final String message, final Object... args) {
+ logOutput(
+ ClassUtils.getCallingMethod(1)
+ + ": "
+ + (message == null ? NULL : String.format(message, args))
+ );
}
/**
@@ -67,12 +159,12 @@ public final class Console {
* or a format string using the remaining args (can be {@code null}).
* @param args The optional arguments used to format the final message.
*/
- public static final void logMethod(String prefix, String message, Object... args) {
+ public void logMethod(final String prefix, final String message, final Object... args) {
logOutput(
- (prefix == null ? "" : prefix + " ") +
- ClassUtils.getCallingMethod(1) +
- ": " +
- (message == null ? "" : String.format(message, args))
+ (prefix == null ? "" : prefix + " ")
+ + ClassUtils.getCallingMethod(1)
+ + ": "
+ + (message == null ? NULL : String.format(message, args))
);
}
Added: pivot/trunk/tests/src/org/apache/pivot/tests/TextAreaConsoleTest.java
URL: http://svn.apache.org/viewvc/pivot/trunk/tests/src/org/apache/pivot/tests/TextAreaConsoleTest.java?rev=1832859&view=auto
==============================================================================
--- pivot/trunk/tests/src/org/apache/pivot/tests/TextAreaConsoleTest.java (added)
+++ pivot/trunk/tests/src/org/apache/pivot/tests/TextAreaConsoleTest.java Mon Jun 4 15:41:02 2018
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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.apache.pivot.tests;
+
+import java.io.IOException;
+import org.apache.pivot.beans.BXML;
+import org.apache.pivot.beans.BXMLSerializer;
+import org.apache.pivot.collections.Map;
+import org.apache.pivot.util.Console;
+import org.apache.pivot.serialization.SerializationException;
+import org.apache.pivot.wtk.Application;
+import org.apache.pivot.wtk.DesktopApplicationContext;
+import org.apache.pivot.wtk.Display;
+import org.apache.pivot.wtk.PushButton;
+import org.apache.pivot.wtk.TextArea;
+import org.apache.pivot.wtk.Window;
+import org.apache.pivot.wtk.util.TextAreaOutputStream;
+
+
+public class TextAreaConsoleTest implements Application {
+ @BXML private Window window;
+ @BXML private PushButton logMessageButton;
+ @BXML private TextArea consoleArea;
+ private Console console;
+ private int line = 1;
+
+ @Override
+ public void startup(Display display, Map<String, String> properties) {
+ BXMLSerializer serializer = new BXMLSerializer();
+ try {
+ serializer.readObject(TextAreaConsoleTest.class, "console_test.bxml");
+ serializer.bind(this);
+ } catch (IOException | SerializationException ex) {
+ throw new RuntimeException(ex);
+ }
+ console = new Console(new TextAreaOutputStream(consoleArea).toPrintStream());
+ logMessageButton.getButtonPressListeners().add((button) -> console.log(String.format("%1$d. Hello, World!", line++)));
+ window.open(display);
+ }
+
+ @Override
+ public boolean shutdown(boolean optional) {
+ if (window != null) {
+ window.close();
+ }
+ return false;
+ }
+
+ public static void main(String[] args) {
+ DesktopApplicationContext.main(TextAreaConsoleTest.class, args);
+ }
+}
Added: pivot/trunk/tests/src/org/apache/pivot/tests/console_test.bxml
URL: http://svn.apache.org/viewvc/pivot/trunk/tests/src/org/apache/pivot/tests/console_test.bxml?rev=1832859&view=auto
==============================================================================
--- pivot/trunk/tests/src/org/apache/pivot/tests/console_test.bxml (added)
+++ pivot/trunk/tests/src/org/apache/pivot/tests/console_test.bxml Mon Jun 4 15:41:02 2018
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to you 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.
+-->
+
+<Window bxml:id="window" title="Console Text Area Test" maximized="true"
+ xmlns:bxml="http://pivot.apache.org/bxml"
+ xmlns:collections="org.apache.pivot.collections"
+ xmlns:content="org.apache.pivot.wtk.content"
+ xmlns="org.apache.pivot.wtk">
+ <TablePane>
+ <columns>
+ <TablePane.Column width="1*"/>
+ </columns>
+ <rows>
+ <TablePane.Row height="3*">
+ <FlowPane>
+ <PushButton bxml:id="logMessageButton" buttonData="Log Message"/>
+ </FlowPane>
+ </TablePane.Row>
+ <TablePane.Row height="1*">
+ <Border title="Console">
+ <ScrollPane>
+ <TextArea bxml:id="consoleArea" editable="false"/>
+ </ScrollPane>
+ </Border>
+ </TablePane.Row>
+ </rows>
+ </TablePane>
+</Window>
Added: pivot/trunk/wtk/src/org/apache/pivot/wtk/util/TextAreaOutputStream.java
URL: http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/util/TextAreaOutputStream.java?rev=1832859&view=auto
==============================================================================
--- pivot/trunk/wtk/src/org/apache/pivot/wtk/util/TextAreaOutputStream.java (added)
+++ pivot/trunk/wtk/src/org/apache/pivot/wtk/util/TextAreaOutputStream.java Mon Jun 4 15:41:02 2018
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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.apache.pivot.wtk.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import org.apache.pivot.wtk.ApplicationContext;
+import org.apache.pivot.wtk.Bounds;
+import org.apache.pivot.wtk.TextArea;
+
+/**
+ * Creates an {@link OutputStream} that outputs to a {@link TextArea}
+ * (in the EDT thread, using callbacks) for display.
+ * <p> Can be used with the {@link org.apache.pivot.util.Console} class for output (using the
+ * {@link #toPrintStream} method).
+ */
+public final class TextAreaOutputStream extends OutputStream {
+ /** The TextArea we are going to stream to. */
+ private TextArea textArea;
+
+ /** The buffered line for this stream. */
+ private ByteArrayOutputStream lineBuffer = new ByteArrayOutputStream(256);
+
+ /**
+ * Only constructor given the {@link TextArea} to stream to.
+ *
+ * @param textAreaToUse The TextArea to use for output.
+ */
+ public TextAreaOutputStream(final TextArea textAreaToUse) {
+ this.textArea = textAreaToUse;
+ }
+
+ /**
+ * @throws IOException if this stream is already closed.
+ */
+ private void checkIfOpen() throws IOException {
+ if (textArea == null || lineBuffer == null) {
+ throw new IOException("TextAreaOutputStream is closed.");
+ }
+ }
+
+ /**
+ * Flush the (byte) line buffer if there is anything cached.
+ * @param addNewLine If there is anything to flush, also add a newline
+ * ('\n') character at the end.
+ */
+ private void flushLineBuffer(final boolean addNewLine) {
+ if (lineBuffer.size() > 0) {
+ byte[] bytes = lineBuffer.toByteArray();
+ // TODO: should we have a charset to use here??
+ String text = new String(bytes);
+ int length = textArea.getCharacterCount();
+ textArea.insertText(text, length);
+ if (addNewLine) {
+ int newLength = length + text.length();
+ textArea.insertText("\n", newLength);
+ }
+ lineBuffer.reset();
+ Bounds beginningOfLineBounds = textArea.getCharacterBounds(length);
+ ApplicationContext.queueCallback(() -> textArea.scrollAreaToVisible(beginningOfLineBounds));
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ flush();
+ this.textArea = null;
+ this.lineBuffer = null;
+ }
+
+ @Override
+ public void flush() throws IOException {
+ checkIfOpen();
+ flushLineBuffer(false);
+ }
+
+ @Override
+ public void write(final int b) throws IOException {
+ if (b == '\n') {
+ flushLineBuffer(true);
+ } else if (b != '\r') {
+ lineBuffer.write(b);
+ }
+ }
+
+ /**
+ * @return A new {@link PrintStream} using this object as the basis.
+ */
+ public PrintStream toPrintStream() {
+ return new PrintStream(this);
+ }
+
+}