]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/AbstractCmsEntryPoint.java
Clean up code
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / AbstractCmsEntryPoint.java
1 package org.argeo.cms;
2
3 import java.util.Locale;
4 import java.util.ResourceBundle;
5
6 import javax.jcr.Node;
7 import javax.jcr.Repository;
8 import javax.jcr.RepositoryException;
9 import javax.jcr.Session;
10 import javax.jcr.nodetype.NodeType;
11
12 import org.apache.commons.logging.Log;
13 import org.apache.commons.logging.LogFactory;
14 import org.argeo.cms.i18n.Msg;
15 import org.argeo.jcr.JcrUtils;
16 import org.eclipse.rap.rwt.RWT;
17 import org.eclipse.rap.rwt.application.AbstractEntryPoint;
18 import org.eclipse.rap.rwt.client.service.BrowserNavigation;
19 import org.eclipse.rap.rwt.client.service.BrowserNavigationEvent;
20 import org.eclipse.rap.rwt.client.service.BrowserNavigationListener;
21 import org.eclipse.swt.widgets.Display;
22 import org.eclipse.swt.widgets.Shell;
23 import org.springframework.security.core.context.SecurityContextHolder;
24
25 /** Manages history and navigation */
26 abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements
27 CmsSession {
28 private final Log log = LogFactory.getLog(AbstractCmsEntryPoint.class);
29
30 private Repository repository;
31 private String workspace;
32 private Session session;
33
34 // current state
35 private Node node;
36 private String state;
37 private String page;
38 private Throwable exception;
39
40 private BrowserNavigation history;
41
42 public AbstractCmsEntryPoint(Repository repository, String workspace) {
43 // if (SecurityContextHolder.getContext().getAuthentication() == null) {
44 // HttpSession httpSession = RWT.getRequest().getSession();
45 // // log.debug("Session: " + httpSession.getId());
46 // SecurityContext contextFromSessionObject = (SecurityContext)
47 // httpSession
48 // .getAttribute(SPRING_SECURITY_CONTEXT_KEY);
49 // if (contextFromSessionObject != null)
50 // SecurityContextHolder.setContext(contextFromSessionObject);
51 // else
52 // logAsAnonymous();
53 // }
54
55 this.repository = repository;
56 this.workspace = workspace;
57 authChange();
58
59 history = RWT.getClient().getService(BrowserNavigation.class);
60 if (history != null)
61 history.addBrowserNavigationListener(new CmsNavigationListener());
62
63 // RWT.setLocale(Locale.FRANCE);
64 }
65
66 @Override
67 protected Shell createShell(Display display) {
68 Shell shell = super.createShell(display);
69 shell.setData(RWT.CUSTOM_VARIANT, CmsStyles.CMS_SHELL);
70 display.disposeExec(new Runnable() {
71
72 @Override
73 public void run() {
74 if (log.isTraceEnabled())
75 log.trace("Logging out " + session);
76 JcrUtils.logoutQuietly(session);
77 }
78 });
79 return shell;
80 }
81
82 /** Recreate header UI */
83 protected abstract void refreshHeader();
84
85 /** Recreate body UI */
86 protected abstract void refreshBody();
87
88 /** Log as anonymous */
89 protected abstract void logAsAnonymous();
90
91 /**
92 * The node to return when no node was found (for authenticated users and
93 * anonymous)
94 */
95 protected abstract Node getDefaultNode(Session session)
96 throws RepositoryException;
97
98 /**
99 * Reasonable default since it is a nt:hierarchyNode and is thus compatible
100 * with the obvious default folder type, nt:folder, conceptual equivalent of
101 * an empty text file in an operating system. To be overridden.
102 */
103 protected String getDefaultNewNodeType() {
104 return CmsTypes.CMS_TEXT;
105 }
106
107 /** Default new folder type (used in mkdirs) is nt:folder. To be overridden. */
108 protected String getDefaultNewFolderType() {
109 return NodeType.NT_FOLDER;
110 }
111
112 public void navigateTo(String state) {
113 exception = null;
114 setState(state);
115 refreshBody();
116 if (history != null)
117 history.pushState(state, state);
118 }
119
120 @Override
121 public void authChange() {
122 try {
123 String currentPath = null;
124 if (node != null)
125 currentPath = node.getPath();
126 JcrUtils.logoutQuietly(session);
127
128 if (SecurityContextHolder.getContext().getAuthentication() == null)
129 logAsAnonymous();
130 session = repository.login(workspace);
131 if (currentPath != null)
132 node = session.getNode(currentPath);
133
134 // refresh UI
135 refreshHeader();
136 refreshBody();
137 } catch (RepositoryException e) {
138 throw new CmsException("Cannot perform auth change", e);
139 }
140
141 }
142
143 @Override
144 public void exception(Throwable e) {
145 this.exception = e;
146 log.error("Unexpected exception in CMS", e);
147 refreshBody();
148 }
149
150 @Override
151 public Object local(Msg msg) {
152 String key = msg.getId();
153 int lastDot = key.lastIndexOf('.');
154 String className = key.substring(0, lastDot);
155 String fieldName = key.substring(lastDot + 1);
156 Locale locale = RWT.getLocale();
157 ResourceBundle rb = ResourceBundle.getBundle(className, locale,
158 msg.getClassLoader());
159 return rb.getString(fieldName);
160 }
161
162 /** Sets the state of the entry point and retrieve the related JCR node. */
163 protected synchronized void setState(String newState) {
164 String previousState = this.state;
165
166 node = null;
167 page = null;
168 this.state = newState;
169
170 try {
171 int firstSlash = state.indexOf('/');
172 if (firstSlash == 0) {
173 if (!session.nodeExists(state))
174 node = addNode(session, state, null);
175 else
176 node = session.getNode(state);
177 page = "";
178 } else if (firstSlash > 0) {
179 String prefix = state.substring(0, firstSlash);
180 String path = state.substring(firstSlash);
181 if (session.getWorkspace().getNodeTypeManager()
182 .hasNodeType(prefix)) {
183 String nodeType = prefix;
184 if (!session.nodeExists(path))
185 node = addNode(session, path, nodeType);
186 else {
187 node = session.getNode(path);
188 if (!node.isNodeType(nodeType))
189 throw new CmsException("Node " + path
190 + " not of type " + nodeType);
191 }
192 } else if ("delete".equals(prefix)) {
193 if (session.itemExists(path)) {
194 Node nodeToDelete = session.getNode(path);
195 // TODO "Are you sure?"
196 nodeToDelete.remove();
197 session.save();
198 log.debug("Deleted " + path);
199 navigateTo(previousState);
200 } else
201 throw new CmsException("Data " + path
202 + " does not exist");
203 } else {
204 if (session.itemExists(path))
205 node = session.getNode(path);
206 else
207 throw new CmsException("Data " + path
208 + " does not exist");
209 }
210 page = prefix;
211 } else {
212 node = getDefaultNode(session);
213 page = state;
214 }
215
216 if (log.isTraceEnabled())
217 log.trace("node=" + node + ", state=" + state + " (page="
218 + page);
219
220 } catch (RepositoryException e) {
221 throw new CmsException("Cannot retrieve node", e);
222 }
223 }
224
225 protected Node addNode(Session session, String path, String nodeType)
226 throws RepositoryException {
227 return JcrUtils.mkdirs(session, path, nodeType != null ? nodeType
228 : getDefaultNewNodeType(), getDefaultNewFolderType(), false);
229 // not saved, so that the UI can discard it later on
230 }
231
232 protected Node getNode() {
233 return node;
234 }
235
236 @Override
237 public String getState() {
238 return state;
239 }
240
241 // String getPage() {
242 // return page;
243 // }
244
245 protected Throwable getException() {
246 return exception;
247 }
248
249 protected void resetException() {
250 exception = null;
251 }
252
253 protected Session getSession() {
254 return session;
255 }
256
257 private class CmsNavigationListener implements BrowserNavigationListener {
258 private static final long serialVersionUID = -3591018803430389270L;
259
260 @Override
261 public void navigated(BrowserNavigationEvent event) {
262 setState(event.getState());
263 refreshBody();
264 }
265 }
266
267 }