001/* 002 * Copyright 2014 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.pagesubscription; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.HashSet; 021import java.util.List; 022import java.util.Map; 023import java.util.Set; 024import java.util.regex.Pattern; 025 026import javax.jcr.Node; 027import javax.jcr.RepositoryException; 028import javax.jcr.Value; 029 030import org.apache.avalon.framework.parameters.Parameters; 031import org.apache.avalon.framework.service.ServiceException; 032import org.apache.avalon.framework.service.ServiceManager; 033import org.apache.cocoon.ProcessingException; 034import org.apache.cocoon.environment.ObjectModelHelper; 035import org.apache.cocoon.environment.Redirector; 036import org.apache.cocoon.environment.Request; 037import org.apache.cocoon.environment.SourceResolver; 038import org.apache.commons.lang.StringUtils; 039 040import org.ametys.core.cocoon.ActionResultGenerator; 041import org.ametys.core.observation.AbstractNotifierAction; 042import org.ametys.core.observation.Event; 043import org.ametys.core.util.mail.SendMailHelper; 044import org.ametys.plugins.repository.AmetysObjectResolver; 045import org.ametys.plugins.repository.RepositoryConstants; 046import org.ametys.plugins.repository.jcr.JCRAmetysObject; 047import org.ametys.plugins.repository.provider.RequestAttributeWorkspaceSelector; 048import org.ametys.runtime.i18n.I18nizableText; 049import org.ametys.web.ObservationConstants; 050import org.ametys.web.repository.page.Page; 051import org.ametys.web.repository.page.jcr.DefaultPage; 052 053/** 054 * Action to subscribe to a page 055 */ 056public class PageSubscribeAction extends AbstractNotifierAction 057{ 058 /** Constant for the attachment node name. */ 059 public static final String SUBSCRIBERS_PROPERTY_NAME = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":subscriberMails"; 060 061 /** The pattern to check emails */ 062 protected static final Pattern EMAIL_VALIDATOR = SendMailHelper.EMAIL_VALIDATION; 063 064 /** The pattern to check text input */ 065 protected static final Pattern TEXT_VALIDATOR = Pattern.compile("^\\s*$"); 066 067 /** The ametys resolver */ 068 protected AmetysObjectResolver _resolver; 069 070 @Override 071 public void service(ServiceManager smanager) throws ServiceException 072 { 073 super.service(smanager); 074 _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE); 075 } 076 077 public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception 078 { 079 Map<String, Object> result = new HashMap<>(); 080 List<I18nizableText> errors = new ArrayList<>(); 081 082 Request request = ObjectModelHelper.getRequest(objectModel); 083 String action = request.getParameter("page-subscribe-action"); 084 result.put("action", action); 085 086 String email = request.getParameter("email"); 087 088 if (email == null || !EMAIL_VALIDATOR.matcher(StringUtils.trimToEmpty(email.toLowerCase())).matches() || TEXT_VALIDATOR.matcher(StringUtils.trimToEmpty(email)).matches()) 089 { 090 errors.add(new I18nizableText("plugin.page-subscription", "PLUGINS_PAGE_SUBSCRIBE_FORM_MAIL_ERROR_MAILBY")); 091 } 092 else 093 { 094 result.put("email", email); 095 } 096 097 String pageId = request.getParameter("page-id"); 098 if (pageId == null) 099 { 100 throw new IllegalArgumentException("Unable to subscribe or unsubscribe to the page: cannot determine the current page"); 101 } 102 else 103 { 104 // Force default workspace 105 String currentWorspace = RequestAttributeWorkspaceSelector.getForcedWorkspace(request); 106 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, "default"); 107 108 try 109 { 110 Page page = _resolver.resolveById(pageId); 111 112 if (page == null) 113 { 114 throw new IllegalArgumentException("Unable to subscribe or unsubscribe to the page: the page of id " + pageId + " is unknown"); 115 } 116 117 if (page instanceof JCRAmetysObject) 118 { 119 Set<String> subscribers = _getSubscribers((JCRAmetysObject) page); 120 121 if (action.equals("subscribe")) 122 { 123 subscribers.add(email); 124 } 125 else if (action.equals("unsubscribe")) 126 { 127 subscribers.remove(email); 128 } 129 130 _setSubscribers((DefaultPage) page, subscribers); 131 132 // Notify observers that page data has been changed. 133 Map<String, Object> eventParams = new HashMap<>(); 134 eventParams.put(ObservationConstants.ARGS_PAGE, page); 135 eventParams.put(ObservationConstants.ARGS_PAGE_ID, page.getId()); 136 _observationManager.notify(new Event(ObservationConstants.EVENT_PAGE_UPDATED, _getCurrentUser(), eventParams)); 137 } 138 else 139 { 140 throw new ProcessingException("Unable to subscribe or unsubscribe to the page: the page is not subscribable"); 141 } 142 } 143 finally 144 { 145 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, currentWorspace); 146 } 147 148 } 149 150 if (!errors.isEmpty()) 151 { 152 result.put("error", errors); 153 } 154 request.setAttribute(ActionResultGenerator.MAP_REQUEST_ATTR, result); 155 156 return EMPTY_MAP; 157 } 158 159 private Set<String> _getSubscribers (JCRAmetysObject page) 160 { 161 Set<String> subscriberMails = new HashSet<>(); 162 163 try 164 { 165 Node node = page.getNode(); 166 if (node.hasProperty(SUBSCRIBERS_PROPERTY_NAME)) 167 { 168 Value[] values = node.getProperty(SUBSCRIBERS_PROPERTY_NAME).getValues(); 169 for (Value value : values) 170 { 171 subscriberMails.add(value.getString()); 172 } 173 } 174 } 175 catch (RepositoryException e) 176 { 177 getLogger().error("Unable to retrieve subscribers for page of id '" + page.getId() + "'", e); 178 } 179 180 return subscriberMails; 181 } 182 183 private void _setSubscribers (DefaultPage page, Set<String> subscribers) 184 { 185 try 186 { 187 Node node = page.getNode(); 188 189 String[] subscribersAsStringArray = subscribers.toArray(new String[subscribers.size()]); 190 node.setProperty(SUBSCRIBERS_PROPERTY_NAME, subscribersAsStringArray); 191 page.saveChanges(); 192 } 193 catch (RepositoryException e) 194 { 195 getLogger().error("Unable to set subscribers for page of id '" + page.getId() + "'", e); 196 } 197 } 198 199}