/** * OpenKM, Open Document Management System (http://www.openkm.com) * Copyright (c) 2006-2011 Paco Avila & Josep Llort * * No bytes were intentionally harmed during the development of this application. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package com.openkm.module.direct; import java.io.StringReader; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.jcr.Node; import javax.jcr.Session; import javax.jcr.Value; import javax.mail.MessagingException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.openkm.bean.Notification; import com.openkm.core.AccessDeniedException; import com.openkm.core.Config; import com.openkm.core.DatabaseException; import com.openkm.core.JcrSessionManager; import com.openkm.core.PathNotFoundException; import com.openkm.core.RepositoryException; import com.openkm.jcr.JCRUtils; import com.openkm.module.NotificationModule; import com.openkm.util.MailUtils; import com.openkm.util.TemplateUtils; import com.openkm.util.UserActivity; import freemarker.template.Configuration; import freemarker.template.Template; public class DirectNotificationModule implements NotificationModule { private static Logger log = LoggerFactory.getLogger(DirectNotificationModule.class); @Override public synchronized void subscribe(String token, String nodePath) throws PathNotFoundException, AccessDeniedException, RepositoryException, DatabaseException { log.debug("subscribe({}, {})", token, nodePath); Node node = null; Node sNode = null; Session session = null; Session systemSession = null; String lt = null; if (Config.SYSTEM_READONLY) { throw new AccessDeniedException("System is in read-only mode"); } try { if (token == null) { session = JCRUtils.getSession(); } else { session = JcrSessionManager.getInstance().get(token); } systemSession = DirectRepositoryModule.getSystemSession(); node = session.getRootNode().getNode(nodePath.substring(1)); sNode = systemSession.getNodeByUUID(node.getUUID()); lt = JCRUtils.getLockToken(node.getUUID()); systemSession.addLockToken(lt); // Perform subscription if (node.isNodeType(Notification.TYPE)) { Value[] actualUsers = node.getProperty(Notification.SUBSCRIPTORS).getValues(); String[] newUsers = new String[actualUsers.length+1]; boolean alreadyAdded = false; for (int i=0; i<actualUsers.length; i++) { newUsers[i] = actualUsers[i].getString(); // Don't add a user twice if (actualUsers[i].getString().equals(session.getUserID())) { alreadyAdded = true; } } if (!alreadyAdded) { newUsers[newUsers.length-1] = session.getUserID(); sNode.setProperty(Notification.SUBSCRIPTORS, newUsers); } } else { sNode.addMixin(Notification.TYPE); sNode.setProperty(Notification.SUBSCRIPTORS, new String[] { session.getUserID() }); } sNode.save(); // Activity log UserActivity.log(session.getUserID(), "SUBSCRIBE_USER", node.getUUID(), nodePath); } catch (javax.jcr.AccessDeniedException e) { log.warn(e.getMessage(), e); JCRUtils.discardsPendingChanges(sNode); throw new AccessDeniedException(e.getMessage(), e); } catch (javax.jcr.PathNotFoundException e) { log.warn(e.getMessage(), e); JCRUtils.discardsPendingChanges(sNode); throw new PathNotFoundException(e.getMessage(), e); } catch (javax.jcr.RepositoryException e) { log.error(e.getMessage(), e); JCRUtils.discardsPendingChanges(sNode); throw new RepositoryException(e.getMessage(), e); } finally { if (lt != null) systemSession.removeLockToken(lt); if (token == null) JCRUtils.logout(session); } log.debug("subscribe: void"); } @Override public synchronized void unsubscribe(String token, String nodePath) throws PathNotFoundException, AccessDeniedException, RepositoryException, DatabaseException { log.debug("unsubscribe({}, {})", token, nodePath); Node node = null; Node sNode = null; Session session = null; Session systemSession = null; String lt = null; if (Config.SYSTEM_READONLY) { throw new AccessDeniedException("System is in read-only mode"); } try { if (token == null) { session = JCRUtils.getSession(); } else { session = JcrSessionManager.getInstance().get(token); } systemSession = DirectRepositoryModule.getSystemSession(); node = session.getRootNode().getNode(nodePath.substring(1)); sNode = systemSession.getNodeByUUID(node.getUUID()); lt = JCRUtils.getLockToken(node.getUUID()); systemSession.addLockToken(lt); // Perform unsubscription if (node.isNodeType(Notification.TYPE)) { Value[] actualUsers = node.getProperty(Notification.SUBSCRIPTORS).getValues(); ArrayList<String> newUsers = new ArrayList<String>(); for (int i=0; i<actualUsers.length; i++) { if (!actualUsers[i].getString().equals(session.getUserID())) { newUsers.add(actualUsers[i].getString()); } } if (newUsers.isEmpty()) { sNode.removeMixin(Notification.TYPE); } else { sNode.setProperty(Notification.SUBSCRIPTORS, (String[])newUsers.toArray(new String[newUsers.size()])); } } sNode.save(); // Activity log UserActivity.log(session.getUserID(), "UNSUBSCRIBE_USER", node.getUUID(), nodePath); } catch (javax.jcr.AccessDeniedException e) { log.warn(e.getMessage(), e); JCRUtils.discardsPendingChanges(sNode); throw new AccessDeniedException(e.getMessage(), e); } catch (javax.jcr.PathNotFoundException e) { log.warn(e.getMessage(), e); JCRUtils.discardsPendingChanges(sNode); throw new PathNotFoundException(e.getMessage(), e); } catch (javax.jcr.RepositoryException e) { log.error(e.getMessage(), e); JCRUtils.discardsPendingChanges(sNode); throw new RepositoryException(e.getMessage(), e); } finally { if (lt != null) systemSession.removeLockToken(lt); if (token == null) JCRUtils.logout(session); } log.debug("unsubscribe: void"); } @Override public List<String> getSubscriptors(String token, String nodePath) throws PathNotFoundException, AccessDeniedException, RepositoryException, DatabaseException { log.debug("getSusbcriptions({}, {})", token, nodePath); List<String> users = new ArrayList<String>(); Session session = null; try { if (token == null) { session = JCRUtils.getSession(); } else { session = JcrSessionManager.getInstance().get(token); } Node node = session.getRootNode().getNode(nodePath.substring(1)); if (node.isNodeType(Notification.TYPE)) { Value[] notifyUsers = node.getProperty(Notification.SUBSCRIPTORS).getValues(); for (int i=0; i<notifyUsers.length; i++) { users.add(notifyUsers[i].getString()); } } } catch (javax.jcr.PathNotFoundException e) { log.warn(e.getMessage(), e); throw new PathNotFoundException(e.getMessage(), e); } catch (javax.jcr.RepositoryException e) { log.error(e.getMessage(), e); throw new RepositoryException(e.getMessage(), e); } finally { if (token == null) JCRUtils.logout(session); } log.debug("getSusbcriptions: {}", users); return users; } @Override public void notify(String token, String nodePath, List<String> users, String message, boolean attachment) throws PathNotFoundException, AccessDeniedException, RepositoryException { log.debug("notify({}, {}, {}, {})", new Object[] { token, nodePath, users, message }); List<String> to = new ArrayList<String>(); Session session = null; if (!users.isEmpty()) { try { log.debug("Nodo: {}, Message: {}", nodePath, message); if (token == null) { session = JCRUtils.getSession(); } else { session = JcrSessionManager.getInstance().get(token); } for (String user : users) { String mail = new DirectAuthModule().getMail(token, user); if (mail != null) { to.add(mail); } } // Get session user email address String from = new DirectAuthModule().getMail(token, session.getUserID()); if (!to.isEmpty() && from != null && !from.isEmpty()) { StringWriter swSubject = new StringWriter(); StringWriter swBody = new StringWriter(); Configuration cfg = TemplateUtils.getConfig(); Map<String, String> model = new HashMap<String, String>(); model.put("documentUrl", Config.APPLICATION_URL+"?docPath=" + URLEncoder.encode(nodePath, "UTF-8")); //vissu touch on oct'9th String kvPath = nodePath; kvPath = kvPath.replaceAll("okm:root","Knowledge Vault"); //model.put("documentPath", nodePath); model.put("documentPath", kvPath); model.put("documentName", JCRUtils.getName(nodePath)); model.put("userId", session.getUserID()); model.put("notificationMessage", message); if (TemplateUtils.templateExists(Config.NOTIFICATION_MESSAGE_SUBJECT)) { Template tpl = cfg.getTemplate(Config.NOTIFICATION_MESSAGE_SUBJECT); tpl.process(model, swSubject); } else { StringReader sr = new StringReader(Config.NOTIFICATION_MESSAGE_SUBJECT); Template tpl = new Template("NotificationMessageSubject", sr, cfg); tpl.process(model, swSubject); sr.close(); } if (TemplateUtils.templateExists(Config.NOTIFICATION_MESSAGE_BODY)) { Template tpl = cfg.getTemplate(Config.NOTIFICATION_MESSAGE_BODY); tpl.process(model, swBody); } else { StringReader sr = new StringReader(Config.NOTIFICATION_MESSAGE_BODY); Template tpl = new Template("NotificationMessageBody", sr, cfg); tpl.process(model, swBody); sr.close(); } if (attachment) { MailUtils.sendDocument((String) from, to, swSubject.toString(), swBody.toString(), nodePath); } else { MailUtils.sendMessage((String) from, to, swSubject.toString(), swBody.toString()); } } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (MessagingException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { if (token == null) JCRUtils.logout(session); } } log.debug("notify: void"); } }