KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > components > slide > impl > JMSContentInterceptor


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.components.slide.impl;
17
18 import java.util.ArrayList JavaDoc;
19 import java.util.Collections JavaDoc;
20 import java.util.Hashtable JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.List JavaDoc;
23
24 import javax.jms.DeliveryMode JavaDoc;
25 import javax.jms.JMSException JavaDoc;
26 import javax.jms.Session JavaDoc;
27 import javax.jms.Topic JavaDoc;
28 import javax.jms.TopicConnection JavaDoc;
29 import javax.jms.TopicConnectionFactory JavaDoc;
30 import javax.jms.TopicPublisher JavaDoc;
31 import javax.jms.TopicSession JavaDoc;
32 import javax.naming.Context JavaDoc;
33 import javax.naming.InitialContext JavaDoc;
34 import javax.naming.NamingException JavaDoc;
35
36 import org.apache.slide.common.NamespaceAccessToken;
37 import org.apache.slide.common.ServiceAccessException;
38 import org.apache.slide.common.SlideToken;
39 import org.apache.slide.content.AbstractContentInterceptor;
40 import org.apache.slide.content.NodeRevisionContent;
41 import org.apache.slide.content.NodeRevisionDescriptor;
42 import org.apache.slide.content.NodeRevisionDescriptors;
43 import org.apache.slide.lock.ObjectLockedException;
44 import org.apache.slide.security.AccessDeniedException;
45 import org.apache.slide.structure.LinkedObjectNotFoundException;
46 import org.apache.slide.structure.ObjectNotFoundException;
47 import org.apache.slide.util.logger.Logger;
48
49 /**
50  * A ContentInterceptor for Slide that publishes
51  * invalidation events to a JMS topic.
52  */

53 public class JMSContentInterceptor extends AbstractContentInterceptor {
54
55     
56     // ---------------------------------------------------- constants
57

58     private static final String JavaDoc LOG_CHANNEL = "JMSContentInterceptor";
59     
60     private static final String JavaDoc PARAM_TOPIC_FACTORY = "topic-factory";
61     private static final String JavaDoc PARAM_TOPIC = "topic";
62     private static final String JavaDoc PARAM_PERSISTENT = "persistent-delivery";
63     private static final String JavaDoc PARAM_PRIORITY = "priority";
64     private static final String JavaDoc PARAM_TIME_TO_LIVE = "time-to-live";
65     private static final String JavaDoc PARAM_INITIAL_CONTEXT_FACTORY = Context.INITIAL_CONTEXT_FACTORY;
66     private static final String JavaDoc PARAM_PROVIDER_URL = Context.PROVIDER_URL;
67     
68     private static final String JavaDoc DEFAULT_TOPIC_FACTORY = "JmsTopicConnectionFactory";
69     private static final String JavaDoc DEFAULT_TOPIC = "topic1";
70     private static final String JavaDoc DEFAULT_PERSISTENT = "false";
71     private static final String JavaDoc DEFAULT_PRIORITY = "4";
72     private static final String JavaDoc DEFAULT_TIME_TO_LIVE = "1000";
73     private static final String JavaDoc DEFAULT_INITIAL_CONTEXT_FACTORY = "org.exolab.jms.jndi.InitialContextFactory";
74     private static final String JavaDoc DEFAULT_PROVIDER_URL = "rmi://localhost:1099/";
75     
76     
77     // ---------------------------------------------------- member variables
78

79     // JMS objects
80
private TopicConnection JavaDoc m_connection;
81     private TopicSession JavaDoc m_session;
82     private Topic JavaDoc m_topic;
83     private TopicPublisher JavaDoc m_publisher;
84     
85     // configuration options
86
private String JavaDoc m_topicFactoryName;
87     private String JavaDoc m_topicName;
88     private int m_deliveryMode;
89     private int m_priority;
90     private long m_timeToLive;
91     private Hashtable JavaDoc m_jndiProps;
92     
93     // queue of messages to be published
94
private List JavaDoc m_queue = Collections.synchronizedList(new ArrayList JavaDoc());
95     
96     // the started state of the interceptor
97
private boolean m_started = false;
98     
99     
100     // ---------------------------------------------------- lifecycle
101

102     public JMSContentInterceptor() {
103     }
104     
105     /**
106      * Configure the interceptor.
107      * <p>
108      * The following parameters are recognized:
109      * <ul>
110      * <li>
111      * <code>java.naming.factory.initial</code> [<code>org.exolab.jms.jndi.InitialContextFactory</code>]
112      * - initial jndi context factory.
113      * </li>
114      * <li>
115      * <code>java.naming.provider.url</code> [<code>rmi://localhost:1099/</code>] - jndi provider url.
116      * </li>
117      * <li>
118      * <code>topic-factory<code> [<code>JmsTopicConnectionFactory</code>] - the JNDI lookup name
119      * of the JMS TopicConnectionFactory.
120      * </li>
121      * <li>
122      * <code>topic</code> [<code>topic1</code>] - the name of the topic to publish messages to.
123      * </li>
124      * <li>
125      * <code>persistent-delivery</code> [<code>false</code>] - message delivery mode.
126      * </li>
127      * <li>
128      * <code>priority</code> [<code>4</code>] - message priority.
129      * </li>
130      * <li>
131      * <code>time-to-live</code> [<code>1000</code>] - message lifetime in ms.
132      * </li>
133      * </ul>
134      * </p>
135      */

136     public void setParameters(Hashtable JavaDoc params) {
137         super.setParameters(params);
138         
139         // parse the JMS related parameters
140
m_topicFactoryName = getParameter(PARAM_TOPIC_FACTORY,DEFAULT_TOPIC_FACTORY);
141         m_topicName = getParameter(PARAM_TOPIC,DEFAULT_TOPIC);
142         boolean persistent = Boolean.valueOf(getParameter(PARAM_PERSISTENT,DEFAULT_PERSISTENT)).booleanValue();
143         
144         m_deliveryMode = persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT;
145         m_priority = Integer.valueOf(getParameter(PARAM_PRIORITY,DEFAULT_PRIORITY)).intValue();
146         m_timeToLive = Long.valueOf(getParameter(PARAM_TIME_TO_LIVE,DEFAULT_TIME_TO_LIVE)).longValue();
147         
148         // parse the JNDI related parameters
149
m_jndiProps = new Hashtable JavaDoc();
150         m_jndiProps.put(Context.INITIAL_CONTEXT_FACTORY,
151                   getParameter(PARAM_INITIAL_CONTEXT_FACTORY,
152                                DEFAULT_INITIAL_CONTEXT_FACTORY)
153         );
154         m_jndiProps.put(Context.PROVIDER_URL,
155                   getParameter(PARAM_PROVIDER_URL,
156                                DEFAULT_PROVIDER_URL)
157         );
158     }
159     
160     /**
161      * Sets up the JMS connection.
162      */

163     public void setNamespace(NamespaceAccessToken nat) {
164         super.setNamespace(nat);
165         
166         // setup the JMS connection and session
167
try {
168             Context JavaDoc context = new InitialContext JavaDoc(m_jndiProps);
169             TopicConnectionFactory JavaDoc topicConnectionFactory = (TopicConnectionFactory JavaDoc)
170                 context.lookup(m_topicFactoryName);
171             m_connection = topicConnectionFactory.createTopicConnection();
172             m_connection.start();
173             m_session = m_connection.createTopicSession(false,Session.DUPS_OK_ACKNOWLEDGE);
174             m_topic = m_session.createTopic(m_topicName);
175             m_publisher = m_session.createPublisher(m_topic);
176             
177             /* a background thread does the actual publishing
178              * of messages. This is because JMS Session
179              * and its derivatives are single threaded
180              * and so if we were to publish messages synchronously
181              * we'd have to create a new Session
182              * each time we need to publish a message.
183              */

184             Thread JavaDoc t = new Thread JavaDoc(new Runnable JavaDoc() {
185                 public void run() {
186                     m_started = true;
187                     while (m_started) {
188                         try {
189                             Thread.sleep(1000);
190                         } catch (InterruptedException JavaDoc e) {
191                             // continue
192
}
193                         if (m_queue.size() == 0) continue;
194                         List JavaDoc list = m_queue;
195                         m_queue = Collections.synchronizedList(new ArrayList JavaDoc());
196                         Iterator JavaDoc iter = list.iterator();
197                         while (iter.hasNext()) {
198                             String JavaDoc msg = (String JavaDoc) iter.next();
199                             if (getLogger().isEnabled(Logger.INFO)) {
200                                 getLogger().log("Sending message: " + msg,Logger.INFO);
201                             }
202                             try {
203                                 m_publisher.publish(m_session.createTextMessage(msg),
204                                     m_deliveryMode,m_priority,m_timeToLive);
205                             }
206                             catch (JMSException JavaDoc e) {
207                                 getLogger().log("Failure sending JMS message.",e,LOG_CHANNEL,Logger.ERROR);
208                             }
209                         }
210                     }
211                 }
212             });
213             t.setPriority(Thread.NORM_PRIORITY);
214             t.start();
215         } catch (NamingException JavaDoc e) {
216             getLogger().log("Failure while connecting to JMS server.",e,LOG_CHANNEL,Logger.ERROR);
217         } catch (JMSException JavaDoc e) {
218             getLogger().log("Failure while connecting to JMS server.",e,LOG_CHANNEL,Logger.ERROR);
219         }
220
221     }
222     
223     private String JavaDoc getParameter(String JavaDoc name, String JavaDoc defaultValue) {
224         String JavaDoc value = super.getParameter(name);
225         if (value == null) {
226             value = defaultValue;
227         }
228         return value;
229     }
230     
231     
232     // ---------------------------------------------------- interception methods
233

234     public void postRemoveContent(
235         SlideToken slideToken,
236         NodeRevisionDescriptors revisions,
237         NodeRevisionDescriptor revision)
238         throws
239             AccessDeniedException,
240             ObjectNotFoundException,
241             LinkedObjectNotFoundException,
242             ObjectLockedException,
243             ServiceAccessException {
244        
245        if (!m_started) {
246            return;
247        }
248        if (revisions == null) {
249            return;
250        }
251        queueMessage(revisions.getUri(),"remove");
252
253     }
254     
255     public void postStoreContent(
256         SlideToken slideToken,
257         NodeRevisionDescriptors revisions,
258         NodeRevisionDescriptor revision,
259         NodeRevisionContent content)
260         throws
261             AccessDeniedException,
262             ObjectNotFoundException,
263             LinkedObjectNotFoundException,
264             ObjectLockedException,
265             ServiceAccessException {
266         
267         if (!m_started) {
268             return;
269         }
270         if (revisions == null) {
271             return;
272         }
273         queueMessage(revisions.getUri(),"store");
274     }
275     
276     private void queueMessage(String JavaDoc uri, String JavaDoc type) {
277         String JavaDoc msg = "slide-interceptor:" + type + "|" + getNamespace().getName() + uri;
278         m_queue.add(msg);
279     }
280     
281     private Logger getLogger() {
282         return getNamespace().getLogger();
283     }
284 }
285
Popular Tags