001/* 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2026, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v2.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.core.net; 015 016import ch.qos.logback.core.util.CloseUtil; 017 018import java.io.ByteArrayOutputStream; 019import java.io.IOException; 020import java.io.OutputStream; 021import java.net.DatagramPacket; 022import java.net.DatagramSocket; 023import java.net.InetAddress; 024import java.net.SocketException; 025import java.net.UnknownHostException; 026 027/** 028 * SyslogOutputStream is a wrapper around the {@link DatagramSocket} class so 029 * that it behaves like an {@link OutputStream}. 030 */ 031public class SyslogOutputStream extends OutputStream { 032 033 /** 034 * The maximum length after which we discard the existing string buffer and 035 * start anew. 036 */ 037 private static final int MAX_LEN = 1024; 038 039 private InetAddress address; 040 private DatagramSocket ds; 041 private ByteArrayOutputStream baos = new ByteArrayOutputStream(); 042 final private int port; 043 044 public SyslogOutputStream(String syslogHost, int port) throws UnknownHostException, SocketException { 045 this.address = InetAddress.getByName(syslogHost); 046 this.port = port; 047 this.ds = new DatagramSocket(); 048 } 049 050 boolean isInvalidState() { 051 if(ds == null || baos == null || address == null) { 052 return true; 053 } 054 return false; 055 } 056 057 public void write(byte[] byteArray, int offset, int len) throws IOException { 058 if(isInvalidState()) return; 059 baos.write(byteArray, offset, len); 060 } 061 062 public void flush() throws IOException { 063 if(isInvalidState()) return; 064 byte[] bytes = baos.toByteArray(); 065 DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, port); 066 067 // clean up for next round 068 if (baos.size() > MAX_LEN) { 069 baos = new ByteArrayOutputStream(); 070 } else { 071 baos.reset(); 072 } 073 074 // after a failure, it can happen that bytes.length is zero 075 // in that case, there is no point in sending out an empty message/ 076 if (bytes.length == 0) { 077 return; 078 } 079 if (this.ds != null) { 080 ds.send(packet); 081 } 082 083 } 084 085 @Override 086 public void close() { 087 CloseUtil.closeQuietly(ds); 088 CloseUtil.closeQuietly(baos); 089 address = null; 090 ds = null; 091 baos = null; 092 } 093 094 public int getPort() { 095 return port; 096 } 097 098 @Override 099 public void write(int b) throws IOException { 100 baos.write(b); 101 } 102 103 int getSendBufferSize() throws SocketException { 104 return ds.getSendBufferSize(); 105 } 106}