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.blossom.dialog;
35
36 import java.util.Map;
37 import java.util.concurrent.ConcurrentHashMap;
38 import javax.inject.Inject;
39 import javax.jcr.Node;
40 import javax.jcr.RepositoryException;
41 import javax.jcr.Session;
42
43 import org.apache.commons.lang.StringUtils;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 import info.magnolia.cms.core.MgnlNodeType;
48 import info.magnolia.cms.util.ContentUtil;
49 import info.magnolia.cms.util.SystemContentWrapper;
50 import info.magnolia.context.SystemContext;
51 import info.magnolia.module.admininterface.ConfiguredDialogHandlerProvider;
52 import info.magnolia.module.admininterface.DialogHandlerManager;
53 import info.magnolia.module.admininterface.DialogMVCHandler;
54 import info.magnolia.objectfactory.Classes;
55 import info.magnolia.objectfactory.Components;
56 import info.magnolia.repository.RepositoryConstants;
57
58
59
60
61
62
63 public class DefaultBlossomDialogRegistry implements BlossomDialogRegistry {
64
65 private static final String DIALOGS_PATH = "/modules/blossom/managed-dialogs";
66 private static final String DIALOGS__BY_NAME = DIALOGS_PATH + "/name";
67 private static final String DIALOGS__BY_ID = DIALOGS_PATH + "/id";
68 private static final String DIALOGS__BY_PATH = DIALOGS_PATH + "/path";
69
70 private final Logger logger = LoggerFactory.getLogger(getClass());
71
72 private final Map<String, BlossomDialogDescription> dialogs = new ConcurrentHashMap<String, BlossomDialogDescription>();
73 private final SystemContext systemContext;
74
75 @Inject
76 public DefaultBlossomDialogRegistry(SystemContext systemContext) throws RepositoryException {
77
78 this.systemContext = systemContext;
79
80 Session session = this.systemContext.getJCRSession(RepositoryConstants.CONFIG);
81 deleteNode(session, DIALOGS__BY_NAME);
82 deleteNode(session, DIALOGS__BY_ID);
83 deleteNode(session, DIALOGS__BY_PATH);
84 session.save();
85 }
86
87 @Override
88 public BlossomDialogDescription getDialogDescription(String id) {
89 return this.dialogs.get(id);
90 }
91
92 @Override
93 public void addDialogDescription(BlossomDialogDescription dialogDescription) throws RepositoryException {
94
95 Class<? extends DialogMVCHandler> dialogClass;
96 try {
97 dialogClass = Classes.getClassFactory().forName(dialogDescription.getDialogClass());
98 } catch (ClassNotFoundException e) {
99 logger.error("Can't find dialog handler class " + dialogDescription.getDialogClass(), e);
100 return;
101 }
102
103 Node configNode = writeDialogDefinition(dialogDescription);
104
105 ConfiguredDialogHandlerProvider provider = new ConfiguredDialogHandlerProvider(dialogDescription.getId(), new SystemContentWrapper(ContentUtil.asContent(configNode)), dialogClass);
106 Components.getComponent(DialogHandlerManager.class).register(provider);
107
108 dialogs.put(dialogDescription.getId(), dialogDescription);
109 }
110
111 protected Node writeDialogDefinition(BlossomDialogDescription dialogDescription) throws RepositoryException {
112
113 String configPath;
114 if (dialogDescription.getId().indexOf(':') != -1) {
115
116 String moduleName = StringUtils.substringBefore(dialogDescription.getId(), ":");
117 String path = StringUtils.substringAfter(dialogDescription.getId(), ":");
118
119 configPath = makeAbsolutePath(DIALOGS__BY_ID, moduleName, path);
120 } else if (dialogDescription.getId().contains("/")) {
121 configPath = makeAbsolutePath(DIALOGS__BY_PATH, dialogDescription.getId());
122 } else {
123 configPath = makeAbsolutePath(DIALOGS__BY_NAME, dialogDescription.getId());
124 }
125
126 Session session = systemContext.getJCRSession(RepositoryConstants.CONFIG);
127 Node configNode = createContentNode(session, configPath);
128 configNode.setProperty("class", dialogDescription.getDialogClass());
129 session.save();
130 return configNode;
131 }
132
133 private Node createContentNode(Session session, String absolutePath) throws RepositoryException {
134 String[] segments = StringUtils.split(absolutePath, "/");
135
136 Node node = session.getRootNode();
137 for (int i = 0; i < segments.length - 1; i++) {
138 node = getOrCreateNode(node, segments[i], MgnlNodeType.NT_CONTENT);
139 }
140
141 return getOrCreateNode(node, segments[segments.length - 1], MgnlNodeType.NT_CONTENTNODE);
142 }
143
144 private Node getOrCreateNode(Node parent, String relPath, String primaryNodeTypeName) throws RepositoryException {
145 if (parent.hasNode(relPath)) {
146 return parent.getNode(relPath);
147 } else {
148 return parent.addNode(relPath, primaryNodeTypeName);
149 }
150 }
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165 private String makeAbsolutePath(String... args) {
166 StringBuilder sb = new StringBuilder();
167 for (String arg : args) {
168 boolean slashPending = true;
169 for (int i = 0; i < arg.length(); i++) {
170 char ch = arg.charAt(i);
171 if (ch == '/') {
172 slashPending = true;
173 } else {
174 if (slashPending) {
175 sb.append('/');
176 slashPending = false;
177 }
178 sb.append(ch);
179 }
180 }
181 }
182 return sb.length() == 0 ? "/" : sb.toString();
183 }
184
185 private void deleteNode(Session session, String absPath) throws RepositoryException {
186 if (session.nodeExists(absPath)) {
187 session.removeItem(absPath);
188 }
189 }
190 }