1 package com.atlassian.plugin.webresource;
2
3 import static com.atlassian.plugin.webresource.AbstractBatchResourceBuilder.skipBatch;
4
5 import com.atlassian.plugin.ModuleDescriptor;
6 import com.atlassian.plugin.PluginAccessor;
7 import com.atlassian.plugin.elements.ResourceDescriptor;
8 import com.atlassian.plugin.servlet.DownloadableResource;
9 import com.atlassian.plugin.servlet.ServletContextFactory;
10
11 import org.apache.commons.lang.StringUtils;
12 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory;
14
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.Collections;
18 import java.util.List;
19 import java.util.Map;
20 import java.util.TreeMap;
21
22
23
24
25
26
27 public class PluginResourceLocatorImpl implements PluginResourceLocator
28 {
29 private static final Logger log = LoggerFactory.getLogger(PluginResourceLocatorImpl.class);
30
31 final private PluginAccessor pluginAccessor;
32 final private WebResourceUrlProvider webResourceUrlProvider;
33 final private ResourceBatchingConfiguration batchingConfiguration;
34 final private List<DownloadableResourceBuilder> builders;
35
36 static final String RESOURCE_SOURCE_PARAM = "source";
37 static final String RESOURCE_BATCH_PARAM = "batch";
38
39 public PluginResourceLocatorImpl(final WebResourceIntegration webResourceIntegration, final ServletContextFactory servletContextFactory, final WebResourceUrlProvider webResourceUrlProvider)
40 {
41 this(webResourceIntegration, servletContextFactory, webResourceUrlProvider, new DefaultResourceBatchingConfiguration());
42 }
43
44 public PluginResourceLocatorImpl(final WebResourceIntegration webResourceIntegration, final ServletContextFactory servletContextFactory, final WebResourceUrlProvider webResourceUrlProvider,
45 final ResourceBatchingConfiguration batchingConfiguration)
46 {
47 this(webResourceIntegration, servletContextFactory, webResourceUrlProvider, new DefaultResourceDependencyResolver(webResourceIntegration, batchingConfiguration), batchingConfiguration);
48 }
49
50 private PluginResourceLocatorImpl(final WebResourceIntegration webResourceIntegration, final ServletContextFactory servletContextFactory, final WebResourceUrlProvider webResourceUrlProvider,
51 final ResourceDependencyResolver dependencyResolver, final ResourceBatchingConfiguration batchingConfiguration)
52 {
53 this.pluginAccessor = webResourceIntegration.getPluginAccessor();
54 this.webResourceUrlProvider = webResourceUrlProvider;
55 this.batchingConfiguration = batchingConfiguration;
56 final SingleDownloadableResourceBuilder singlePluginBuilder = new SingleDownloadableResourceBuilder(pluginAccessor, servletContextFactory);
57 builders = Collections.unmodifiableList(Arrays.asList(new SuperBatchDownloadableResourceBuilder(dependencyResolver, pluginAccessor,
58 webResourceUrlProvider, singlePluginBuilder), new SuperBatchSubResourceBuilder(dependencyResolver, singlePluginBuilder),
59 new ContextBatchDownloadableResourceBuilder(dependencyResolver, pluginAccessor, webResourceUrlProvider, singlePluginBuilder),
60 new ContextBatchSubResourceBuilder(dependencyResolver, singlePluginBuilder), new SingleBatchDownloadableResourceBuilder(pluginAccessor,
61 webResourceUrlProvider, singlePluginBuilder), singlePluginBuilder));
62
63 }
64
65 public boolean matches(final String url)
66 {
67 for (final DownloadableResourceBuilder builder : builders)
68 {
69 if (builder.matches(url))
70 {
71 return true;
72 }
73 }
74
75 return false;
76 }
77
78 public DownloadableResource getDownloadableResource(final String url, final Map<String, String> queryParams)
79 {
80 try
81 {
82 for (final DownloadableResourceBuilder builder : builders)
83 {
84 if (builder.matches(url))
85 {
86 return builder.parse(url, queryParams);
87 }
88 }
89 }
90 catch (final UrlParseException e)
91 {
92 log.error("Unable to parse URL: " + url, e);
93 }
94
95
96 return null;
97 }
98
99 public List<PluginResource> getPluginResources(final String moduleCompleteKey)
100 {
101 final ModuleDescriptor<?> moduleDescriptor = pluginAccessor.getEnabledPluginModule(moduleCompleteKey);
102 if ((moduleDescriptor == null) || !(moduleDescriptor instanceof WebResourceModuleDescriptor))
103 {
104 log.error("Error loading resource \"" + moduleCompleteKey + "\". Resource is not a Web Resource Module");
105 return Collections.emptyList();
106 }
107
108 final boolean singleMode = !batchingConfiguration.isPluginWebResourceBatchingEnabled();
109 final List<PluginResource> resources = new ArrayList<PluginResource>();
110
111 for (final ResourceDescriptor resourceDescriptor : moduleDescriptor.getResourceDescriptors())
112 {
113 if (singleMode || skipBatch(resourceDescriptor))
114 {
115 final boolean cache = !"false".equalsIgnoreCase(resourceDescriptor.getParameter("cache"));
116 resources.add(new SinglePluginResource(resourceDescriptor.getName(), moduleDescriptor.getCompleteKey(), cache,
117 resourceDescriptor.getParameters()));
118 }
119 else
120 {
121 final BatchPluginResource batchResource = createBatchResource(moduleDescriptor.getCompleteKey(), resourceDescriptor);
122 if (!resources.contains(batchResource))
123 {
124 resources.add(batchResource);
125 }
126 }
127 }
128 return resources;
129 }
130
131
132 String[] splitLastPathPart(final String resourcePath)
133 {
134 int indexOfSlash = resourcePath.lastIndexOf('/');
135 if (resourcePath.endsWith("/"))
136 {
137 indexOfSlash = resourcePath.lastIndexOf('/', indexOfSlash - 1);
138 }
139
140 if (indexOfSlash < 0)
141 {
142 return null;
143 }
144
145 return new String[] { resourcePath.substring(0, indexOfSlash + 1), resourcePath.substring(indexOfSlash + 1) };
146 }
147
148 private BatchPluginResource createBatchResource(final String moduleCompleteKey, final ResourceDescriptor resourceDescriptor)
149 {
150 final String name = resourceDescriptor.getName();
151 final String type = name.substring(name.lastIndexOf(".") + 1);
152 final Map<String, String> params = new TreeMap<String, String>();
153 for (final String param : BATCH_PARAMS)
154 {
155 final String value = resourceDescriptor.getParameter(param);
156 if (StringUtils.isNotEmpty(value))
157 {
158 params.put(param, value);
159 }
160 }
161
162 return new BatchPluginResource(moduleCompleteKey, type, params, Collections.<DownloadableResource> emptyList());
163 }
164
165 public String getResourceUrl(final String moduleCompleteKey, final String resourceName)
166 {
167 return webResourceUrlProvider.getResourceUrl(moduleCompleteKey, resourceName);
168 }
169 }