1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.exoplatform.services.cms.watch.impl;
18
19 import java.util.ArrayList;
20 import java.util.List;
21
22 import javax.jcr.Node;
23 import javax.jcr.NodeIterator;
24 import javax.jcr.Session;
25 import javax.jcr.Value;
26 import javax.jcr.nodetype.NodeType;
27 import javax.jcr.observation.Event;
28 import javax.jcr.observation.EventListener;
29 import javax.jcr.observation.ObservationManager;
30 import javax.jcr.query.Query;
31 import javax.jcr.query.QueryManager;
32 import javax.jcr.query.QueryResult;
33
34 import org.exoplatform.container.xml.InitParams;
35 import org.exoplatform.services.cms.templates.TemplateService;
36 import org.exoplatform.services.cms.watch.WatchDocumentService;
37 import org.exoplatform.services.jcr.RepositoryService;
38 import org.exoplatform.services.jcr.config.RepositoryEntry;
39 import org.exoplatform.services.jcr.core.ManageableRepository;
40 import org.exoplatform.services.log.ExoLogger;
41 import org.exoplatform.services.log.Log;
42 import org.picocontainer.Startable;
43
44 public class WatchDocumentServiceImpl implements WatchDocumentService, Startable {
45
46 final public static String EXO_WATCHABLE_MIXIN = "exo:watchable" ;
47 final public static String EMAIL_WATCHERS_PROP = "exo:emailWatcher" ;
48 final public static String RSS_WATCHERS_PROP = "exo:rssWatcher" ;
49 final private static String WATCHABLE_MIXIN_QUERY = "//element(*,exo:watchable)" ;
50
51 private RepositoryService repoService_ ;
52 private MessageConfig messageConfig_ ;
53 private TemplateService templateService_ ;
54 private static final Log LOG = ExoLogger.getLogger(WatchDocumentServiceImpl.class.getName());
55
56
57
58
59
60
61
62 public WatchDocumentServiceImpl(InitParams params,
63 RepositoryService repoService, TemplateService templateService) {
64 repoService_ = repoService ;
65 templateService_ = templateService ;
66 }
67
68
69
70
71 public void initializeMessageConfig(MessageConfigPlugin msgConfigPlugin) {
72 messageConfig_ = msgConfigPlugin.getMessageConfig();
73 }
74
75
76
77
78 public int getNotificationType(Node documentNode, String userName) throws Exception {
79 NodeType[] mixinTypes = documentNode.getMixinNodeTypes() ;
80 NodeType watchableMixin = null ;
81 if(mixinTypes.length>0) {
82 for(NodeType nodeType: mixinTypes) {
83 if(nodeType.getName().equalsIgnoreCase(EXO_WATCHABLE_MIXIN)) {
84 watchableMixin = nodeType ;
85 break ;
86 }
87 }
88 }
89 if(watchableMixin == null) return -1 ;
90 boolean notifyByEmail = checkNotifyTypeOfWatcher(documentNode,userName,EMAIL_WATCHERS_PROP) ;
91 boolean notifyByRss = checkNotifyTypeOfWatcher(documentNode,userName,RSS_WATCHERS_PROP) ;
92 if( notifyByEmail && notifyByRss) return FULL_NOTIFICATION ;
93 if(notifyByEmail) return NOTIFICATION_BY_EMAIL ;
94 if(notifyByRss) return NOTIFICATION_BY_RSS ;
95 return -1 ;
96 }
97
98
99
100
101 public void watchDocument(Node documentNode, String userName, int notifyType) throws Exception {
102 Session session = documentNode.getSession() ;
103 Value newWatcher = session.getValueFactory().createValue(userName) ;
104 if(!documentNode.isNodeType(EXO_WATCHABLE_MIXIN)) {
105 documentNode.addMixin(EXO_WATCHABLE_MIXIN) ;
106 if(notifyType == NOTIFICATION_BY_EMAIL) {
107 documentNode.setProperty(EMAIL_WATCHERS_PROP,new Value[] {newWatcher}) ;
108 documentNode.save() ;
109 session.save() ;
110 EmailNotifyListener listener = new EmailNotifyListener(documentNode) ;
111 observeNode(documentNode,listener) ;
112 }
113 session.save() ;
114 } else {
115 List<Value> watcherList = new ArrayList<Value>() ;
116 if(notifyType == NOTIFICATION_BY_EMAIL) {
117 if(documentNode.hasProperty(EMAIL_WATCHERS_PROP)) {
118 for(Value watcher : documentNode.getProperty(EMAIL_WATCHERS_PROP).getValues()) {
119 watcherList.add(watcher) ;
120 }
121 watcherList.add(newWatcher) ;
122 }
123
124 documentNode.setProperty(EMAIL_WATCHERS_PROP,watcherList.toArray(new Value[watcherList.size()])) ;
125 documentNode.save() ;
126 }
127 session.save() ;
128 }
129 }
130
131
132
133
134 public void unwatchDocument(Node documentNode, String userName, int notificationType) throws Exception {
135 if(!documentNode.isNodeType(EXO_WATCHABLE_MIXIN)) return ;
136 Session session = documentNode.getSession() ;
137 if(notificationType == NOTIFICATION_BY_EMAIL) {
138 Value[] watchers = documentNode.getProperty(EMAIL_WATCHERS_PROP).getValues() ;
139 List<Value> watcherList = new ArrayList<Value>() ;
140 for(Value watcher: watchers) {
141 if(!watcher.getString().equals(userName)) {
142 watcherList.add(watcher) ;
143 }
144 }
145 documentNode.setProperty(EMAIL_WATCHERS_PROP,watcherList.toArray(new Value[watcherList.size()])) ;
146 }
147 documentNode.save() ;
148 session.save() ;
149 }
150
151
152
153
154
155
156
157
158
159
160 private void observeNode(Node node, EventListener listener) throws Exception {
161 String workspace = node.getSession().getWorkspace().getName() ;
162 Session systemSession = repoService_.getCurrentRepository().getSystemSession(workspace) ;
163 List<String> list = getDocumentNodeTypes(node) ;
164 String[] observedNodeTypeNames = list.toArray(new String[list.size()]) ;
165 ObservationManager observationManager = systemSession.getWorkspace().getObservationManager() ;
166 observationManager.addEventListener(listener,Event.PROPERTY_CHANGED,
167 node.getPath(),true,null,observedNodeTypeNames,false) ;
168 systemSession.logout();
169 }
170
171
172
173
174
175
176
177
178
179 private boolean checkNotifyTypeOfWatcher(Node documentNode, String userName,String notificationType) throws Exception {
180 if(documentNode.hasProperty(notificationType)) {
181 Value [] watchers = documentNode.getProperty(notificationType).getValues() ;
182 for(Value value: watchers) {
183 if(userName.equalsIgnoreCase(value.getString())) return true ;
184 }
185 }
186 return false ;
187 }
188
189
190
191
192
193
194
195 private List<String> getDocumentNodeTypes(Node node) throws Exception {
196 List<String> nodeTypeNameList = new ArrayList<String>() ;
197 NodeType primaryType = node.getPrimaryNodeType() ;
198 if(templateService_.isManagedNodeType(primaryType.getName())) {
199 nodeTypeNameList.add(primaryType.getName()) ;
200 }
201 for(NodeType nodeType: node.getMixinNodeTypes()) {
202 if(templateService_.isManagedNodeType(nodeType.getName())) {
203 nodeTypeNameList.add(nodeType.getName()) ;
204 }
205 }
206 return nodeTypeNameList ;
207 }
208
209
210
211
212
213 private void reInitObserver() throws Exception {
214 RepositoryEntry repo = repoService_.getCurrentRepository().getConfiguration();
215 ManageableRepository repository = repoService_.getCurrentRepository();
216 String[] workspaceNames = repository.getWorkspaceNames() ;
217 for(String workspace: workspaceNames) {
218 Session session = repository.getSystemSession(workspace) ;
219 QueryManager queryManager = null ;
220 try{
221 queryManager = session.getWorkspace().getQueryManager() ;
222 } catch (Exception e) {
223 if (LOG.isErrorEnabled()) {
224 LOG.error("Unexpected error", e);
225 }
226 }
227 if(queryManager == null) {
228 session.logout();
229 continue ;
230 }
231 try {
232 Query query = queryManager.createQuery(WATCHABLE_MIXIN_QUERY,Query.XPATH) ;
233 QueryResult queryResult = query.execute() ;
234 for(NodeIterator iter = queryResult.getNodes(); iter.hasNext(); ) {
235 Node observedNode = iter.nextNode() ;
236 EmailNotifyListener emailNotifyListener = new EmailNotifyListener(observedNode) ;
237 ObservationManager manager = session.getWorkspace().getObservationManager() ;
238 List<String> list = getDocumentNodeTypes(observedNode) ;
239 String[] observedNodeTypeNames = list.toArray(new String[list.size()]) ;
240 manager.addEventListener(emailNotifyListener,Event.PROPERTY_CHANGED,
241 observedNode.getPath(),true,null,observedNodeTypeNames,false) ;
242 }
243 session.logout();
244 } catch (Exception e) {
245 if (LOG.isWarnEnabled()) {
246 LOG.warn("==>>> Cannot init observer for node: "
247 +e.getLocalizedMessage() + " in '"+repo.getName()+"' repository");
248 }
249 if (LOG.isErrorEnabled()) {
250 LOG.error("Unexpected error", e);
251 }
252 }
253 }
254 }
255
256
257
258
259
260
261 protected MessageConfig getMessageConfig() { return messageConfig_ ; }
262
263
264
265
266 public void start() {
267 try {
268 reInitObserver() ;
269 }catch (Exception e) {
270 if (LOG.isWarnEnabled()) {
271 LOG.warn("==>>> Exeption when startd WatchDocumentSerice!!!!");
272 }
273 }
274 }
275
276
277
278
279 public void stop() { }
280 }