/*
* Copyright (C) 2005-2015 Team XBMC
* http://xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XBMC Remote; see the file license. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
package org.xbmc.android.jsonrpc.io;
import org.codehaus.jackson.JsonNode;
import org.xbmc.android.jsonrpc.api.R;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.util.Log;
/**
* Stuff that breaks while accessing the API
*
* @author freezy <freezy@xbmc.org>
* @author Joel Stemmer <stemmertech@gmail.com>
*/
public class ApiException extends Exception {
private final static String TAG = ApiException.class.getSimpleName();
/**
* The URL of the API could not be parsed. See logs for more info.
*/
public static final int MALFORMED_URL = 0x01;
/**
* Connection problem, please check logs.
*/
public static final int IO_EXCEPTION = 0x02;
/**
* Data could not been read from server.
*/
public static final int IO_EXCEPTION_WHILE_READING = 0x03;
/**
* Data could not been sent to server.
*/
public static final int IO_EXCEPTION_WHILE_WRITING = 0x04;
/**
* Error while connecting to server.
*/
public static final int IO_EXCEPTION_WHILE_OPENING = 0x05;
/**
* Connection timed out.
*/
public static final int IO_SOCKETTIMEOUT = 0x06;
/**
* Host not found.
*/
public static final int IO_UNKNOWN_HOST = 0x07;
/**
* Connection was terminated unexpectedly.
*/
public static final int IO_DISCONNECTED = 0x08;
/**
* Unsupported encoding.
*/
public static final int UNSUPPORTED_ENCODING = 0x09;
/**
* Error when serializing JSON data.
*/
public static final int JSON_EXCEPTION = 0x0a;
/**
* Received different response than expected.
*/
public static final int RESPONSE_ERROR = 0x0b;
/**
* JSON-RPC returned an error.
*/
public static final int API_ERROR = 0x0c;
/**
* Unknown HTTP status code received (not in between 100 and 599).
*/
public static final int HTTP_UNKNOWN = 0x0d;
/**
* Informational HTTP code received (100 - 199).
*/
public static final int HTTP_INFO = 0x0e;
/**
* Success HTTP code received (200 - 299).
*/
public static final int HTTP_SUCCESS = 0x0f;
/**
* Redirection HTTP code received (300 - 399).
*/
public static final int HTTP_REDIRECTION = 0x10;
/**
* Client error HTTP code received (400 - 499).
*/
public static final int HTTP_CLIENT_ERROR = 0x11;
/**
* Server error HTTP code received (500 - 599).
*/
public static final int HTTP_SERVER_ERROR = 0x12;
/**
* Bad request HTTP code received (400).
*/
public static final int HTTP_BAD_REQUEST = 0x13;
/**
* Unauthorized HTTP code received (401).
*/
public static final int HTTP_UNAUTHORIZED = 0x14;
/**
* Forbidden HTTP code received (403).
*/
public static final int HTTP_FORBIDDEN = 0x15;
/**
* Not found HTTP code received (404).
*/
public static final int HTTP_NOT_FOUND = 0x16;
public static final String EXTRA_ERROR_CODE = "org.xbmc.android.jsonprc.extra.ERROR_CODE";
public static final String EXTRA_ERROR_MESSAGE = "org.xbmc.android.jsonprc.extra.ERROR_MESSAGE";
public static final String EXTRA_ERROR_HINT = "org.xbmc.android.jsonprc.extra.ERROR_HINT";
private int code;
public ApiException(int code, String message) {
super(message);
this.code = code;
Log.e(TAG, message, this);
}
public ApiException(int code, String message, Throwable cause) {
super(message, cause);
this.code = code;
Log.e(TAG, message, this);
}
public ApiException(JsonNode node) {
super(node.get("error").get("message").getValueAsText());
final StringBuilder sb = new StringBuilder("API Error: ");
try {
this.code = API_ERROR;
sb.append("Error in ");
sb.append(node.get("error").get("data").get("method").getValueAsText());
sb.append(" for ");
sb.append(node.get("error").get("data").get("stack").get("name").getValueAsText());
sb.append(": ");
sb.append(node.get("error").get("data").get("stack").get("property").get("message").getValueAsText());
} catch(NullPointerException e) {
// this message didn't conform to our expected format
throw new RuntimeException(node.toString());
}
Log.e(TAG, sb.toString());
}
public int getCode() {
return code;
}
/**
* Returns a "user friendly" error message that can be displayed to end users.
* @param c Application context
* @return End user error message
*/
public String getDisplayableMessage(Context c) {
final String msg = getError(c.getResources(), code);
return msg == null ? this.getMessage() : msg;
}
/**
* Returns a user friendly suggestion why the error happened.
* @param c Application context
* @return Error hint
*/
public String getHint(Context c) {
return getHint(c.getResources(), code);
}
public static String getError(Resources r, int error) {
switch (error) {
case MALFORMED_URL:
return r.getString(R.string.error_malformed_url);
case IO_EXCEPTION:
return r.getString(R.string.error_io_exception);
case IO_EXCEPTION_WHILE_READING:
return r.getString(R.string.error_io_exception_while_reading);
case IO_EXCEPTION_WHILE_WRITING:
return r.getString(R.string.error_io_exception_while_writing);
case IO_EXCEPTION_WHILE_OPENING:
return r.getString(R.string.error_io_exception_while_connecting);
case IO_SOCKETTIMEOUT:
return r.getString(R.string.error_connection_timeout);
case IO_UNKNOWN_HOST:
return r.getString(R.string.error_unknown_host);
case UNSUPPORTED_ENCODING:
return r.getString(R.string.error_encoding);
case JSON_EXCEPTION:
return r.getString(R.string.error_parse_json);
case RESPONSE_ERROR:
return r.getString(R.string.error_response);
case API_ERROR:
return r.getString(R.string.error_api);
case HTTP_UNKNOWN:
case HTTP_INFO:
case HTTP_SUCCESS:
case HTTP_REDIRECTION:
case HTTP_CLIENT_ERROR:
case HTTP_SERVER_ERROR:
return r.getString(R.string.error_http);
case HTTP_BAD_REQUEST:
return r.getString(R.string.error_http_400);
case HTTP_UNAUTHORIZED:
return r.getString(R.string.error_http_401);
case HTTP_FORBIDDEN:
return r.getString(R.string.error_http_403);
case HTTP_NOT_FOUND:
return r.getString(R.string.error_http_404);
}
return null;
}
public static String getHint(Resources r, int error) {
switch (error) {
case MALFORMED_URL:
return r.getString(R.string.error_malformed_url_hint);
case IO_EXCEPTION:
return r.getString(R.string.error_io_exception_hint);
case IO_EXCEPTION_WHILE_READING:
return r.getString(R.string.error_io_exception_while_reading_hint);
case IO_EXCEPTION_WHILE_WRITING:
return r.getString(R.string.error_io_exception_while_writing_hint);
case IO_EXCEPTION_WHILE_OPENING:
return r.getString(R.string.error_io_exception_while_connecting_hint);
case IO_SOCKETTIMEOUT:
return r.getString(R.string.error_connection_timeout_hint);
case IO_UNKNOWN_HOST:
return r.getString(R.string.error_unknown_host_hint);
case UNSUPPORTED_ENCODING:
return r.getString(R.string.error_encoding_hint);
case JSON_EXCEPTION:
return r.getString(R.string.error_parse_json_hint);
case RESPONSE_ERROR:
return r.getString(R.string.error_response_hint);
case API_ERROR:
return r.getString(R.string.error_api_hint);
case HTTP_UNKNOWN:
case HTTP_INFO:
case HTTP_SUCCESS:
case HTTP_REDIRECTION:
case HTTP_CLIENT_ERROR:
case HTTP_SERVER_ERROR:
return r.getString(R.string.error_http_hint);
case HTTP_BAD_REQUEST:
return r.getString(R.string.error_http_400_hint);
case HTTP_UNAUTHORIZED:
return r.getString(R.string.error_http_401_hint);
case HTTP_FORBIDDEN:
return r.getString(R.string.error_http_403_hint);
case HTTP_NOT_FOUND:
return r.getString(R.string.error_http_404_hint);
}
return null;
}
public Bundle getBundle() {
final Bundle b = new Bundle();
b.putInt(EXTRA_ERROR_CODE, code);
b.putString(EXTRA_ERROR_MESSAGE, getMessage());
return b;
}
public Bundle getBundle(Resources r) {
final Bundle b = new Bundle();
b.putInt(EXTRA_ERROR_CODE, code);
b.putString(EXTRA_ERROR_MESSAGE, getError(r, code));
b.putString(EXTRA_ERROR_HINT, getHint(r, code));
return b;
}
private static final long serialVersionUID = -8668163106123710291L;
}