1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.client.console.panels;
20
21 import com.fasterxml.jackson.databind.JsonNode;
22 import com.fasterxml.jackson.databind.json.JsonMapper;
23 import java.io.IOException;
24 import java.util.List;
25 import org.apache.commons.lang3.StringUtils;
26 import org.apache.syncope.client.console.SyncopeConsoleSession;
27 import org.apache.syncope.client.console.SyncopeWebApplication;
28 import org.apache.syncope.client.console.commons.ImplementationInfoProvider.ViewMode;
29 import org.apache.syncope.client.console.pages.BasePage;
30 import org.apache.syncope.client.console.rest.ImplementationRestClient;
31 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
32 import org.apache.syncope.client.ui.commons.Constants;
33 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
34 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
35 import org.apache.syncope.common.lib.to.ImplementationTO;
36 import org.apache.syncope.common.lib.types.ImplementationEngine;
37 import org.apache.wicket.PageReference;
38 import org.apache.wicket.ajax.AjaxEventBehavior;
39 import org.apache.wicket.ajax.AjaxRequestTarget;
40 import org.apache.wicket.markup.head.IHeaderResponse;
41 import org.apache.wicket.markup.head.OnLoadHeaderItem;
42 import org.apache.wicket.markup.html.WebMarkupContainer;
43 import org.apache.wicket.markup.html.form.TextArea;
44 import org.apache.wicket.model.Model;
45 import org.apache.wicket.model.PropertyModel;
46 import org.apache.wicket.spring.injection.annot.SpringBean;
47 import org.apache.wicket.util.io.IOUtils;
48
49 public class ImplementationModalPanel extends AbstractModalPanel<ImplementationTO> {
50
51 private static final long serialVersionUID = 5283548960927517342L;
52
53 protected static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
54
55 @SpringBean
56 protected ImplementationRestClient implementationRestClient;
57
58 protected final ImplementationTO implementation;
59
60 protected final ViewMode viewMode;
61
62 protected boolean create = false;
63
64 public ImplementationModalPanel(
65 final BaseModal<ImplementationTO> modal,
66 final ImplementationTO implementation,
67 final PageReference pageRef) {
68
69 super(modal, pageRef);
70 this.implementation = implementation;
71 this.viewMode = SyncopeWebApplication.get().getImplementationInfoProvider().getViewMode(implementation);
72 this.create = implementation.getKey() == null;
73
74 add(new AjaxTextFieldPanel(
75 Constants.KEY_FIELD_NAME,
76 Constants.KEY_FIELD_NAME,
77 new PropertyModel<>(implementation, Constants.KEY_FIELD_NAME), false).
78 addRequiredLabel().setEnabled(create));
79
80 List<String> classes = SyncopeWebApplication.get().getImplementationInfoProvider().
81 getClasses(implementation, viewMode);
82
83 AjaxDropDownChoicePanel<String> javaClass = new AjaxDropDownChoicePanel<>(
84 "javaClass", "Class", new PropertyModel<>(implementation, "body"));
85 javaClass.setNullValid(false);
86 javaClass.setChoices(classes);
87 javaClass.addRequiredLabel();
88 javaClass.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true);
89 javaClass.setVisible(viewMode == ViewMode.JAVA_CLASS);
90 add(javaClass);
91
92 AjaxDropDownChoicePanel<String> jsonClass = new AjaxDropDownChoicePanel<>(
93 "jsonClass", "Class", new Model<>());
94 jsonClass.setNullValid(false);
95 jsonClass.setChoices(classes);
96 jsonClass.addRequiredLabel();
97 jsonClass.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true);
98 jsonClass.setVisible(viewMode == ViewMode.JSON_BODY);
99 if (viewMode == ViewMode.JSON_BODY && StringUtils.isNotBlank(implementation.getBody())) {
100 try {
101 JsonNode node = MAPPER.readTree(implementation.getBody());
102 if (node.has("_class")) {
103 jsonClass.setModelObject(node.get("_class").asText());
104 }
105 } catch (IOException e) {
106 LOG.error("Could not parse as JSON payload: {}", implementation.getBody(), e);
107 }
108 }
109 jsonClass.setReadOnly(jsonClass.getModelObject() != null);
110 add(jsonClass);
111
112 WebMarkupContainer groovyClassContainer = new WebMarkupContainer("groovyClassContainer");
113 groovyClassContainer.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true);
114 groovyClassContainer.setVisible(viewMode != ViewMode.JAVA_CLASS);
115 add(groovyClassContainer);
116
117 if (StringUtils.isBlank(implementation.getBody())
118 && implementation.getEngine() == ImplementationEngine.GROOVY) {
119
120 String templateClassName = SyncopeWebApplication.get().getImplementationInfoProvider().
121 getGroovyTemplateClassName(implementation.getType());
122 if (templateClassName != null) {
123 try {
124 implementation.setBody(StringUtils.substringAfter(
125 IOUtils.toString(ImplementationModalPanel.class.getResourceAsStream(
126 "/org/apache/syncope/client/console/implementations/" + templateClassName
127 + ".groovy")),
128 "*/\n"));
129 } catch (IOException e) {
130 LOG.error("Could not load the expected Groovy template {} for {}",
131 templateClassName, implementation.getType(), e);
132 }
133 }
134 }
135
136 TextArea<String> groovyClass = new TextArea<>("groovyClass", new PropertyModel<>(implementation, "body"));
137 groovyClass.setMarkupId("groovyClass").setOutputMarkupPlaceholderTag(true);
138 groovyClass.setVisible(viewMode != ViewMode.JAVA_CLASS);
139 groovyClass.setRequired(true);
140 groovyClassContainer.add(groovyClass);
141
142 jsonClass.add(new AjaxEventBehavior(Constants.ON_CHANGE) {
143
144 private static final long serialVersionUID = 5538299138211283825L;
145
146 @Override
147 protected void onEvent(final AjaxRequestTarget target) {
148 Class<?> clazz = SyncopeWebApplication.get().getImplementationInfoProvider().
149 getClass(implementation.getType(), jsonClass.getModelObject());
150 if (clazz != null) {
151 try {
152 target.appendJavaScript("editor.getDoc().setValue('"
153 + MAPPER.writeValueAsString(clazz.getDeclaredConstructor().newInstance())
154 + "');");
155 } catch (Exception e) {
156 LOG.error("Could not generate a value for {}", jsonClass.getModelObject(), e);
157 }
158 }
159 }
160 });
161 }
162
163 @Override
164 public ImplementationTO getItem() {
165 return implementation;
166 }
167
168 @Override
169 public void renderHead(final IHeaderResponse response) {
170 super.renderHead(response);
171 if (viewMode != ViewMode.JAVA_CLASS) {
172 response.render(OnLoadHeaderItem.forScript(
173 "editor = CodeMirror.fromTextArea("
174 + "document.getElementById('groovyClassForm').children['groovyClass'], {"
175 + " readOnly: false, "
176 + " lineNumbers: true, "
177 + " lineWrapping: true, "
178 + " matchBrackets: true,"
179 + " autoCloseBrackets: true,"
180 + (viewMode == ViewMode.GROOVY_BODY ? " mode: 'text/x-groovy'," : "")
181 + " autoRefresh: true"
182 + "});"
183 + "editor.on('change', updateTextArea);"));
184 }
185 }
186
187 @Override
188 public void onSubmit(final AjaxRequestTarget target) {
189 try {
190 if (create) {
191 implementationRestClient.create(implementation);
192 } else {
193 implementationRestClient.update(implementation);
194 }
195
196 modal.close(target);
197 SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
198 } catch (Exception e) {
199 LOG.error("While creating or updating Implementation", e);
200 SyncopeConsoleSession.get().onException(e);
201 }
202 ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
203 }
204 }