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