001/**
002 * Copyright 2015 DuraSpace, Inc.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.fcrepo.client;
017
018import java.io.Closeable;
019import java.io.IOException;
020import java.io.InputStream;
021import java.net.URI;
022
023/**
024 * Represents a response from a fedora repository using a {@link FcrepoClient}.
025 * <p>
026 * This class implements {@link Closeable}.  Suggested usage is to create the {@code FcrepoResponse} within
027 * a try-with-resources block, insuring that any resources held by the response are freed automatically.
028 * </p>
029 * <pre>
030 * FcrepoClient client = ...;
031 * try (FcrepoResponse res = client.get(...)) {
032 *     // do something with the response
033 * } catch (FcrepoOperationFailedException|IOException e) {
034 *     // handle any exceptions
035 * }
036 * </pre>
037 * Closed responses have no obligation to provide access to released resources.
038 *
039 * @author Aaron Coburn
040 * @since October 20, 2014
041 */
042public class FcrepoResponse implements Closeable {
043
044    private URI url;
045
046    private int statusCode;
047
048    private URI location;
049
050    private InputStream body;
051
052    private String contentType;
053
054    private boolean closed = false;
055
056    /**
057     * Create a FcrepoResponse object from the http response
058     *
059     * @param url the requested URL
060     * @param statusCode the HTTP status code
061     * @param contentType the mime-type of the response
062     * @param location the location of a related resource
063     * @param body the response body stream
064     */
065    public FcrepoResponse(final URI url, final int statusCode,
066            final String contentType, final URI location, final InputStream body) {
067        this.setUrl(url);
068        this.setStatusCode(statusCode);
069        this.setLocation(location);
070        this.setContentType(contentType);
071        this.setBody(body);
072    }
073
074    /**
075     * {@inheritDoc}
076     * <p>
077     * Implementation note: Invoking this method will close the underlying {@code InputStream} containing the entity
078     * body of the HTTP response.
079     * </p>
080     *
081     * @throws IOException if there is an error closing the underlying HTTP response stream.
082     */
083    @Override
084    public void close() throws IOException {
085        if (!this.closed && this.body != null) {
086            try {
087                this.body.close();
088            } finally {
089                this.closed = true;
090            }
091        }
092    }
093
094    /**
095     * Whether or not the resources have been freed from this response.  There should be no expectation that a closed
096     * response provides access to the {@link #getBody() entity body}.
097     *
098     * @return {@code true} if resources have been freed, otherwise {@code false}
099     */
100    public boolean isClosed() {
101        return closed;
102    }
103
104    /**
105     * url getter
106     *
107     * @return the requested URL
108     */
109    public URI getUrl() {
110        return url;
111    }
112
113    /**
114     * url setter
115     * 
116     * @param url the requested URL
117     */
118    public void setUrl(final URI url) {
119        this.url = url;
120    }
121
122    /**
123     * statusCode getter
124     *
125     * @return the HTTP status code
126     */
127    public int getStatusCode() {
128        return statusCode;
129    }
130
131    /**
132     * statusCode setter
133     * 
134     * @param statusCode the HTTP status code
135     */
136    public void setStatusCode(final int statusCode) {
137        this.statusCode = statusCode;
138    }
139
140    /**
141     * body getter
142     *
143     * @return the response body as a stream
144     */
145    public InputStream getBody() {
146        return body;
147    }
148
149    /**
150     * body setter
151     * 
152     * @param body the contents of the response body
153     */
154    public void setBody(final InputStream body) {
155        this.body = body;
156    }
157
158    /**
159     * location getter
160     * 
161     * @return the location of a related resource
162     */
163    public URI getLocation() {
164        return location;
165    }
166
167    /**
168     * location setter
169     * 
170     * @param location the value of a related resource
171     */
172    public void setLocation(final URI location) {
173        this.location = location;
174    }
175
176    /**
177     * contentType getter
178     *
179     * @return the mime-type of response
180     */
181    public String getContentType() {
182        return contentType;
183    }
184
185    /**
186     * contentType setter
187     *
188     * @param contentType the mime-type of the response
189     */
190    public void setContentType(final String contentType) {
191        this.contentType = contentType;
192    }
193}