2 * jSite - Client.java - Copyright © 2006–2012 David Roden
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 package de.todesbaum.util.freenet.fcp2;
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.List;
25 import net.pterodactylus.util.io.StreamCopier.ProgressListener;
28 * A Client executes {@link Command}s over a {@link Connection} to a
29 * {@link Node} and delivers resulting {@link Message}s.
31 * @author David Roden <droden@gmail.com>
34 public class Client implements ConnectionListener {
36 /** The connection this client operates on. */
37 private final Connection connection;
39 /** The identifiers the client filters messages for. */
40 private List<String> identifiers = new ArrayList<String>();
42 /** The queued messages. */
43 private final List<Message> messageQueue = new ArrayList<Message>();
45 /** Whether the client was disconnected. */
46 private boolean disconnected = false;
48 /** Whether to catch all messages from the connection. */
49 private boolean catchAll = false;
52 * Creates a new client that operates on the specified connection.
55 * The connection to operate on
57 public Client(Connection connection) {
58 this.connection = connection;
59 connection.addConnectionListener(this);
63 * Creates a new client that operates on the specified connection and
64 * immediately executes the specified command.
67 * The connection to operate on
69 * The command to execute
71 * if an I/O error occurs
72 * @see #execute(Command)
74 public Client(Connection connection, Command command) throws IOException {
80 * Returns whether this client catches all messages going over the
83 * @return <code>true</code> if the client catches all messages,
84 * <code>false</code> otherwise
86 public boolean isCatchAll() {
91 * Sets whether this client catches all messages going over the connection.
94 * <code>true</code> if the client should catch all messages,
95 * <code>false</code> otherwise
97 public void setCatchAll(boolean catchAll) {
98 this.catchAll = catchAll;
102 * Executes the specified command. This will also clear the queue of
103 * messages, discarding all messages that resulted from the previous command
104 * and have not yet been read.
107 * The command to execute
108 * @throws IOException
109 * if an I/O error occurs
110 * @see #execute(Command, boolean)
112 public void execute(Command command) throws IOException {
113 execute(command, true);
117 * Executes the specified command. This will also clear the queue of
118 * messages, discarding all messages that resulted from the previous
119 * command and have not yet been read.
122 * The command to execute
123 * @param progressListener
124 * The progress listener for payload transfers
125 * @throws IOException
126 * if an I/O error occurs
127 * @see #execute(Command, boolean)
129 public void execute(Command command, ProgressListener progressListener) throws IOException {
130 execute(command, true, progressListener);
134 * Executes the specified command and optionally clears the list of
135 * identifiers this clients listens to before starting the command.
138 * The command to execute
139 * @param removeExistingIdentifiers
140 * If <code>true</code>, the list of identifiers that this
141 * clients listens to is cleared
142 * @throws IOException
143 * if an I/O error occurs
145 public void execute(Command command, boolean removeExistingIdentifiers) throws IOException {
146 execute(command, removeExistingIdentifiers, null);
150 * Executes the specified command and optionally clears the list of
151 * identifiers this clients listens to before starting the command.
154 * The command to execute
155 * @param removeExistingIdentifiers
156 * If <code>true</code>, the list of identifiers that this
157 * clients listens to is cleared
158 * @param progressListener
159 * The progress listener for payload transfers
160 * @throws IOException
161 * if an I/O error occurs
163 public void execute(Command command, boolean removeExistingIdentifiers, ProgressListener progressListener) throws IOException {
164 synchronized (messageQueue) {
165 messageQueue.clear();
166 if (removeExistingIdentifiers) {
169 identifiers.add(command.getIdentifier());
171 connection.execute(command, progressListener);
175 * Returns the next message, waiting endlessly for it, if need be. If you
176 * are not sure whether a message will arrive, better use
177 * {@link #readMessage(long)} to only wait for a specific time.
179 * @return The next message that resulted from the execution of the last
181 * @see #readMessage(long)
182 * @see #execute(Command)
184 public Message readMessage() {
185 return readMessage(0);
189 * Returns the next message. If the message queue is currently empty, at
190 * least <code>maxWaitTime</code> milliseconds will be waited for a
194 * The minimum time to wait for a message, in milliseconds
195 * @return The message, or <code>null</code> if no message arrived in time
196 * or the client is currently disconnected
197 * @see #isDisconnected()
198 * @see Object#wait(long)
200 public Message readMessage(long maxWaitTime) {
201 synchronized (messageQueue) {
205 if (messageQueue.size() == 0) {
207 messageQueue.wait(maxWaitTime);
208 } catch (InterruptedException ie1) {
211 if (messageQueue.size() > 0) {
212 return messageQueue.remove(0);
219 * Returns whether the client is currently disconnected.
221 * @return <code>true</code> if the client is disconnected,
222 * <code>false</code> otherwise
224 public boolean isDisconnected() {
225 synchronized (messageQueue) {
233 public void messageReceived(Connection connection, Message message) {
234 synchronized (messageQueue) {
235 if (catchAll || (message.getIdentifier().length() == 0) || identifiers.contains(message.getIdentifier())) {
236 messageQueue.add(message);
237 messageQueue.notify();
245 public void connectionTerminated(Connection connection) {
246 synchronized (messageQueue) {
248 messageQueue.notify();