001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018: package org.apache.lenya.inbox.xml;
019:
020: import java.util.ArrayList;
021: import java.util.List;
022:
023: import javax.xml.parsers.ParserConfigurationException;
024:
025: import org.apache.avalon.framework.service.ServiceManager;
026: import org.apache.axis.components.uuid.UUIDGen;
027: import org.apache.axis.components.uuid.UUIDGenFactory;
028: import org.apache.lenya.ac.AccessControlException;
029: import org.apache.lenya.ac.Group;
030: import org.apache.lenya.ac.Identifiable;
031: import org.apache.lenya.ac.User;
032: import org.apache.lenya.cms.cocoon.source.SourceUtil;
033: import org.apache.lenya.inbox.Inbox;
034: import org.apache.lenya.inbox.InboxMessage;
035: import org.apache.lenya.notification.Message;
036: import org.apache.lenya.notification.Notifier;
037: import org.apache.lenya.util.Assert;
038: import org.apache.lenya.xml.DocumentHelper;
039: import org.apache.lenya.xml.NamespaceHelper;
040: import org.w3c.dom.Document;
041: import org.w3c.dom.Element;
042:
043: /**
044: * Inbox based on XML sources.
045: */
046: public class XmlSourceInbox implements Inbox {
047:
048: private ServiceManager manager;
049: private User user;
050:
051: /**
052: * @param manager The service manager.
053: * @param user The user.
054: */
055: public XmlSourceInbox(ServiceManager manager, User user) {
056: this .manager = manager;
057: this .user = user;
058: }
059:
060: public synchronized InboxMessage add(Message message) {
061: InboxMessage msg = new XmlSourceInboxMessage(this ,
062: generateId(), message, false);
063: messages().add(msg);
064: save();
065: return msg;
066: }
067:
068: protected String generateId() {
069: UUIDGen generator = UUIDGenFactory.getUUIDGen();
070: String id = generator.nextUUID();
071: return id;
072: }
073:
074: public synchronized void remove(InboxMessage message) {
075: Assert.isTrue("contained", messages().contains(message));
076: messages().remove(message);
077: save();
078: }
079:
080: public InboxMessage[] getMessages() {
081: List messages = messages();
082: return (InboxMessage[]) messages
083: .toArray(new InboxMessage[messages.size()]);
084: }
085:
086: private List messages;
087:
088: protected List messages() {
089: if (this .messages == null) {
090: load();
091: }
092: return this .messages;
093: }
094:
095: private long lastModified = -1;
096:
097: protected synchronized void load() {
098: this .messages = new ArrayList();
099: try {
100:
101: if (SourceUtil.exists(getSourceUri(), this .manager)) {
102:
103: this .lastModified = SourceUtil.getLastModified(
104: getSourceUri(), this .manager);
105: Document xml = SourceUtil.readDOM(getSourceUri(),
106: this .manager);
107:
108: Assert.isTrue("document element is <inbox>", xml
109: .getDocumentElement().getLocalName().equals(
110: "inbox"));
111: NamespaceHelper helper = new NamespaceHelper(
112: Notifier.NAMESPACE, "", xml);
113:
114: Element[] messageElements = helper.getChildren(xml
115: .getDocumentElement(), "message");
116: for (int i = 0; i < messageElements.length; i++) {
117:
118: String id;
119: if (messageElements[i].hasAttribute("id")) {
120: id = messageElements[i].getAttribute("id");
121: } else {
122: id = generateId();
123: }
124:
125: String senderId = messageElements[i]
126: .getAttribute("sender");
127: User sender = getUser(senderId);
128:
129: Element recipientElement = helper.getFirstChild(
130: messageElements[i], "recipients");
131:
132: Element[] userElements = helper.getChildren(
133: recipientElement, "user");
134: Element[] groupElements = helper.getChildren(
135: recipientElement, "group");
136:
137: Identifiable[] recipients = new Identifiable[userElements.length
138: + groupElements.length];
139:
140: for (int u = 0; u < userElements.length; u++) {
141: String userId = userElements[u]
142: .getAttribute("id");
143: recipients[u] = getUser(userId);
144: }
145:
146: for (int g = 0; g < groupElements.length; g++) {
147: String groupId = groupElements[g]
148: .getAttribute("id");
149: recipients[userElements.length + g] = getGroup(groupId);
150: }
151:
152: Element bodyElement = helper.getFirstChild(
153: messageElements[i], "body");
154: Element bodyTextElement = helper.getFirstChild(
155: bodyElement, "text");
156: String body = DocumentHelper
157: .getSimpleElementText(bodyTextElement);
158: Element[] bodyParamElements = helper.getChildren(
159: bodyElement, "param");
160: String[] bodyParams = new String[bodyParamElements.length];
161: for (int p = 0; p < bodyParamElements.length; p++) {
162: bodyParams[p] = DocumentHelper
163: .getSimpleElementText(bodyParamElements[p]);
164: }
165:
166: Element subjectElement = helper.getFirstChild(
167: messageElements[i], "subject");
168: Element subjectTextElement = helper.getFirstChild(
169: subjectElement, "text");
170: String subject = DocumentHelper
171: .getSimpleElementText(subjectTextElement);
172: Element[] subjectParamElements = helper
173: .getChildren(subjectElement, "param");
174: String[] subjectParams = new String[subjectParamElements.length];
175: for (int p = 0; p < subjectParamElements.length; p++) {
176: subjectParams[p] = DocumentHelper
177: .getSimpleElementText(subjectParamElements[p]);
178: }
179:
180: String readString = "false";
181: if (messageElements[i].hasAttribute("read")) {
182: readString = messageElements[i]
183: .getAttribute("read");
184: }
185: boolean read = Boolean.valueOf(readString)
186: .booleanValue();
187:
188: Message message = new Message(subject,
189: subjectParams, body, bodyParams, sender,
190: recipients);
191: InboxMessage msg = new XmlSourceInboxMessage(this ,
192: id, message, read);
193: this .messages.add(msg);
194: }
195: }
196:
197: } catch (Exception e) {
198: throw new RuntimeException(e);
199: }
200: }
201:
202: protected User getUser(String id) throws AccessControlException {
203: return this .user.getAccreditableManager().getUserManager()
204: .getUser(id);
205: }
206:
207: protected Group getGroup(String id) throws AccessControlException {
208: return this .user.getAccreditableManager().getGroupManager()
209: .getGroup(id);
210: }
211:
212: private String sourceUri;
213:
214: protected String getSourceUri() {
215: if (this .sourceUri == null) {
216: String configUri = this .user.getAccreditableManager()
217: .getConfigurationCollectionUri();
218: if (configUri.endsWith("/")) {
219: configUri = configUri.substring(0,
220: configUri.length() - 1);
221: }
222: this .sourceUri = configUri + "/inboxes/"
223: + this .user.getId() + ".xml";
224: }
225: return this .sourceUri;
226: }
227:
228: protected synchronized void save() {
229: try {
230:
231: long newLastModified = SourceUtil.getLastModified(
232: getSourceUri(), this .manager);
233: if (this .lastModified > -1
234: && newLastModified > this .lastModified) {
235: throw new RuntimeException(
236: "The inbox file ["
237: + getSourceUri()
238: + "] has been changed externally and can't be saved.");
239: }
240:
241: NamespaceHelper helper = buildXml();
242: SourceUtil.writeDOM(helper.getDocument(), getSourceUri(),
243: this .manager);
244: this .lastModified = SourceUtil.getLastModified(
245: getSourceUri(), this .manager);
246: } catch (Exception e) {
247: throw new RuntimeException(e);
248: }
249: }
250:
251: protected NamespaceHelper buildXml()
252: throws ParserConfigurationException {
253: NamespaceHelper helper = new NamespaceHelper(
254: Notifier.NAMESPACE, "", "inbox");
255:
256: InboxMessage[] messages = getMessages();
257: for (int i = 0; i < messages.length; i++) {
258:
259: Message message = messages[i].getMessage();
260:
261: Element messageElement = helper.createElement("message");
262: helper.getDocument().getDocumentElement().appendChild(
263: messageElement);
264: User sender = (User) message.getSender();
265: messageElement.setAttribute("sender", sender.getId());
266:
267: Element recipientsElement = helper
268: .createElement("recipients");
269: messageElement.appendChild(recipientsElement);
270:
271: Identifiable[] recipients = message.getRecipients();
272: for (int r = 0; r < recipients.length; r++) {
273: if (recipients[r] instanceof User) {
274: Element userElement = helper.createElement("user");
275: userElement.setAttribute("id",
276: ((User) recipients[r]).getId());
277: recipientsElement.appendChild(userElement);
278: } else if (recipients[r] instanceof Group) {
279: Element groupElement = helper
280: .createElement("group");
281: groupElement.setAttribute("id",
282: ((Group) recipients[r]).getId());
283: recipientsElement.appendChild(groupElement);
284: }
285: }
286:
287: Element subjectElement = helper.createElement("subject");
288: messageElement.appendChild(subjectElement);
289: Element subjectTextElement = helper.createElement("text",
290: message.getSubject());
291: subjectElement.appendChild(subjectTextElement);
292: String[] subjectParams = message.getSubjectParameters();
293: for (int p = 0; p < subjectParams.length; p++) {
294: Element paramElement = helper.createElement("param",
295: subjectParams[p]);
296: subjectElement.appendChild(paramElement);
297: }
298:
299: Element bodyElement = helper.createElement("body");
300: messageElement.appendChild(bodyElement);
301: Element bodyTextElement = helper.createElement("text",
302: message.getBody());
303: bodyElement.appendChild(bodyTextElement);
304: String[] bodyParams = message.getBodyParameters();
305: for (int p = 0; p < bodyParams.length; p++) {
306: Element paramElement = helper.createElement("param",
307: bodyParams[p]);
308: bodyElement.appendChild(paramElement);
309: }
310:
311: messageElement.setAttribute("read", Boolean
312: .toString(messages[i].isMarkedAsRead()));
313: messageElement.setAttribute("id", messages[i].getId());
314: }
315: return helper;
316: }
317:
318: public InboxMessage getMessage(String id) {
319: InboxMessage[] messages = getMessages();
320: for (int i = 0; i < messages.length; i++) {
321: if (messages[i].getId().equals(id)) {
322: return messages[i];
323: }
324: }
325: throw new RuntimeException("No message found with ID [" + id
326: + "]");
327: }
328: }
|