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