blob: 21a0a2e2393f54d8a3063e441bc86fad4cb5b17b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.lenya.inbox.xml;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.axis.components.uuid.UUIDGen;
import org.apache.axis.components.uuid.UUIDGenFactory;
import org.apache.lenya.ac.AccessControlException;
import org.apache.lenya.ac.Group;
import org.apache.lenya.ac.Identifiable;
import org.apache.lenya.ac.User;
import org.apache.lenya.cms.cocoon.source.SourceUtil;
import org.apache.lenya.inbox.Inbox;
import org.apache.lenya.inbox.InboxMessage;
import org.apache.lenya.notification.Message;
import org.apache.lenya.notification.Notifier;
import org.apache.lenya.util.Assert;
import org.apache.lenya.xml.DocumentHelper;
import org.apache.lenya.xml.NamespaceHelper;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* Inbox based on XML sources.
*/
public class XmlSourceInbox implements Inbox {
private ServiceManager manager;
private User user;
/**
* @param manager The service manager.
* @param user The user.
*/
public XmlSourceInbox(ServiceManager manager, User user) {
this.manager = manager;
this.user = user;
}
public synchronized InboxMessage add(Message message) {
InboxMessage msg = new XmlSourceInboxMessage(this, generateId(), message, false);
messages().add(msg);
save();
return msg;
}
protected String generateId() {
UUIDGen generator = UUIDGenFactory.getUUIDGen();
String id = generator.nextUUID();
return id;
}
public synchronized void remove(InboxMessage message) {
Assert.isTrue("contained", messages().contains(message));
messages().remove(message);
save();
}
public InboxMessage[] getMessages() {
List messages = messages();
return (InboxMessage[]) messages.toArray(new InboxMessage[messages.size()]);
}
private List messages;
protected List messages() {
if (this.messages == null) {
load();
}
return this.messages;
}
private long lastModified = -1;
protected synchronized void load() {
this.messages = new ArrayList();
try {
if (SourceUtil.exists(getSourceUri(), this.manager)) {
this.lastModified = SourceUtil.getLastModified(getSourceUri(), this.manager);
Document xml = SourceUtil.readDOM(getSourceUri(), this.manager);
Assert.isTrue("document element is <inbox>", xml.getDocumentElement()
.getLocalName().equals("inbox"));
NamespaceHelper helper = new NamespaceHelper(Notifier.NAMESPACE, "", xml);
Element[] messageElements = helper.getChildren(xml.getDocumentElement(), "message");
for (int i = 0; i < messageElements.length; i++) {
String id;
if (messageElements[i].hasAttribute("id")) {
id = messageElements[i].getAttribute("id");
}
else {
id = generateId();
}
String senderId = messageElements[i].getAttribute("sender");
User sender = getUser(senderId);
Element recipientElement = helper.getFirstChild(messageElements[i],
"recipients");
Element[] userElements = helper.getChildren(recipientElement, "user");
Element[] groupElements = helper.getChildren(recipientElement, "group");
Identifiable[] recipients = new Identifiable[userElements.length
+ groupElements.length];
for (int u = 0; u < userElements.length; u++) {
String userId = userElements[u].getAttribute("id");
recipients[u] = getUser(userId);
}
for (int g = 0; g < groupElements.length; g++) {
String groupId = groupElements[g].getAttribute("id");
recipients[userElements.length + g] = getGroup(groupId);
}
Element bodyElement = helper.getFirstChild(messageElements[i], "body");
Element bodyTextElement = helper.getFirstChild(bodyElement, "text");
String body = DocumentHelper.getSimpleElementText(bodyTextElement);
Element[] bodyParamElements = helper.getChildren(bodyElement, "param");
String[] bodyParams = new String[bodyParamElements.length];
for (int p = 0; p < bodyParamElements.length; p++) {
bodyParams[p] = DocumentHelper.getSimpleElementText(bodyParamElements[p]);
}
Element subjectElement = helper.getFirstChild(messageElements[i], "subject");
Element subjectTextElement = helper.getFirstChild(subjectElement, "text");
String subject = DocumentHelper.getSimpleElementText(subjectTextElement);
Element[] subjectParamElements = helper.getChildren(subjectElement, "param");
String[] subjectParams = new String[subjectParamElements.length];
for (int p = 0; p < subjectParamElements.length; p++) {
subjectParams[p] = DocumentHelper
.getSimpleElementText(subjectParamElements[p]);
}
String readString = "false";
if (messageElements[i].hasAttribute("read")) {
readString = messageElements[i].getAttribute("read");
}
boolean read = Boolean.valueOf(readString).booleanValue();
Message message = new Message(subject, subjectParams, body, bodyParams, sender,
recipients);
InboxMessage msg = new XmlSourceInboxMessage(this, id, message, read);
this.messages.add(msg);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
protected User getUser(String id) throws AccessControlException {
return this.user.getAccreditableManager().getUserManager().getUser(id);
}
protected Group getGroup(String id) throws AccessControlException {
return this.user.getAccreditableManager().getGroupManager().getGroup(id);
}
private String sourceUri;
protected String getSourceUri() {
if (this.sourceUri == null) {
String configUri = this.user.getAccreditableManager().getConfigurationCollectionUri();
if (configUri.endsWith("/")) {
configUri = configUri.substring(0, configUri.length() - 1);
}
this.sourceUri = configUri + "/inboxes/" + this.user.getId() + ".xml";
}
return this.sourceUri;
}
protected synchronized void save() {
try {
long newLastModified = SourceUtil.getLastModified(getSourceUri(), this.manager);
if (this.lastModified > -1 && newLastModified > this.lastModified) {
throw new RuntimeException("The inbox file [" + getSourceUri()
+ "] has been changed externally and can't be saved.");
}
NamespaceHelper helper = buildXml();
SourceUtil.writeDOM(helper.getDocument(), getSourceUri(), this.manager);
this.lastModified = SourceUtil.getLastModified(getSourceUri(), this.manager);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
protected NamespaceHelper buildXml() throws ParserConfigurationException {
NamespaceHelper helper = new NamespaceHelper(Notifier.NAMESPACE, "", "inbox");
InboxMessage[] messages = getMessages();
for (int i = 0; i < messages.length; i++) {
Message message = messages[i].getMessage();
Element messageElement = helper.createElement("message");
helper.getDocument().getDocumentElement().appendChild(messageElement);
User sender = (User) message.getSender();
messageElement.setAttribute("sender", sender.getId());
Element recipientsElement = helper.createElement("recipients");
messageElement.appendChild(recipientsElement);
Identifiable[] recipients = message.getRecipients();
for (int r = 0; r < recipients.length; r++) {
if (recipients[r] instanceof User) {
Element userElement = helper.createElement("user");
userElement.setAttribute("id", ((User) recipients[r]).getId());
recipientsElement.appendChild(userElement);
} else if (recipients[r] instanceof Group) {
Element groupElement = helper.createElement("group");
groupElement.setAttribute("id", ((Group) recipients[r]).getId());
recipientsElement.appendChild(groupElement);
}
}
Element subjectElement = helper.createElement("subject");
messageElement.appendChild(subjectElement);
Element subjectTextElement = helper.createElement("text", message.getSubject());
subjectElement.appendChild(subjectTextElement);
String[] subjectParams = message.getSubjectParameters();
for (int p = 0; p < subjectParams.length; p++) {
Element paramElement = helper.createElement("param", subjectParams[p]);
subjectElement.appendChild(paramElement);
}
Element bodyElement = helper.createElement("body");
messageElement.appendChild(bodyElement);
Element bodyTextElement = helper.createElement("text", message.getBody());
bodyElement.appendChild(bodyTextElement);
String[] bodyParams = message.getBodyParameters();
for (int p = 0; p < bodyParams.length; p++) {
Element paramElement = helper.createElement("param", bodyParams[p]);
bodyElement.appendChild(paramElement);
}
messageElement.setAttribute("read", Boolean.toString(messages[i].isMarkedAsRead()));
messageElement.setAttribute("id", messages[i].getId());
}
return helper;
}
public InboxMessage getMessage(String id) {
InboxMessage[] messages = getMessages();
for (int i = 0; i < messages.length; i++) {
if (messages[i].getId().equals(id)) {
return messages[i];
}
}
throw new RuntimeException("No message found with ID [" + id + "]");
}
}