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.plugins.repository.AmetysObjectResolver; 044import org.ametys.plugins.repository.RepositoryConstants; 045import org.ametys.plugins.repository.jcr.JCRAmetysObject; 046import org.ametys.plugins.repository.provider.RequestAttributeWorkspaceSelector; 047import org.ametys.runtime.i18n.I18nizableText; 048import org.ametys.web.ObservationConstants; 049import org.ametys.web.repository.page.Page; 050import org.ametys.web.repository.page.jcr.DefaultPage; 051 052/** 053 * Action to subscribe to a page 054 */ 055public class PageSubscribeAction extends AbstractNotifierAction 056{ 057 /** Constant for the attachment node name. */ 058 public static final String SUBSCRIBERS_PROPERTY_NAME = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":subscriberMails"; 059 060 /** The pattern to check emails */ 061 protected static final Pattern EMAIL_VALIDATOR = Pattern.compile("^([a-z0-9._-]+@[a-z0-9.-]{2,}[.][a-zA-Z0-9]{2,})?$"); 062 063 /** The pattern to check text input */ 064 protected static final Pattern TEXT_VALIDATOR = Pattern.compile("^\\s*$"); 065 066 /** The ametys resolver */ 067 protected AmetysObjectResolver _resolver; 068 069 @Override 070 public void service(ServiceManager smanager) throws ServiceException 071 { 072 super.service(smanager); 073 _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE); 074 } 075 076 public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception 077 { 078 Map<String, Object> result = new HashMap<>(); 079 List<I18nizableText> errors = new ArrayList<>(); 080 081 Request request = ObjectModelHelper.getRequest(objectModel); 082 String action = request.getParameter("page-subscribe-action"); 083 result.put("action", action); 084 085 String email = request.getParameter("email"); 086 087 if (email == null || !EMAIL_VALIDATOR.matcher(StringUtils.trimToEmpty(email.toLowerCase())).matches() || TEXT_VALIDATOR.matcher(StringUtils.trimToEmpty(email)).matches()) 088 { 089 errors.add(new I18nizableText("plugin.page-subscription", "PLUGINS_PAGE_SUBSCRIBE_FORM_MAIL_ERROR_MAILBY")); 090 } 091 else 092 { 093 result.put("email", email); 094 } 095 096 String pageId = request.getParameter("page-id"); 097 if (pageId == null) 098 { 099 throw new IllegalArgumentException("Unable to subscribe or unsubscribe to the page: cannot determine the current page"); 100 } 101 else 102 { 103 // Force default workspace 104 String currentWorspace = RequestAttributeWorkspaceSelector.getForcedWorkspace(request); 105 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, "default"); 106 107 try 108 { 109 Page page = _resolver.resolveById(pageId); 110 111 if (page == null) 112 { 113 throw new IllegalArgumentException("Unable to subscribe or unsubscribe to the page: the page of id " + pageId + " is unknown"); 114 } 115 116 if (page instanceof JCRAmetysObject) 117 { 118 Set<String> subscribers = _getSubscribers((JCRAmetysObject) page); 119 120 if (action.equals("subscribe")) 121 { 122 subscribers.add(email); 123 } 124 else if (action.equals("unsubscribe")) 125 { 126 subscribers.remove(email); 127 } 128 129 _setSubscribers((DefaultPage) page, subscribers); 130 131 // Notify observers that page data has been changed. 132 Map<String, Object> eventParams = new HashMap<>(); 133 eventParams.put(ObservationConstants.ARGS_PAGE, page); 134 eventParams.put(ObservationConstants.ARGS_PAGE_ID, page.getId()); 135 _observationManager.notify(new Event(ObservationConstants.EVENT_PAGE_UPDATED, _getCurrentUser(), eventParams)); 136 } 137 else 138 { 139 throw new ProcessingException("Unable to subscribe or unsubscribe to the page: the page is not subscribable"); 140 } 141 } 142 finally 143 { 144 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, currentWorspace); 145 } 146 147 } 148 149 if (!errors.isEmpty()) 150 { 151 result.put("error", errors); 152 } 153 request.setAttribute(ActionResultGenerator.MAP_REQUEST_ATTR, result); 154 155 return EMPTY_MAP; 156 } 157 158 private Set<String> _getSubscribers (JCRAmetysObject page) 159 { 160 Set<String> subscriberMails = new HashSet<>(); 161 162 try 163 { 164 Node node = page.getNode(); 165 if (node.hasProperty(SUBSCRIBERS_PROPERTY_NAME)) 166 { 167 Value[] values = node.getProperty(SUBSCRIBERS_PROPERTY_NAME).getValues(); 168 for (Value value : values) 169 { 170 subscriberMails.add(value.getString()); 171 } 172 } 173 } 174 catch (RepositoryException e) 175 { 176 getLogger().error("Unable to retrieve subscribers for page of id '" + page.getId() + "'", e); 177 } 178 179 return subscriberMails; 180 } 181 182 private void _setSubscribers (DefaultPage page, Set<String> subscribers) 183 { 184 try 185 { 186 Node node = page.getNode(); 187 188 String[] subscribersAsStringArray = subscribers.toArray(new String[subscribers.size()]); 189 node.setProperty(SUBSCRIBERS_PROPERTY_NAME, subscribersAsStringArray); 190 page.saveChanges(); 191 } 192 catch (RepositoryException e) 193 { 194 getLogger().error("Unable to set subscribers for page of id '" + page.getId() + "'", e); 195 } 196 } 197 198}