/*
* A CCNx chat program.
*
* Copyright (C) 2008, 2009, 2010, 2011 Palo Alto Research Center, Inc.
*
* This work is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
* This work is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details. You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
package org.ccnx.ccn.apps.ccnchat;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import org.ccnx.ccn.apps.ccnchat.CCNChatNet.CCNChatCallback;
import org.ccnx.ccn.config.ConfigurationException;
import org.ccnx.ccn.protocol.MalformedContentNameStringException;
/**
* A text-based interface to CCNChat.
*
* Because we don't want to depend on an external curses library,
* the UI uses a 2-mode interface. The normal mode is OUTPUT, which
* means received chat messages are displayed immediately. If the
* user pressed ENTER, we switch to INPUT mode. Received chat messages
* are queued and only displayed when the user leaves INPUT mode
* by pressing ENTER again.
*
* System.in is buffered, so we can only get when the user presses ENTER.
* We will save whatever what typed before and put it as the start of
* the INPUT line.
*/
public class CCNChatText implements Runnable, CCNChatCallback {
public static void usage() {
System.err.println("usage: CCNChat <ccn URI>");
}
/**
* @param args
*/
public static void main(String[] args) {
if (args.length != 1) {
usage();
System.exit(-1);
}
CCNChatText client;
try {
client = new CCNChatText(args[0]);
client.start();
} catch (MalformedContentNameStringException e) {
System.err.println("Not a valid ccn URI: " + args[0] + ": " + e.getMessage());
e.printStackTrace();
} catch (ConfigurationException e) {
System.err.println("Configuration exception running ccnChat: " + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
System.err.println("IOException handling chat messages: " + e.getMessage());
e.printStackTrace();
}
}
public void run() {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
output("Mode = " + _mode + "\n");
output("Press ENTER to switch to INPUT mode.\n");
while(true) {
String message = null;
String moreMessage = null;
// Check for a character input
try {
if( br.ready() ) {
_mode = Mode.MODE_INPUT;
}
} catch(Exception e) {
}
switch(_mode) {
case MODE_INPUT:
// Read in the current input and put it out there
try {
if (null == (message = br.readLine())) {
System.out.println();
System.out.println("Bye");
System.exit(0);
}
} catch (IOException e1) {
e1.printStackTrace();
}
System.out.print("INPUT: " + message);
try {
if (null == (moreMessage = br.readLine())) {
System.out.println();
System.out.println("Bye");
System.exit(0);
}
_chat.sendMessage(message + moreMessage);
} catch(Exception e) {
e.printStackTrace();
}
_mode = Mode.MODE_OUTPUT;
break;
case MODE_OUTPUT:
try {
message = _queue.poll(50, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
}
if( null != message ) {
output(message);
}
break;
}
}
}
// =========================================================
// Internal methods
private final CCNChatNet _chat;
private final Thread _thd;
private final LinkedBlockingQueue<String> _queue = new LinkedBlockingQueue<String>();
private Mode _mode = Mode.MODE_OUTPUT;
private enum Mode {
MODE_INPUT,
MODE_OUTPUT
}
/**
* Send a message to the console. Message should include its
* own newline, if so desired.
* @param message
*/
protected void output(String message) {
System.out.print(message);
}
protected CCNChatText(String namespace) throws MalformedContentNameStringException {
_chat = new CCNChatNet(this, namespace);
_thd = new Thread(this, "CCNChatText");
}
/**
* Called by window thread when when window closes
*/
protected void stop() throws IOException {
_chat.shutdown();
}
/**
* This blocks until _chat.shutdown() called.
*
* This is run in the main() thread.
*
* @throws IOException
* @throws MalformedContentNameStringException
* @throws ConfigurationException
*/
protected void start() throws ConfigurationException, MalformedContentNameStringException, IOException {
_thd.start();
_chat.setLogging(Level.WARNING);
_chat.listen();
}
public void recvMessage(String message) {
_queue.add(message);
}
}