001package com.nimbusds.oauth2.sdk.http; 002 003 004import java.io.BufferedReader; 005import java.io.IOException; 006import java.io.InputStream; 007import java.io.InputStreamReader; 008import java.net.HttpURLConnection; 009import java.net.URL; 010import javax.mail.internet.ContentType; 011import javax.mail.internet.ParseException; 012 013import net.jcip.annotations.ThreadSafe; 014import org.apache.commons.io.input.BoundedInputStream; 015 016 017/** 018 * The default retriever of resources specified by URL. Provides setting of 019 * HTTP connect and read timeouts as well as a size limit of the retrieved 020 * entity. Caching header directives are not honoured. 021 */ 022@ThreadSafe 023public class DefaultResourceRetriever extends AbstractRestrictedResourceRetriever implements RestrictedResourceRetriever { 024 025 026 /** 027 * The system line separator. 028 */ 029 private final String lineSeparator; 030 031 032 /** 033 * Creates a new resource retriever. The HTTP timeouts and entity size 034 * limit are set to zero (infinite). 035 */ 036 public DefaultResourceRetriever() { 037 038 this(0, 0); 039 } 040 041 042 /** 043 * Creates a new resource retriever. The HTTP entity size limit is set 044 * to zero (infinite). 045 * 046 * @param connectTimeout The HTTP connects timeout, in milliseconds, 047 * zero for infinite. Must not be negative. 048 * @param readTimeout The HTTP read timeout, in milliseconds, zero 049 * for infinite. Must not be negative. 050 */ 051 public DefaultResourceRetriever(final int connectTimeout, final int readTimeout) { 052 053 this(connectTimeout, readTimeout, 0); 054 } 055 056 057 /** 058 * Creates a new resource retriever. 059 * 060 * @param connectTimeout The HTTP connects timeout, in milliseconds, 061 * zero for infinite. Must not be negative. 062 * @param readTimeout The HTTP read timeout, in milliseconds, zero 063 * for infinite. Must not be negative. 064 * @param sizeLimit The HTTP entity size limit, in bytes, zero for 065 * infinite. Must not be negative. 066 */ 067 public DefaultResourceRetriever(final int connectTimeout, final int readTimeout, final int sizeLimit) { 068 069 super(connectTimeout, readTimeout, sizeLimit); 070 lineSeparator = System.getProperty("line.separator"); 071 } 072 073 074 @Override 075 public Resource retrieveResource(final URL url) 076 throws IOException { 077 078 HttpURLConnection con; 079 try { 080 con = (HttpURLConnection)url.openConnection(); 081 } catch (ClassCastException e) { 082 throw new IOException("Couldn't open HTTP(S) connection: " + e.getMessage(), e); 083 } 084 085 con.setConnectTimeout(getConnectTimeout()); 086 con.setReadTimeout(getReadTimeout()); 087 088 StringBuilder sb = new StringBuilder(); 089 090 InputStream inputStream = con.getInputStream(); 091 092 if (getSizeLimit() > 0) { 093 inputStream = new BoundedInputStream(inputStream, getSizeLimit()); 094 } 095 096 BufferedReader input = new BufferedReader(new InputStreamReader(inputStream)); 097 098 String line; 099 100 while ((line = input.readLine()) != null) { 101 102 sb.append(line); 103 sb.append(lineSeparator); 104 } 105 106 input.close(); 107 108 // Check HTTP code + message 109 final int statusCode = con.getResponseCode(); 110 final String statusMessage = con.getResponseMessage(); 111 112 // Ensure 2xx status code 113 if (statusCode > 299 || statusCode < 200) { 114 throw new IOException("HTTP " + statusCode + ": " + statusMessage); 115 } 116 117 // Parse the Content-Type header 118 ContentType contentType = null; 119 120 if (con.getContentType() != null) { 121 try { 122 contentType = new ContentType(con.getContentType()); 123 } catch (ParseException e) { 124 throw new IOException("Couldn't parse Content-Type header: " + e.getMessage(), e); 125 } 126 } 127 128 return new Resource(sb.toString(), contentType); 129 } 130}