/** * 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.drill.exec.compile; import java.io.IOException; import java.io.Writer; import com.google.common.base.Preconditions; import org.apache.log4j.Level; import org.slf4j.Logger; /** * A simple Writer that will forward whole lines (lines ending with a newline) to * a Logger. The newlines themselves are not forwarded. */ public class LogWriter extends Writer { private final Logger logger; // the underlying logger to write to private final int level; // the debug level to write at private final StringBuilder stringBuilder; // a buffer for incomplete lines private boolean isClosed; // close() has been called /** * Constructor. * * @param logger the logger this Writer should write to * @param level the debug level to write to the logger with */ public LogWriter(final Logger logger, final Level level) { Preconditions.checkNotNull(logger); Preconditions.checkArgument((level == Level.DEBUG) || (level == Level.ERROR) || (level == Level.INFO) || (level == Level.TRACE) || (level == Level.WARN), "level must be a logging level"); this.logger = logger; this.level = level.toInt(); stringBuilder = new StringBuilder(80); isClosed = false; } @Override public void write(char[] cbuf, int off, int len) throws IOException { checkNotClosed(); stringBuilder.append(cbuf, off, len); // log all of the whole lines we have do { final int newlinePos = stringBuilder.indexOf("\n"); if (newlinePos < 0) { break; } final String oneLine = stringBuilder.substring(0, newlinePos); // leaves out the newline writeToLog(oneLine); stringBuilder.delete(0, newlinePos + 1); // removes the newline as well } while (stringBuilder.length() > 0); } @Override public void flush() throws IOException { checkNotClosed(); flushToLog(); } @Override public void close() throws IOException { checkNotClosed(); isClosed = true; flushToLog(); } /* * Assumes there are no newlines. */ private void flushToLog() { writeToLog(stringBuilder.toString()); stringBuilder.setLength(0); } private void writeToLog(final String s) { if ((s == null) || s.isEmpty()) { return; } switch(level) { case Level.DEBUG_INT: logger.debug(s); break; case Level.ERROR_INT: logger.error(s); break; case Level.INFO_INT: logger.info(s); break; case Level.TRACE_INT: logger.trace(s); break; case Level.WARN_INT: logger.warn(s); break; default: throw new IllegalStateException(); } } private void checkNotClosed() throws IOException { if (isClosed) { throw new IOException("LogWriter is already closed()"); } } }