Java tutorial
/* * R Service Bus * * Copyright (c) Copyright of Open Analytics NV, 2010-2015 * * =========================================================================== * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package eu.openanalytics.rsb.component; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.UUID; import javax.annotation.Resource; import javax.ws.rs.GET; import javax.ws.rs.HEAD; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.ResponseBuilder; import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.StreamingOutput; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.cxf.common.util.Base64Utility; import org.springframework.stereotype.Component; import eu.openanalytics.rsb.Constants; import eu.openanalytics.rsb.Util; import eu.openanalytics.rsb.data.PersistedResult; import eu.openanalytics.rsb.data.SecureResultStore; /** * Serves R job process result files.<br/> * <i>NB. Could very well be replaced with a static file serving context on a frontal * web server.</i> * * @author "OpenAnalytics <rsb.development@openanalytics.eu>" */ @Component("resultResource") @Produces("application/octet-stream") @Path("/" + Constants.RESULT_PATH + "/{applicationName}/{resourceName}") public class ResultResource extends AbstractResource { @Resource private SecureResultStore resultStore; // exposed for testing void setResultStore(final SecureResultStore resultStore) { this.resultStore = resultStore; } /** * Serves a single result file. * * @param applicationName * @param resourceName * @return * @throws IOException */ @GET public Response getResult(@PathParam("applicationName") final String applicationName, @PathParam("resourceName") final String resourceName) throws IOException { final PersistedResult persistedResult = getPersistedResultOrDie(applicationName, resourceName); final ResponseBuilder rb = Response.ok(); addEtagHeader(persistedResult, rb); rb.entity(new StreamingOutput() { public void write(final OutputStream output) throws IOException { final InputStream data = persistedResult.getData(); IOUtils.copy(data, output); IOUtils.closeQuietly(data); IOUtils.closeQuietly(output); } }); return rb.build(); } /** * Provides HTTP meta-information only for a single result file. * * @param applicationName * @param resourceName * @return * @throws IOException */ @HEAD public Response getResultMeta(@PathParam("applicationName") final String applicationName, @PathParam("resourceName") final String resourceName) throws IOException { final PersistedResult persistedResult = getPersistedResultOrDie(applicationName, resourceName); final ResponseBuilder rb = Response.noContent(); addContentLengthHeader(persistedResult, rb); addEtagHeader(persistedResult, rb); return rb.build(); } private void addEtagHeader(final PersistedResult persistedResult, final ResponseBuilder rb) { rb.header(HttpHeaders.ETAG, getEtag(persistedResult)); } private void addContentLengthHeader(final PersistedResult persistedResult, final ResponseBuilder rb) throws IOException { rb.header(HttpHeaders.CONTENT_LENGTH, Long.toString(persistedResult.getDataLength())); } private PersistedResult getPersistedResultOrDie(final String applicationName, final String resourceName) { if (!Util.isValidApplicationName(applicationName)) { throw new IllegalArgumentException("Invalid application name: " + applicationName); } final UUID jobId = UUID.fromString(FilenameUtils.getBaseName(resourceName)); final PersistedResult persistedResult = resultStore.findByApplicationNameAndJobId(applicationName, getUserName(), jobId); if (persistedResult == null) { throw new WebApplicationException(Response.status(Status.NOT_FOUND).build()); } return persistedResult; } // exposed for unit testing static String getEtag(final PersistedResult persistedResult) { return Base64Utility .encode((persistedResult.getApplicationName() + "/" + persistedResult.getJobId()).getBytes()); } }