View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements. See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache license, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License. You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the license for the specific language governing permissions and
    15   * limitations under the license.
    16   */
    17  package org.apache.logging.log4j.core.net.server;
    18
    19  import java.io.IOException;
    20  import java.io.InputStream;
    21  import java.nio.charset.Charset;
    22
    23  import org.apache.logging.log4j.core.LogEvent;
    24  import org.apache.logging.log4j.core.LogEventListener;
    25  import org.apache.logging.log4j.core.impl.Log4jLogEvent;
    26  import org.apache.logging.log4j.util.Strings;
    27
    28  import com.fasterxml.jackson.databind.ObjectMapper;
    29  import com.fasterxml.jackson.databind.ObjectReader;
    30
    31  /**
    32   * Reads and logs {@link LogEvent}s from an {@link InputStream}.
    33   */
    34  public abstract class InputStreamLogEventBridge extends AbstractLogEventBridge<InputStream> {
    35
    36      private final int bufferSize;
    37
    38      private final Charset charset;
    39
    40      private final String eventEndMarker;
    41
    42      private final ObjectReader objectReader;
    43
    44      public InputStreamLogEventBridge(final ObjectMapper mapper, final int bufferSize, final Charset charset, final String eventEndMarker) {
    45          this.bufferSize = bufferSize;
    46          this.charset = charset;
    47          this.eventEndMarker = eventEndMarker;
    48          this.objectReader = mapper.reader(Log4jLogEvent.class);
    49      }
    50
    51      abstract protected int[] getEventIndices(final String text, int beginIndex);
    52
    53      @Override
    54      public void logEvents(final InputStream inputStream, final LogEventListener logEventListener) throws IOException {
    55          String workingText = Strings.EMPTY;
    56          try {
    57              // Allocate buffer once
    58              final byte[] buffer = new byte[bufferSize];
    59              String textRemains = workingText = Strings.EMPTY;
    60              while (true) {
    61                  // Process until the stream is EOF.
    62                  final int streamReadLength = inputStream.read(buffer);
    63                  if (streamReadLength == END) {
    64                      // The input stream is EOF
    65                      break;
    66                  }
    67                  final String text = workingText = textRemains + new String(buffer, 0, streamReadLength, charset);
    68                  int beginIndex = 0;
    69                  while (true) {
    70                      // Extract and log all XML events in the buffer
    71                      final int[] pair = getEventIndices(text, beginIndex);
    72                      final int eventStartMarkerIndex = pair[0];
    73                      if (eventStartMarkerIndex < 0) {
    74                          // No more events or partial XML only in the buffer.
    75                          // Save the unprocessed string part
    76                          textRemains = text.substring(beginIndex);
    77                          break;
    78                      }
    79                      final int eventEndMarkerIndex = pair[1];
    80                      if (eventEndMarkerIndex > 0) {
    81                          final int eventEndXmlIndex = eventEndMarkerIndex + eventEndMarker.length();
    82                          final String textEvent = workingText = text.substring(eventStartMarkerIndex, eventEndXmlIndex);
    83                          final LogEvent logEvent = unmarshal(textEvent);
    84                          logEventListener.log(logEvent);
    85                          beginIndex = eventEndXmlIndex;
    86                      } else {
    87                          // No more events or partial XML only in the buffer.
    88                          // Save the unprocessed string part
    89                          textRemains = text.substring(beginIndex);
    90                          break;
    91                      }
    92                  }
    93              }
    94          } catch (final IOException ex) {
    95              logger.error(workingText, ex);
    96          }
    97      }
    98
    99      protected Log4jLogEvent unmarshal(final String jsonEvent) throws IOException {
    100         return this.objectReader.readValue(jsonEvent);
    101     }
    102
    103 }