forked from upstream-mirrors/OpenTracks
b84da40365
(Merge to Head)
191 lines
6.5 KiB
Java
191 lines
6.5 KiB
Java
/*
|
|
* Copyright 2010 Google Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
* use this file except in compliance with the License. You may obtain a copy of
|
|
* the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations under
|
|
* the License.
|
|
*/
|
|
package com.google.android.apps.mymaps;
|
|
|
|
import com.google.android.apps.mytracks.MyTracksConstants;
|
|
import com.google.android.apps.mytracks.io.AuthManager;
|
|
import com.google.android.apps.mytracks.io.gdata.GDataClientFactory;
|
|
import com.google.android.common.gdata.AndroidXmlParserFactory;
|
|
import com.google.wireless.gdata.client.GDataClient;
|
|
import com.google.wireless.gdata.client.HttpException;
|
|
import com.google.wireless.gdata.maps.MapsClient;
|
|
import com.google.wireless.gdata.maps.xml.XmlMapsGDataParserFactory;
|
|
import com.google.wireless.gdata.parser.xml.SimplePullParser.ParseException;
|
|
import com.google.wireless.gdata2.ConflictDetectedException;
|
|
import com.google.wireless.gdata2.client.AuthenticationException;
|
|
|
|
import android.content.Context;
|
|
import android.util.Log;
|
|
|
|
import java.io.IOException;
|
|
|
|
/**
|
|
* MyMapsGDataWrapper provides a wrapper around GData operations that maintains
|
|
* the GData client, and provides a method to run gdata queries with proper
|
|
* error handling. After a query is run, the wrapper can be queried about the
|
|
* error that occurred.
|
|
*/
|
|
public class MyMapsGDataWrapper {
|
|
/**
|
|
* A QueryFunction is passed in when executing a query. The query function
|
|
* of the class is called with the GData client as a parameter. The
|
|
* function should execute whatever operations it desires on the client
|
|
* without concern for whether the client will throw an error.
|
|
*/
|
|
public interface QueryFunction {
|
|
public abstract void query(MapsClient client)
|
|
throws AuthenticationException, IOException, ParseException,
|
|
ConflictDetectedException, Exception;
|
|
}
|
|
|
|
// The types of error that may be encountered
|
|
/** No error occurred. */
|
|
public static final int ERROR_NO_ERROR = 0;
|
|
/** There was an authentication error, the auth token may be invalid. */
|
|
public static final int ERROR_AUTH = 1;
|
|
/** There was an internal error on the server side. */
|
|
public static final int ERROR_INTERNAL = 2;
|
|
/** There was an error connecting to the server. */
|
|
public static final int ERROR_CONNECTION = 3;
|
|
/** The item queried did not exit. */
|
|
public static final int ERROR_NOT_FOUND = 4;
|
|
/** There was an error parsing or serializing locally. */
|
|
public static final int ERROR_LOCAL = 5;
|
|
/** There was a conflict, update the entry and try again. */
|
|
public static final int ERROR_CONFLICT = 6;
|
|
/**
|
|
* A query was run after cleaning up the wrapper, so the client was invalid.
|
|
*/
|
|
public static final int ERROR_CLEANED_UP = 7;
|
|
/** An unknown error occurred. */
|
|
public static final int ERROR_UNKNOWN = 100;
|
|
|
|
private final GDataClient androidGdataClient;
|
|
private final MapsClient client;
|
|
|
|
private String errorMessage;
|
|
private int errorType;
|
|
private AuthManager auth;
|
|
private boolean retryOnAuthFailure;
|
|
private int retriesPending;
|
|
private boolean cleanupCalled;
|
|
|
|
public MyMapsGDataWrapper(Context context) {
|
|
androidGdataClient = GDataClientFactory.getGDataClient(context);
|
|
client =
|
|
new MapsClient(androidGdataClient, new XmlMapsGDataParserFactory(
|
|
new AndroidXmlParserFactory()));
|
|
errorType = ERROR_NO_ERROR;
|
|
errorMessage = null;
|
|
auth = null;
|
|
retryOnAuthFailure = false;
|
|
retriesPending = 0;
|
|
cleanupCalled = false;
|
|
}
|
|
|
|
public boolean runQuery(final QueryFunction query) {
|
|
if (client == null) {
|
|
errorType = ERROR_CLEANED_UP;
|
|
errorMessage = "GData Wrapper has already been cleaned up!";
|
|
return false;
|
|
}
|
|
try {
|
|
query.query(client);
|
|
errorType = ERROR_NO_ERROR;
|
|
errorMessage = null;
|
|
return true;
|
|
} catch (AuthenticationException e) {
|
|
Log.e(MyTracksConstants.TAG, "Exception", e);
|
|
errorType = ERROR_AUTH;
|
|
errorMessage = e.getMessage();
|
|
} catch (HttpException e) {
|
|
Log.e(MyTracksConstants.TAG, "HttpException", e);
|
|
errorMessage = e.getMessage();
|
|
if (errorMessage != null && errorMessage.contains("401")) {
|
|
errorType = ERROR_AUTH;
|
|
} else {
|
|
errorType = ERROR_CONNECTION;
|
|
}
|
|
} catch (IOException e) {
|
|
Log.e(MyTracksConstants.TAG, "Exception", e);
|
|
errorMessage = e.getMessage();
|
|
if (errorMessage != null && errorMessage.contains("503")) {
|
|
errorType = ERROR_INTERNAL;
|
|
} else {
|
|
errorType = ERROR_CONNECTION;
|
|
}
|
|
} catch (ParseException e) {
|
|
Log.e(MyTracksConstants.TAG, "Exception", e);
|
|
errorType = ERROR_LOCAL;
|
|
errorMessage = e.getMessage();
|
|
} catch (ConflictDetectedException e) {
|
|
Log.e(MyTracksConstants.TAG, "Exception", e);
|
|
errorType = ERROR_CONFLICT;
|
|
errorMessage = e.getMessage();
|
|
} catch (Exception e) {
|
|
Log.e(MyTracksConstants.TAG, "Exception", e);
|
|
errorType = ERROR_UNKNOWN;
|
|
errorMessage = e.getMessage();
|
|
e.printStackTrace();
|
|
}
|
|
Log.d(MyTracksConstants.TAG, "GData error encountered: " + errorMessage);
|
|
if (errorType == ERROR_AUTH && auth != null) {
|
|
Runnable whenFinished = null;
|
|
if (retryOnAuthFailure) {
|
|
retriesPending++;
|
|
whenFinished = new Runnable() {
|
|
public void run() {
|
|
retriesPending--;
|
|
retryOnAuthFailure = false;
|
|
runQuery(query);
|
|
if (cleanupCalled && retriesPending == 0) {
|
|
cleanUp();
|
|
}
|
|
}
|
|
};
|
|
}
|
|
auth.invalidateAndRefresh(whenFinished);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public int getErrorType() {
|
|
return errorType;
|
|
}
|
|
|
|
public String getErrorMessage() {
|
|
return errorMessage;
|
|
}
|
|
|
|
// cleanUp must be called when done using this wrapper to close the client.
|
|
// Note that the cleanup will be delayed if auth failure retries were
|
|
// requested and there is a pending retry.
|
|
public void cleanUp() {
|
|
if (retriesPending == 0 && !cleanupCalled) {
|
|
androidGdataClient.close();
|
|
}
|
|
cleanupCalled = true;
|
|
}
|
|
|
|
public void setAuthManager(AuthManager newAuth) {
|
|
this.auth = newAuth;
|
|
}
|
|
|
|
public void setRetryOnAuthFailure(boolean retry) {
|
|
retryOnAuthFailure = retry;
|
|
}
|
|
}
|