package com.nostra13.socialsharing.twitter.extpack.winterwell.jtwitter; import java.io.IOException; import java.text.ParseException; import com.nostra13.socialsharing.twitter.extpack.winterwell.json.JSONException; /** * A runtime exception for when Twitter requests don't work. All {@link Twitter} * methods can throw this. * <p> * This contains several subclasses which should be thrown to mark different * problems. Error handling is particularly important as Twitter tends to be a * bit flaky. * <p> * I believe unchecked exceptions are preferable to checked ones, because they * avoid the problems caused by swallowing exceptions. But if you don't like * runtime exceptions, just edit this class. * * @author Daniel Winterstein */ public class TwitterException extends RuntimeException { /** * Subclass of 403 thrown when you breach the access level of the app / * oauth-token. * * @see Twitter_Account#getAccessLevel() */ public static class AccessLevel extends E401 { private static final long serialVersionUID = 1L; public AccessLevel(String msg) { super(msg); } } /** * Exception thrown when Twitter doesn't like a parameter. E.g. if you set a * since_id which goes back too far, you'll see this. * <p> * This extends E403 because Twitter uses http code 403 (forbidden) to * signal this. */ public static class BadParameter extends E403 { private static final long serialVersionUID = 1L; public BadParameter(String msg) { super(msg); } } /** * An unauthorised exception. This is thrown (eg) if a password is wrong or * a login is required. It may also be thrown when accessing a protected * stream (you might expect an E403 there, but be prepared for an E401). */ public static class E401 extends E40X { private static final long serialVersionUID = 1L; public E401(String string) { super(string); } } /** * A Forbidden exception. This is thrown if the authenticating used does not * have the right to make a request. Possible causes: - Accessing a * suspended account (ie. trying to look at messages from a spambot) - * Accessing a protected stream - Repeatedly posting the same status - If * search is passed a sinceId which is too old. Though the API documentation * suggests a 404 should be thrown instead. */ public static class E403 extends E40X { private static final long serialVersionUID = 1L; public E403(String string) { super(string); } } /** * Indicates a 404: resource does not exist error from Twitter. Note: *Used* * to be thrown in relation to suspended users (e.g. spambots) These now get * a 403, as of August 2010. */ public static class E404 extends E40X { private static final long serialVersionUID = 1L; public E404(String string) { super(string); } } /** * Not Acceptable. One or more of the parameters are not suitable for the * resource. The track parameter, for example, would throw this error if: * * The track keyword is too long or too short. The bounding box specified is * invalid. No predicates defined for filtered resource, for example, * neither track nor follow parameter defined. Follow userid cannot be read. */ public static class E406 extends E40X { private static final long serialVersionUID = 1L; public E406(String string) { super(string); } } /** * A user-error. This is sub-classed to provide more info. * <p> * This indicates an error in you request. You should catch E40X and deal * with the cause. Don't just re-try -- it won't work. */ public static class E40X extends TwitterException { private static final long serialVersionUID = 1L; public E40X(String string) { super(string); } } /** * Too Long. A parameter list is too long. The track parameter, for example, * would throw this error if: * * Too many track tokens specified for role; contact API team for increased * access. Too many bounding boxes specified for role; contact API team for * increased access. Too many follow userids specified for role; contact API * team for increased access. */ public static class E413 extends E40X { private static final long serialVersionUID = 1L; public E413(String string) { super(string); } } /** * Range Unacceptable. Possible reasons are: * * Count parameter is not allowed in role. Count parameter value is too * large. */ public static class E416 extends E40X { private static final long serialVersionUID = 1L; public E416(String string) { super(string); } } /** * A code 50X error (e.g. 502) - indicating something went wrong at * Twitter's end. The API equivalent of the Fail Whale. Usually retrying in * a minute will fix this. * <p> * Note: some socket exceptions are assumed to be server errors - because * they probably are - but could conceivably be caused by an error in your * internet connection. */ public static class E50X extends TwitterException { private static final long serialVersionUID = 1L; public E50X(String string) { super(msg(string)); } /** * Sometimes Twitter sends a full web page by mistake. */ static String msg(String msg) { if (msg==null) return null; // strip any html tags // NB: this doesn't clean out script tags msg = InternalUtils.TAG_REGEX.matcher(msg).replaceAll(""); msg = msg.replaceAll("\\s+", " "); if (msg.length() > 280) msg = msg.substring(0, 280) + "..."; return msg; } } /** * Subclass of 403 thrown when you follow too many people. */ public static class FollowerLimit extends E403 { private static final long serialVersionUID = 1L; public FollowerLimit(String msg) { super(msg); } } /** * An IO exception, eg. a network issue. Call {@link #getCause()} to get the * original IOException */ // ?? Should this extend E50X? public static class IO extends TwitterException { private static final long serialVersionUID = 1L; public IO(IOException e) { super(e); } @Override public IOException getCause() { return (IOException) super.getCause(); } } /** * Problems reading the JSON returned by Twitter. This should not normally * occur! This indicates either a change in the API, or a bug in JTwitter. */ public static class Parsing extends TwitterException { private static final long serialVersionUID = 1L; /** * Convenience to shorten a potentially long string. */ private static String clip(String json, int len) { return json == null ? null : json.length() <= len ? json : json .substring(len) + "..."; } public Parsing(String json, JSONException e) { super((json==null? String.valueOf(e) : clip(json, 280)) +causeLine(e), e); } /** * Where did this error come from? an ultra mini stack-trace * @param e * @return " caused by ..." or "" */ private static String causeLine(JSONException e) { if (e==null) return ""; StackTraceElement[] st = e.getStackTrace(); for (StackTraceElement ste : st) { if (ste.getClassName().contains("JSON")) continue; return " caused by "+ste; } return ""; } public Parsing(String date, ParseException e) { super(date, e); } } /** * Indicates a rate limit error (i.e. you've over-used Twitter) */ public static class RateLimit extends TwitterException { private static final long serialVersionUID = 1L; public RateLimit(String string) { super(string); } } /** * Subclass of 403 thrown when you try to do something twice, like post the * same status. This is only thrown for immediate repetition. You may get a * plain E403 instead for less blatant repetition. */ public static class Repetition extends E403 { private static final long serialVersionUID = 1L; public Repetition(String tweet) { super("Already tweeted! " + tweet); } } /** * Exception thrown when trying to query a suspended account. Note that * *deleted* accounts may generate an E404 instead. * <p> * This extends E403 because Twitter uses http code 403 (forbidden) to * signal this. */ public static class SuspendedUser extends E403 { private static final long serialVersionUID = 1L; SuspendedUser(String msg) { super(msg); } } /** * A timeout exception - probably caused by Twitter being overloaded. */ public static class Timeout extends TwitterException.E50X { private static final long serialVersionUID = 1L; public Timeout(String string) { super(string); } } /** * A code 420 error indicates that the account has been logging in too * often. This code will be the indication that the account has exceeded the * per-account-per-application connection limit. This situation should be * raised to the user, as they have been automatically and temporarily * banned from User Streams for an excessive login rate. The user should be * advised to shut down extra copies of the application, perhaps instances * running on another device, to restore streaming access. */ public static class TooManyLogins extends E40X { private static final long serialVersionUID = 1L; public TooManyLogins(String string) { super(string); } } /** * Thrown if you poll too frequently. */ public static class TooRecent extends E403 { private static final long serialVersionUID = 1L; TooRecent(String msg) { super(msg); } } /** * Exception thrown if something goes wrong with twilonger.com integration * for long tweets. */ public static class TwitLongerException extends TwitterException { private static final long serialVersionUID = 1L; public TwitLongerException(String string, String details) { super(string, details); } } /** * Something has gone wrong. Occasionally Twitter behaves strangely. */ public static class Unexplained extends TwitterException { private static final long serialVersionUID = 1L; public Unexplained(String msg) { super(msg); } } /** * Legacy exception thrown when trying to use basic auth instead of oauth. */ public static class UpdateToOAuth extends E401 { private static final long serialVersionUID = 1L; public UpdateToOAuth() { super( "You need to switch to OAuth. Twitter no longer support basic authentication."); } } private static final long serialVersionUID = 1L; private String additionalInfo = ""; /** * Wrap an exception as a TwitterException. */ TwitterException(Exception e) { super(e); // avoid gratuitous nesting of exceptions assert !(e instanceof TwitterException) : e; } /** * @param string */ public TwitterException(String string) { super(string); } TwitterException(String msg, Exception e) { super(msg, e); // avoid gratuitous nesting of exceptions assert !(e instanceof TwitterException) : e; } public TwitterException(String string, String additionalInfo) { this(string); this.setAdditionalInfo(additionalInfo); } public String getAdditionalInfo() { return additionalInfo; } public void setAdditionalInfo(String additionalInfo) { this.additionalInfo = additionalInfo; } }