<commit_before>/*
 * Copyright (c) 2009-2010, <NAME> and Zepheira LLC Some rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * - Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution. 
 * - Neither the name of the openrdf.org nor the names of its contributors may
 *   be used to endorse or promote products derived from this software without
 *   specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 */
package org.openrdf.http.object.exceptions;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.zip.GZIPInputStream;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;

/**
 * Base class for HTTP exceptions.
 */
public abstract class ResponseException extends RuntimeException {

	public static ResponseException create(HttpResponse resp) throws IOException {
		StatusLine line = resp.getStatusLine();
		int code = line.getStatusCode();
		return create(code, line.getReasonPhrase(), readMessage(resp));
	}

	public static ResponseException create(final int status, String msg, String stack) {
		switch (status) {
		case 502:
			return new BadGateway(msg, stack);
		case 400:
			return new BadRequest(msg, stack);
		case 409:
			return new Conflict(msg, stack);
		case 504:
			return new GatewayTimeout(msg, stack);
		case 410:
			return new Gone(msg, stack);
		case 415:
			return new UnsupportedMediaType(msg, stack);
		case 500:
			return new InternalServerError(msg, stack);
		case 405:
			return new MethodNotAllowed(msg, stack);
		case 406:
			return new NotAcceptable(msg, stack);
		case 404:
			return new NotFound(msg, stack);
		case 501:
			return new NotImplemented(msg, stack);
		case 503:
			return new ServiceUnavailable(msg, stack);
		default:
			return new ResponseException(msg, stack) {
				private static final long serialVersionUID = 3458241161561417132L;

				public boolean isCommon() {
					return true;
				}

				public int getStatusCode() {
					return status;
				}
			};
		}
	}

	private static String readMessage(HttpResponse resp) throws IOException {
		HttpEntity entity = resp.getEntity();
		if (entity == null)
			return null; // no response
		try {
			StringWriter string = new StringWriter();
			InputStream in = entity.getContent();
			Header hd = resp.getFirstHeader("Content-Encoding");
			if (hd != null && "gzip".equals(hd.getValue())) {
				in = new GZIPInputStream(in);
			}
			InputStreamReader reader = new InputStreamReader(in, "UTF-8");
			try {
				int read;
				char[] cbuf = new char[1024];
				while ((read = reader.read(cbuf)) >= 0) {
					string.write(cbuf, 0, read);
				}
			} finally {
				reader.close();
			}
			String body = string.toString();
			if (body.startsWith("<")) {
				if (body.contains("<pre") && body.contains("</pre>")) {
					body = body.replaceAll(".*<pre[^>]*>", "");
					body = body.replaceAll("</pre>.*", "");
				} else if (body.contains("<PRE") && body.contains("</PRE>")) {
					body = body.replaceAll(".*<PRE[^>]*>", "");
					body = body.replaceAll("</PRE>.*", "");
				}
				body = body.replaceAll("<[^>]*>", "\n");
				body = body.replaceAll("\n+", "\n");
				body = body.replaceAll("&lt;", "<");
				body = body.replaceAll("&gt;", ">");
				body = body.replaceAll("&nbsp;", " ");
				body = body.replaceAll("&amp;", "&");
			}
			return body.trim();
		} catch (UnsupportedEncodingException e) {
			throw new AssertionError(e);
		} catch (IOException e) {
			return null;
		} finally {
			entity.consumeContent();
		}
	}

	private static final long serialVersionUID = -4156041448577237448L;
	private String msg;

	public ResponseException(String message) {
		super(message);
		this.msg = trimMessage(message);
	}

	public ResponseException(String message, Throwable cause) {<commit_msg>Read error message from error page title (instead of error response status text)<commit_after>/*
 * Copyright (c) 2009-2010, <NAME> and Zepheira LLC Some rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * - Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution. 
 * - Neither the name of the openrdf.org nor the names of its contributors may
 *   be used to endorse or promote products derived from this software without
 *   specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 */
package org.openrdf.http.object.exceptions;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.zip.GZIPInputStream;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;

/**
 * Base class for HTTP exceptions.
 */
public abstract class ResponseException extends RuntimeException {

	public static ResponseException create(HttpResponse resp) throws IOException {
		StatusLine line = resp.getStatusLine();
		int code = line.getStatusCode();
		String[] titleBody = readMessage(resp, line.getReasonPhrase());
		return create(code, titleBody[0], titleBody[1]);
	}

	public static ResponseException create(int status, String msg, String stack) {
		switch (status) {
		case 400:
			return new BadRequest(msg, stack);
		case 404:
			return new NotFound(msg, stack);
		case 405:
			return new MethodNotAllowed(msg, stack);
		case 406:
			return new NotAcceptable(msg, stack);
		case 409:
			return new Conflict(msg, stack);
		case 410:
			return new Gone(msg, stack);
		case 415:
			return new UnsupportedMediaType(msg, stack);
		case 500:
			return new InternalServerError(msg, stack);
		case 501:
			return new NotImplemented(msg, stack);
		case 503:
			return new ServiceUnavailable(msg, stack);
		case 504:
			return new GatewayTimeout(msg, stack);
		default:
			return new BadGateway(msg, stack);
		}
	}

	private static String[] readMessage(HttpResponse resp, String defaultTitle) throws IOException {
		HttpEntity entity = resp.getEntity();
		if (entity == null)
			return new String[]{defaultTitle, null}; // no response
		try {
			StringWriter string = new StringWriter();
			InputStream in = entity.getContent();
			Header hd = resp.getFirstHeader("Content-Encoding");
			if (hd != null && "gzip".equals(hd.getValue())) {
				in = new GZIPInputStream(in);
			}
			InputStreamReader reader = new InputStreamReader(in, "UTF-8");
			try {
				int read;
				char[] cbuf = new char[1024];
				while ((read = reader.read(cbuf)) >= 0) {
					string.write(cbuf, 0, read);
				}
			} finally {
				reader.close();
			}
			String title = defaultTitle;
			String body = string.toString();
			if (body.startsWith("<")) {
				if (body.contains("<title") && body.contains("</title>")) {
					title = body.replaceAll(".*<title[^>]*>", "");
					title = title.replaceAll("</title>.*", "");
					title = decodeHtmlText(title);
				} else if (body.contains("<TITLE") && body.contains("</TITLE>")) {
					title = body.replaceAll(".*<TITLE[^>]*>", "");
					title = title.replaceAll("</TITLE>.*", "");
					title = decodeHtmlText(title);
				}
				if (body.contains("<pre") && body.contains("</pre>")) {
					body = body.replaceAll(".*<pre[^>]*>", "");
					body = body.replaceAll("</pre>.*", "");
				} else if (body.contains("<PRE") && body.contains("</PRE>")) {
					body = body.replaceAll(".*<PRE[^>]*>", "");
					body = body.replaceAll("</PRE>.*", "");
				}
				body = decodeHtmlText(body);
			}
			return new String[]{title, body.trim()};
		} catch (UnsupportedEncodingException e) {
			throw new AssertionError(e);
		} catch (IOException e) {
			return new String[]{defaultTitle, null};
		} finally {
			entity.consumeContent();
		}
	}

	private static String decodeHtmlText(String body) {
		body = body.replaceAll("<[^>]*>", "\n");
		body = body.replaceAll("\n+", "\n");
		body = body.replaceAll("&lt;", "<");
		body = body.replaceAll("&gt;", ">");
		body = body.replaceAll("&nbsp;", " ");
		body = body.replaceAll("&amp;", "&");
		return body;
	}

	private static final long serialVersionUID = -4156041448577237448L;
	private String msg;

	public ResponseException(String message) {
		super(message);
		this.msg = trimMessage(message);
	}

	public ResponseException(String message, Throwable cause) {
{'fraction_non_alphanumeric': 0.12197167349981364, 'fraction_numerical': 0.014722325754752142, 'mean_word_length': 4.003729603729604, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5221250', 'n_tokens_mistral': 3633, 'n_tokens_neox': 3029, 'n_words': 1042}