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.notification;
019:
020: import java.util.Arrays;
021: import java.util.HashSet;
022: import java.util.Iterator;
023: import java.util.Set;
024:
025: import org.apache.avalon.framework.context.Context;
026: import org.apache.avalon.framework.context.ContextException;
027: import org.apache.avalon.framework.context.Contextualizable;
028: import org.apache.avalon.framework.logger.AbstractLogEnabled;
029: import org.apache.avalon.framework.service.ServiceException;
030: import org.apache.avalon.framework.service.ServiceManager;
031: import org.apache.avalon.framework.service.Serviceable;
032: import org.apache.cocoon.components.ContextHelper;
033: import org.apache.cocoon.environment.Request;
034: import org.apache.cocoon.environment.Session;
035: import org.apache.cocoon.transformation.I18nTransformer;
036: import org.apache.excalibur.source.Source;
037: import org.apache.excalibur.source.SourceResolver;
038: import org.apache.lenya.ac.Group;
039: import org.apache.lenya.ac.Identifiable;
040: import org.apache.lenya.ac.User;
041: import org.apache.lenya.xml.DocumentHelper;
042: import org.apache.lenya.xml.NamespaceHelper;
043: import org.w3c.dom.Document;
044: import org.w3c.dom.Element;
045:
046: /**
047: * Base class for notifier implementation.
048: */
049: public abstract class AbstractNotifier extends AbstractLogEnabled
050: implements Notifier, Serviceable, Contextualizable {
051:
052: public void notify(Message message) throws NotificationException {
053:
054: Set noDuplicates = new HashSet();
055:
056: Identifiable[] recipients = message.getRecipients();
057:
058: for (int i = 0; i < recipients.length; i++) {
059: if (recipients[i] instanceof Group) {
060: Group group = (Group) recipients[i];
061: noDuplicates.addAll(Arrays.asList(group.getMembers()));
062: } else {
063: noDuplicates.add(recipients[i]);
064: }
065: }
066:
067: for (Iterator i = noDuplicates.iterator(); i.hasNext();) {
068: Identifiable identifiable = (Identifiable) i.next();
069: if (identifiable instanceof User) {
070: User user = (User) identifiable;
071: Message translatedMessage = translateMessage(user
072: .getDefaultMenuLocale(), message);
073: notify(user, translatedMessage);
074: }
075: }
076:
077: }
078:
079: protected abstract void notify(User user, Message translatedMessage)
080: throws NotificationException;
081:
082: protected Message translateMessage(String locale, Message message)
083: throws NotificationException {
084:
085: SourceResolver resolver = null;
086: Source source = null;
087: try {
088:
089: NamespaceHelper helper = new NamespaceHelper(NAMESPACE,
090: "not", "message");
091: Document doc = helper.getDocument();
092: NamespaceHelper i18nHelper = new NamespaceHelper(
093: I18nTransformer.I18N_NAMESPACE_URI, "i18n", doc);
094:
095: Element docElement = doc.getDocumentElement();
096:
097: Element subjectElement = helper.createElement("subject");
098: docElement.appendChild(subjectElement);
099: Element i18nTranslateSubjectElement = i18nHelper
100: .createElement("translate");
101: subjectElement.appendChild(i18nTranslateSubjectElement);
102: Element subjectI18nElement = i18nHelper.createElement(
103: "text", message.getSubject());
104: i18nTranslateSubjectElement.appendChild(subjectI18nElement);
105:
106: String[] subjectParams = message.getSubjectParameters();
107: for (int i = 0; i < subjectParams.length; i++) {
108: Element paramElement = i18nHelper.createElement(
109: "param", subjectParams[i]);
110: i18nTranslateSubjectElement.appendChild(paramElement);
111: }
112:
113: Element bodyElement = helper.createElement("body");
114: docElement.appendChild(bodyElement);
115: Element i18nTranslateElement = i18nHelper
116: .createElement("translate");
117: bodyElement.appendChild(i18nTranslateElement);
118: Element bodyI18nElement = i18nHelper.createElement("text",
119: message.getBody());
120: i18nTranslateElement.appendChild(bodyI18nElement);
121:
122: String[] msgParams = message.getBodyParameters();
123: for (int i = 0; i < msgParams.length; i++) {
124: Element paramElement = i18nHelper.createElement(
125: "param", msgParams[i]);
126: i18nTranslateElement.appendChild(paramElement);
127: }
128:
129: Session session = this .request.getSession();
130: session.setAttribute("notification.dom", doc);
131:
132: resolver = (SourceResolver) this .manager
133: .lookup(SourceResolver.ROLE);
134: source = resolver.resolveURI(
135: "cocoon://modules/notification/message/" + locale,
136: null, null);
137:
138: if (source.exists()) {
139: doc = DocumentHelper.readDocument(source
140: .getInputStream());
141: helper = new NamespaceHelper(NAMESPACE, "not", doc);
142:
143: subjectElement = helper.getFirstChild(doc
144: .getDocumentElement(), "subject");
145: String subject = DocumentHelper
146: .getSimpleElementText(subjectElement);
147:
148: bodyElement = helper.getFirstChild(doc
149: .getDocumentElement(), "body");
150: String body = DocumentHelper
151: .getSimpleElementText(bodyElement);
152:
153: return new Message(subject, new String[0], body,
154: new String[0], message.getSender(), message
155: .getRecipients());
156: } else {
157: // this happens in the test
158: getLogger()
159: .info(
160: "cocoon protocol not available, not translating message");
161: return message;
162: }
163: } catch (Exception e) {
164: throw new NotificationException(e);
165: } finally {
166: if (resolver != null) {
167: if (source != null) {
168: resolver.release(source);
169: }
170: this .manager.release(resolver);
171: }
172: }
173:
174: }
175:
176: protected ServiceManager manager;
177:
178: public void service(ServiceManager manager) throws ServiceException {
179: this .manager = manager;
180: }
181:
182: private Request request;
183:
184: public void contextualize(Context context) throws ContextException {
185: this.request = ContextHelper.getRequest(context);
186: }
187:
188: }
|