-
Notifications
You must be signed in to change notification settings - Fork 736
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Better error messages #254
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
package org.kohsuke.github; | ||
|
||
import java.io.IOException; | ||
import java.net.HttpURLConnection; | ||
import java.net.URL; | ||
|
||
import javax.annotation.CheckForNull; | ||
|
||
/** | ||
* {@link IOException} for http exceptions because {@link HttpURLConnection} throws un-discerned | ||
* {@link IOException} and it can help to know the http response code to decide how to handle an | ||
* http exceptions. | ||
* | ||
* @author <a href="mailto:[email protected]">Cyrille Le Clerc</a> | ||
*/ | ||
public class HttpException extends IOException { | ||
static final long serialVersionUID = 1L; | ||
|
||
private final int responseCode; | ||
private final String responseMessage; | ||
private final String url; | ||
|
||
/** | ||
* @param message The detail message (which is saved for later retrieval | ||
* by the {@link #getMessage()} method) | ||
* @param responseCode Http response code. {@code -1} if no code can be discerned. | ||
* @param responseMessage Http response message | ||
* @param url The url that was invoked | ||
* @see HttpURLConnection#getResponseCode() | ||
* @see HttpURLConnection#getResponseMessage() | ||
*/ | ||
public HttpException(String message, int responseCode, String responseMessage, String url) { | ||
super(message); | ||
this.responseCode = responseCode; | ||
this.responseMessage = responseMessage; | ||
this.url = url; | ||
} | ||
|
||
/** | ||
* @param message The detail message (which is saved for later retrieval | ||
* by the {@link #getMessage()} method) | ||
* @param responseCode Http response code. {@code -1} if no code can be discerned. | ||
* @param responseMessage Http response message | ||
* @param url The url that was invoked | ||
* @param cause The cause (which is saved for later retrieval by the | ||
* {@link #getCause()} method). (A null value is permitted, | ||
* and indicates that the cause is nonexistent or unknown.) | ||
* @see HttpURLConnection#getResponseCode() | ||
* @see HttpURLConnection#getResponseMessage() | ||
*/ | ||
public HttpException(String message, int responseCode, String responseMessage, String url, Throwable cause) { | ||
super(message, cause); | ||
this.responseCode = responseCode; | ||
this.responseMessage = responseMessage; | ||
this.url = url; | ||
} | ||
|
||
/** | ||
* @param message The detail message (which is saved for later retrieval | ||
* by the {@link #getMessage()} method) | ||
* @param responseCode Http response code. {@code -1} if no code can be discerned. | ||
* @param responseMessage Http response message | ||
* @param url The url that was invoked | ||
* @param cause The cause (which is saved for later retrieval by the | ||
* {@link #getCause()} method). (A null value is permitted, | ||
* and indicates that the cause is nonexistent or unknown.) | ||
* @see HttpURLConnection#getResponseCode() | ||
* @see HttpURLConnection#getResponseMessage() | ||
*/ | ||
public HttpException(int responseCode, String responseMessage, String url, Throwable cause) { | ||
super("Server returned HTTP response code: " + responseCode + ", message: '" + responseMessage + "'" + | ||
" for URL: " + url, cause); | ||
this.responseCode = responseCode; | ||
this.responseMessage = responseMessage; | ||
this.url = url; | ||
} | ||
|
||
/** | ||
* @param responseCode Http response code. {@code -1} if no code can be discerned. | ||
* @param responseMessage Http response message | ||
* @param url The url that was invoked | ||
* @param cause The cause (which is saved for later retrieval by the | ||
* {@link #getCause()} method). (A null value is permitted, | ||
* and indicates that the cause is nonexistent or unknown.) | ||
* @see HttpURLConnection#getResponseCode() | ||
* @see HttpURLConnection#getResponseMessage() | ||
*/ | ||
public HttpException(int responseCode, String responseMessage, @CheckForNull URL url, Throwable cause) { | ||
this(responseCode, responseMessage, url == null ? null : url.toString(), cause); | ||
} | ||
|
||
/** | ||
* Http response code of the request that cause the exception | ||
* | ||
* @return {@code -1} if no code can be discerned. | ||
*/ | ||
public int getResponseCode() { | ||
return responseCode; | ||
} | ||
|
||
/** | ||
* Http response message of the request that cause the exception | ||
* | ||
* @return {@code null} if no response message can be discerned. | ||
*/ | ||
public String getResponseMessage() { | ||
return responseMessage; | ||
} | ||
|
||
/** | ||
* The http URL that caused the exception | ||
* | ||
* @return url | ||
*/ | ||
public String getUrl() { | ||
return url; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,6 +48,8 @@ | |
import java.util.Locale; | ||
import java.util.Map; | ||
import java.util.NoSuchElementException; | ||
import java.util.logging.Level; | ||
import java.util.logging.Logger; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
import java.util.zip.GZIPInputStream; | ||
|
@@ -64,7 +66,9 @@ | |
*/ | ||
class Requester { | ||
private static final List<String> METHODS_WITHOUT_BODY = asList("GET", "DELETE"); | ||
|
||
|
||
protected final transient Logger logger = Logger.getLogger(getClass().getName()); | ||
|
||
private final GitHub root; | ||
private final List<Entry> args = new ArrayList<Entry>(); | ||
private final Map<String,String> headers = new LinkedHashMap<String, String>(); | ||
|
@@ -473,21 +477,33 @@ private void setupConnection(URL url) throws IOException { | |
} | ||
|
||
private <T> T parse(Class<T> type, T instance) throws IOException { | ||
if (uc.getResponseCode()==304) | ||
return null; // special case handling for 304 unmodified, as the content will be "" | ||
InputStreamReader r = null; | ||
int responseCode = -1; | ||
String responseMessage = null; | ||
try { | ||
responseCode = uc.getResponseCode(); | ||
responseMessage = uc.getResponseMessage(); | ||
if (responseCode == 304) { | ||
return null; // special case handling for 304 unmodified, as the content will be "" | ||
} | ||
|
||
r = new InputStreamReader(wrapStream(uc.getInputStream()), "UTF-8"); | ||
String data = IOUtils.toString(r); | ||
if (type!=null) | ||
try { | ||
return MAPPER.readValue(data,type); | ||
} catch (JsonMappingException e) { | ||
throw (IOException)new IOException("Failed to deserialize "+data).initCause(e); | ||
throw (IOException)new IOException("Failed to deserialize " +data).initCause(e); | ||
} | ||
if (instance!=null) | ||
return MAPPER.readerForUpdating(instance).<T>readValue(data); | ||
return null; | ||
} catch (FileNotFoundException e) { | ||
// java.net.URLConnection handles 404 exception has FileNotFoundException, don't wrap exception in HttpException | ||
// to preserve backward compatibility | ||
throw e; | ||
} catch (IOException e) { | ||
throw new HttpException(responseCode, responseMessage, uc.getURL(), e); | ||
} finally { | ||
IOUtils.closeQuietly(r); | ||
} | ||
|
@@ -508,7 +524,18 @@ private InputStream wrapStream(InputStream in) throws IOException { | |
* Handle API error by either throwing it or by returning normally to retry. | ||
*/ | ||
/*package*/ void handleApiError(IOException e) throws IOException { | ||
if (uc.getResponseCode() == 401) // Unauthorized == bad creds | ||
int responseCode; | ||
try { | ||
responseCode = uc.getResponseCode(); | ||
} catch (IOException e2) { | ||
// likely to be a network exception (e.g. SSLHandshakeException), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Best to log at |
||
// uc.getResponseCode() and any other getter on the response will cause an exception | ||
if (logger.isLoggable(Level.FINE)) | ||
logger.log(Level.FINE, "Silently ignore exception retrieving response code for '" + uc.getURL() + "'" + | ||
" handling exception " + e, e); | ||
throw e; | ||
} | ||
if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) // 401 / Unauthorized == bad creds | ||
throw e; | ||
|
||
if ("0".equals(uc.getHeaderField("X-RateLimit-Remaining"))) { | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this intended to be
@CheckForNull
? The next overload seems to imply that it is.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed deserves a
@CheckForNull
but as@CheckForNull
and@Nonnull
are not used in this project and as we only havejavax.annotation.CheckForNull
that @stephenc don't like, I did not dare to add it.I am happy to add
@javax.annotation.CheckForNull
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not a maintainer of this plugin, so if the plugin maintainers want to have you use an annotation that is - in its current source - illegal under the terms of the JCP and may put you in breech of contract if you ever signed a JCP agreement, that is your and their business
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stephenc can you please remind me which annotation library is "the right one" and I'll commit the change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to ask the owner of this codebase what one they prefer.
Now as to which is correct:
javax
package for authoring classes that you redistribute where the spec of those classes has been published via the JCP process.javax.annotations.NonNull
(which is not the one everyone is using you will note)So where I have a choice I will use the
edu.
version... under the non GPL license... Because in those cases I can choose to "do the right thing"... If there is ever even an official published draft of annotations for this in 'javax` I will switch to themThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stephenc since you seem to have a strong opinion would you mind proposing a patch to
plugin-pom
to forbid usage of the one(s) you do not like and/or enforce usage of the one(s) you do like, bearing in mind thatedu.umd.cs.findbugs.annotations.NonNull
was@Deprecated
incom.google.code.findbugs:annotations:3.0.0
and thatcom.github.stephenc.findbugs:findbugs-annotations:1.3.9-1
is clearly outdated?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the way I can guess that the owner of this codebase is not really interested in the question and you can use whatever you find convenient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stephenc thanks, I am a bit stuck, net.sourceforge.findbugs:annotations is LGPL and thus incompatible with the MIT license of this project. com.github.stephenc.findbugs:findbugs-annotations is ASL2 and thus could be OK.
I'll wait for the owner of the code base to make a suggestion :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I discussed this subject with the owner of the code base, and the owner has agreed that they personally will start making an effort to use the
edu
one.I will merge the PR on my ASL clean room version of find bugs annotations tomorrow and release into central (without
@Deprecacted
)What you choose to do is up to you
Sent from my iPhone