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