/* * Copyright (c) 2012 - 2016 Jadler contributors * This program is made available under the terms of the MIT License. */ package net.jadler.stubbing; import net.jadler.exception.JadlerException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import org.apache.commons.io.IOUtils; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.nio.charset.Charset; import net.jadler.AbstractRequestMatching; import net.jadler.Jadler; import org.apache.commons.collections.MultiMap; import org.apache.commons.collections.map.MultiValueMap; import org.apache.commons.lang.Validate; /** * Internal class for defining http stubs in a fluid fashion. You shouldn't create instances * of this class on your own, please see {@link Jadler#onRequest()} * for more information on creating instances of this class. */ public class Stubbing extends AbstractRequestMatching<RequestStubbing> implements RequestStubbing, ResponseStubbing { private static final String CONTENT_TYPE_HEADER = "Content-Type"; Responder responder; final List<MutableStubResponse> stubResponses; private final MultiMap defaultHeaders; private final int defaultStatus; private final Charset defaultEncoding; /** * @param defaultHeaders default headers to be present in every http stub response * @param defaultStatus default http status of every http stub response * (can be overridden in the particular stub) * @param defaultEncoding default encoding of every stub response body (can be overridden in the particular stub) */ @SuppressWarnings("unchecked") Stubbing(final Charset defaultEncoding, final int defaultStatus, final MultiMap defaultHeaders) { this.stubResponses = new ArrayList<MutableStubResponse>(); this.defaultHeaders = new MultiValueMap(); this.defaultHeaders.putAll(defaultHeaders); this.defaultStatus = defaultStatus; this.defaultEncoding = defaultEncoding; this.responder = null; } /** * {@inheritDoc} */ @Override public ResponseStubbing respond() { return this.thenRespond(); } /** * {@inheritDoc} */ @Override public ResponseStubbing thenRespond() { final MutableStubResponse response = new MutableStubResponse(); response.addHeaders(defaultHeaders); response.setStatus(defaultStatus); response.setEncoding(defaultEncoding); response.setBody(""); stubResponses.add(response); return this; } /** * {@inheritDoc} */ @Override public void respondUsing(final Responder responder) { Validate.notNull(responder, "responder cannot be null"); this.responder = responder; } /** * {@inheritDoc} */ @Override public ResponseStubbing withContentType(final String contentType) { currentResponse().setHeaderCaseInsensitive(CONTENT_TYPE_HEADER, contentType); return this; } /** * {@inheritDoc} */ @Override public ResponseStubbing withEncoding(final Charset encoding) { currentResponse().setEncoding(encoding); return this; } /** * {@inheritDoc} */ @Override public ResponseStubbing withBody(final String responseBody) { currentResponse().setBody(responseBody); return this; } /** * {@inheritDoc} */ @Override public ResponseStubbing withBody(final Reader reader) { try { final String responseBody; try { responseBody = IOUtils.toString(reader); } catch (final IOException ex) { throw new JadlerException("An error ocurred while reading the response body from " + "the given Reader instance.", ex); } return this.withBody(responseBody); } finally { IOUtils.closeQuietly(reader); } } /** * {@inheritDoc} */ @Override public ResponseStubbing withBody(final InputStream is) { try { final byte[] responseBody; try { responseBody = IOUtils.toByteArray(is); } catch (final IOException e) { throw new JadlerException("A problem occurred while reading the given input stream", e); } return this.withBody(responseBody); } finally { IOUtils.closeQuietly(is); } } /** * {@inheritDoc} */ @Override public ResponseStubbing withBody(final byte[] responseBody) { currentResponse().setBody(responseBody); return this; } /** * {@inheritDoc} */ @Override public ResponseStubbing withHeader(final String name, final String value) { currentResponse().addHeader(name, value); return this; } /** * {@inheritDoc} */ @Override public ResponseStubbing withStatus(final int status) { currentResponse().setStatus(status); return this; } /** * {@inheritDoc} */ @Override public ResponseStubbing withDelay(long delayValue, TimeUnit delayUnit) { currentResponse().setDelay(java.util.concurrent.TimeUnit.MILLISECONDS.convert(delayValue, delayUnit)); return this; } /** * Creates a {@link HttpStub} instance from this Stubbing instance. * Must be called once this stubbing has been finished. * @return {@link HttpStub} instance configured using values from this stubbing */ public HttpStub createRule() { if (this.responder != null) { return new HttpStub(predicates, this.responder); } final List<StubResponse> res = new ArrayList<StubResponse>(this.stubResponses.size()); for(final MutableStubResponse msr: this.stubResponses) { res.add(msr.toStubResponse()); } return new HttpStub(predicates, new StaticResponder(res)); } private MutableStubResponse currentResponse() { return stubResponses.get(stubResponses.size() - 1); } }