package com.lmit.jenkins.android.networking; import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.Map; import android.content.Context; 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 JenkinsCloudAPIClient { private static Logger log = Logger.getInstance(); private Context ctx; private boolean cacheHit = false; private boolean forceRefresh = false; private boolean appendMode = false; public JenkinsCloudAPIClient(Context ctx) { this.ctx = ctx; } public void setForceRefresh(boolean refresh) { forceRefresh = refresh; } public void setAppendMode(boolean mode) { appendMode = mode; } public boolean isCacheHit() { return cacheHit; } public void doGet(final boolean forceRefresh, final String path, final SyncCallback<JenkinsCloudNode> syncCallback, Class<? extends JenkinsCloudNode> targetClass, Map<String, String> userHeaders, String itemsFrom, String items) { JenkinsCloudNode localData = LocalStorage.getInstance().getNode(path, targetClass); if(!Configuration.getInstance().isConnected()) { cacheModeQuery(syncCallback, localData); return; } if (!forceRefresh) { if (localData != null) { String eTag = localData.getEtag(); log.debug("HTTP-Cache HIT! " + (eTag == null ? "" : "eTag=" + eTag)); if (eTag != null) { userHeaders.put("If-None-Match", eTag); } else { syncCallback.onSuccess(localData); cacheHit = true; return; } } else { log.debug("Cache MISS!"); } } else { log.debug("Force fetching of new data"); } final HudsonMobiAsyncHttpClient client = new HudsonMobiAsyncHttpClient(); client.setUserHeaders(userHeaders); String query = path; if (itemsFrom != null && items != null) { query += (query.indexOf('?') > 0 ? "&":"?"); query += "x-jenkinscloud-accept-items=" + items + "&x-jenkinscloud-accept-from=" + itemsFrom; } client.call(forceRefresh, query, new SyncCallbackWrapper<JenkinsCloudNode>( syncCallback) { @Override public void onSuccess(JenkinsCloudNode result) { Configuration.getInstance().setLastRefreshTimestamp( "" + new Date().getTime()); Configuration.getInstance().save(); saveResultInLocalDB(path, result, forceRefresh); ImageDownloader.getInstance().preloadImage(path, result); syncCallback.onSuccess(result); } }); } public void doPostSynch(final String path, SyncCallback<JenkinsCloudNode> syncCallback, Map<String, String> userHeaders, byte[] postData, String postContentType) { if (!Configuration.getInstance().isConnected()) { syncCallback.onFailure(new ClientDisconnectedException()); return; } final HudsonMobiSynchHttpClient client = new HudsonMobiSynchHttpClient(); client.setUserHeaders(userHeaders); String query = path; client.doPost(query, postData, postContentType, new SyncCallbackWrapper<JenkinsCloudNode>( syncCallback) { @Override public void onSuccess(JenkinsCloudNode result) { saveResultInLocalDB(path, result, true); ImageDownloader.getInstance().preloadImage(path, result); super.onSuccess(result); } }); } private void cacheModeQuery( final SyncCallback<JenkinsCloudNode> syncCallback, JenkinsCloudNode localData) { if(localData != null) { syncCallback.onSuccess(localData); } else { syncCallback.onFailure(new ClientDisconnectedException()); } } public void callSync(final String path, final SyncCallback<JenkinsCloudNode> syncCallback, Map<String, String> headers, String itemsFrom, String items) { JenkinsCloudNode localData = LocalStorage.getInstance() .getNode(path); if(!Configuration.getInstance().isConnected()) { cacheModeQuery(syncCallback, localData); return; } if (!forceRefresh) { if (localData != null && !Configuration.getInstance().isConnected()) { log.debug("Cache HIT " + path + ": returning node as working in disconnected mode"); cacheHit = true; syncCallback.onSuccess(localData); return; } else if (localData == null) { log.debug("Cache MISS!"); } } else { log.debug("Force fetching of new data"); } final JenkinsCloudNode cachedData = localData; final HudsonMobiSynchHttpClient client = new HudsonMobiSynchHttpClient(); client.setUserHeaders(headers); String query = path; if (itemsFrom != null && items != null) { query += (query.indexOf('?') > 0 ? "&":"?"); query += "x-jenkinscloud-accept-items=" + items + "&x-jenkinscloud-accept-from=" + itemsFrom; } client.call(forceRefresh, query, new SyncCallback<JenkinsCloudNode>() { @Override public void onSuccess(JenkinsCloudNode result) { Configuration.getInstance().setLastRefreshTimestamp( "" + new Date().getTime()); Configuration.getInstance().save(); saveResultInLocalDB(path, result, forceRefresh); syncCallback.onSuccess(result); } @Override public void onFailure(Throwable e) { if(cachedData != null) { syncCallback.onSuccess(cachedData); } else { syncCallback.onFailure(e); } } }); } private void saveResultInLocalDB(final String path, final JenkinsCloudNode result, boolean refresh) { if (result != null) { if (appendMode) { JenkinsCloudNode existingNode = LocalStorage.getInstance().getNode(path); List<JenkinsCloudDataNode> newPayload = new LinkedList<JenkinsCloudDataNode>(); if(existingNode instanceof JenkinsCloudDataNode) { newPayload.addAll(((JenkinsCloudDataNode) existingNode).getPayload()); newPayload.addAll(((JenkinsCloudDataNode) result).getPayload()); ((JenkinsCloudDataNode) existingNode).setPayload(newPayload); } LocalStorage.getInstance().replaceNode(path, existingNode); } else { if(refresh) { LocalStorage.getInstance().evictNode(path, result); } LocalStorage.getInstance().putNode(path, result); } } } }