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