/*
* Copyright (C) 2013 4th Line GmbH, Switzerland
*
* The contents of this file are subject to the terms of either the GNU
* Lesser General Public License Version 2 or later ("LGPL") or the
* Common Development and Distribution License Version 1 or later
* ("CDDL") (collectively, the "License"). You may not use this file
* except in compliance with the License. See LICENSE.txt for more
* information.
*
* This program 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.
*/
package com.kitty.poclient.upnp;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.fourthline.cling.model.message.StreamRequestMessage;
import org.fourthline.cling.model.message.StreamResponseMessage;
import org.fourthline.cling.transport.spi.StreamClient;
import org.fourthline.cling.transport.spi.StreamClientConfiguration;
import org.seamless.util.Exceptions;
import android.util.Log;
import com.kitty.poclient.common.Constant;
import com.kitty.poclient.common.UpnpApp;
/**
* Implements the timeout/callback processing and unifies exception handling.
*
* @author Christian Bauer
*/
// Timeout of // sendBroadcast
public abstract class MyAbstractStreamClient<C extends StreamClientConfiguration, REQUEST> implements StreamClient<C> {
final private static Logger log = Logger.getLogger(StreamClient.class.getName());
private static final String TAG = MyAbstractStreamClient.class.getSimpleName() + " ";
@Override
public StreamResponseMessage sendRequest(StreamRequestMessage requestMessage) throws InterruptedException {
if (log.isLoggable(Level.FINE))
log.fine("Preparing HTTP request: " + requestMessage);
REQUEST request = createRequest(requestMessage);
if (request == null)
return null;
Callable<StreamResponseMessage> callable = createCallable(requestMessage, request);
// We want to track how long it takes
long start = System.currentTimeMillis();
// Execute the request on a new thread
Future<StreamResponseMessage> future = getConfiguration().getRequestExecutorService().submit(callable);
// Wait on the current thread for completion
try {
if (log.isLoggable(Level.FINE))
log.fine("Waiting " + getConfiguration().getTimeoutSeconds() + " seconds for HTTP request to complete: " + requestMessage);
StreamResponseMessage response = future.get(getConfiguration().getTimeoutSeconds(), TimeUnit.SECONDS);
// Log a warning if it took too long
long elapsed = System.currentTimeMillis() - start;
if (log.isLoggable(Level.FINEST))
log.finest("Got HTTP response in " + elapsed + "ms: " + requestMessage);
if (getConfiguration().getLogWarningSeconds() > 0 && elapsed > getConfiguration().getLogWarningSeconds() * 1000) {
log.warning("HTTP request took a long time (" + elapsed + "ms): " + requestMessage);
}
return response;
} catch (InterruptedException ex) {
if (log.isLoggable(Level.FINE))
log.fine("Interruption, aborting request: " + requestMessage);
abort(request);
throw new InterruptedException("HTTP request interrupted and aborted");
} catch (TimeoutException ex) {
log.info("Timeout of " + getConfiguration().getTimeoutSeconds() + " seconds while waiting for HTTP request to complete, aborting: " + requestMessage);
if (getIpAddress(requestMessage).equals(Constant.DEVICE_IP_ADDRESS)) { // 条件:当前请求的IP端口等于已经选定设备的IP端口
UpnpApp.sendBroadcast(Constant.ACTION_DEAL_STREAMCLIENT_TIMEOUT_OR_FAILURE);
Log.e(TAG, "sendBroadcast --> TimeoutException");
}
abort(request);
return null;
} catch (ExecutionException ex) {
Throwable cause = ex.getCause();
if (!logExecutionException(cause)) {
log.log(Level.WARNING, "HTTP request failed: " + requestMessage, Exceptions.unwrap(cause));
}
return null;
} finally {
onFinally(request);
}
}
private String getIpAddress(StreamRequestMessage requestMessage) {
String str = requestMessage.toString();
String ip = str.substring(str.indexOf("http://") + 7, str.lastIndexOf(":"));
Log.e(TAG, "TimeoutException:ip=" + ip);
return ip;
}
/**
* Create a proprietary representation of this request, log warnings and
* return <code>null</code> if creation fails.
*/
abstract protected REQUEST createRequest(StreamRequestMessage requestMessage);
/**
* Create a callable procedure that will execute the request.
*/
abstract protected Callable<StreamResponseMessage> createCallable(StreamRequestMessage requestMessage, REQUEST request);
/**
* Cancel and abort the request immediately, with the proprietary API.
*/
abstract protected void abort(REQUEST request);
/**
* @return <code>true</code> if no more logging of this exception should be
* done.
*/
abstract protected boolean logExecutionException(Throwable t);
protected void onFinally(REQUEST request) {
// Do nothing
}
}