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;
18  
19  import org.apache.logging.log4j.Logger;
20  import org.apache.logging.log4j.core.appender.AppenderRuntimeException;
21  import org.apache.logging.log4j.status.StatusLogger;
22  
23  import java.io.IOException;
24  import java.io.OutputStream;
25  import java.net.DatagramPacket;
26  import java.net.DatagramSocket;
27  import java.net.InetAddress;
28  import java.net.SocketException;
29  import java.net.UnknownHostException;
30  
31  /**
32   * OutputStream for UDP connections.
33   */
34  public class DatagramOutputStream extends OutputStream {
35  
36      /**
37       * Allow subclasses access to the status logger without creating another instance.
38       */
39      protected static final Logger LOGGER = StatusLogger.getLogger();
40  
41      private static final int SHIFT_1 = 8;
42      private static final int SHIFT_2 = 16;
43      private static final int SHIFT_3 = 24;
44  
45      private DatagramSocket ds;
46      private final InetAddress address;
47      private final int port;
48  
49      private byte[] data;
50  
51      /**
52       * The Constructor.
53       * @param host The host to connect to.
54       * @param port The port on the host.
55       */
56      public DatagramOutputStream(final String host, final int port) {
57          this.port = port;
58          try {
59              address = InetAddress.getByName(host);
60          } catch (final UnknownHostException ex) {
61              final String msg = "Could not find host " + host;
62              LOGGER.error(msg, ex);
63              throw new AppenderRuntimeException(msg, ex);
64          }
65  
66          try {
67              ds = new DatagramSocket();
68          } catch (final SocketException ex) {
69              final String msg = "Could not instantiate DatagramSocket to " + host;
70              LOGGER.error(msg, ex);
71              throw new AppenderRuntimeException(msg, ex);
72          }
73      }
74  
75      @Override
76      public synchronized void write(final byte[] bytes, final int offset, final int length) throws IOException {
77          copy(bytes, offset, length);
78      }
79  
80      @Override
81      public synchronized void write(final int i) throws IOException {
82          copy(new byte[] {(byte) (i >>> SHIFT_3), (byte) (i >>> SHIFT_2), (byte) (i >>> SHIFT_1), (byte) i}, 0, 4);
83      }
84  
85      @Override
86      public synchronized void write(final byte[] bytes) throws IOException {
87          copy(bytes, 0, bytes.length);
88      }
89  
90      @Override
91      public synchronized void flush() throws IOException {
92          if (this.data != null && this.ds != null && this.address != null) {
93              final DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
94              ds.send(packet);
95          }
96          data = null;
97      }
98  
99      @Override
100     public synchronized void close() throws IOException {
101         if (ds != null) {
102             if (data != null) {
103                 flush();
104             }
105             ds.close();
106             ds = null;
107         }
108     }
109 
110     private void copy(final byte[] bytes, final int offset, final int length) {
111         final int index = data == null ? 0 : data.length;
112         final byte[] copy = new byte[length + index];
113         if (data != null) {
114             System.arraycopy(data, 0, copy, 0, index);
115         }
116         System.arraycopy(bytes, offset, copy, index, length);
117         data = copy;
118     }
119 }