/* * $HeadURL:: $ $Id: * AmbraStreamResult.java 946 2006-11-03 22:23:42Z viru $ * * Copyright (c) 2006-2010 by Public Library of Science * http://plos.org * http://ambraproject.org * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.ambraproject.struts2; import com.opensymphony.xwork2.ActionInvocation; import org.ambraproject.web.HttpResourceServer; import org.apache.struts2.dispatcher.StreamResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Date; /** * Custom webwork result class to stream back objects from OTM blobs. Takes appropriate http * headers and sets them the response stream as well as taking in an optional parameter indicating * whether to set the content-diposition to an attachment. * * Reading inputStream requires a transaction. That can be acomplished if action implements * TransactionAware interface. * */ public class AmbraStreamResult extends StreamResult { private boolean isAttachment = false; private static final Logger log = LoggerFactory.getLogger(AmbraStreamResult.class); private HttpResourceServer server = new HttpResourceServer(); /* * inherited javadoc */ protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception { final InputStream inputStream = (InputStream) invocation.getStack().findValue("inputStream"); Date date = (Date) invocation.getStack().findValue("lastModified"); HttpResourceServer.Resource resource; long lastModified = (date == null) ? System.currentTimeMillis() : date.getTime(); if (log.isDebugEnabled()) { log.debug("LastModified "+new Date(lastModified)); } HttpServletResponse oResponse = (HttpServletResponse) invocation.getInvocationContext().get(HTTP_RESPONSE); // If the filestore is setup to handle reproxy we add information // to the response header so that perlbal can go directly to the // file via http instead of ambra wasting time delivering it. String resproxyURL = (String) invocation.getStack().findValue("xReproxyList"); if (resproxyURL != null) { oResponse.addHeader("X-Reproxy-URL", resproxyURL ); String reproxyCacheSettings = (String) invocation.getStack().findValue("reproxyCacheSettings"); if (reproxyCacheSettings != null) oResponse.addHeader("X-Reproxy-Cache-For", reproxyCacheSettings ); } String name = "--unnamed--"; // Set the content-disposition if (this.contentDisposition != null) { name = getProperty("contentDisposition", this.contentDisposition, invocation); oResponse.addHeader("Content-disposition", (isAttachment ? "attachment; " : "") + name); } else if (isAttachment) { oResponse.addHeader("Content-disposition", "attachment;"); } String contentType = getProperty("contentType", this.contentType, invocation); Long contentLength = (Long) invocation.getStack().findValue("contentLength"); if (contentLength == null) throw new IllegalArgumentException("'contentLength' must be set in '" + invocation.getAction().getClass()); if (log.isDebugEnabled()) log.debug("Received InputStream of length="+contentLength); resource = new HttpResourceServer.Resource(name, contentType, contentLength, lastModified) { public byte[] getContent() { return null; } public InputStream streamContent() throws IOException { return inputStream; } }; HttpServletRequest oRequest = (HttpServletRequest) invocation.getInvocationContext().get(HTTP_REQUEST); server.serveResource(oRequest, oResponse, resource, resproxyURL); } private String getProperty(final String propertyName, final String param,final ActionInvocation invocation) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { final Object action = invocation.getAction(); final String methodName = "get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1); final Method method = action.getClass().getMethod(methodName); final Object o = method.invoke(action); final String propertyValue = (o != null ? o.toString() : null); if (null == propertyValue) { return conditionalParse(param, invocation); } return propertyValue; } /** * Tests if the content disposition-type is "attachment". * * @return Returns the isAttachment. */ public boolean isAttachment() { return isAttachment; } /** * If set to true, will add attachment to content disposition * * @param isAttachment The isAttachment to set. */ public void setIsAttachment(boolean isAttachment) { this.isAttachment = isAttachment; } }