Example usage for java.lang InterruptedException InterruptedException

List of usage examples for java.lang InterruptedException InterruptedException

Introduction

In this page you can find the example usage for java.lang InterruptedException InterruptedException.

Prototype

public InterruptedException() 

Source Link

Document

Constructs an InterruptedException with no detail message.

Usage

From source file:org.htmlunit.NanoHTTPD.java

/**
 * Decodes the percent encoding scheme. <br/>
 * For example: "an+example%20string" -> "an example string"
 *//*from   w ww .  j av  a2s . c  om*/
protected String decodePercent(final String str) throws InterruptedException {
    try {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            switch (c) {
            case '+':
                sb.append(' ');
                break;
            case '%':
                sb.append((char) Integer.parseInt(str.substring(i + 1, i + 3), 16));
                i += 2;
                break;
            default:
                sb.append(c);
                break;
            }
        }
        return sb.toString();
    } catch (Exception e) {
        throw new InterruptedException();
    }
}

From source file:org.jboss.tools.ws.ui.utils.JAXRSTester.java

/**
 * Call a JAX-RS service/*from   www.  j a  va2s.  com*/
 * @param address
 * @param parameters
 * @param headers
 * @param methodType
 * @param requestBody
 * @param proxy
 * @param port
 * @throws Exception
 */
public void doTest(String address, Map<String, String> parameters, Map<String, String> headers,
        String methodType, String requestBody, String proxy, int port, String uid, String pwd)
        throws Exception {

    // handle the proxy
    Proxy proxyObject = null;
    if (proxy != null && proxy.length() > 0 && port > 0) {
        InetSocketAddress proxyAddress = new InetSocketAddress(proxy, port);
        proxyObject = new Proxy(Proxy.Type.HTTP, proxyAddress);
    }

    // clear the returned results
    resultBody = EMPTY_STRING;

    // get the parms string
    String query = buildWebQuery(parameters);

    // Clear the address of any leading/trailing spaces
    address = address.trim();

    // build the complete URL
    URL url = null;
    if (query != null && query.trim().length() > 0) {
        // add the ? if there are parameters
        if (!address.endsWith("?") && !address.contains("?")) {//$NON-NLS-1$ //$NON-NLS-2$

            // if we're a "GET" - add the ? by default
            if (methodType.equalsIgnoreCase("GET")) { //$NON-NLS-1$
                address = address + "?"; //$NON-NLS-1$

                // if we're a PUT or POST, check if we have parms
                // and add the ? if we do
            } else if (methodType.equalsIgnoreCase("POST")//$NON-NLS-1$ 
                    || methodType.equalsIgnoreCase("PUT") //$NON-NLS-1$
                    || methodType.equalsIgnoreCase("DELETE")) { //$NON-NLS-1$
                if (query.trim().length() > 0) {
                    address = address + "?"; //$NON-NLS-1$
                }
            }
        } else if (address.contains("?")) { //$NON-NLS-1$
            address = address + "&"; //$NON-NLS-1$
        }
        // add parms to the url if we have some
        url = new URL(address + query);
    } else {
        url = new URL(address);
    }

    // make connection
    HttpURLConnection httpurlc = null;
    if (proxyObject == null) {
        httpurlc = (HttpURLConnection) url.openConnection();
    } else {
        // if have proxy, pass it along
        httpurlc = (HttpURLConnection) url.openConnection(proxyObject);
    }

    // since we are expecting output back, set to true
    httpurlc.setDoOutput(true);

    // not sure what this does - may be used for authentication?
    httpurlc.setAllowUserInteraction(false);

    // set whether this is a GET or POST
    httpurlc.setRequestMethod(methodType);

    // if we have headers to add
    if (headers != null && !headers.isEmpty()) {
        Iterator<?> iter = headers.entrySet().iterator();
        while (iter.hasNext()) {
            Entry<?, ?> entry = (Entry<?, ?>) iter.next();
            if (entry.getKey() != null && entry.getKey() instanceof String)
                httpurlc.addRequestProperty((String) entry.getKey(), (String) entry.getValue());
        }
    }

    // if we have basic authentication to add, add it!
    if (uid != null && pwd != null) {
        String authStr = uid + ':' + pwd;
        byte[] authEncByte = Base64.encodeBase64(authStr.getBytes());
        String authStringEnc = new String(authEncByte);
        httpurlc.addRequestProperty("Authorization", "Basic " + authStringEnc); //$NON-NLS-1$//$NON-NLS-2$
    }

    requestHeaders = httpurlc.getRequestProperties();

    // Check if task has been interrupted
    if (Thread.interrupted()) {
        throw new InterruptedException();
    }

    // CONNECT!
    httpurlc.connect();

    // Check if task has been interrupted
    if (Thread.interrupted()) {
        throw new InterruptedException();
    }

    // If we are doing a POST and we have some request body to pass along, do it
    if (requestBody != null && (methodType.equalsIgnoreCase("POST") //$NON-NLS-1$
            || methodType.equalsIgnoreCase("PUT"))) { //$NON-NLS-1$
        requestBody = WSTestUtils.stripNLsFromXML(requestBody);
        OutputStreamWriter out = new OutputStreamWriter(httpurlc.getOutputStream());
        String stripped = stripCRLF(requestBody);
        out.write(stripped);
        out.close();
    }

    // Check if task has been interrupted
    if (Thread.interrupted()) {
        throw new InterruptedException();
    }

    // if we have headers to pass to user, copy them
    if (httpurlc.getHeaderFields() != null) {
        resultHeaders = httpurlc.getHeaderFields();
    }

    // retrieve result and put string results into the response
    InputStream is = null;
    try {
        is = httpurlc.getInputStream();
        // Check if task has been interrupted
        if (Thread.interrupted()) {
            throw new InterruptedException();
        }
        BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));//$NON-NLS-1$
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) {
            sb.append(line);
            sb.append("\n");//$NON-NLS-1$
        }
        br.close();
        resultBody = sb.toString();
        // Check if task has been interrupted
        if (Thread.interrupted()) {
            throw new InterruptedException();
        }
    } catch (IOException ie) {
        try {
            is = httpurlc.getErrorStream();

            // is possible that we're getting nothing back in the error stream
            if (is != null) {
                BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));//$NON-NLS-1$
                StringBuilder sb = new StringBuilder();
                String line;
                while ((line = br.readLine()) != null) {
                    sb.append(line);
                    sb.append("\n");//$NON-NLS-1$
                }
                br.close();
                resultBody = sb.toString();
            }
        } catch (IOException ie2) {
            resultBody = ie2.getLocalizedMessage();
        }
    }

    // as a last resort, if we still have nothing to report,
    // show an error message to the user
    if (resultBody == null || resultBody.trim().isEmpty()) {
        resultBody = JBossWSUIMessages.JAXRSRSTestView_Message_Unsuccessful_Test;
    }

    // disconnect explicitly (may not be necessary)
    httpurlc.disconnect();
}

From source file:net.rim.ejde.internal.ui.wizards.BasicBlackBerryProjectWizardPageTwo.java

private IStatus changeToNewProject() {
    class UpdateRunnable implements IRunnableWithProgress {
        public IStatus infoStatus = Status.OK_STATUS;

        public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
            try {
                if (fIsAutobuild == null) {
                    fIsAutobuild = Boolean.valueOf(CoreUtility.setAutoBuilding(false));
                }//from   ww w  .j  a  va2  s.  c  o  m
                infoStatus = updateProject(monitor);
            } catch (CoreException e) {
                throw new InvocationTargetException(e);
            } catch (OperationCanceledException e) {
                throw new InterruptedException();
            } finally {
                monitor.done();
            }
        }
    }
    UpdateRunnable op = new UpdateRunnable();
    try {
        getContainer().run(true, false, new WorkspaceModifyDelegatingOperation(op));
        return op.infoStatus;
    } catch (InvocationTargetException e) {
        final String title = Messages.NewBlackBerryProjectWizardPageTwo_error_title;
        final String message = Messages.NewBlackBerryProjectWizardPageTwo_error_message;
        ExceptionHandler.handle(e, getShell(), title, message);
    } catch (InterruptedException e) {
        // cancel pressed
    }
    return null;
}

From source file:com.offbynull.portmapper.common.NetworkUtils.java

/**
 * Attempts to put together a list of gateway addresses using pre-set values and running OS-specific processes.
 * @return a list of possible addresses for gateway device
 * @throws InterruptedException if interrupted
 */// ww  w  .  j a  va  2 s .co m
public static Set<InetAddress> getPotentialGatewayAddresses() throws InterruptedException {
    // Ask OS for gateway address
    String netstatOutput = "";
    try {
        netstatOutput = ProcessUtils.runProcessAndDumpOutput(5000L, "netstat", "-rn");
    } catch (IOException ioe) { // NOPMD
        // do nothing
        if (Thread.currentThread().isInterrupted()) {
            throw new InterruptedException();
        }
    }
    LinkedHashSet<String> strAddresses = new LinkedHashSet<>(RegexUtils.findAllIpv4Addresses(netstatOutput));

    // Push in defaults
    strAddresses.addAll(PRESET_IPV4_GATEWAY_ADDRESSES);

    LinkedHashSet<InetAddress> addresses = new LinkedHashSet<>();
    for (String strAddress : strAddresses) {
        try {
            InetAddress addr = InetAddress.getByName(strAddress);
            if (!addr.isAnyLocalAddress()) {
                addresses.add(addr);
            }
        } catch (UnknownHostException uhe) { // NOPMD
            // do nothing
        }
    }

    return addresses;
}

From source file:org.apache.http.impl.conn.FixedPoolingClientConnectionManager.java

ManagedClientConnection leaseConnection(final Future<HttpPoolEntry> future, final long timeout,
        final TimeUnit tunit) throws InterruptedException, ConnectionPoolTimeoutException {
    HttpPoolEntry entry;//from w  w  w. ja va2  s  .co  m
    try {
        entry = future.get(timeout, tunit);
        if (entry == null || future.isCancelled()) {
            throw new InterruptedException();
        }
        if (entry.getConnection() == null) {
            throw new IllegalStateException("Pool entry with no connection");
        }
        if (this.log.isDebugEnabled()) {
            this.log.debug("Connection leased: " + format(entry) + formatStats(entry.getRoute()));
        }
        return new ManagedClientConnectionImpl(this, this.operator, entry);
    } catch (ExecutionException ex) {
        Throwable cause = ex.getCause();
        if (cause == null) {
            cause = ex;
        }
        this.log.error("Unexpected exception leasing connection from pool", cause);
        // Should never happen
        throw new InterruptedException();
    } catch (TimeoutException ex) {
        throw new ConnectionPoolTimeoutException("Timeout waiting for connection");
    }
}

From source file:org.marketcetera.util.except.ExceptUtilsTest.java

@Test
public void wrap() {
    wrapHelper(new CloneNotSupportedException(), false);
    wrapHelper(new InterruptedException(), true);
    wrapHelper(new InterruptedIOException(), true);
    wrapHelper(new ClosedByInterruptException(), true);
    wrapHelper(new FileLockInterruptionException(), true);
    wrapHelper(new InterruptedNamingException(), true);
    wrapHelper(new I18NInterruptedException(), true);
    wrapHelper(new I18NInterruptedRuntimeException(), true);
}

From source file:org.apache.http2.impl.conn.PoolingClientConnectionManager.java

ManagedClientConnection leaseConnection(final Future<HttpPoolEntry> future, final long timeout,
        final TimeUnit tunit) throws InterruptedException, ConnectionPoolTimeoutException {
    HttpPoolEntry entry;/*from ww w. ja v  a 2s  . c  o m*/
    try {
        entry = future.get(timeout, tunit);
        if (entry == null || future.isCancelled()) {
            throw new InterruptedException();
        }
        if (entry.getConnection() == null) {
            throw new IllegalStateException("Pool entry with no connection");
        }
        if (this.log.isDebugEnabled()) {
            this.log.debug("Connection leased: " + format(entry) + formatStats(entry.getRoute()));
        }
        return new ManagedClientConnectionImpl(this, this.operator, entry);
    } catch (ExecutionException ex) {
        Throwable cause = ex.getCause();
        if (cause == null) {
            cause = ex;
        }
        this.log.error("Unexpected exception leasing connection from pool", cause);
        // Should never happen
        throw new InterruptedException();
    } catch (TimeoutException ex) {
        throw new ConnectionPoolTimeoutException("Timeout waiting for connection from pool");
    }
}

From source file:org.roda_project.commons_ip.model.impl.eark.EARKMETSUtils.java

public static void addRepresentationMETSToZipAndToMainMETS(Map<String, ZipEntryInfo> zipEntries,
        MetsWrapper mainMETSWrapper, String representationId, MetsWrapper representationMETSWrapper,
        String representationMetsPath, Path buildDir) throws IPException, InterruptedException {
    try {/*w  w w .  j a  v a 2  s.  co  m*/
        if (Thread.interrupted()) {
            throw new InterruptedException();
        }
        addMETSToZip(zipEntries, representationMETSWrapper, representationMetsPath, buildDir, false);
        Mptr mptr = new Mptr();
        mptr.setLOCTYPE(LocType.URL.toString());
        mptr.setType(IPConstants.METS_TYPE_SIMPLE);
        mptr.setHref(METSUtils.encodeHref(representationMetsPath));
        DivType representationDiv = createDivForStructMap(representationId);
        representationDiv.getMptr().add(mptr);
        mainMETSWrapper.getRepresentationsDiv().getDiv().add(representationDiv);
    } catch (JAXBException | IOException e) {
        throw new IPException("Error saving representation METS", e);
    }
}

From source file:org.tinymediamanager.scraper.http.Url.java

/**
 * Gets the input stream./*from ww  w .  ja v a2  s .  co  m*/
 * 
 * @return the input stream
 * @throws IOException
 *           Signals that an I/O exception has occurred.
 */
public InputStream getInputStream() throws IOException, InterruptedException {
    // workaround for local files
    if (url.startsWith("file:")) {
        String newUrl = url.replace("file:/", "");
        File file = new File(newUrl);
        return new FileInputStream(file);
    }

    InputStream is = null;

    // replace our API keys for logging...
    String logUrl = url.replaceAll("api_key=\\w+", "api_key=<API_KEY>").replaceAll("api/\\d+\\w+",
            "api/<API_KEY>");
    LOGGER.debug("getting " + logUrl);

    Request.Builder requestBuilder = new Request.Builder();
    requestBuilder.url(url);

    // set custom headers
    for (Pair<String, String> header : headersRequest) {
        requestBuilder.addHeader(header.first().toString(), header.second().toString());
    }

    request = requestBuilder.build();

    try {
        call = client.newCall(request);
        response = call.execute();
        headersResponse = response.headers();
        responseCode = response.code();
        responseMessage = response.message();

        // log any "connection problems"
        if (responseCode < 200 || responseCode >= 400) {
            cleanup();
            LOGGER.error("bad http response: " + responseCode + " ; " + responseMessage);
            return null;
        }

        if (response.body().contentType() != null) { // could be null, see AnimeDB
            responseCharset = response.body().contentType().charset();
            responseContentType = response.body().contentType().toString();
        }
        is = response.body().byteStream();
    } catch (InterruptedIOException | IllegalStateException e) {
        LOGGER.info("aborted request: " + logUrl + " ; " + e.getMessage());
        cleanup();
        throw new InterruptedException();
    } catch (UnknownHostException e) {
        LOGGER.error("proxy or host not found/reachable; " + e.getMessage());
    } catch (Exception e) {
        LOGGER.error("Exception getting url " + logUrl + " ; " + e.getMessage(), e);
    }
    return is;
}

From source file:edu.mit.mobile.android.locast.sync.SyncEngine.java

/**
 * @param toSync/*from w ww .ja  va 2  s.co m*/
 * @param account
 * @param extras
 * @param provider
 * @param syncResult
 * @return true if the item was sync'd successfully. Soft errors will cause this to return
 *         false.
 * @throws RemoteException
 * @throws SyncException
 * @throws JSONException
 * @throws IOException
 * @throws NetworkProtocolException
 * @throws NoPublicPath
 * @throws OperationApplicationException
 * @throws InterruptedException
 */
public boolean sync(Uri toSync, Account account, Bundle extras, ContentProviderClient provider,
        SyncResult syncResult) throws RemoteException, SyncException, JSONException, IOException,
        NetworkProtocolException, NoPublicPath, OperationApplicationException, InterruptedException {

    String pubPath = null;

    //
    // Handle http or https uris separately. These require the
    // destination uri.
    //
    if ("http".equals(toSync.getScheme()) || "https".equals(toSync.getScheme())) {
        pubPath = toSync.toString();

        if (!extras.containsKey(EXTRA_DESTINATION_URI)) {
            throw new IllegalArgumentException("missing EXTRA_DESTINATION_URI when syncing HTTP URIs");
        }
        toSync = Uri.parse(extras.getString(EXTRA_DESTINATION_URI));
    }

    final String type = provider.getType(toSync);
    final boolean isDir = type.startsWith(CONTENT_TYPE_PREFIX_DIR);

    final boolean manualSync = extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);

    // skip any items already sync'd
    if (!manualSync && mLastUpdated.isUpdatedRecently(toSync)) {
        if (DEBUG) {
            Log.d(TAG, "not syncing " + toSync + " as it's been updated recently");
        }
        syncResult.stats.numSkippedEntries++;
        return false;
    }

    // the sync map will convert the json data to ContentValues
    final SyncMap syncMap = MediaProvider.getSyncMap(provider, toSync);

    final Uri toSyncWithoutQuerystring = toSync.buildUpon().query(null).build();

    final HashMap<String, SyncStatus> syncStatuses = new HashMap<String, SyncEngine.SyncStatus>();
    final ArrayList<ContentProviderOperation> cpo = new ArrayList<ContentProviderOperation>();
    final LinkedList<String> cpoPubUris = new LinkedList<String>();

    //
    // first things first, upload any content that needs to be
    // uploaded.
    //

    try {
        uploadUnpublished(toSync, account, provider, syncMap, syncStatuses, syncResult);

        if (Thread.interrupted()) {
            throw new InterruptedException();
        }

        // this should ensure that all items have a pubPath when we
        // query it below.

        if (pubPath == null) {
            // we should avoid calling this too much as it
            // can be expensive
            pubPath = MediaProvider.getPublicPath(mContext, toSync);
        }
    } catch (final NoPublicPath e) {
        // TODO this is a special case and this is probably not the best place to handle this.
        // Ideally, this should be done in such a way as to reduce any extra DB queries -
        // perhaps by doing a join with the parent.
        if (syncMap.isFlagSet(SyncMap.FLAG_PARENT_MUST_SYNC_FIRST)) {
            if (DEBUG) {
                Log.d(TAG, "skipping " + toSync + " whose parent hasn't been sync'd first");
            }
            syncResult.stats.numSkippedEntries++;
            return false;
        }

        // if it's an item, we can handle it.
        if (isDir) {
            throw e;
        }
    }

    if (pubPath == null) {

        // this should have been updated already by the initial
        // upload, so something must be wrong
        throw new SyncException("never got a public path for " + toSync);
    }

    if (DEBUG) {
        Log.d(TAG, "sync(toSync=" + toSync + ", account=" + account + ", extras=" + extras + ", manualSync="
                + manualSync + ",...)");
        Log.d(TAG, "pubPath: " + pubPath);
    }

    final long request_time = System.currentTimeMillis();

    HttpResponse hr = mNetworkClient.get(pubPath);

    final long response_time = System.currentTimeMillis();

    // the time compensation below allows a time-based synchronization to function even if the
    // local clock is entirely wrong. The server's time is extracted using the Date header and
    // all are compared relative to the respective clock reference. Any data that's stored on
    // the mobile should be stored relative to the local clock and the server will respect the
    // same.
    long serverTime;

    try {
        serverTime = getServerTime(hr);
    } catch (final DateParseException e) {
        Log.w(TAG, "could not retrieve date from server. Using local time, which may be incorrect.", e);
        serverTime = System.currentTimeMillis();
    }

    // TODO check out
    // http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html
    final long response_delay = response_time - request_time;
    if (DEBUG) {
        Log.d(TAG, "request took " + response_delay + "ms");
    }
    final long localTime = request_time;

    // add this to the server time to get the local time
    final long localOffset = (localTime - serverTime);

    if (Math.abs(localOffset) > 30 * 60 * 1000) {
        Log.w(TAG, "local clock is off by " + localOffset + "ms");
    }

    if (Thread.interrupted()) {
        throw new InterruptedException();
    }

    final HttpEntity ent = hr.getEntity();

    String selection;
    String selectionInverse;
    String[] selectionArgs;

    if (isDir) {

        final JSONArray ja = new JSONArray(StreamUtils.inputStreamToString(ent.getContent()));
        ent.consumeContent();

        final int len = ja.length();
        selectionArgs = new String[len];

        // build the query to see which items are already in the
        // database
        final StringBuilder sb = new StringBuilder();

        sb.append("(");

        for (int i = 0; i < len; i++) {
            if (Thread.interrupted()) {
                throw new InterruptedException();
            }

            final SyncStatus syncStatus = loadItemFromJsonObject(ja.getJSONObject(i), syncMap, serverTime);

            syncStatuses.put(syncStatus.remote, syncStatus);

            selectionArgs[i] = syncStatus.remote;

            // add in a placeholder for the query
            sb.append('?');
            if (i != (len - 1)) {
                sb.append(',');
            }

        }
        sb.append(")");

        final String placeholders = sb.toString();
        selection = JsonSyncableItem._PUBLIC_URI + " IN " + placeholders;
        selectionInverse = JsonSyncableItem._PUBLIC_URI + " NOT IN " + placeholders;
    } else {

        final JSONObject jo = new JSONObject(StreamUtils.inputStreamToString(ent.getContent()));
        ent.consumeContent();
        final SyncStatus syncStatus = loadItemFromJsonObject(jo, syncMap, serverTime);

        syncStatuses.put(syncStatus.remote, syncStatus);

        selection = JsonSyncableItem._PUBLIC_URI + "=?";
        selectionInverse = JsonSyncableItem._PUBLIC_URI + "!=?";
        selectionArgs = new String[] { syncStatus.remote };
    }

    // first check without the querystring. This will ensure that we
    // properly mark things that we already have in the database.
    final Cursor check = provider.query(toSyncWithoutQuerystring, SYNC_PROJECTION, selection, selectionArgs,
            null);

    // these items are on both sides
    try {
        final int pubUriCol = check.getColumnIndex(JsonSyncableItem._PUBLIC_URI);
        final int idCol = check.getColumnIndex(JsonSyncableItem._ID);

        // All the items in this cursor should be found on both
        // the client and the server.
        for (check.moveToFirst(); !check.isAfterLast(); check.moveToNext()) {
            if (Thread.interrupted()) {
                throw new InterruptedException();
            }

            final long id = check.getLong(idCol);
            final Uri localUri = ContentUris.withAppendedId(toSync, id);

            final String pubUri = check.getString(pubUriCol);

            final SyncStatus itemStatus = syncStatuses.get(pubUri);

            itemStatus.state = SyncState.BOTH_UNKNOWN;

            itemStatus.local = localUri;

            // make the status searchable by both remote and
            // local uri
            syncStatuses.put(localUri.toString(), itemStatus);
        }
    } finally {
        check.close();
    }

    Cursor c = provider.query(toSync, SYNC_PROJECTION, selection, selectionArgs, null);

    // these items are on both sides
    try {
        final int pubUriCol = c.getColumnIndex(JsonSyncableItem._PUBLIC_URI);
        final int localModifiedCol = c.getColumnIndex(JsonSyncableItem._MODIFIED_DATE);
        final int serverModifiedCol = c.getColumnIndex(JsonSyncableItem._SERVER_MODIFIED_DATE);
        final int idCol = c.getColumnIndex(JsonSyncableItem._ID);

        // All the items in this cursor should be found on both
        // the client and the server.
        for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
            if (Thread.interrupted()) {
                throw new InterruptedException();
            }

            final long id = c.getLong(idCol);
            final Uri localUri = ContentUris.withAppendedId(toSync, id);

            final String pubUri = c.getString(pubUriCol);

            final SyncStatus itemStatus = syncStatuses.get(pubUri);

            if (itemStatus.state == SyncState.ALREADY_UP_TO_DATE
                    || itemStatus.state == SyncState.NOW_UP_TO_DATE) {
                if (DEBUG) {
                    Log.d(TAG, localUri + "(" + pubUri + ")" + " is already up to date.");
                }
                continue;
            }

            itemStatus.local = localUri;

            // make the status searchable by both remote and local uri
            syncStatuses.put(localUri.toString(), itemStatus);

            // last modified as stored in the DB, in phone time
            final long itemLocalModified = c.getLong(localModifiedCol);

            // last modified as stored in the DB, in server time
            final long itemServerModified = c.getLong(serverModifiedCol);
            final long localAge = localTime - itemLocalModified;

            final long remoteAge = serverTime - itemStatus.remoteModifiedTime;

            final long ageDifference = Math.abs(localAge - remoteAge);

            // up to date, as far remote -> local goes
            if (itemServerModified == itemStatus.remoteModifiedTime) {
                itemStatus.state = SyncState.ALREADY_UP_TO_DATE;
                if (DEBUG) {
                    Log.d(TAG, pubUri + " is up to date.");
                }

                // need to download
            } else if (localAge > remoteAge) {
                if (DEBUG) {
                    final long serverModified = itemStatus.remoteModifiedTime;

                    Log.d(TAG,
                            pubUri + " : local is " + ageDifference + "ms older ("
                                    + android.text.format.DateUtils.formatDateTime(mContext, itemLocalModified,
                                            FORMAT_ARGS_DEBUG)
                                    + ") than remote (" + android.text.format.DateUtils.formatDateTime(mContext,
                                            serverModified, FORMAT_ARGS_DEBUG)
                                    + "); updating local copy...");
                }

                itemStatus.state = SyncState.REMOTE_DIRTY;

                final ContentProviderOperation.Builder b = ContentProviderOperation.newUpdate(localUri);

                // update this so it's in the local timescale
                correctServerOffset(itemStatus.remoteCVs, JsonSyncableItem._CREATED_DATE,
                        JsonSyncableItem._CREATED_DATE, localOffset);
                correctServerOffset(itemStatus.remoteCVs, JsonSyncableItem._SERVER_MODIFIED_DATE,
                        JsonSyncableItem._MODIFIED_DATE, localOffset);

                b.withValues(itemStatus.remoteCVs);
                b.withExpectedCount(1);

                cpo.add(b.build());
                cpoPubUris.add(pubUri);

                syncResult.stats.numUpdates++;

                // need to upload
            } else if (localAge < remoteAge) {
                if (DEBUG) {
                    final long serverModified = itemStatus.remoteModifiedTime;

                    Log.d(TAG,
                            pubUri + " : local is " + ageDifference + "ms newer ("
                                    + android.text.format.DateUtils.formatDateTime(mContext, itemLocalModified,
                                            FORMAT_ARGS_DEBUG)
                                    + ") than remote (" + android.text.format.DateUtils.formatDateTime(mContext,
                                            serverModified, FORMAT_ARGS_DEBUG)
                                    + "); publishing to server...");
                }
                itemStatus.state = SyncState.LOCAL_DIRTY;

                mNetworkClient.putJson(pubPath, JsonSyncableItem.toJSON(mContext, localUri, c, syncMap));
            }

            mLastUpdated.markUpdated(localUri);

            syncResult.stats.numEntries++;
        } // end for
    } finally {

        c.close();
    }

    /*
     * Apply updates in bulk
     */
    if (cpo.size() > 0) {
        if (DEBUG) {
            Log.d(TAG, "applying " + cpo.size() + " bulk updates...");
        }

        final ContentProviderResult[] r = provider.applyBatch(cpo);
        if (DEBUG) {
            Log.d(TAG, "Done applying updates. Running postSync handler...");
        }

        for (int i = 0; i < r.length; i++) {
            final ContentProviderResult res = r[i];
            final SyncStatus ss = syncStatuses.get(cpoPubUris.get(i));
            if (ss == null) {
                Log.e(TAG, "can't get sync status for " + res.uri);
                continue;
            }
            syncMap.onPostSyncItem(mContext, account, ss.local, ss.remoteJson,
                    res.count != null ? res.count == 1 : true);

            ss.state = SyncState.NOW_UP_TO_DATE;
        }

        if (DEBUG) {
            Log.d(TAG, "done running postSync handler.");
        }

        cpo.clear();
        cpoPubUris.clear();
    }

    if (Thread.interrupted()) {
        throw new InterruptedException();
    }

    /*
     * Look through the SyncState.state values and find ones that need to be stored.
     */

    for (final Map.Entry<String, SyncStatus> entry : syncStatuses.entrySet()) {
        if (Thread.interrupted()) {
            throw new InterruptedException();
        }

        final String pubUri = entry.getKey();
        final SyncStatus status = entry.getValue();
        if (status.state == SyncState.REMOTE_ONLY) {
            if (DEBUG) {
                Log.d(TAG, pubUri + " is not yet stored locally, adding...");
            }

            // update this so it's in the local timescale
            correctServerOffset(status.remoteCVs, JsonSyncableItem._CREATED_DATE,
                    JsonSyncableItem._CREATED_DATE, localOffset);
            correctServerOffset(status.remoteCVs, JsonSyncableItem._SERVER_MODIFIED_DATE,
                    JsonSyncableItem._MODIFIED_DATE, localOffset);

            final ContentProviderOperation.Builder b = ContentProviderOperation.newInsert(toSync);
            b.withValues(status.remoteCVs);

            cpo.add(b.build());
            cpoPubUris.add(pubUri);
            syncResult.stats.numInserts++;

        }
    }

    /*
     * Execute the content provider operations in bulk.
     */
    if (cpo.size() > 0) {
        if (DEBUG) {
            Log.d(TAG, "bulk inserting " + cpo.size() + " items...");
        }
        final ContentProviderResult[] r = provider.applyBatch(cpo);
        if (DEBUG) {
            Log.d(TAG, "applyBatch completed. Processing results...");
        }

        int successful = 0;
        for (int i = 0; i < r.length; i++) {
            final ContentProviderResult res = r[i];
            if (res.uri == null) {
                syncResult.stats.numSkippedEntries++;
                Log.e(TAG, "result from content provider bulk operation returned null");
                continue;
            }
            final String pubUri = cpoPubUris.get(i);
            final SyncStatus ss = syncStatuses.get(pubUri);

            if (ss == null) {
                syncResult.stats.numSkippedEntries++;
                Log.e(TAG, "could not find sync status for " + cpoPubUris.get(i));
                continue;
            }

            ss.local = res.uri;
            if (DEBUG) {
                Log.d(TAG, "onPostSyncItem(" + res.uri + ", ...); pubUri: " + pubUri);
            }

            syncMap.onPostSyncItem(mContext, account, res.uri, ss.remoteJson,
                    res.count != null ? res.count == 1 : true);

            ss.state = SyncState.NOW_UP_TO_DATE;
            successful++;
        }
        if (DEBUG) {
            Log.d(TAG, successful + " batch inserts successfully applied.");
        }
    } else {
        if (DEBUG) {
            Log.d(TAG, "no updates to perform.");
        }
    }

    /**
     * Look through all the items that we didn't already find on the server side, but which
     * still have a public uri. They should be checked to make sure they're not deleted.
     */
    c = provider.query(toSync, SYNC_PROJECTION,
            ProviderUtils.addExtraWhere(selectionInverse, JsonSyncableItem._PUBLIC_URI + " NOT NULL"),
            selectionArgs, null);

    try {
        final int idCol = c.getColumnIndex(JsonSyncableItem._ID);
        final int pubUriCol = c.getColumnIndex(JsonSyncableItem._PUBLIC_URI);

        cpo.clear();

        for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
            final String pubUri = c.getString(pubUriCol);
            SyncStatus ss = syncStatuses.get(pubUri);

            final Uri item = isDir ? ContentUris.withAppendedId(toSyncWithoutQuerystring, c.getLong(idCol))
                    : toSync;

            if (ss == null) {
                ss = syncStatuses.get(item.toString());
            }

            if (DEBUG) {
                Log.d(TAG, item + " was not found in the main list of items on the server (" + pubPath
                        + "), but appears to be a child of " + toSync);

                if (ss != null) {
                    Log.d(TAG, "found sync status for " + item + ": " + ss);
                }
            }

            if (ss != null) {
                switch (ss.state) {
                case ALREADY_UP_TO_DATE:
                case NOW_UP_TO_DATE:
                    if (DEBUG) {
                        Log.d(TAG, item + " is already up to date. No need to see if it was deleted.");
                    }
                    continue;

                case BOTH_UNKNOWN:
                    if (DEBUG) {
                        Log.d(TAG,
                                item + " was found on both sides, but has an unknown sync status. Skipping...");
                    }
                    continue;

                default:

                    Log.w(TAG, "got an unexpected state for " + item + ": " + ss);
                }

            } else {
                ss = new SyncStatus(pubUri, SyncState.LOCAL_ONLY);
                ss.local = item;

                hr = mNetworkClient.head(pubUri);

                switch (hr.getStatusLine().getStatusCode()) {
                case 200:
                    if (DEBUG) {
                        Log.d(TAG, "HEAD " + pubUri + " returned 200");
                    }
                    ss.state = SyncState.BOTH_UNKNOWN;
                    break;

                case 404:
                    if (DEBUG) {
                        Log.d(TAG, "HEAD " + pubUri + " returned 404. Deleting locally...");
                    }
                    ss.state = SyncState.DELETED_REMOTELY;
                    final ContentProviderOperation deleteOp = ContentProviderOperation
                            .newDelete(ContentUris.withAppendedId(toSyncWithoutQuerystring, c.getLong(idCol)))
                            .build();
                    cpo.add(deleteOp);

                    break;

                default:
                    syncResult.stats.numIoExceptions++;
                    Log.w(TAG, "HEAD " + pubUri + " got unhandled result: " + hr.getStatusLine());
                }
            }
            syncStatuses.put(pubUri, ss);
        } // for cursor

        if (cpo.size() > 0) {
            final ContentProviderResult[] results = provider.applyBatch(cpo);

            for (final ContentProviderResult result : results) {
                if (result.count != 1) {
                    throw new SyncException("Error deleting item");
                }
            }
        }

    } finally {
        c.close();
    }

    syncStatuses.clear();

    mLastUpdated.markUpdated(toSync);

    return true;
}