PipedWriter.java revision dfc6136d9473dfd0aa5b310035ce48d5f8eebe0d
1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson// BEGIN android-note
19da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson// We've made several changes including:
20da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson//  - move checks into the synchronized method in PipedReader
21da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson//  - reply on PipedReader's isClosed field (rather than having 2 flags)
22da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson//  - avoid shallow concurrency problems
23da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson//  - improved consistency with PipedOutputStream
24da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson// END android-note
25da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.io;
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Places information on a communications pipe. When two threads want to pass
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * data back and forth, one creates a piped writer and the other creates a piped
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * reader.
32f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson *
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see PipedReader
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class PipedWriter extends Writer {
36dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson
37dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson    private PipedReader destination;
38dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson    private boolean isClosed;
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new unconnected {@code PipedWriter}. The resulting writer
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * must be connected to a {@code PipedReader} before data may be written to
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * it.
44f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see PipedReader
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public PipedWriter() {
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super();
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
52dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson     * Constructs a new {@code PipedWriter} connected to {@code destination}.
53dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson     * Any data written to this writer can be read from {@code destination}.
54f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
55dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson     * @param destination
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code PipedReader} to connect to.
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
58dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson     *             if {@code destination} is already connected.
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
60dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson    public PipedWriter(PipedReader destination) throws IOException {
61dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson        super(destination);
62dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson        connect(destination);
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Closes this writer. If a {@link PipedReader} is connected to this writer,
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * it is closed as well and the pipe is disconnected. Any data buffered in
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the reader can still be read.
69f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while closing this writer.
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void close() throws IOException {
75dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson        PipedReader reader = destination;
76da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson        if (reader != null) {
77da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson            reader.done();
78dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson            isClosed = true;
79dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson            destination = null;
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Connects this {@code PipedWriter} to a {@link PipedReader}. Any data
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * written to this writer becomes readable in the reader.
86f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
87da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson     * @param reader
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the reader to connect to.
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this writer is closed or already connected, or if {@code
91da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson     *             reader} is already connected.
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
93da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson    public void connect(PipedReader reader) throws IOException {
94da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson        if (reader == null) {
95da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson            throw new NullPointerException();
96da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson        }
97da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson        synchronized (reader) {
98dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson            if (this.destination != null) {
99dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson                throw new IOException("Pipe already connected");
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
101da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson            reader.establishConnection();
102da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson            this.lock = reader;
103dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson            this.destination = reader;
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Notifies the readers of this {@code PipedReader} that characters can be read. This
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * method does nothing if this Writer is not connected.
110f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an I/O error occurs while flushing this writer.
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void flush() throws IOException {
116dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson        PipedReader reader = destination;
117dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson        if (isClosed) {
118dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson            throw new IOException("Pipe is closed");
119dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson        }
120da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson        if (reader == null) {
121da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson            return;
122da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson        }
123da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson
124da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson        synchronized (reader) {
125da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson            reader.notifyAll();
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Writes {@code count} characters from the character array {@code buffer}
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * starting at offset {@code index} to this writer. The written data can
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * then be read from the connected {@link PipedReader} instance.
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Separate threads should be used to write to a {@code PipedWriter} and to
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * read from the connected {@code PipedReader}. If the same thread is used,
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * a deadlock may occur.
137f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param buffer
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the buffer to write.
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param offset
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the index of the first character in {@code buffer} to write.
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param count
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the number of characters from {@code buffer} to write to this
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            writer.
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IndexOutOfBoundsException
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code offset < 0} or {@code count < 0}, or if {@code
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             offset + count} is bigger than the length of {@code buffer}.
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws InterruptedIOException
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the pipe is full and the current thread is interrupted
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             waiting for space to write data. This case is not currently
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             handled correctly.
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this writer is closed or not connected, if the target
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             reader is closed or if the thread reading from the target
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             reader is no longer alive. This case is currently not handled
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             correctly.
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NullPointerException
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code buffer} is {@code null}.
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void write(char[] buffer, int offset, int count) throws IOException {
162dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson        PipedReader reader = destination;
163da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson        if (reader == null) {
164b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IOException("Pipe not connected");
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
166da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson        reader.receive(buffer, offset, count);
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Writes a single character {@code c} to this writer. This character can
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * then be read from the connected {@link PipedReader} instance.
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Separate threads should be used to write to a {@code PipedWriter} and to
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * read from the connected {@code PipedReader}. If the same thread is used,
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * a deadlock may occur.
176f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param c
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the character to write.
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws InterruptedIOException
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the pipe is full and the current thread is interrupted
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             waiting for space to write data. This case is not currently
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             handled correctly.
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this writer is closed or not connected, if the target
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             reader is closed or if the thread reading from the target
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             reader is no longer alive. This case is currently not handled
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             correctly.
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void write(int c) throws IOException {
191dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson        PipedReader reader = destination;
192da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson        if (reader == null) {
193b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IOException("Pipe not connected");
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
195da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson        reader.receive((char) c);
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
198