001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.logging.log4j.io;
019
020 import java.nio.CharBuffer;
021
022 import org.apache.logging.log4j.Level;
023 import org.apache.logging.log4j.Marker;
024 import org.apache.logging.log4j.spi.ExtendedLogger;
025
026 /**
027 *
028 * @since 2.1
029 */
030 public class CharStreamLogger {
031 private final ExtendedLogger logger;
032 private final Level level;
033 private final Marker marker;
034 private final StringBuilder msg = new StringBuilder();
035 private boolean closed = false;
036
037 public CharStreamLogger(final ExtendedLogger logger, final Level level, final Marker marker) {
038 this.logger = logger;
039 this.level = level == null ? logger.getLevel() : level;
040 this.marker = marker;
041 }
042
043 public void close(final String fqcn) {
044 synchronized (this.msg) {
045 this.closed = true;
046 logEnd(fqcn);
047 }
048 }
049
050 private void log(final String fqcn) {
051 // convert to string now so async loggers work
052 this.logger.logIfEnabled(fqcn, this.level, this.marker, this.msg.toString());
053 this.msg.setLength(0);
054 }
055
056 private void logEnd(final String fqcn) {
057 if (this.msg.length() > 0) {
058 log(fqcn);
059 }
060 }
061
062 public void put(final String fqcn, final char[] cbuf, final int off, final int len) {
063 put(fqcn, CharBuffer.wrap(cbuf), off, len);
064 }
065
066 public void put(final String fqcn, final CharSequence str, final int off, final int len) {
067 if (len >= 0) {
068 synchronized (this.msg) {
069 if (this.closed) {
070 return;
071 }
072 int start = off;
073 final int end = off + len;
074 for (int pos = off; pos < end; pos++) {
075 final char c = str.charAt(pos);
076 switch (c) {
077 case '\r':
078 case '\n':
079 this.msg.append(str, start, pos);
080 start = pos + 1;
081 if (c == '\n') {
082 log(fqcn);
083 }
084 break;
085 }
086 }
087 this.msg.append(str, start, end);
088 }
089 } else {
090 logEnd(fqcn);
091 }
092 }
093
094 public void put(final String fqcn, final int c) {
095 if (c >= 0) {
096 synchronized (this.msg) {
097 if (this.closed) {
098 return;
099 }
100 switch (c) {
101 case '\n':
102 log(fqcn);
103 break;
104 case '\r':
105 break;
106 default:
107 this.msg.append((char) c);
108 }
109 }
110 } else {
111 logEnd(fqcn);
112 }
113 }
114 }