1 package com.atlassian.plugin.servlet;
2
3 import com.atlassian.plugin.ModuleDescriptor;
4 import com.atlassian.plugin.Plugin;
5 import com.atlassian.plugin.PluginAccessor;
6 import com.atlassian.plugin.PluginManager;
7 import com.atlassian.plugin.elements.ResourceLocation;
8 import org.apache.commons.logging.Log;
9 import org.apache.commons.logging.LogFactory;
10
11 import javax.servlet.http.HttpServletRequest;
12 import javax.servlet.http.HttpServletResponse;
13 import java.io.IOException;
14
15
16
17
18
19
20
21 public class PluginResourceDownload implements DownloadStrategy
22 {
23 private static final Log log = LogFactory.getLog(PluginResourceDownload.class);
24 private static final String DOWNLOAD_RESOURCE = "download";
25 private final ResourceUrlParser urlParser = new ResourceUrlParser(BaseFileServerServlet.RESOURCE_URL_PREFIX);
26 private PluginAccessor pluginAccessor;
27
28
29 public PluginResourceDownload()
30 {
31 }
32
33 public PluginResourceDownload(PluginAccessor pluginAccessor)
34 {
35 this.pluginAccessor = pluginAccessor;
36 }
37
38 public boolean matches(String urlPath)
39 {
40 return urlParser.matches(urlPath);
41 }
42
43 public void setPluginManager(PluginManager pluginManager)
44 {
45 this.pluginAccessor = pluginManager;
46 }
47
48 public void serveFile(BaseFileServerServlet servlet, HttpServletRequest httpServletRequest,
49 HttpServletResponse httpServletResponse) throws IOException
50 {
51 String requestUri = servlet.urlDecode(httpServletRequest.getRequestURI());
52 PluginResource resource = urlParser.parse(requestUri);
53
54 if (resource != null)
55 {
56 servePluginResource(servlet, httpServletRequest, httpServletResponse, resource.getModuleCompleteKey(),
57 resource.getResourceName());
58 }
59 else
60 {
61 log.info("Invalid resource path spec: " + httpServletRequest.getRequestURI());
62 httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
63 }
64 }
65
66 protected void servePluginResource(BaseFileServerServlet servlet, HttpServletRequest httpServletRequest,
67 HttpServletResponse httpServletResponse, String moduleCompleteKey, String resourceName)
68 throws IOException
69 {
70 DownloadableResource resource = null;
71
72
73 if (moduleCompleteKey.indexOf(":") > -1)
74 {
75 ModuleDescriptor moduleDescriptor = pluginAccessor.getPluginModule(moduleCompleteKey);
76 if (moduleDescriptor != null && pluginAccessor.isPluginModuleEnabled(moduleCompleteKey))
77 {
78 resource = getResourceFromModule(moduleDescriptor, resourceName, servlet);
79 }
80 else
81 {
82 log.info("Module not found: " + moduleCompleteKey);
83 httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
84 }
85 }
86 else
87 {
88 Plugin plugin = pluginAccessor.getPlugin(moduleCompleteKey);
89 resource = getResourceFromPlugin(plugin, resourceName, "", servlet);
90 }
91
92 if (resource == null)
93 {
94 resource = getResourceFromPlugin(moduleCompleteKey, resourceName, servlet);
95 }
96
97 if (resource != null)
98 {
99 resource.serveResource(httpServletRequest, httpServletResponse);
100 }
101 else
102 {
103 log.info("Unable to find resource for plugin: " + moduleCompleteKey + " and path: " + resourceName);
104 }
105 }
106
107 private DownloadableResource getResourceFromPlugin(String moduleKey, String resourcePath,
108 BaseFileServerServlet servlet)
109 {
110 if (moduleKey.indexOf(':') < 0 || moduleKey.indexOf(':') == moduleKey.length() - 1)
111 {
112 return null;
113 }
114
115 Plugin plugin = pluginAccessor.getPlugin(moduleKey.substring(0, moduleKey.indexOf(':')));
116 if (plugin == null)
117 {
118 return null;
119 }
120
121 return getResourceFromPlugin(plugin, resourcePath, "", servlet);
122 }
123
124 private DownloadableResource getResourceFromPlugin(Plugin plugin, String resourcePath, String filePath,
125 BaseFileServerServlet servlet)
126 {
127 ResourceLocation resourceLocation = plugin.getResourceLocation(DOWNLOAD_RESOURCE, resourcePath);
128
129 if (resourceLocation != null)
130 {
131 return getDownloadablePluginResource(servlet, plugin, resourceLocation, filePath);
132 }
133 else
134 {
135 String[] nextParts = splitLastPathPart(resourcePath);
136 if (nextParts == null)
137 {
138 return null;
139 }
140 else
141 {
142 return getResourceFromPlugin(plugin, nextParts[0], nextParts[1] + filePath, servlet);
143 }
144 }
145 }
146
147 private DownloadableResource getResourceFromModule(ModuleDescriptor moduleDescriptor, String filePath,
148 BaseFileServerServlet servlet)
149 {
150 return getResourceFromModule(moduleDescriptor, filePath, "", servlet);
151 }
152
153 DownloadableResource getResourceFromModule(ModuleDescriptor moduleDescriptor, String resourcePath, String filePath,
154 BaseFileServerServlet servlet)
155 {
156 Plugin plugin = pluginAccessor.getPlugin(moduleDescriptor.getPluginKey());
157 ResourceLocation resourceLocation = moduleDescriptor.getResourceLocation(DOWNLOAD_RESOURCE, resourcePath);
158
159 if (resourceLocation != null)
160 {
161 return getDownloadablePluginResource(servlet, plugin, resourceLocation, filePath);
162 }
163 else
164 {
165 String[] nextParts = splitLastPathPart(resourcePath);
166 if (nextParts == null)
167 {
168 return null;
169 }
170 else
171 {
172 return getResourceFromModule(moduleDescriptor, nextParts[0], nextParts[1] + filePath, servlet);
173 }
174 }
175 }
176
177 private DownloadableResource getDownloadablePluginResource(BaseFileServerServlet servlet, Plugin plugin,
178 ResourceLocation resourceLocation, String filePath)
179 {
180 if ("webContext".equalsIgnoreCase(resourceLocation.getParameter(
181 "source")))
182 return new DownloadableWebResource(servlet, plugin, resourceLocation, filePath);
183 else
184 return new DownloadableClasspathResource(servlet, plugin, resourceLocation, filePath);
185 }
186
187 String[] splitLastPathPart(String resourcePath)
188 {
189 int indexOfSlash = resourcePath.lastIndexOf('/');
190 if (resourcePath.endsWith("/"))
191 {
192 indexOfSlash = resourcePath.lastIndexOf('/', indexOfSlash - 1);
193 }
194
195 if (indexOfSlash < 0) return null;
196
197 return new String[]{
198 resourcePath.substring(0, indexOfSlash + 1),
199 resourcePath.substring(indexOfSlash + 1)
200 };
201 }
202 }
203