I have problem of playing back the recorded media file from red5 published stream, following is my code. I could see a file called out.flv is created, but this out.flv can not be played back.
public class Red5ClientTest {
private static Timer timer;
private static RTMPClient client;
private static String sourceStreamName;
private static int videoTs;
private static int audioTs;
private static FLVWriter writer;
private static int bytesRead =0;
public static void main(String[] args) throws IOException {
String sourceHost = "localhost";
int sourcePort = 1935;
String sourceApp = "oflaDemo";
sourceStreamName = "myStream";
timer = new Timer();
client = new RTMPClient();
String path = "c:\\temp\\out.flv";
File file = new File(path);
if (!file.exists()) {
file.createNewFile();
}
writer = new FLVWriter(file,true);
client.setStreamEventDispatcher(new StreamEventDispatcher());
client.setStreamEventHandler(new INetStreamEventHandler() {
public void onStreamEvent(Notify notify) {
System.out.printf("onStreamEvent: %s\n", notify);
ObjectMap<?, ?> map = (ObjectMap<?, ?>) notify.getCall().getArguments()[0];
String code = (String) map.get("code");
System.out.printf("<:%s\n", code);
if (StatusCodes.NS_PLAY_STREAMNOTFOUND.equals(code)) {
System.out.println("Requested stream was not found");
client.disconnect();
}
else if (StatusCodes.NS_PLAY_UNPUBLISHNOTIFY.equals(code)
|| StatusCodes.NS_PLAY_COMPLETE.equals(code)) {
System.out.println("Source has stopped publishing or play is complete");
client.disconnect();
}
}
});
client.setConnectionClosedHandler(new Runnable() {
public void run() {
if (writer != null) {
writer.close();
}
System.out.println("Source connection has been closed, proxy will be stopped");
System.exit(0);
}
});
client.setExceptionHandler(new ClientExceptionHandler() {
#Override
public void handleException(Throwable throwable) {
throwable.printStackTrace();
System.exit(1);
}
});
// connect the consumer
Map<String, Object> defParams = client.makeDefaultConnectionParams(sourceHost, sourcePort,
sourceApp);
// add pageurl and swfurl
defParams.put("pageUrl", "");
defParams.put("swfUrl", "app:/Red5-StreamRelay.swf");
// indicate for the handshake to generate swf verification data
client.setSwfVerification(true);
// connect the client
client.connect(sourceHost, sourcePort, defParams, new IPendingServiceCallback() {
public void resultReceived(IPendingServiceCall call) {
System.out.println("connectCallback");
ObjectMap<?, ?> map = (ObjectMap<?, ?>) call.getResult();
String code = (String) map.get("code");
if ("NetConnection.Connect.Rejected".equals(code)) {
System.out.printf("Rejected: %s\n", map.get("description"));
client.disconnect();
//proxy.stop();
}
else if ("NetConnection.Connect.Success".equals(code)) {
// 1. Wait for onBWDone
timer.schedule(new BandwidthStatusTask(), 2000L);
Object result = call.getResult();
System.out.println("Red5ClientTest.main()");
}
else {
System.out.printf("Unhandled response code: %s\n", code);
}
}
});
// keep sleeping main thread while the proxy runs
// kill the timer
//timer.cancel();
System.out.println("Stream relay exit");
}
/**
* Handles result from subscribe call.
*/
private static final class SubscribeStreamCallBack implements IPendingServiceCallback {
public void resultReceived(IPendingServiceCall call) {
System.out.println("resultReceived: " + call);
Object result = call.getResult();
System.out.println("results came {}" + result);
}
}
private static final class StreamEventDispatcher implements IEventDispatcher {
public void dispatchEvent(IEvent event) {
System.out.println("ClientStream.dispachEvent()" + event.toString());
try {
//RTMPMessage build = RTMPMessage.build((IRTMPEvent) event);
IRTMPEvent rtmpEvent = (IRTMPEvent) event;
ITag tag = new Tag();
tag.setDataType(rtmpEvent.getDataType());
if (rtmpEvent instanceof VideoData) {
videoTs += rtmpEvent.getTimestamp();
tag.setTimestamp(videoTs);
}
else if (rtmpEvent instanceof AudioData) {
audioTs += rtmpEvent.getTimestamp();
tag.setTimestamp(audioTs);
}
IoBuffer data = ((IStreamData) rtmpEvent).getData().asReadOnlyBuffer();
tag.setBodySize(data.limit());
tag.setBody(data);
try {
writer.writeTag(tag);
} catch (Exception e) {
throw new RuntimeException(e);
}
System.out.println("writting....");
}
catch (Exception e) {//IOException
e.printStackTrace();
}
}
}
private static final class BandwidthStatusTask extends TimerTask {
#Override
public void run() {
// check for onBWDone
System.out.println("Bandwidth check done: " + client.isBandwidthCheckDone());
// cancel this task
this.cancel();
// create a task to wait for subscribed
timer.schedule(new PlayStatusTask(), 1000L);
// 2. send FCSubscribe
client.subscribe(new SubscribeStreamCallBack(), new Object[] { sourceStreamName });
}
}
private static final class PlayStatusTask extends TimerTask {
#Override
public void run() {
// checking subscribed
System.out.println("Subscribed: " + client.isSubscribed());
// cancel this task
this.cancel();
// 3. create stream
client.createStream(new CreateStreamCallback());
}
}
/**
* Creates a "stream" via playback, this is the source stream.
*/
private static final class CreateStreamCallback implements IPendingServiceCallback {
public void resultReceived(IPendingServiceCall call) {
System.out.println("resultReceived: " + call);
int streamId = ((Number) call.getResult()).intValue();
System.out.println("stream id: " + streamId);
// send our buffer size request
if (sourceStreamName.endsWith(".flv") || sourceStreamName.endsWith(".f4v")
|| sourceStreamName.endsWith(".mp4")) {
client.play(streamId, sourceStreamName, 0, -1);
}
else {
client.play(streamId, sourceStreamName, -1, 0);
}
}
}
}
what could I be doing possibly wrong here?
Finally got it
public class TeqniRTMPClient {
private static final Logger logger = LoggerFactory.getLogger(MyRtmpClient.class);
public static void main(String args[]) throws IOException {
TeqniRTMPClient client = new TeqniRTMPClient("localhost", 1935, "oflaDemo", "myStream");
client.recordStream();
}
private RTMPClient client;
private ITagWriter writer;
private String sourceHost;
private int sourcePort;
private String sourceApp;
private String sourceStreamName;
private int lastTimestamp;
private int startTimestamp = -1;
public TeqniRTMPClient(String sourceHost, int sourcePort, String sourceApp,
String sourceStreamName) {
super();
this.sourceHost = sourceHost;
this.sourcePort = sourcePort;
this.sourceApp = sourceApp;
this.sourceStreamName = sourceStreamName;
}
public void recordStream() throws IOException {
client = new RTMPClient();
String path = "c:\\temp\\out.flv";
File file = new File(path);
if (!file.exists()) {
file.createNewFile();
}
FLVService flvService = new FLVService();
flvService.setGenerateMetadata(true);
try {
IStreamableFile flv = flvService.getStreamableFile(file);
writer = flv.getWriter();
}
catch (Exception e) {
throw new RuntimeException(e);
}
client.setStreamEventDispatcher(new StreamEventDispatcher());
client.setStreamEventHandler(new INetStreamEventHandler() {
public void onStreamEvent(Notify notify) {
System.out.printf("onStreamEvent: %s\n", notify);
ObjectMap<?, ?> map = (ObjectMap<?, ?>) notify.getCall().getArguments()[0];
String code = (String) map.get("code");
System.out.printf("<:%s\n", code);
if (StatusCodes.NS_PLAY_STREAMNOTFOUND.equals(code)) {
System.out.println("Requested stream was not found");
client.disconnect();
}
else if (StatusCodes.NS_PLAY_UNPUBLISHNOTIFY.equals(code)
|| StatusCodes.NS_PLAY_COMPLETE.equals(code)) {
System.out.println("Source has stopped publishing or play is complete");
client.disconnect();
}
}
});
client.setExceptionHandler(new ClientExceptionHandler() {
#Override
public void handleException(Throwable throwable) {
throwable.printStackTrace();
System.exit(1);
}
});
client.setConnectionClosedHandler(new Runnable() {
public void run() {
if (writer != null) {
writer.close();
}
System.out.println("Source connection has been closed, proxy will be stopped");
System.exit(0);
}
});
// connect the consumer
Map<String, Object> defParams = client.makeDefaultConnectionParams(sourceHost, sourcePort,
sourceApp);
// add pageurl and swfurl
defParams.put("pageUrl", "");
defParams.put("swfUrl", "app:/Red5-StreamRelay.swf");
// indicate for the handshake to generate swf verification data
client.setSwfVerification(true);
// connect the client
client.connect(sourceHost, sourcePort, defParams, new IPendingServiceCallback() {
public void resultReceived(IPendingServiceCall call) {
System.out.println("connectCallback");
ObjectMap<?, ?> map = (ObjectMap<?, ?>) call.getResult();
String code = (String) map.get("code");
if ("NetConnection.Connect.Rejected".equals(code)) {
System.out.printf("Rejected: %s\n", map.get("description"));
client.disconnect();
}
else if ("NetConnection.Connect.Success".equals(code)) {
// 1. Wait for onBWDone
client.createStream(new CreateStreamCallback());
Object result = call.getResult();
System.out.println("Red5ClientTest.main()");
}
else {
System.out.printf("Unhandled response code: %s\n", code);
}
}
});
}
class CreateStreamCallback implements IPendingServiceCallback {
public void resultReceived(IPendingServiceCall call) {
System.out.println("resultReceived: " + call);
int streamId = ((Number) call.getResult()).intValue();
System.out.println("stream id: " + streamId);
// send our buffer size request
if (sourceStreamName.endsWith(".flv") || sourceStreamName.endsWith(".f4v")
|| sourceStreamName.endsWith(".mp4")) {
client.play(streamId, sourceStreamName, 0, -1);
}
else {
client.play(streamId, sourceStreamName, -1, 0);
}
}
}
class StreamEventDispatcher implements IEventDispatcher {
private int videoTs;
private int audioTs;
public void dispatchEvent(IEvent event) {
System.out.println("ClientStream.dispachEvent()" + event.toString());
try {
IRTMPEvent rtmpEvent = (IRTMPEvent) event;
logger.debug("rtmp event: " + rtmpEvent.getHeader() + ", "
+ rtmpEvent.getClass().getSimpleName());
if (!(rtmpEvent instanceof IStreamData)) {
logger.debug("skipping non stream data");
return;
}
if (rtmpEvent.getHeader().getSize() == 0) {
logger.debug("skipping event where size == 0");
return;
}
byte dataType = rtmpEvent.getDataType();
ITag tag = new Tag();
tag.setDataType(dataType);
if (rtmpEvent instanceof VideoData) {
VideoData video = (VideoData) rtmpEvent;
FrameType frameType = video.getFrameType();
videoTs += rtmpEvent.getTimestamp();
tag.setTimestamp(videoTs);
}
else if (rtmpEvent instanceof AudioData) {
audioTs += rtmpEvent.getTimestamp();
tag.setTimestamp(audioTs);
}
IoBuffer data = ((IStreamData) rtmpEvent).getData().asReadOnlyBuffer();
tag.setBodySize(data.limit());
tag.setBody(data);
try {
writer.writeTag(tag);
}
catch (Exception e) {
throw new RuntimeException(e);
}
System.out.println("writting....");
}
catch (Exception e) {//IOException
e.printStackTrace();
}
}
}
}
Related
I am trying to upload a file with AWS SDK to demonstrate upload break due to any reason. But I see it is uploading from the beginning always. The code there is pretty straight-forward, but the problem comes with saving persistent obj status so that we can re-use in resuming upload.
Here is my code:
public class Upload2 {
private static final File RESUME_UPLOAD_INFO = new File(System.getProperty("user.home"), "resumeUploadFile");
private static final boolean UPLOAD_HALF_AND_KILL = !RESUME_UPLOAD_INFO.exists();
private static Upload upload;
public static void main(String[] args) throws Exception
{
log("Execution started");
String bucket = "itpc123412";
String key = "s3.txt";
String file_path = "C:\\Users\\rkompelli\\Desktop\\abc3.txt";
File f = new File(file_path);
TransferManager tm = AWSConfiguration.getConnectionTransfer();
System.out.println(RESUME_UPLOAD_INFO.exists());
if (UPLOAD_HALF_AND_KILL)
{
PutObjectRequest por = new PutObjectRequest(bucket, key,f);
log("Starting from scratch");
upload = tm.upload(por, LISTENER);
}
else
{
log("Starting again");
upload = tm.resumeUpload(PersistableUpload.deserializeFrom(new FileInputStream(RESUME_UPLOAD_INFO)));
upload.addProgressListener(LISTENER);
}
log("Total bytes to transfer: " + upload.getProgress().getTotalBytesToTransfer());
log("Bytes transferred: " + upload.getProgress().getBytesTransferred());
upload.waitForCompletion();
log("Done");
tm.shutdownNow();
if (upload.isDone())
RESUME_UPLOAD_INFO.delete();
System.exit(0);
}
private static void log(String msg)
{
System.out.println(DateFormat.getTimeInstance().format(new Date()) + ": " + msg);
}
private static long LAST_LOGGED_BYTES;
private static final S3ProgressListener LISTENER = new S3SyncProgressListener()
{
#Override
public void progressChanged(ProgressEvent pe)
{
long bytes = upload.getProgress().getBytesTransferred();
if (pe.getEventType().isByteCountEvent())
{
if (LAST_LOGGED_BYTES == 0 || bytes - LAST_LOGGED_BYTES > 5)
{
LAST_LOGGED_BYTES = bytes;
log("uploaded: " + NumberFormat.getNumberInstance().format(bytes));
}
}
if (bytes > upload.getProgress().getTotalBytesToTransfer()/2 && UPLOAD_HALF_AND_KILL)
{
log("IF 2 in get progress");
log("Exiting");
System.exit(0);
}
}
#Override
public void onPersistableTransfer(final PersistableTransfer pt)
{
// TODO should not be blocked
try
{
log("Saving upload state");
pt.serialize(new FileOutputStream(RESUME_UPLOAD_INFO));
}
catch (Exception e)
{
e.printStackTrace();
}
}
};
}
I noticed that onPersistableTransfer() event is not executing which has code to serialize the obj.
I'm working on a system Reader-Writer with the Java threads, and it must be prioritized : the reader has the priority over the writer.
I wrote a source-code, which compiles and can be executed without any problem. But I would want to be really sure it's correct.
Can you tell me if you see some errors ?
Well, first I have to explain you the aim of my little program. At regular intervals, a message is displayed to the user. The latter can modify it, and change its display delay (the "interval of time"). A message is identified by an ID.
So if the user type : 0 \n Hello \n 2, it means the message n°0 is now "Hello" and will be displayed every 2 seconds.
Each message is taken care by a thread. I have to use semaphores.
SOURCE-CODES.
The reader :
public class Lecteur extends Thread {
private Message<String> message;
public Lecteur(Message<String> message) {
this.message = message;
}
public void run() {
try {
while(true) {
System.out.println(message.getContent());
int time = message.getRefresh_time()*1000;
Thread.sleep(time);
}
} catch(InterruptedException e) {
System.out.println(e);
}
}
}
The writer :
import java.util.HashMap;
import java.util.Scanner;
public class GestionnaireSaisie extends Thread {
private HashMap<Integer, Message<String>> messages;
public GestionnaireSaisie(HashMap<Integer, Message<String>> messages) {
this.messages = messages;
}
public void run() {
Scanner scanner = new Scanner(System.in);
int id;
String content;
int time_refresh;
while (true) {
id = scanner.nextInt();
content = scanner.next();
time_refresh = scanner.nextInt();
Message<String> found_msg = messages.get(id);
found_msg.setContent(content);
found_msg.setRefreshTime(time_refresh);
}
}
}
And the most interesting class, the shared object which contains shared data :
import java.util.concurrent.Semaphore;
public class Message<T> {
private static int maxid;
private int id;
private T content;
private int refresh_time;
public Semaphore mutex_content, mutex_refresh_time, semNbl;
public static int nbL = 0;
public int getId() {
return id;
}
public Message(T content, int refresh_time, Semaphore mutex_content, Semaphore mutex_refresh_time, Semaphore semNbl) {
id = maxid;
Message.maxid++;
this.content = content;
this.refresh_time = refresh_time;
this.mutex_content = mutex_content;
this.mutex_refresh_time = mutex_refresh_time;
this.semNbl = semNbl;
}
// <!-- CONTENT
public void setContent(T content) {
try {
mutex_content.acquire();
this.content = content;
mutex_content.release();
} catch(InterruptedException e) {
System.out.println(e);
}
}
public T getContent() {
T ret = null;
try {
semNbl.acquire();
Message.nbL++;
if(Message.nbL == 1) {
mutex_content.acquire();
}
semNbl.release();
ret = content;
semNbl.acquire();
Message.nbL--;
if(Message.nbL == 0) {
mutex_content.release();
}
semNbl.release();
} catch(InterruptedException e) {
System.out.println(e);
}
return ret;
}
// CONTENT -->
// <!-- REFRESH TIME
public void setRefreshTime(int refresh_time) {
try {
mutex_refresh_time.acquire();
this.refresh_time = refresh_time;
mutex_refresh_time.release();
} catch(InterruptedException e) {
System.out.println(e);
}
}
public int getRefresh_time() {
int ret = 0;
try {
semNbl.acquire();
Message.nbL++;
if(Message.nbL == 1) {
mutex_refresh_time.acquire();
}
semNbl.release();
ret = refresh_time;
semNbl.acquire();
Message.nbL--;
if(Message.nbL == 0) {
mutex_refresh_time.release();
}
semNbl.release();
} catch(InterruptedException e) {
System.out.println(e);
}
return ret;
}
// REFRESH TIME -->
}
Here some code to test it :
Semaphore mutex_content = new Semaphore(1);
Semaphore mutex_refresh_time = new Semaphore(1);
Semaphore semNbl = new Semaphore(1);
Message<String> message1 = new Message<String>("Bonjour le monde !", 5, mutex_content, mutex_refresh_time, semNbl);
new Lecteur(message1).start();
HashMap<Integer, Message<String>> messages = new HashMap<Integer, Message<String>>();
messages.put(message1.getId(), message1);
GestionnaireSaisie gs = new GestionnaireSaisie(messages);
gs.start();
I am building an app with a self-made LruDiskCache to reduce loading times. The LruDiskCache downloads a file if it is not already present and returns it via a callback. I'm having a very weird issue where the first image isn't loaded properly. This only happends the first time a activity is started. If you open the same activity a secon time the image is loaded properly.
After debugging i found that i get the following debug message: --- SkImageDecoder Factory returned null. I've read multiple issues regarding this problem, but the all involve downloading an image through an inputstream, while i'm first downloading the image to persistent storage.
My cache-class:
public class LruDiskCache {
private static final String LOGTAG = "LruDiskCache";
//Cache size
private final long cacheMaxSize;
private volatile long currentCacheSize;
public static final int DEFAULT_CACHE_SIZE_KB = 1024;
public static final int MINIMUM_CACHE_SIZE_KB = 128;
//Preferences
private final String cachePreferencesName;
private final String chachePreferencesSize = "cacheSize";
private final SharedPreferences cachePreferences;
//Lock
private final Object mDiskCacheLock = new Object();
//Cache Path
private final File cachePath;
//Initialisation
private boolean openingCache;
//Static variables
private static final long BYTES_IN_KB = 1024;
public LruDiskCache (Context c, String cacheName, int cacheMaxSizeKB){
//Preferences
cachePreferencesName = cacheName + "CachePreferences";
cachePreferences = c.getSharedPreferences(cachePreferencesName, Context.MODE_PRIVATE);
//Paths
cachePath = new File(c.getFilesDir().getPath()+"/"+cacheName);
//Cache size
if(cacheMaxSizeKB < MINIMUM_CACHE_SIZE_KB){
throw new IllegalArgumentException
("Invalid cache size, size must be bigger than "
+ MINIMUM_CACHE_SIZE_KB + "kb.");
}
cacheMaxSize = cacheMaxSizeKB * BYTES_IN_KB;
//Initialize
openingCache = true;
new InitializeCache().execute();
}
//PUBLIC METHODS
public synchronized void getRemoteFile(URL remoteFile, Callback c){
if(openingCache){
try {
mDiskCacheLock.wait(1000);
} catch (InterruptedException e) {
c.onRequestedFileRetrieved(null, false);
}
}
String path = createFilePath(remoteFile);
File f = new File(path);
if(f.exists() && f.isFile()){
f.setLastModified(System.currentTimeMillis());
c.onRequestedFileRetrieved(f, true);
} else {
new RemoteFileDownloadTask(remoteFile, f, c).execute();
}
}
//PRIVATE METHODS
private String createFilePath(URL key){
return cachePath + "/" + key.getHost() + key.getPath();
}
private synchronized void cleanUpCache(){
long cacheSize = getDirSize(cachePath);
int failedToDeleteCounter = 0;
while(cacheSize > cacheMaxSize){
File toDelete = getFirstRequestedFile(cachePath);
Log.w("LruDiskCache", "File to be deleted: " + toDelete.getName() + ".");
long toDeleteSize = toDelete.length();
if(!toDelete.delete()){
failedToDeleteCounter++;
} else {
Log.w("LruDiskCache", "Deleted file to clean cache.");
cacheSize -= toDeleteSize;
}
if(failedToDeleteCounter > 100){
Log.w("LruDiskCache", "Failed to clean cache, could not delete files.");
break;
}
}
}
private File getFirstRequestedFile(File directory){
File first = null;
for(File f : directory.listFiles()){
if(f.isFile()){
if(first == null){
first = f;
} else {
if(f.lastModified() < first.lastModified()){
first = f;
}
}
} else if (f.isDirectory()) {
File firstReqInDir = getFirstRequestedFile(f);
if(first == null){
first = firstReqInDir;
} else if (firstReqInDir.lastModified() < first.lastModified()){
first = firstReqInDir;
}
}
}
return first;
}
private long getDirSize(File dir) {
long bytes = 0;
for (File f : dir.listFiles()) {
if (f.isDirectory()) {
bytes += getDirSize(f);
} else {
bytes += f.length();
}
}
return bytes;
}
//ASYNC TASKS
private class InitializeCache implements Runnable{
public void execute(){
new Thread(this).start();
}
#Override
public void run() {
synchronized (mDiskCacheLock) {
Log.d("Initialize cache", "Starting init...");
if (!cachePath.exists()) {
if (!cachePath.mkdirs()) {
mDiskCacheLock.notifyAll();
openingCache = false;
}
}
currentCacheSize = getDirSize(cachePath);
Log.d("LruDiskCache", "Cache size: " + currentCacheSize / BYTES_IN_KB + "kb.");
if(currentCacheSize > cacheMaxSize){
cleanUpCache();
}
Log.d("Initialize cache", "Did init...");
mDiskCacheLock.notifyAll();
openingCache = false;
}
}
}
private class RemoteFileDownloadTask extends AsyncTask<Void, Void, File> {
private final Callback c;
private URL remoteFile;
private File localFile;
protected RemoteFileDownloadTask(URL remoteFile, File localFile, Callback c){
this.c = c;
this.remoteFile = remoteFile;
this.localFile = localFile;
}
#Override
protected File doInBackground(Void... params) {
if(retrieveRemoteFile(remoteFile, localFile)){
return localFile;
} else {
return null;
}
}
#Override
protected void onPostExecute(File file) {
super.onPostExecute(file);
currentCacheSize += file.length();
if(currentCacheSize > cacheMaxSize){
cleanUpCache();
}
c.onRequestedFileRetrieved(file, true);
}
public boolean retrieveRemoteFile(URL remote, File filePath) {
try {
if (filePath.exists() && filePath.isFile()) {
return true;
} else {
if (!filePath.getParentFile().exists()) {
if (!filePath.getParentFile().mkdirs()) {
return false;
}
}
}
} catch (Exception e){
return false;
}
Log.w("LruDiskCache", "Created empty file: " + filePath.getPath());
Log.w("LruDiskCache", "Downloading source from: " + remote.toString());
try {
FileOutputStream fos;
InputStream is;
BufferedInputStream bis;
fos = new FileOutputStream(filePath);
HttpURLConnection con = (HttpURLConnection) remote.openConnection();
if(con.getResponseCode() != HttpURLConnection.HTTP_OK){
Log.e("Receiver", "HTTP Response code is not OK");
return false;
}
is = con.getInputStream();
bis = new BufferedInputStream(is);
while(bis.available() > 0){
fos.write(bis.read());
}
bis.close();
is.close();
fos.close();
} catch (Exception e) {
return false;
}
Log.d("LruDiskCacheReceiver", filePath.getPath() + " received, " + filePath.length() + " bytes.");
return true;
}
}
//CALLBACK INTERFACE
public interface Callback{
public abstract void onRequestedFileRetrieved(File f, boolean success);
}
}
And the implementation is shown here:
URL emblemURL = new URL(data[position].getEmblemUrl());
cache.getRemoteFile(emblemURL, new LruDiskCache.Callback() {
#Override
public void onRequestedFileRetrieved(File f, boolean success) {
if (success && f.exists()) {
Drawable bitmap = Drawable.createFromPath(f.getAbsolutePath());
emblem.setImageDrawable(bitmap);
}
}
});
Any help is appreciated.
I am using org.fusesource.mqtt (mqtt-client-1.0-20120208.162159-18-uber) and wrote a listener in Java based on the non-blocking example.
I use my listener class in the following way:
Listener mqList = new Listener("tcp://localhost:1883", "mytopic/#", "c:/test.log", true);
new Thread(mqList).start( );
This work perfectly.
If I create two instances/threads then conflicts seem to arise and I get connect/disconnect messages flowing over me.
Here is the usage that fails:
Listener mqList = new Listener("tcp://localhost:1883", "mytopic/#", "c:/test.log", true);
new Thread(mqList).start( );
Listener mqList1 = new Listener("tcp://localhost:1883", "mytopic1/#", "c:/test1.log", true);
new Thread(mqList1).start( );
My Listener class is quite simple and I am puzzled why this does not work in multiple threads. Any ideas/hints?
Here is my class definition:
import org.fusesource.hawtbuf.Buffer;
import org.fusesource.hawtbuf.UTF8Buffer;
import org.fusesource.mqtt.client.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.logging.*;
import java.io.*;
import java.net.URISyntaxException;
public class Listener implements Runnable{
private static final long DEFAULT_SLEEP_BEFORE_RE_ATTEMPT_IN_SECONDS = 5000;
private static final long DEFAULT_MAX_RE_ATTEMPT_DURATION_IN_SECONDS = 3600 * 3;
private long listenerSleepBeforeReAttemptInSeconds;
private long listenerMaxReAttemptDurationInSeconds;
private MQTT mqtt;
private ArrayList<Topic> topics;
private boolean listenerDebug;
private String listenerHostURI;
private String listenerTopic;
private String listenerLogFile;
private long listenerLastSuccessfulSubscription;
private Logger fLogger;
private String NEW_LINE = System.getProperty("line.separator");
public Listener(String listenerHostURI, String listenerTopic, String logFile, boolean debug) {
this(listenerHostURI, listenerTopic, logFile, DEFAULT_SLEEP_BEFORE_RE_ATTEMPT_IN_SECONDS, DEFAULT_MAX_RE_ATTEMPT_DURATION_IN_SECONDS, debug);
}
public Listener(String listenerHostURI, String listenerTopic, String logFile, long listenerSleepBeforeReAttemptInSeconds, long listenerMaxReAttemptDurationInSeconds, boolean debug) {
init(listenerHostURI, listenerTopic, logFile, listenerSleepBeforeReAttemptInSeconds, listenerMaxReAttemptDurationInSeconds, debug);
}
private void init(String listenerHostURI, String listenerTopic, String logFile, long listenerSleepBeforeReAttemptInSeconds, long listenerMaxReAttemptDurationInSeconds, boolean debug) {
this.listenerHostURI = listenerHostURI;
this.listenerTopic = listenerTopic;
this.listenerLogFile = logFile;
this.listenerSleepBeforeReAttemptInSeconds = listenerSleepBeforeReAttemptInSeconds;
this.listenerMaxReAttemptDurationInSeconds = listenerMaxReAttemptDurationInSeconds;
this.listenerDebug = debug;
initMQTT();
}
private void initMQTT() {
mqtt = new MQTT();
listenerLastSuccessfulSubscription = System.currentTimeMillis();
try {
fLogger = Logger.getLogger("eTactica.mqtt.listener");
FileHandler handler = new FileHandler(listenerLogFile);
fLogger.addHandler(handler);
} catch (IOException e) {
System.out.println("Logger - Failed");
}
try {
mqtt.setHost(listenerHostURI);
} catch (URISyntaxException e) {
stderr("setHost failed: " + e);
stderr(e);
}
QoS qos = QoS.AT_MOST_ONCE;
topics = new ArrayList<Topic>();
topics.add(new Topic(listenerTopic, qos));
}
private void stdout(String x) {
if (listenerDebug) {
fLogger.log(Level.INFO, x + NEW_LINE);
}
}
private void stderr(String x) {
if (listenerDebug) {
fLogger.log(Level.SEVERE, x + NEW_LINE);
}
}
private void stderr(Throwable e) {
if (listenerDebug) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
fLogger.log(Level.SEVERE, sw.toString() + NEW_LINE);
}
}
private void subscriptionSuccessful() {
listenerLastSuccessfulSubscription = System.currentTimeMillis();
}
private boolean tryToListen() {
return ((System.currentTimeMillis() - listenerLastSuccessfulSubscription) < listenerMaxReAttemptDurationInSeconds * 1000);
}
private void sleepBeforeReAttempt() throws InterruptedException {
stdout(String.format(("Listener stopped, re-attempt in %s seconds."), listenerSleepBeforeReAttemptInSeconds));
Thread.sleep(listenerSleepBeforeReAttemptInSeconds);
}
private void listenerReAttemptsOver() {
stdout(String.format(("Listener stopped since reattempts have failed for %s seconds."), listenerMaxReAttemptDurationInSeconds));
}
private void listen() {
final CallbackConnection connection = mqtt.callbackConnection();
final CountDownLatch done = new CountDownLatch(1);
/* Runtime.getRuntime().addShutdownHook(new Thread(){
#Override
public void run() {
setName("MQTT client shutdown");
stderr("Disconnecting the client.");
connection.getDispatchQueue().execute(new Runnable() {
public void run() {
connection.disconnect(new Callback<Void>() {
public void onSuccess(Void value) {
stdout("Disconnecting onSuccess.");
done.countDown();
}
public void onFailure(Throwable value) {
stderr("Disconnecting onFailure: " + value);
stderr(value);
done.countDown();
}
});
}
});
}
});
*/
connection.listener(new org.fusesource.mqtt.client.Listener() {
public void onConnected() {
stdout("Listener onConnected");
}
public void onDisconnected() {
stdout("Listener onDisconnected");
}
public void onPublish(UTF8Buffer topic, Buffer body, Runnable ack) {
stdout(topic + " --> " + body.toString());
ack.run();
}
public void onFailure(Throwable value) {
stdout("Listener onFailure: " + value);
stderr(value);
done.countDown();
}
});
connection.resume();
connection.connect(new Callback<Void>() {
public void onFailure(Throwable value) {
stderr("Connect onFailure...: " + value);
stderr(value);
done.countDown();
}
public void onSuccess(Void value) {
final Topic[] ta = topics.toArray(new Topic[topics.size()]);
connection.subscribe(ta, new Callback<byte[]>() {
public void onSuccess(byte[] value) {
for (int i = 0; i < value.length; i++) {
stdout("Subscribed to Topic: " + ta[i].name() + " with QoS: " + QoS.values()[value[i]]);
}
subscriptionSuccessful();
}
public void onFailure(Throwable value) {
stderr("Subscribe failed: " + value);
stderr(value);
done.countDown();
}
});
}
});
try {
done.await();
} catch (Exception e) {
stderr(e);
}
}
#Override
public void run() {
while (tryToListen()) {
initMQTT();
listen();
try {
sleepBeforeReAttempt();
} catch (InterruptedException e) {
stderr("Sleep failed:" + e);
stderr(e);
}
}
listenerReAttemptsOver();
}
}
A TCP port can have only one listener. That number in "tcp://localhost:1883" has to be unique for each listener. Someplace, presumably (I'm not familiar with this specific API) you're probably starting a client with a port number too; the numbers must match between the client and server.
I am really not clear on explaining this requirement but what I need basically is a JSP page that connects to a Unix server and gets the word count of a file and displays on the JSP page. I have looked on various questions here but nothing helped. A sample code would be of much help. Thanks
Kavin, I guess you must have found some other solution or moved on by now. However, I just came across a requirement that led me to this page.
I looked through the somewhat smuckish responses on this page and many others but could not find a simple to use Telnet client at all.
I spent a little bit of time and wrote a simple client on top of Commons Net's solution. Please forgive the System.out and System.err in the code, I got it to barely work.
public static void main(String[] args) throws Exception {
SimpleTelnetClient client = new SimpleTelnetClient("localhost", 2323);
client.connect();
String result = client.waitFor("login:");
System.out.println("Got " + result);
client.send("username");
result = client.waitFor("Password:");
System.out.println("Got " + result);
client.send("password");
client.waitFor("#");
client.send("ls -al");
result = client.waitFor("#");
System.out.println("Got " + result);
client.send("exit");
}
Not sure if it will help you anymore, but perhaps it could be a starting point for others.
import java.io.InputStream;
import java.io.PrintStream;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import org.apache.commons.net.telnet.EchoOptionHandler;
import org.apache.commons.net.telnet.InvalidTelnetOptionException;
import org.apache.commons.net.telnet.SuppressGAOptionHandler;
import org.apache.commons.net.telnet.TelnetClient;
import org.apache.commons.net.telnet.TerminalTypeOptionHandler;
public class SimpleTelnetClient {
static class Responder extends Thread {
private StringBuilder builder = new StringBuilder();
private final SimpleTelnetClient checker;
private CountDownLatch latch;
private String waitFor = null;
private boolean isKeepRunning = true;
Responder(SimpleTelnetClient checker) {
this.checker = checker;
}
boolean foundWaitFor(String waitFor) {
return builder.toString().contains(waitFor);
}
public synchronized String getAndClearBuffer() {
String result = builder.toString();
builder = new StringBuilder();
return result;
}
#Override
public void run() {
while (isKeepRunning) {
String s;
try {
s = checker.messageQueue.take();
} catch (InterruptedException e) {
break;
}
synchronized (Responder.class) {
builder.append(s);
}
if (waitFor != null && latch != null && foundWaitFor(waitFor)) {
latch.countDown();
}
}
}
public String waitFor(String waitFor) {
synchronized (Responder.class) {
if (foundWaitFor(waitFor)) {
return getAndClearBuffer();
}
}
this.waitFor = waitFor;
latch = new CountDownLatch(1);
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
return null;
}
String result = null;
synchronized (Responder.class) {
result = builder.toString();
builder = new StringBuilder();
}
return result;
}
}
static class TelnetReader extends Thread {
private final SimpleTelnetClient checker;
private final TelnetClient tc;
TelnetReader(SimpleTelnetClient checker, TelnetClient tc) {
this.checker = checker;
this.tc = tc;
}
#Override
public void run() {
InputStream instr = tc.getInputStream();
try {
byte[] buff = new byte[1024];
int ret_read = 0;
do {
ret_read = instr.read(buff);
if (ret_read > 0) {
checker.sendForResponse(new String(buff, 0, ret_read));
}
} while (ret_read >= 0);
} catch (Exception e) {
System.err.println("Exception while reading socket:" + e.getMessage());
}
try {
tc.disconnect();
checker.stop();
System.out.println("Disconnected.");
} catch (Exception e) {
System.err.println("Exception while closing telnet:" + e.getMessage());
}
}
}
private String host;
private BlockingQueue<String> messageQueue = new LinkedBlockingQueue<String>();
private int port;
private TelnetReader reader;
private Responder responder;
private TelnetClient tc;
public SimpleTelnetClient(String host, int port) {
this.host = host;
this.port = port;
}
protected void stop() {
responder.isKeepRunning = false;
responder.interrupt();
}
public void send(String command) {
PrintStream ps = new PrintStream(tc.getOutputStream());
ps.println(command);
ps.flush();
}
public void sendForResponse(String s) {
messageQueue.add(s);
}
public void connect() throws Exception {
tc = new TelnetClient();
TerminalTypeOptionHandler ttopt = new TerminalTypeOptionHandler("VT100", false, false, true, false);
EchoOptionHandler echoopt = new EchoOptionHandler(true, false, true, false);
SuppressGAOptionHandler gaopt = new SuppressGAOptionHandler(true, true, true, true);
try {
tc.addOptionHandler(ttopt);
tc.addOptionHandler(echoopt);
tc.addOptionHandler(gaopt);
} catch (InvalidTelnetOptionException e) {
System.err.println("Error registering option handlers: " + e.getMessage());
}
tc.connect(host, port);
reader = new TelnetReader(this, tc);
reader.start();
responder = new Responder(this);
responder.start();
}
public String waitFor(String s) {
return responder.waitFor(s);
}
}
Why wouldn't you just use an open source telnet client. There is bound to be several to choose from. Google lists many.