/**
* The MIT License
*
* Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.hudsonci.utils.hamcrest;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
public class URLRespondsWithStatusMatcher extends TypeSafeMatcher<URL> {
private int statusCode = -2; // since -1 means the response was non-http-valid
private int timeout = 0; // negative timeout would throw iae, default infinite
private int receivedStatusCode = 0;
private boolean timedOut = false;
private Exception e;
private String urlString;
public URLRespondsWithStatusMatcher(final int statusCode) {
this(statusCode, 0);
}
public URLRespondsWithStatusMatcher(final int statusCode, final int timeout) {
if(timeout < 0){
throw new IllegalArgumentException("timeout cannot be negative");
}
if(statusCode < -1){
throw new IllegalArgumentException("status code cannot be less than negative one");
}
this.statusCode = statusCode;
this.timeout = timeout;
}
public void describeTo(Description description) {
if(timedOut){
description.appendValue(urlString).appendText(" to connect within ").appendValue(timeout).appendText("ms");
} else if (e != null){
description.appendValue(urlString).appendText(" to successfully connect");
} else {
description.appendValue(urlString).appendText(" to respond with ").appendValue(statusCode);
}
}
@Override
protected void describeMismatchSafely(URL item, Description mismatchDescription) {
if(timedOut){
mismatchDescription.appendText("took longer.");
if(this.e != null){
mismatchDescription.appendText(this.e.getMessage());
}
} else if (e != null){
mismatchDescription.appendText("got ").appendValue(this.e);
// description.appendText("got exception ").appendValue(e);
} else {
mismatchDescription.appendText("was ").appendValue(receivedStatusCode);
}
}
@Override
protected boolean matchesSafely(URL item) {
this.urlString = item.toString();
try {
URL url = new URL(item.toString());
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
if(timeout > -1){
urlConnection.setConnectTimeout(timeout);
urlConnection.setReadTimeout(timeout);
}
urlConnection.setUseCaches(false);
urlConnection.connect();
this.receivedStatusCode = urlConnection.getResponseCode();
} catch (SocketTimeoutException ste){
timedOut = true;
this.e = ste;
} catch (IOException ioe) {
this.e = ioe;
} catch (Exception e){
this.e = e;
}
return (!timedOut && e == null && this.receivedStatusCode == this.statusCode);
}
}