NotificationsSettingsOperation.java
14.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/*
* Decompiled with CFR 0_118.
*
* Could not load the following classes:
* com.adobe.granite.ui.components.HtmlResponse
* com.adobe.granite.xss.XSSAPI
* com.day.cq.i18n.I18n
* javax.servlet.http.HttpServletRequest
* org.apache.commons.lang.StringUtils
* org.apache.felix.scr.annotations.Component
* org.apache.felix.scr.annotations.Properties
* org.apache.felix.scr.annotations.Property
* org.apache.felix.scr.annotations.Service
* org.apache.sling.api.SlingHttpServletRequest
* org.apache.sling.api.request.RequestParameter
* org.apache.sling.api.resource.ModifiableValueMap
* org.apache.sling.api.resource.PersistenceException
* org.apache.sling.api.resource.Resource
* org.apache.sling.api.resource.ResourceResolver
* org.apache.sling.api.resource.ResourceUtil
* org.apache.sling.api.resource.ValueMap
* org.apache.sling.servlets.post.Modification
*/
package com.adobe.cq.mobile.notifications.impl.operations;
import com.adobe.cq.mobile.platform.MobileResource;
import com.adobe.cq.mobile.platform.MobileResourceLocator;
import com.adobe.cq.mobile.platform.MobileResourceType;
import com.adobe.cq.mobile.platform.impl.operations.MobileAbstractOperation;
import com.adobe.granite.ui.components.HtmlResponse;
import com.adobe.granite.xss.XSSAPI;
import com.day.cq.i18n.I18n;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.request.RequestParameter;
import org.apache.sling.api.resource.ModifiableValueMap;
import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.servlets.post.Modification;
@Component(metatype=0, label="Associate a Remote Push Cloud Service with the Mobile Application.")
@Service
@Properties(value={@Property(name="sling.post.operation", value={"mobileapps:notificationSettings"})})
public class NotificationsSettingsOperation
extends MobileAbstractOperation {
public static final String OPERATION_NAME = "notificationSettings";
public static final String PARAM_APP_INSTANCE = "appInstance";
public static final String PARAM_NOTIFICATION_CONFIG = "notificationConfig";
public static final String PARAM_NOTIFICATION_CLOUD = "rpsCloudServicePath";
public static final String CQ_APPS_NOTIFICATION_CONFIG = "cq-apps-notification-config";
public static final String APP_ROOT = "/content/mobileapps";
public static final String PLUGIN_RESOURCE = "plugin";
public static final String PLUGIN_NAME = "name";
public static final String PLUGIN_SPEC = "spec";
public static final String PLUGIN_VERSION = "version";
public static final String PLUGIN_IS_PUSH = "isPush";
public static final String PLUGIN_TAG_ROOT = "/widget/plugins/";
public static final String PLUGIN_PGB_TAG_ROOT = "/widget/gap_plugins/";
@Override
protected void perform(SlingHttpServletRequest request, HtmlResponse response, List<Modification> changes) {
MobileResourceLocator locator;
I18n i18n = new I18n((HttpServletRequest)request);
RequestParameter appInstanceParam = request.getRequestParameter("appInstance");
if (appInstanceParam == null) {
String message = i18n.get("Missing mandatory parameter {0}", null, new Object[]{"appInstance"});
String title = i18n.get("Error");
this.generateError(response, message, title);
return;
}
Resource appInstance = request.getResourceResolver().getResource(appInstanceParam.toString());
if (appInstance == null) {
String message = i18n.get("Unable to resolve mobile application {0}", null, new Object[]{appInstanceParam.toString()});
String title = i18n.get("Error");
this.generateError(response, message, title);
return;
}
MobileResource mobileResource = (MobileResource)appInstance.adaptTo(MobileResource.class);
if (!mobileResource.isA(MobileResourceType.INSTANCE.getType())) {
String message = i18n.get("The resource {0} must be a mobile application", null, new Object[]{mobileResource.getPath()});
String title = i18n.get("Error");
this.generateError(response, message, title);
return;
}
String configPath = request.getParameter("notificationConfig");
if (StringUtils.isEmpty((String)configPath)) {
String message = i18n.get("Missing mandatory parameter {0}", null, new Object[]{"notificationConfig"});
String title = i18n.get("Error");
this.generateError(response, message, title);
return;
}
ResourceResolver resolver = appInstance.getResourceResolver();
if (this.checkForDuplicateConfig(response, i18n, appInstance, configPath, resolver, locator = (MobileResourceLocator)resolver.adaptTo(MobileResourceLocator.class))) {
return;
}
String cloudServicePath = request.getParameter("rpsCloudServicePath");
if (StringUtils.isEmpty((String)cloudServicePath)) {
String message = i18n.get("Missing mandatory parameter {0}", null, new Object[]{"rpsCloudServicePath"});
String title = i18n.get("Error");
this.generateError(response, message, title);
return;
}
this.updateMobileServicesConfig(appInstance, cloudServicePath, configPath, response);
this.updatePushPluginInfo(appInstance, configPath, resolver, response, i18n);
response.setPath(appInstance.getPath());
response.setLocation(appInstance.getPath());
response.addLink("cq-apps-notification-config", this.xssAPI.getValidHref(configPath), i18n.get("Open Configuration"));
}
private boolean checkForDuplicateConfig(HtmlResponse response, I18n i18n, Resource appInstance, String configPath, ResourceResolver resolver, MobileResourceLocator locator) {
Resource appRootResource = resolver.resolve("/content/mobileapps");
Iterable<MobileResource> shells = locator.findResourcesByType(appRootResource, MobileResourceType.INSTANCE.getType());
for (MobileResource shell : shells) {
ValueMap instanceVM;
String notificationConfig;
if (shell.getPath().equals(appInstance.getPath()) || (instanceVM = shell.getProperties()) == null || !instanceVM.containsKey((Object)"notificationConfig") || !(notificationConfig = (String)instanceVM.get("notificationConfig", String.class)).equals(configPath)) continue;
String message = i18n.get("Notification configuration '{0}' already used by '{1}'", "Cloud config path and Title of app instance", new Object[]{notificationConfig, shell.getTitle()});
String title = i18n.get("Error");
this.generateError(response, message, title);
this.addLink(response, "cq-apps-response-already-used-push-config", notificationConfig, i18n.get("Rejected Push Cloud Config"));
return true;
}
return false;
}
private void updateMobileServicesConfig(Resource appInstance, String cloudServicePath, String configPath, HtmlResponse response) {
Resource appContent = appInstance.getChild("jcr:content");
ResourceResolver resolver = appInstance.getResourceResolver();
String appContentPath = appContent.getPath();
ModifiableValueMap properties = (ModifiableValueMap)appContent.adaptTo(ModifiableValueMap.class);
boolean modified = properties.containsKey((Object)"notificationConfig");
properties.put((Object)"notificationConfig", (Object)configPath);
modified = modified || properties.containsKey((Object)"rpsCloudServicePath");
properties.put((Object)"rpsCloudServicePath", (Object)cloudServicePath);
boolean hasCloudConfig = properties.containsKey((Object)"mobileServiceConfig") || properties.containsKey((Object)"phonegapConfig");
String[] configs = (String[])properties.get("cq:cloudserviceconfigs", String[].class);
ArrayList<String> newConfigs = new ArrayList<String>();
if (configs != null) {
for (int i = 0; i < configs.length; ++i) {
ValueMap vm;
Resource configResource = resolver.resolve(configs[i]);
if (configResource == null || ResourceUtil.isNonExistingResource((Resource)configResource) || (vm = configResource.getParent().getChild("jcr:content").getValueMap()).get((Object)"pushServiceId") != null) continue;
newConfigs.add(configs[i]);
}
}
newConfigs.add(configPath);
String[] props = new String[newConfigs.size()];
props = newConfigs.toArray(props);
properties.put((Object)"cq:cloudserviceconfigs", (Object)props);
String property = appContentPath + "/" + "notificationConfig";
String clouds = appContentPath + "/" + "cq:cloudserviceconfigs";
if (modified) {
response.onModified(property);
} else {
response.onCreated(property);
}
if (hasCloudConfig) {
response.onModified(clouds);
} else {
response.onCreated(clouds);
}
}
private void updatePushPluginInfo(Resource appInstance, String configPath, ResourceResolver resolver, HtmlResponse response, I18n i18n) {
Resource configResource = resolver.resolve(configPath);
if (configResource == null || ResourceUtil.isNonExistingResource((Resource)configResource)) {
String message = i18n.get("Unable to read {0}", "Internal error indicating the path passed in does not exist.", new Object[]{configPath});
String title = i18n.get("Error");
this.generateError(response, message, title);
return;
}
Resource pluginResource = configResource.getParent().getChild("plugin");
if (pluginResource == null || ResourceUtil.isNonExistingResource((Resource)pluginResource)) {
String parentPath = configResource.getParent().getPath();
String message = i18n.get("Unable to read plugin information from child of {0}", "Internal error indicating the plugin info is not where is should be.", new Object[]{parentPath});
String title = i18n.get("Error");
this.generateError(response, message, title);
return;
}
ValueMap pluginInfo = pluginResource.getValueMap();
String pluginName = (String)pluginInfo.get("name", String.class);
String pluginSpec = (String)pluginInfo.get("spec", String.class);
String pluginVersion = (String)pluginInfo.get("version", String.class);
if (StringUtils.isEmpty((String)pluginName) || StringUtils.isEmpty((String)pluginSpec) || StringUtils.isEmpty((String)pluginVersion)) {
String message = i18n.get("Cloud config must contain a plugin folder with attributes for {0}, {1}, and {2}", "Push plugins must contain these three data fields, and one or more of them are missing.", new Object[]{"name", "spec", "version"});
String title = i18n.get("Error");
this.generateError(response, message, title);
return;
}
Resource appContent = appInstance.getChild("jcr:content");
if (appContent == null) {
String message = i18n.get("Unable to find the app's content resource under {0}", "Internal error - an app instance should always have a jcr:content node.", new Object[]{appInstance.getPath()});
String title = i18n.get("Error");
this.generateError(response, message, title);
return;
}
String pluginPath = appContent.getPath() + "/widget/plugins/" + pluginName;
String pgbPath = appContent.getPath() + "/widget/gap_plugins/" + pluginName;
try {
this.removePushPlugins(resolver, appContent.getPath() + "/widget/plugins/");
ResourceUtil.getOrCreateResource((ResourceResolver)resolver, (String)pluginPath, (String)"nt:unstructured", (String)"nt:unstructured", (boolean)true);
ModifiableValueMap pluginAttributes = (ModifiableValueMap)resolver.getResource(pluginPath).adaptTo(ModifiableValueMap.class);
pluginAttributes.put((Object)"spec", (Object)pluginSpec);
pluginAttributes.put((Object)"isPush", (Object)true);
this.removePushPlugins(resolver, appContent.getPath() + "/widget/gap_plugins/");
ResourceUtil.getOrCreateResource((ResourceResolver)resolver, (String)pgbPath, (String)"nt:unstructured", (String)"nt:unstructured", (boolean)true);
ModifiableValueMap pgbPluginAttributes = (ModifiableValueMap)resolver.getResource(pgbPath).adaptTo(ModifiableValueMap.class);
pgbPluginAttributes.put((Object)"version", (Object)pluginVersion);
pgbPluginAttributes.put((Object)"isPush", (Object)true);
}
catch (PersistenceException e) {
String message = i18n.get("Unable to save plugin information to app config at {0}", "The information could not be saved. Permissions issues might cause this.", new Object[]{appContent.getPath()});
String title = i18n.get("Error");
this.generateError(response, message, title);
return;
}
}
private void removePushPlugins(ResourceResolver resolver, String pluginParentFolder) throws PersistenceException {
Resource pushFolder = ResourceUtil.getOrCreateResource((ResourceResolver)resolver, (String)pluginParentFolder, (String)"nt:unstructured", (String)"nt:unstructured", (boolean)true);
Iterable existingPlugins = pushFolder.getChildren();
for (Resource plugin : existingPlugins) {
Boolean isPlugin = (Boolean)plugin.getValueMap().get("isPush", Boolean.class);
if (isPlugin == null || !isPlugin.booleanValue()) continue;
resolver.delete(plugin);
}
}
}