package com.lmit.jenkins.android.networking;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.Semaphore;
import android.content.Context;
import com.lmit.jenkins.android.activity.JenkinsMobi;
import com.lmit.jenkins.android.addon.ApplicationStatus;
import com.lmit.jenkins.android.addon.LocalStorage;
import com.lmit.jenkins.android.configuration.Configuration;
import com.lmit.jenkins.android.logger.Logger;
import com.lmit.jenkinscloud.commons.JenkinsCloudDataNode;
import com.lmit.jenkinscloud.commons.JenkinsCloudNode;
import com.lmit.jenkinscloud.commons.SyncCallback;
public class BackgroundLoader {
private static final long LOAD_ITEMS_SLEEP_TIME_MSEC = 100L;
private static Logger log = Logger.getInstance();
private static LinkedBlockingDeque<ExecutionRequest> executionRequests = new LinkedBlockingDeque<ExecutionRequest>();
private boolean stop;
public static class ExecutionRequest {
private Context ctx;
private String pluginId;
private int fromNode;
private int maxNodes;
public ExecutionRequest(Context ctx, String pluginId, int from, int max) {
this.ctx = ctx;
this.pluginId = pluginId;
this.fromNode = from;
this.maxNodes = max;
}
public int getFromNode() {
return fromNode;
}
public void setFromNode(int fromNode) {
this.fromNode = fromNode;
}
public int getMaxNodes() {
return maxNodes;
}
public void setMaxNodes(int maxNodes) {
this.maxNodes = maxNodes;
}
public Context getCtx() {
return ctx;
}
public void setCtx(Context ctx) {
this.ctx = ctx;
}
public String getPluginId() {
return pluginId;
}
public void setPluginId(String pluginId) {
this.pluginId = pluginId;
}
}
private static BackgroundLoader instance;
public static BackgroundLoader getInstance() {
if (instance == null) {
instance = new BackgroundLoader();
}
return instance;
}
private BackgroundLoader() {
Thread th = new Thread(new Runnable() {
@Override
public void run() {
while (!stop) {
ExecutionRequest request;
try {
log.debug("backgroud loader waiting for new requests");
request = executionRequests.take();
startLoad(request.getCtx(), request.getPluginId());
} catch (InterruptedException e) {
;
}
}
instance = null;
}
});
th.setName("Background-load");
th.start();
}
public void enqueue(ExecutionRequest request) {
log.debug("New background loading request for pluginId='"
+ request.getPluginId() + "'");
stop = false;
executionRequests.offer(request);
}
private void startLoad(final Context ctx, final String pluginId) {
log.debug("Running background load for pluginId='" + pluginId + "'");
LocalStorage store = LocalStorage.getInstance();
JenkinsCloudAPIClient client = new JenkinsCloudAPIClient(JenkinsMobi.getAppContext());
String rootPath = Configuration.getInstance().getHomeNode();
JenkinsCloudDataNode rootNode = (JenkinsCloudDataNode) store.getNode(rootPath);
Map<String, String> headers = Configuration.getInstance().getRequestHeaders();
load(client, headers, rootPath, rootNode);
}
private void load(final JenkinsCloudAPIClient client,
final Map<String, String> headers, final String parentPath,
final JenkinsCloudDataNode node) {
if(!Configuration.getInstance().isConnected()) {
return;
}
if (node == null || node.getPath() == null || node.getPath().equals("menu")) {
return;
}
String path = node.getPath();
final String currentPath = getPath(parentPath, path);
if (currentPath == null) {
return;
}
log.debug("Background loading of " + currentPath);
final List<JenkinsCloudDataNode> subNodesToLoad =
new ArrayList<JenkinsCloudDataNode>();
final Semaphore callFinished = new Semaphore(1);
try {
callFinished.acquire();
} catch (InterruptedException e1) {
}
client.doGet(false, currentPath, new SyncCallback<JenkinsCloudNode>() {
@Override
public void onSuccess(JenkinsCloudNode result) {
if (result instanceof JenkinsCloudDataNode) {
JenkinsCloudDataNode resultNode = (JenkinsCloudDataNode) result;
List<JenkinsCloudDataNode> resultSubNodes = resultNode.getPayload();
if (resultSubNodes != null) {
for (JenkinsCloudDataNode subNode : resultSubNodes) {
if (subNode.isPreload()) {
subNodesToLoad.add((JenkinsCloudDataNode) subNode);
}
}
}
}
callFinished.release();
}
@Override
public void onFailure(Throwable e) {
log.error("Cannot load node", e);
callFinished.release();
}
}, JenkinsCloudDataNode.class, headers, null, null);
try {
callFinished.acquire();
} catch (InterruptedException e1) {
}
for (JenkinsCloudDataNode subNode : subNodesToLoad) {
load(client, headers, currentPath, subNode);
try {
Thread.sleep(LOAD_ITEMS_SLEEP_TIME_MSEC);
} catch (InterruptedException e1) {
}
}
}
private String getPath(String parentPath,
String nodePath) {
if(nodePath == null) {
return null;
}
if(nodePath.equals("/")) {
nodePath = "";
}
if(nodePath.startsWith("/")) {
return null;
}
if(!parentPath.endsWith("/")) {
parentPath += "/";
}
return parentPath + nodePath;
}
public void stop() {
stop = true;
}
}