Author: sebb
Date: Thu Mar 3 20:52:41 2011
New Revision: 1076791
URL: http://svn.apache.org/viewvc?rev=1076791&view=rev
Log:
NET-344 Telnet client: Support Listener Notification of Incoming Data.
Added:
commons/proper/net/trunk/src/main/java/org/apache/commons/net/telnet/TelnetInputListener.java
(with props)
Modified:
commons/proper/net/trunk/src/changes/changes.xml
commons/proper/net/trunk/src/main/java/org/apache/commons/net/telnet/TelnetClient.java
commons/proper/net/trunk/src/main/java/org/apache/commons/net/telnet/TelnetInputStream.java
Modified: commons/proper/net/trunk/src/changes/changes.xml
URL:
http://svn.apache.org/viewvc/commons/proper/net/trunk/src/changes/changes.xml?rev=1076791&r1=1076790&r2=1076791&view=diff
==============================================================================
--- commons/proper/net/trunk/src/changes/changes.xml (original)
+++ commons/proper/net/trunk/src/changes/changes.xml Thu Mar 3 20:52:41 2011
@@ -71,6 +71,9 @@ The <action> type attribute can be add,u
<action issue="NET-343" dev="sebb" type="add" due-to="Archie
Cobbs">
Telnet client: Support Client-initiated Subnegotiation Messages.
</action>
+ <action issue="NET-344" dev="sebb" type="add" due-to="Archie
Cobbs">
+ Telnet client: Support Listener Notification of Incoming Data.
+ </action>
<action issue="NET-270" dev="sebb" type="fix">
Incorrect error handling in method initiateListParsing of
FTPClient.
</action>
Modified:
commons/proper/net/trunk/src/main/java/org/apache/commons/net/telnet/TelnetClient.java
URL:
http://svn.apache.org/viewvc/commons/proper/net/trunk/src/main/java/org/apache/commons/net/telnet/TelnetClient.java?rev=1076791&r1=1076790&r2=1076791&view=diff
==============================================================================
---
commons/proper/net/trunk/src/main/java/org/apache/commons/net/telnet/TelnetClient.java
(original)
+++
commons/proper/net/trunk/src/main/java/org/apache/commons/net/telnet/TelnetClient.java
Thu Mar 3 20:52:41 2011
@@ -53,6 +53,7 @@ public class TelnetClient extends Telnet
private InputStream __input;
private OutputStream __output;
protected boolean readerThread = true;
+ private TelnetInputListener inputListener;
/***
* Default TelnetClient constructor.
@@ -329,9 +330,29 @@ public class TelnetClient extends Telnet
/***
* Sets the status of the reader thread.
- * The reader thread status will apply to all subsequent connections
+ *
+ * <p>
+ * When enabled, a seaparate internal reader thread is created for new
+ * connections to read incoming data as it arrives. This results in
+ * immediate handling of option negotiation, notifications, etc.
+ * (at least until the fixed-size internal buffer fills up).
+ * Otherwise, no thread is created an all negotiation and option
+ * handling is deferred until a read() is performed on the
+ * {@link #getInputStream input stream}.
+ * </p>
+ *
* <p>
- * @param flag - true switches the reader thread on, false switches it off
+ * The reader thread must be enabled for {@link TelnetInputListener}
+ * support.
+ * </p>
+ *
+ * <p>
+ * When this method is invoked, the reader thread status will apply to all
+ * subsequent connections; the current connection (if any) is not affected.
+ * </p>
+ *
+ * @param flag true to enable the reader thread, false to disable
+ * @see #registerInputListener
***/
public void setReaderThread(boolean flag)
{
@@ -341,10 +362,57 @@ public class TelnetClient extends Telnet
/***
* Gets the status of the reader thread.
* <p>
- * @return true if the reader thread is on, false otherwise
+ * @return true if the reader thread is enabled, false otherwise
***/
public boolean getReaderThread()
{
return (readerThread);
}
+
+ /***
+ * Register a listener to be notified when new incoming data is
+ * available to be read on the {@link #getInputStream input stream}.
+ * Only one listener is supported at a time.
+ *
+ * <p>
+ * More precisely, notifications are issued whenever the number of
+ * bytes available for immediate reading (i.e., the value returned
+ * by {@link InputStream#available}) transitions from zero to non-zero.
+ * Note that (in general) multiple reads may be required to empty the
+ * buffer and reset this notification, because incoming bytes are being
+ * added to the internal buffer asynchronously.
+ * </p>
+ *
+ * <p>
+ * Notifications are only supported when a {@link #setReaderThread
+ * reader thread} is enabled for the connection.
+ * </p>
+ *
+ * @param listener listener to be registered; replaces any previous
+ * @since 3.0
+ ***/
+ public synchronized void registerInputListener(TelnetInputListener
listener)
+ {
+ this.inputListener = listener;
+ }
+
+ /***
+ * Unregisters the current {@link TelnetInputListener}, if any.
+ *
+ * @since 3.0
+ ***/
+ public synchronized void unregisterInputListener()
+ {
+ this.inputListener = null;
+ }
+
+ // Notify input listener
+ void notifyInputListener() {
+ TelnetInputListener listener;
+ synchronized (this) {
+ listener = this.inputListener;
+ }
+ if (listener != null)
+ listener.telnetInputAvailable();
+ }
}
Added:
commons/proper/net/trunk/src/main/java/org/apache/commons/net/telnet/TelnetInputListener.java
URL:
http://svn.apache.org/viewvc/commons/proper/net/trunk/src/main/java/org/apache/commons/net/telnet/TelnetInputListener.java?rev=1076791&view=auto
==============================================================================
---
commons/proper/net/trunk/src/main/java/org/apache/commons/net/telnet/TelnetInputListener.java
(added)
+++
commons/proper/net/trunk/src/main/java/org/apache/commons/net/telnet/TelnetInputListener.java
Thu Mar 3 20:52:41 2011
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+/***
+ * Listener interface used for notification that incoming data is
+ * available to be read.
+ *
+ * @see TelnetClient
+ * @since 3.0
+ ***/
+public interface TelnetInputListener
+{
+
+ /***
+ * Callback method invoked when new incoming data is available on a
+ * {@link TelnetClient}'s {@link TelnetClient#getInputStream input stream}.
+ *
+ * @see TelnetClient#registerInputListener
+ ***/
+ public void telnetInputAvailable();
+}
Propchange:
commons/proper/net/trunk/src/main/java/org/apache/commons/net/telnet/TelnetInputListener.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
commons/proper/net/trunk/src/main/java/org/apache/commons/net/telnet/TelnetInputListener.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Modified:
commons/proper/net/trunk/src/main/java/org/apache/commons/net/telnet/TelnetInputStream.java
URL:
http://svn.apache.org/viewvc/commons/proper/net/trunk/src/main/java/org/apache/commons/net/telnet/TelnetInputStream.java?rev=1076791&r1=1076790&r2=1076791&view=diff
==============================================================================
---
commons/proper/net/trunk/src/main/java/org/apache/commons/net/telnet/TelnetInputStream.java
(original)
+++
commons/proper/net/trunk/src/main/java/org/apache/commons/net/telnet/TelnetInputStream.java
Thu Mar 3 20:52:41 2011
@@ -298,13 +298,15 @@ final class TelnetInputStream extends Bu
// synchronized(__client) critical sections are to protect against
// TelnetOutputStream writing through the telnet client at same time
// as a processDo/Will/etc. command invoked from TelnetInputStream
- // tries to write.
- private void __processChar(int ch) throws InterruptedException
+ // tries to write. Returns true if buffer was previously empty.
+ private boolean __processChar(int ch) throws InterruptedException
{
// Critical section because we're altering __bytesAvailable,
// __queueTail, and the contents of _queue.
+ boolean bufferWasEmpty;
synchronized (__queue)
{
+ bufferWasEmpty = (__bytesAvailable == 0);
while (__bytesAvailable >= __queue.length - 1)
{
// The queue is full. We need to wait before adding any more
data to it. Hopefully the stream owner
@@ -341,6 +343,7 @@ final class TelnetInputStream extends Bu
if (++__queueTail >= __queue.length)
__queueTail = 0;
}
+ return bufferWasEmpty;
}
@Override
@@ -615,15 +618,21 @@ _outerLoop:
break _outerLoop;
}
+ // Process new character
+ boolean notify = false;
try
{
- __processChar(ch);
+ notify = __processChar(ch);
}
catch (InterruptedException e)
{
if (__isClosed)
break _outerLoop;
}
+
+ // Notify input listener if buffer was previously empty
+ if (notify)
+ __client.notifyInputListener();
}
}
catch (IOException ioe)
@@ -632,6 +641,7 @@ _outerLoop:
{
__ioException = ioe;
}
+ __client.notifyInputListener();
}
synchronized (__queue)