1 package com.atlassian.plugin.refimpl.webresource;
2
3 import com.atlassian.plugin.Plugin;
4 import com.atlassian.plugin.PluginAccessor;
5 import com.atlassian.plugin.event.PluginEventListener;
6 import com.atlassian.plugin.event.PluginEventManager;
7 import com.atlassian.plugin.event.events.PluginDisabledEvent;
8 import com.atlassian.plugin.event.events.PluginEnabledEvent;
9 import com.atlassian.plugin.event.events.PluginModuleDisabledEvent;
10 import com.atlassian.plugin.event.events.PluginModuleEnabledEvent;
11 import com.atlassian.plugin.refimpl.ContainerManager;
12 import com.atlassian.plugin.refimpl.ParameterUtils;
13 import com.atlassian.plugin.webresource.UrlMode;
14 import com.atlassian.plugin.webresource.WebResourceIntegration;
15 import com.atlassian.plugin.webresource.cdn.CDNStrategy;
16 import com.atlassian.sal.api.component.ComponentLocator;
17 import com.atlassian.sal.api.features.DarkFeatureManager;
18 import com.atlassian.sal.api.message.I18nResolver;
19 import com.atlassian.sal.api.message.LocaleResolver;
20 import com.atlassian.util.concurrent.ResettableLazyReference;
21 import com.google.common.collect.ImmutableMap;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24
25 import javax.servlet.ServletContext;
26 import java.io.File;
27 import java.util.HashMap;
28 import java.util.Locale;
29 import java.util.Map;
30 import java.util.Optional;
31 import java.util.Set;
32 import java.util.TreeSet;
33
34 public class SimpleWebResourceIntegration implements WebResourceIntegration {
35 private static final Logger log = LoggerFactory.getLogger(SimpleWebResourceIntegration.class);
36
37
38
39
40 public static class I18nHasher {
41 private final ResettableLazyReference<String> hashLazyReference;
42
43 public I18nHasher(PluginAccessor pluginAccessor, PluginEventManager eventManager) {
44 hashLazyReference = new ResettableLazyReference<String>() {
45 @Override
46 protected String create() throws Exception {
47
48 Set<String> versions = new TreeSet<>();
49 for (Plugin plugin : pluginAccessor.getEnabledPlugins()) {
50
51
52 versions.add(plugin.getKey() + " v. " + plugin.getPluginInformation().getVersion());
53 }
54 return "" + versions.hashCode();
55 }
56 };
57 eventManager.register(this);
58 }
59
60 public String get() {
61 return hashLazyReference.get();
62 }
63
64 @PluginEventListener
65 public void onPluginDisabled(final PluginDisabledEvent event) {
66 hashLazyReference.reset();
67 }
68
69 @PluginEventListener
70 public void onPluginEnabled(final PluginEnabledEvent event) {
71 hashLazyReference.reset();
72 }
73
74 @PluginEventListener
75 public void onPluginModuleEnabled(final PluginModuleEnabledEvent event) {
76 hashLazyReference.reset();
77 }
78
79 @PluginEventListener
80 public void onPluginModuleDisabled(final PluginModuleDisabledEvent event) {
81 hashLazyReference.reset();
82 }
83 }
84
85
86 private final String systemBuildNumber;
87 private final LocaleResolver localeResolver;
88 private final I18nResolver i18nResolver;
89 private final String refappVersion;
90 private final PluginEventManager eventManager;
91 private final ThreadLocal<Map<String, Object>> requestCache = new ThreadLocal<Map<String, Object>>() {
92 @Override
93 protected Map<String, Object> initialValue() {
94
95
96
97 return new HashMap<>();
98 }
99 };
100 private final I18nHasher i18nHasher;
101
102 public SimpleWebResourceIntegration(final ServletContext servletContext, final LocaleResolver localeResolver,
103 final I18nResolver i18nResolver, final PluginEventManager eventManager) {
104 this(servletContext, localeResolver, i18nResolver, eventManager, "(unknown)");
105 }
106
107 public SimpleWebResourceIntegration(final ServletContext servletContext, final LocaleResolver localeResolver,
108 final I18nResolver i18nResolver, final PluginEventManager eventManager, final String refappVersion) {
109
110
111 systemBuildNumber = String.valueOf(System.currentTimeMillis());
112 this.localeResolver = localeResolver;
113 this.i18nResolver = i18nResolver;
114 this.eventManager = eventManager;
115 this.refappVersion = refappVersion;
116 this.i18nHasher = new I18nHasher(ContainerManager.getInstance().getPluginAccessor(), eventManager);
117 }
118
119 @Override
120 public Locale getLocale() {
121 return localeResolver.getLocale();
122 }
123
124 @Override
125 public String getI18nText(final Locale locale, final String s) {
126 return i18nResolver.getText(locale, s);
127 }
128
129 @Override
130 public String getI18nRawText(final Locale locale, final String s) {
131 return i18nResolver.getRawText(locale, s);
132 }
133
134 @Override
135 public CDNStrategy getCDNStrategy() {
136 return null;
137 }
138
139 public String getBaseUrl() {
140 return getBaseUrl(UrlMode.AUTO);
141 }
142
143 public String getBaseUrl(UrlMode urlMode) {
144
145
146 String baseUrl = ParameterUtils.getBaseUrl(urlMode);
147 return "/".equals(baseUrl) ? "" : baseUrl;
148 }
149
150 public PluginAccessor getPluginAccessor() {
151 return ContainerManager.getInstance().getPluginAccessor();
152 }
153
154 public Map<String, Object> getRequestCache() {
155 return requestCache.get();
156 }
157
158 public String getSystemBuildNumber() {
159 return systemBuildNumber;
160 }
161
162 public String getSystemCounter() {
163 return "1";
164 }
165
166 public String getSuperBatchVersion() {
167 return "1";
168 }
169
170 public String getStaticResourceLocale() {
171 log.warn("`getStaticResourceLocale` is deprecated and not used anymore!");
172 return getLocale().toString();
173 }
174
175 @Override
176 public String getI18nStateHash() {
177 return i18nHasher.get();
178 }
179
180 public File getTemporaryDirectory() {
181 final String tempDir = System.getProperty("java.io.tmpdir");
182 return new File(tempDir);
183 }
184
185 public Map<String, String> getResourceSubstitutionVariables() {
186 String pdl = System.getProperty("pdl.dir", "");
187
188 if (pdl.length() > 0 && !pdl.endsWith("/")) {
189 pdl += "/";
190 }
191 return ImmutableMap.of("pdl.dir", pdl);
192 }
193
194 @Override
195 public boolean useAsyncAttributeForScripts() {
196 final Optional<DarkFeatureManager> darkFeatureManagerMaybe = Optional.of(ComponentLocator.getComponent(DarkFeatureManager.class));
197
198 return darkFeatureManagerMaybe
199 .map(dfManager -> dfManager.isFeatureEnabledForAllUsers("ENABLE_ASYNC_SCRIPTS"))
200 .orElse(false);
201 }
202
203 @Override
204 public PluginEventManager getPluginEventManager() {
205 return this.eventManager;
206 }
207
208 @Override
209 public Set<String> allowedCondition1Keys() {
210 return null;
211 }
212
213 @Override
214 public Set<String> allowedTransform1Keys() {
215 return null;
216 }
217
218 @Override
219 public boolean forbidCondition1AndTransformer1() {
220 return false;
221 }
222
223 @Override
224 public String getHostApplicationVersion() {
225 return refappVersion;
226 }
227
228 @Override
229 public Iterable<Locale> getSupportedLocales() {
230 return localeResolver.getSupportedLocales();
231 }
232 }