1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.nordija.tapestry.bayeux.downloads;
17
18 import org.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
20 import org.apache.hivemind.ApplicationRuntimeException;
21 import org.apache.tapestry.IRequestCycle;
22 import org.apache.tapestry.engine.IEngineService;
23 import org.apache.tapestry.engine.ILink;
24 import org.apache.tapestry.services.LinkFactory;
25 import org.apache.tapestry.spec.IApplicationSpecification;
26
27 import javax.servlet.http.HttpServletResponse;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.io.OutputStream;
31 import java.util.HashMap;
32 import java.util.Map;
33
34
35
36
37
38
39
40
41
42
43
44 public class DownloadService implements IEngineService {
45
46 public static final String SERVICE_NAME = "downloads";
47
48 public static final String RESOURCE_ID_PARAM_NAME = "resourceId";
49 public static final String DOWNLOAD_RESOURCE_SOURCE_EXT_PARAM_NAME = "downloadResourceSourceExtentionName";
50 public static final String BAYEUX_DOWNLOADS_EXTENTIONS_PREFIX = "bayeux.downloads.";
51 public static final String DEFAULT_RESOURCE_SOURCE_NAME = "resourcesource";
52
53 private static final Log LOG = LogFactory.getLog(DownloadService.class);
54
55 private HttpServletResponse response;
56
57 private LinkFactory linkFactory;
58
59 public void setResponse(HttpServletResponse response) {
60 this.response = response;
61 }
62
63 public void setLinkFactory(LinkFactory linkFactory) {
64 this.linkFactory = linkFactory;
65 }
66
67 public String getName() {
68 return SERVICE_NAME;
69 }
70
71 public ILink getLink(boolean post, Object parameter) {
72 String resourceId = (String) ((Object[]) parameter)[0];
73 String extName = (String) ((Object[]) parameter)[1];
74 Map parameters = new HashMap();
75 parameters.put("service", getName());
76 parameters.put(RESOURCE_ID_PARAM_NAME, resourceId);
77 parameters.put(DOWNLOAD_RESOURCE_SOURCE_EXT_PARAM_NAME, extName);
78 return linkFactory.constructLink(this, post, parameters, true);
79 }
80
81 public void service(IRequestCycle cycle) throws IOException {
82
83
84 IApplicationSpecification specification = cycle.getInfrastructure().getApplicationSpecification();
85
86
87 String downloadResourceSourceExtName = cycle.getParameter(DOWNLOAD_RESOURCE_SOURCE_EXT_PARAM_NAME);
88
89 if (downloadResourceSourceExtName == null) {
90 if (LOG.isDebugEnabled()) {
91 LOG.debug("no '" + DOWNLOAD_RESOURCE_SOURCE_EXT_PARAM_NAME + "' parameter found. Will try to use the default downloadResourceSource '" + DEFAULT_RESOURCE_SOURCE_NAME + "'");
92 }
93 downloadResourceSourceExtName = DEFAULT_RESOURCE_SOURCE_NAME;
94 }
95
96
97 DownloadResourceSource source = (DownloadResourceSource) specification.getExtension(BAYEUX_DOWNLOADS_EXTENTIONS_PREFIX + downloadResourceSourceExtName, DownloadResourceSource.class);
98
99
100 String resourceId = cycle.getParameter(RESOURCE_ID_PARAM_NAME);
101
102 if (resourceId == null) {
103 throw new ApplicationRuntimeException("unable to process download link, no '" + RESOURCE_ID_PARAM_NAME + "' parameter found");
104 }
105
106 if (LOG.isDebugEnabled()) {
107 LOG.debug("going to process download resource with id '" + resourceId + "'");
108 }
109
110
111 DownloadResource downloadResource = source.getDownloadResource(cycle, resourceId);
112 if (downloadResource == null) {
113 throw new ApplicationRuntimeException("unable to process download link, no resource found on id: '" + resourceId + "'");
114 }
115
116 streamResource(resourceId, downloadResource);
117 }
118
119 void streamResource(String resourceId, DownloadResource resource) throws IOException {
120 if (LOG.isDebugEnabled()) {
121 LOG.debug("streaming resource '" + resourceId + "' with content-type '" + resource.getContentType() + "'");
122 }
123 response.setContentType(resource.getContentType());
124 String contentDisposition = resource.getContentDisposition();
125 if (contentDisposition != null) {
126 response.setHeader("Content-disposition", contentDisposition);
127 }
128 OutputStream out = response.getOutputStream();
129 InputStream resourceInput = null;
130 try {
131 resourceInput = resource.getInputStream();
132 byte[] buf = new byte[1024];
133 int bytesRead;
134 while ((bytesRead = resourceInput.read(buf)) != -1) {
135 out.write(buf, 0, bytesRead);
136 }
137 out.flush();
138 } finally {
139 if (resourceInput != null) {
140 resourceInput.close();
141 }
142 }
143 }
144 }