Guard connectPromise not being null
[netconf.git] / netconf / netconf-netty-util / src / main / java / org / opendaylight / netconf / nettyutil / handler / BufferedWriter.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.netconf.nettyutil.handler;
9
10 import com.google.common.base.Preconditions;
11 import java.io.IOException;
12 import java.io.Writer;
13
14 /**
15  * Custom BufferedWriter optimized for netconf pipeline implemented instead of default BufferedWriter provided by jdk.
16  *
17  * <p>
18  * The line separator instance field in java.io.BufferedWriter is
19  * assigned using AccessController and takes considerable amount of time especially
20  * if lots of BufferedWriters are created in the system.
21  *
22  * <p>
23  * This implementation should only be used if newLine method is not required
24  * such as netconf message to XML encoders.
25  * Methods in this implementation are not synchronized.
26  */
27 public final class BufferedWriter extends Writer {
28
29     private static final int DEFAULT_CHAR_BUFFER_SIZE = 8192;
30
31     private final Writer writer;
32     private final char[] buffer;
33     private final int bufferSize;
34
35     private int nextChar = 0;
36
37     public BufferedWriter(final Writer writer) {
38         this(writer, DEFAULT_CHAR_BUFFER_SIZE);
39     }
40
41     public BufferedWriter(final Writer writer, final int bufferSize) {
42         super(writer);
43         Preconditions.checkArgument(bufferSize > 0, "Buffer size <= 0");
44         this.writer = writer;
45         this.buffer = new char[bufferSize];
46         this.bufferSize = bufferSize;
47     }
48
49     private void flushBuffer() throws IOException {
50         if (nextChar == 0) {
51             return;
52         }
53         writer.write(buffer, 0, nextChar);
54         nextChar = 0;
55     }
56
57     @Override
58     public void write(final int character) throws IOException {
59         if (nextChar >= bufferSize) {
60             flushBuffer();
61         }
62         buffer[nextChar++] = (char) character;
63     }
64
65     @Override
66     @SuppressWarnings("checkstyle:hiddenField")
67     public void write(final char[] buffer, final int offset, final int length) throws IOException {
68         if (offset < 0 || offset > buffer.length
69                 || length < 0 || offset + length > buffer.length || offset + length < 0) {
70             throw new IndexOutOfBoundsException(
71                     String.format("Buffer size: %d, Offset: %d, Length: %d", buffer.length, offset, length));
72         } else if (length == 0) {
73             return;
74         }
75
76         if (length >= bufferSize) {
77             flushBuffer();
78             writer.write(buffer, offset, length);
79             return;
80         }
81
82         int bufferOffset = offset;
83         final int t = offset + length;
84         while (bufferOffset < t) {
85             final int d = Math.min(bufferSize - nextChar, t - bufferOffset);
86             System.arraycopy(buffer, bufferOffset, this.buffer, nextChar, d);
87             bufferOffset += d;
88             nextChar += d;
89             if (nextChar >= bufferSize) {
90                 flushBuffer();
91             }
92         }
93     }
94
95     @Override
96     public void write(final String string, final int offset, final int length) throws IOException {
97         int bufferOffset = offset;
98         final int t = offset + length;
99         while (bufferOffset < t) {
100             final int d = Math.min(bufferSize - nextChar, t - bufferOffset);
101             string.getChars(bufferOffset, bufferOffset + d, buffer, nextChar);
102             bufferOffset += d;
103             nextChar += d;
104             if (nextChar >= bufferSize) {
105                 flushBuffer();
106             }
107         }
108     }
109
110     @Override
111     public void flush() throws IOException {
112         flushBuffer();
113         writer.flush();
114     }
115
116     @Override
117     public void close() throws IOException {
118         try {
119             flushBuffer();
120         } finally {
121             writer.close();
122         }
123     }
124 }