2424import org .metafacture .framework .annotations .Out ;
2525import org .metafacture .framework .helpers .DefaultObjectPipe ;
2626
27+ import java .io .ByteArrayInputStream ;
2728import java .io .IOException ;
29+ import java .io .InputStream ;
2830import java .io .InputStreamReader ;
2931import java .io .Reader ;
32+ import java .io .SequenceInputStream ;
33+ import java .net .HttpURLConnection ;
3034import java .net .URL ;
31- import java .net .URLConnection ;
3235import java .util .Arrays ;
3336import java .util .HashMap ;
3437import java .util .Map ;
3538import java .util .regex .Pattern ;
3639
3740/**
38- * Opens a {@link URLConnection } and passes a reader to the receiver.
41+ * Opens an {@link HttpURLConnection } and passes a reader to the receiver.
3942 *
4043 * @author Christoph Böhme
4144 * @author Jan Schnasse
@@ -55,14 +58,50 @@ public final class HttpOpener extends DefaultObjectPipe<String, ObjectReceiver<R
5558 private static final String ACCEPT_DEFAULT = "*/*" ;
5659 private static final String ENCODING_DEFAULT = "UTF-8" ;
5760
61+ private static final String INPUT_DESIGNATOR = "@-" ;
62+
63+ private static final Method DEFAULT_METHOD = Method .GET ;
64+ private static final String DEFAULT_PREFIX = "ERROR: " ;
65+
5866 private final Map <String , String > headers = new HashMap <>();
5967
68+ private Method method ;
69+ private String body ;
70+ private String errorPrefix ;
71+ private String url ;
72+ private boolean inputUsed ;
73+
74+ public enum Method {
75+
76+ DELETE (false ),
77+ GET (false ),
78+ HEAD (false ),
79+ OPTIONS (false ),
80+ POST (true ),
81+ PUT (true ),
82+ TRACE (false );
83+
84+ private final boolean inputAsBody ;
85+
86+ Method (final boolean inputAsBody ) {
87+ this .inputAsBody = inputAsBody ;
88+ }
89+
90+ private boolean getInputAsBody () {
91+ return inputAsBody ;
92+ }
93+
94+ }
95+
6096 /**
6197 * Creates an instance of {@link HttpOpener}.
6298 */
6399 public HttpOpener () {
64100 setAccept (ACCEPT_DEFAULT );
65101 setEncoding (ENCODING_DEFAULT );
102+ setErrorPrefix (DEFAULT_PREFIX );
103+ setMethod (DEFAULT_METHOD );
104+ setUrl (INPUT_DESIGNATOR );
66105 }
67106
68107 /**
@@ -76,6 +115,15 @@ public void setAccept(final String accept) {
76115 setHeader (ACCEPT_HEADER , accept );
77116 }
78117
118+ /**
119+ * Sets the HTTP request body.
120+ *
121+ * @param body the request body
122+ */
123+ public void setBody (final String body ) {
124+ this .body = body ;
125+ }
126+
79127 /**
80128 * Sets the preferred encoding of the HTTP response. This value is in the
81129 * accept-charset header. Additonally, the encoding is used for reading the
@@ -89,6 +137,15 @@ public void setEncoding(final String encoding) {
89137 setHeader (ENCODING_HEADER , encoding );
90138 }
91139
140+ /**
141+ * Sets the error prefix.
142+ *
143+ * @param errorPrefix the error prefix
144+ */
145+ public void setErrorPrefix (final String errorPrefix ) {
146+ this .errorPrefix = errorPrefix ;
147+ }
148+
92149 /**
93150 * Sets a request property, or multiple request properties separated by
94151 * {@code \n}.
@@ -117,21 +174,85 @@ public void setHeader(final String key, final String value) {
117174 headers .put (key .toLowerCase (), value );
118175 }
119176
177+ /**
178+ * Sets the HTTP request method.
179+ *
180+ * @param method the request method
181+ */
182+ public void setMethod (final Method method ) {
183+ this .method = method ;
184+ }
185+
186+ /**
187+ * Sets the HTTP request URL.
188+ *
189+ * @param url the request URL
190+ */
191+ public void setUrl (final String url ) {
192+ this .url = url ;
193+ }
194+
120195 @ Override
121- public void process (final String urlStr ) {
196+ public void process (final String input ) {
122197 try {
123- final URL url = new URL (urlStr );
124- final URLConnection con = url .openConnection ();
125- headers .forEach (con ::addRequestProperty );
126- String enc = con .getContentEncoding ();
127- if (enc == null ) {
128- enc = headers .get (ENCODING_HEADER );
198+ final String requestUrl = getInput (input , url );
199+ final String requestBody = getInput (input ,
200+ body == null && method .getInputAsBody () ? INPUT_DESIGNATOR : body );
201+
202+ final HttpURLConnection connection =
203+ (HttpURLConnection ) new URL (requestUrl ).openConnection ();
204+
205+ connection .setRequestMethod (method .name ());
206+ headers .forEach (connection ::addRequestProperty );
207+
208+ if (requestBody != null ) {
209+ connection .setDoOutput (true );
210+ connection .getOutputStream ().write (requestBody .getBytes ());
211+ }
212+
213+ final InputStream errorStream = connection .getErrorStream ();
214+ final InputStream inputStream ;
215+
216+ if (errorStream != null ) {
217+ if (errorPrefix != null ) {
218+ final InputStream errorPrefixStream = new ByteArrayInputStream (errorPrefix .getBytes ());
219+ inputStream = new SequenceInputStream (errorPrefixStream , errorStream );
220+ }
221+ else {
222+ inputStream = errorStream ;
223+ }
129224 }
130- getReceiver ().process (new InputStreamReader (con .getInputStream (), enc ));
225+ else {
226+ inputStream = connection .getInputStream ();
227+ }
228+
229+ final String contentEncoding = getEncoding (connection .getContentEncoding ());
230+ getReceiver ().process (new InputStreamReader (inputStream , contentEncoding ));
131231 }
132232 catch (final IOException e ) {
133233 throw new MetafactureException (e );
134234 }
135235 }
136236
237+ private String getInput (final String input , final String value ) {
238+ final String result ;
239+
240+ if (!INPUT_DESIGNATOR .equals (value )) {
241+ result = value ;
242+ }
243+ else if (inputUsed ) {
244+ result = null ;
245+ }
246+ else {
247+ inputUsed = true ;
248+ result = input ;
249+ }
250+
251+ return result ;
252+ }
253+
254+ private String getEncoding (final String contentEncoding ) {
255+ return contentEncoding != null ? contentEncoding : headers .get (ENCODING_HEADER );
256+ }
257+
137258}
0 commit comments