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 */ 017package org.apache.logging.log4j.core.net.server; 018 019import java.io.InputStream; 020import java.nio.charset.Charset; 021 022import org.apache.logging.log4j.core.LogEvent; 023import org.apache.logging.log4j.core.jackson.Log4jJsonObjectMapper; 024import org.apache.logging.log4j.util.Chars; 025 026/** 027 * Reads and logs JSON {@link LogEvent}s from an {@link InputStream}.. 028 */ 029public class JsonInputStreamLogEventBridge extends InputStreamLogEventBridge { 030 031 private static final int[] END_PAIR = new int[] { END, END }; 032 private static final char EVENT_END_MARKER = '}'; 033 private static final char EVENT_START_MARKER = '{'; 034 private static final char JSON_ESC = '\\'; 035 private static final char JSON_STR_DELIM = Chars.DQUOTE; 036 private static final boolean THREAD_CONTEXT_MAP_AS_LIST = false; 037 038 public JsonInputStreamLogEventBridge() { 039 this(1024, Charset.defaultCharset()); 040 } 041 042 public JsonInputStreamLogEventBridge(final int bufferSize, final Charset charset) { 043 super(new Log4jJsonObjectMapper(THREAD_CONTEXT_MAP_AS_LIST), bufferSize, charset, 044 String.valueOf(EVENT_END_MARKER)); 045 } 046 047 @Override 048 protected int[] getEventIndices(final String text, final int beginIndex) { 049 // Scan the text for the end of the next JSON object. 050 final int start = text.indexOf(EVENT_START_MARKER, beginIndex); 051 if (start == END) { 052 return END_PAIR; 053 } 054 final char[] charArray = text.toCharArray(); 055 int stack = 0; 056 boolean inStr = false; 057 boolean inEsc = false; 058 for (int i = start; i < charArray.length; i++) { 059 final char c = charArray[i]; 060 if (inEsc) { 061 // Skip this char and continue 062 inEsc = false; 063 } else { 064 switch (c) { 065 case EVENT_START_MARKER: 066 if (!inStr) { 067 stack++; 068 } 069 break; 070 case EVENT_END_MARKER: 071 if (!inStr) { 072 stack--; 073 } 074 break; 075 case JSON_STR_DELIM: 076 inStr = !inStr; 077 break; 078 case JSON_ESC: 079 inEsc = true; 080 break; 081 } 082 if (stack == 0) { 083 return new int[] { start, i }; 084 } 085 } 086 } 087 return END_PAIR; 088 } 089 090}