org.prebake.service.LogRecordWriter.java Source code

Java tutorial

Introduction

Here is the source code for org.prebake.service.LogRecordWriter.java

Source

// Copyright 2010, Mike Samuel
//
// 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.prebake.service;

import java.io.Closeable;
import java.io.Flushable;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.logging.LogRecord;

import javax.annotation.Nullable;

import com.google.common.io.Closeables;
import com.google.common.io.Flushables;

import org.prebake.js.Executor;

/**
 * Responsible for formatting log messages.
 *
 * @author Mike Samuel <mikesamuel@gmail.com>
 */
final class LogRecordWriter implements Closeable, Flushable {
    final Appendable out;

    LogRecordWriter(Appendable out) {
        this.out = out;
    }

    public void close() {
        if (out instanceof Closeable) {
            Closeables.closeQuietly((Closeable) out);
        }
    }

    public void flush() {
        if (out instanceof Flushable) {
            Flushables.flushQuietly((Flushable) out);
        }
    }

    public void writeRecord(LogRecord r) {
        try {
            out.append(r.getLevel().getName()).append(':')
                    .append(MessageFormat.format(r.getMessage(), r.getParameters())).append('\n');
            publishThrowable(r.getThrown(), EMPTY_STACK);
        } catch (IOException ex) {
            // Ignore.  We can't recover but shouldn't interrupt existing operations.
            ex.printStackTrace();
        }
    }

    private static final StackTraceElement[] EMPTY_STACK = new StackTraceElement[0];

    private void publishThrowable(@Nullable Throwable th, StackTraceElement[] output) throws IOException {
        if (th == null) {
            return;
        }
        String s = th.toString();
        publishLine(s, 2);
        if (th instanceof Executor.AbnormalExitException) {
            String jsStack = ((Executor.AbnormalExitException) th).getScriptTrace();
            if (jsStack.length() != 0) {
                for (String jsStackLine : jsStack.split("[\r\n]+")) {
                    if (jsStackLine.startsWith("\tat ")) {
                        jsStackLine = jsStackLine.substring(4);
                    }
                    publishLine(jsStackLine, 4);
                }
            }
        } else {
            StackTraceElement[] els = th.getStackTrace();
            int nToSkip = 0;
            for (int i = els.length, j = output.length; --i >= 0 && --j >= 0; ++nToSkip) {
                if (!els[i].equals(output[j])) {
                    break;
                }
            }
            int n = els.length - nToSkip;
            for (int i = 0; i < n; ++i) {
                StackTraceElement el = els[i];
                if (showStack(el)) {
                    publishLine(el.toString(), 4);
                    while (++i < n) {
                        publishLine(els[i].toString(), 4);
                    }
                    break;
                }
            }
            if (nToSkip != 0) {
                publishLine("... " + nToSkip + " more", 4);
            }
            publishThrowable(th.getCause(), els);
        }
    }

    private void publishLine(String s, int indent) throws IOException {
        int pos = 0, n = s.length();
        for (int i = 0; i < n; ++i) {
            char ch = s.charAt(i);
            if (ch == '\r' || ch == '\n') {
                String chunk = s.substring(pos, i);
                publishChunk(chunk, indent);
                pos = i + 1;
            }
        }
        publishChunk(s.substring(pos, n), indent);
    }

    private void publishChunk(String oneLine, int indent) throws IOException {
        int pos = 0, n = oneLine.length();
        int lineLen = 80 - indent;
        while (pos + lineLen < n) {
            String line = oneLine.substring(pos, pos += lineLen - 2);
            indent(indent);
            out.append(line).append(" \\\n");
        }
        indent(indent);
        out.append(oneLine.substring(pos)).append('\n');
    }

    private static final String SIXTEEN_SPACES = "                ";
    static {
        assert SIXTEEN_SPACES.length() == 16;
    }

    private void indent(int indent) throws IOException {
        while (indent > 16) {
            out.append(SIXTEEN_SPACES);
            indent -= 16;
        }
        out.append(SIXTEEN_SPACES, 0, indent);
    }

    private static boolean showStack(StackTraceElement el) {
        String cn = el.getClassName();
        return !("org.mozilla.javascript.Parser".equals(cn)
                || "org.mozilla.javascript.DefaultErrorReporter".equals(cn));
    }
}