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 package info.magnolia.module.groovy.app.action;
35
36 import info.magnolia.cms.core.Path;
37 import info.magnolia.jcr.util.NodeUtil;
38 import info.magnolia.module.groovy.support.HierarchyManagerProvider.UserContextHierarchyManagerProvider;
39 import info.magnolia.module.groovy.support.classes.MgnlGroovyClassLoader;
40 import info.magnolia.ui.api.action.ActionExecutionException;
41 import info.magnolia.ui.form.EditorCallback;
42 import info.magnolia.ui.form.EditorValidator;
43 import info.magnolia.ui.form.action.SaveFormAction;
44 import info.magnolia.ui.form.action.SaveFormActionDefinition;
45 import info.magnolia.ui.vaadin.integration.jcr.JcrNodeAdapter;
46
47 import java.util.List;
48
49 import javax.jcr.Node;
50 import javax.jcr.RepositoryException;
51
52 import org.codehaus.groovy.ast.ASTNode;
53 import org.codehaus.groovy.ast.ClassNode;
54 import org.codehaus.groovy.ast.builder.AstBuilder;
55 import org.codehaus.groovy.control.CompilationFailedException;
56 import org.codehaus.groovy.control.CompilePhase;
57
58 import com.vaadin.data.Item;
59
60
61
62
63 public class SaveScriptAction extends SaveFormAction {
64 private final static MgnlGroovyClassLoader CL_TO_VERIFY_SOURCE = new MgnlGroovyClassLoader(new UserContextHierarchyManagerProvider());
65
66 public SaveScriptAction(SaveFormActionDefinition definition, Item item, EditorCallback callback, EditorValidator validator) {
67 super(definition, (JcrNodeAdapter) item, callback, validator);
68 }
69
70 @Override
71 public void execute() throws ActionExecutionException {
72 validator.showValidation(true);
73 if (validator.isValid()) {
74 try {
75 verifySource(item, CL_TO_VERIFY_SOURCE);
76 final Node node = item.applyChanges();
77 if (node.isNew()) {
78 setNodeName(node, item);
79 }
80 node.getSession().save();
81 } catch (RepositoryException e) {
82 throw new ActionExecutionException(e);
83 } catch (CompilationFailedException e) {
84 throw new ActionExecutionException(e.getCause() != null ? e.getCause().getMessage() : e.getMessage());
85 }
86 }
87 callback.onSuccess(getDefinition().getName());
88
89 }
90
91 @Override
92 protected void setNodeName(Node node, JcrNodeAdapter item) throws RepositoryException {
93 final String source = (String) item.getItemProperty("text").getValue();
94 String newNodeName = resolveNewGroovyFullyQualifiedClassName(source, item);
95 if (!node.getName().equals(newNodeName)) {
96 newNodeName = Path.getUniqueLabel(node.getSession(), node.getParent().getPath(), Path.getValidatedLabel(newNodeName));
97 item.setNodeName(newNodeName);
98 NodeUtil.renameNode(node, newNodeName);
99 }
100 }
101
102
103
104
105 protected void verifySource(Node node, JcrNodeAdapter item, MgnlGroovyClassLoader groovyClassLoader) throws RepositoryException, CompilationFailedException {
106 verifySource(item, groovyClassLoader);
107 }
108
109 protected void verifySource(JcrNodeAdapter item, MgnlGroovyClassLoader groovyClassLoader) throws RepositoryException, CompilationFailedException {
110 final com.vaadin.data.Property<Boolean> scriptProperty = item.getItemProperty("script");
111 final boolean isScript = scriptProperty != null && scriptProperty.getValue() != null ? scriptProperty.getValue() : false;
112 final String source = (String) item.getItemProperty("text").getValue();
113
114 if (isScript) {
115 groovyClassLoader.verify(source, false, null);
116 } else {
117 String path = item.getJcrItem().getPath();
118 if (item.isNew()) {
119 String nodeName = resolveNewGroovyFullyQualifiedClassName(source, item);
120 path = path.endsWith("/") ? path + nodeName : path + "/" + nodeName;
121 item.setNodeName(nodeName);
122 }
123 groovyClassLoader.verify(source, true, path);
124 }
125 }
126
127 private String resolveNewGroovyFullyQualifiedClassName(String source, JcrNodeAdapter item) throws RepositoryException {
128 final List<ASTNode> nodes = new AstBuilder().buildFromString(CompilePhase.CONVERSION, source);
129 for (ASTNode astNode : nodes) {
130 if (astNode instanceof ClassNode) {
131 ClassNode cn = (ClassNode) astNode;
132 String name = cn.getNameWithoutPackage();
133 if (!name.startsWith("script")) {
134 return name;
135 }
136 }
137 }
138 return "untitledGroovyScript";
139 }
140
141 }