001: /* Copyright 2002 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005:
006: package org.jasig.portal;
007:
008: import java.io.IOException;
009: import java.io.InputStream;
010: import java.util.Enumeration;
011: import java.util.Hashtable;
012: import java.util.Iterator;
013: import java.util.Map;
014: import java.util.Set;
015:
016: import javax.servlet.ServletOutputStream;
017: import javax.servlet.http.HttpServletRequest;
018: import javax.servlet.http.HttpServletResponse;
019:
020: import org.apache.commons.logging.Log;
021: import org.apache.commons.logging.LogFactory;
022:
023: /**
024: * Provides file download capability for the portal.
025: *
026: * @author <a href="mailto:svenkatesh@interactivebusiness.com">Sridhar Venkatesh</a>
027: * @author Peter Kharchenko {@link <a href="mailto:pkharchenko@interactivebusiness.com"">pkharchenko@interactivebusiness.com"</a>}
028: */
029: public class DownloadDispatchWorker implements IWorkerRequestProcessor {
030:
031: private static final Log log = LogFactory
032: .getLog(DownloadDispatchWorker.class);
033:
034: public void processWorkerDispatch(PortalControlStructures pcs)
035: throws PortalException {
036: HttpServletRequest req = pcs.getHttpServletRequest();
037: HttpServletResponse res = pcs.getHttpServletResponse();
038:
039: // determine the channel, follow the same logic as the standard uPortal processing.
040: // (although, in general, worker processors can make their own rules
041: String channelTarget = null;
042: Hashtable targetParams = new Hashtable();
043:
044: // check if the uP_channelTarget parameter has been passed
045: channelTarget = req.getParameter("uP_channelTarget");
046: if (channelTarget == null) {
047: // determine target channel id
048: UPFileSpec upfs = new UPFileSpec(req);
049: channelTarget = upfs.getTargetNodeId();
050: }
051:
052: // gather parameters
053: if (channelTarget != null) {
054: Enumeration en = req.getParameterNames();
055: if (en != null) {
056: while (en.hasMoreElements()) {
057: String pName = (String) en.nextElement();
058: if (!pName.equals("uP_channelTarget")) {
059: Object[] val = (Object[]) req
060: .getParameterValues(pName);
061: if (val == null) {
062: val = ((IRequestParamWrapper) req)
063: .getObjectParameterValues(pName);
064: }
065: targetParams.put(pName, val);
066: }
067: }
068: }
069:
070: IChannel ch = pcs.getChannelManager().getChannelInstance(
071: channelTarget);
072:
073: if (ch != null) {
074: // set pcs
075: if (ch instanceof IPrivilegedChannel) {
076: ((IPrivilegedChannel) ch)
077: .setPortalControlStructures(pcs);
078: }
079: // set runtime data
080: ChannelRuntimeData rd = new ChannelRuntimeData();
081: rd.setParameters(targetParams);
082: rd.setBrowserInfo(new BrowserInfo(req));
083: rd.setHttpRequestMethod(req.getMethod());
084: rd.setRemoteAddress(req.getRemoteAddr());
085: rd.setUPFile(new UPFileSpec(null,
086: UPFileSpec.RENDER_METHOD,
087: UserInstance.USER_LAYOUT_ROOT_NODE,
088: channelTarget, null));
089:
090: if (ch instanceof org.jasig.portal.IMimeResponse) {
091: ch.setRuntimeData(rd);
092:
093: org.jasig.portal.IMimeResponse ds = (org.jasig.portal.IMimeResponse) ch;
094: ServletOutputStream out = null;
095: InputStream ios = null;
096: try {
097:
098: // Set the headers if available
099: Map httpHeaders = ds.getHeaders();
100: if (httpHeaders != null) {
101: Set headerKeys = httpHeaders.keySet();
102: Iterator it = headerKeys.iterator();
103: while (it.hasNext()) {
104: String param = (String) it.next();
105: String value = (String) httpHeaders
106: .get(param);
107: res.setHeader(param, value);
108: }
109: httpHeaders.clear();
110: }
111:
112: // Set the MIME content type
113: res.setContentType(ds.getContentType());
114:
115: // Set the data
116: out = res.getOutputStream();
117: ios = ds.getInputStream();
118: if (ios != null) {
119: int size = 0;
120: byte[] contentBytes = new byte[8192];
121: while ((size = ios.read(contentBytes)) != -1) {
122: out.write(contentBytes, 0, size);
123: }
124: } else {
125: /**
126: * The channel has more complicated processing it needs to do on the
127: * output stream
128: */
129: ds.downloadData(out);
130: }
131: out.flush();
132: } catch (Exception e) {
133: ds.reportDownloadError(e);
134: } finally {
135: try {
136: if (ios != null)
137: ios.close();
138: if (out != null)
139: out.close();
140: } catch (IOException ioe) {
141: log
142: .error(
143: "DownloadDispatchWorker:processWorkerDispatch unable to close IOStream ",
144: ioe);
145: }
146: }
147: } else if (ch instanceof org.jasig.portal.IDirectResponse) {
148: //We are allowing the rendering of URLs in the IDirectResponse interface
149: //so the tag needs to be set for the uPfile
150: rd.getUPFile().setTagId(
151: PortalSessionManager.INTERNAL_TAG_VALUE);
152: rd.setTargeted(true);
153: ch.setRuntimeData(rd);
154:
155: org.jasig.portal.IDirectResponse dirResp = (org.jasig.portal.IDirectResponse) ch;
156:
157: dirResp.setResponse(res);
158: } else {
159: log
160: .error("DownloadDispatchWorker::processWorkerDispatch(): Channel (instanceId=\""
161: + channelTarget
162: + "\" needs to implement org.jasig.portal.IMimeResponse interface in order to download files.");
163: }
164: } else {
165: log
166: .warn("DownloadDispatchWorker::processWorkerDispatch(): unable to obtain instance a channel. instanceId=\""
167: + channelTarget + "\".");
168: }
169: } else {
170: log
171: .error("DownloadDispatchWorker::processWorkerDispatch(): unable to determine instance Id of the target channel. requestURL=\""
172: + pcs.getHttpServletRequest()
173: .getRequestURI() + "\".");
174: }
175: }
176: }
|