/** * Licensed to Apereo under one or more contributor license agreements. See the NOTICE file * distributed with this work for additional information regarding copyright ownership. Apereo * licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use * this file except in compliance with the License. You may obtain a copy of the License at the * following location: * * <p>http://www.apache.org/licenses/LICENSE-2.0 * * <p>Unless required by applicable law or agreed to in writing, software distributed under the * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ package org.jasig.portlet.emailpreview.controller; import java.util.HashMap; import java.util.Map; import javax.annotation.Resource; import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import javax.portlet.PortletMode; import javax.portlet.PortletPreferences; import javax.portlet.PortletRequest; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import javax.portlet.WindowState; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jasig.portlet.emailpreview.MailStoreConfiguration; import org.jasig.portlet.emailpreview.dao.MailPreferences; import org.jasig.portlet.emailpreview.service.auth.IAuthenticationService; import org.jasig.portlet.emailpreview.service.auth.IAuthenticationServiceRegistry; import org.jasig.portlet.emailpreview.service.link.IEmailLinkService; import org.jasig.portlet.emailpreview.service.link.ILinkServiceRegistry; import org.jasig.portlet.emailpreview.util.EmailAccountUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.portlet.ModelAndView; /** * @author Jen Bourey, jbourey@unicon.net * @author Drew Wills, drew@unicon.net */ @Controller @RequestMapping("VIEW") public class EmailSummaryController extends BaseEmailController { public static final String WELCOME_TITLE_PREFERENCE = "welcomeTitle"; public static final String WELCOME_INSTRUCTIONS_PREFERENCE = "welcomeInstructions"; public static final String DEFAULT_VIEW_PREFERENCE = "defaultView"; public static final String PAGE_SIZE_PREFERENCE = "pageSize"; public static final String ALLOW_DELETE_PREFERENCE = "allowDelete"; public static final String SUPPORTS_TOGGLE_SEEN_KEY = "supportsToggleSeen"; private static final String SHOW_CONFIG_LINK_KEY = "showConfigLink"; private static final String DEFAULT_WELCOME_TITLE = "Welcome to Email Preview"; private static final String DEFAULT_WELCOME_INSTRUCTIONS = ""; private static final String MSG_CONTAINER = "messagesInfoContainer"; private final Log log = LogFactory.getLog(this.getClass()); private String adminRoleName = "admin"; @Autowired(required = true) private IAuthenticationServiceRegistry authServiceRegistry; @Autowired(required = true) private ILinkServiceRegistry linkServiceRegistry; @Resource private Map<String, String> jsErrorMessages; @Resource private Map<String, String> jsMessages; @Resource protected ViewSelectorDefault viewSelector; /** Three possible views for this controller. */ public enum View { /** Indicates the portlet is not yet (completely) configured */ WELCOME("welcome") { @Override public ModelAndView show( RenderRequest req, RenderResponse res, EmailSummaryController controller) { PortletPreferences prefs = req.getPreferences(); Map<String, Object> model = new HashMap<String, Object>(); model.put( WELCOME_TITLE_PREFERENCE, prefs.getValue(WELCOME_TITLE_PREFERENCE, DEFAULT_WELCOME_TITLE)); model.put( WELCOME_INSTRUCTIONS_PREFERENCE, prefs.getValue(WELCOME_INSTRUCTIONS_PREFERENCE, DEFAULT_WELCOME_INSTRUCTIONS)); return new ModelAndView(getKey(), model); } }, /** Indicates the portlet is not yet (completely) configured */ ROLLUP("rollup") { @Override public ModelAndView show( RenderRequest req, RenderResponse res, EmailSummaryController controller) { Map<String, Object> model = new HashMap<String, Object>(); MailStoreConfiguration config = controller.serviceBroker.getConfiguration(req); IAuthenticationService authService = controller.authServiceRegistry.getAuthenticationService( config.getAuthenticationServiceKey()); String emailAddress = EmailAccountUtils.determineUserEmailAddress(req, config, authService); model.put("emailAddress", emailAddress); return new ModelAndView(getKey(), model); } }, /** Tabular view of the INBOX with lots of features */ PREVIEW("preview") { @Override public ModelAndView show( RenderRequest req, RenderResponse res, EmailSummaryController controller) { Map<String, Object> model = new HashMap<String, Object>(); PortletPreferences prefs = req.getPreferences(); // PageSize: this value can be set by administrators as a publish-time // portlet preference, and (normally) overridden by users as a // user-defined portlet preference. int pageSize = Integer.parseInt(prefs.getValue(PAGE_SIZE_PREFERENCE, "10")); // James W - Removed option for 50 because it has some issues with behavior needing addressing. See EMAILPLT-119 pageSize = pageSize == 50 ? 20 : pageSize; model.put(PAGE_SIZE_PREFERENCE, pageSize); // Check to see if the portlet is configured to display a link // to config mode and if it applies to this user boolean showConfigLink = Boolean.valueOf(prefs.getValue(SHOW_CONFIG_LINK_KEY, "false")); if (showConfigLink) { showConfigLink = req.isUserInRole(controller.adminRoleName); } model.put("showConfigLink", showConfigLink); // Also see if the portlet is configured // to permit users to delete messages boolean allowDelete = Boolean.valueOf(prefs.getValue(ALLOW_DELETE_PREFERENCE, "false")); model.put("allowDelete", allowDelete); MailStoreConfiguration config = controller.serviceBroker.getConfiguration(req); model.put("markMessagesAsRead", config.getMarkMessagesAsRead()); // Check if this mail server supports setting the READ/UNREAD flag model.put(SUPPORTS_TOGGLE_SEEN_KEY, config.supportsToggleSeen()); //Display message in a table model.put(MSG_CONTAINER, "table"); model.put( MailPreferences.ALLOW_RENDERING_EMAIL_CONTENT.getKey(), config.getAllowRenderingEmailContent()); return new ModelAndView(getKey(), model); } }, /** Mobile view of the INBOX with lots of features */ MOBILEPREVIEW("mobilePreview") { @Override public ModelAndView show( RenderRequest req, RenderResponse res, EmailSummaryController controller) { Map<String, Object> model = new HashMap<String, Object>(); PortletPreferences prefs = req.getPreferences(); // PageSize: this value can be set by administrators as a publish-time // portlet preference, and (normally) overridden by users as a // user-defined portlet preference. int pageSize = Integer.parseInt(prefs.getValue(PAGE_SIZE_PREFERENCE, "10")); model.put(PAGE_SIZE_PREFERENCE, pageSize); // Check to see if the portlet is configured to display a link // to config mode and if it applies to this user boolean showConfigLink = Boolean.valueOf(prefs.getValue(SHOW_CONFIG_LINK_KEY, "false")); if (showConfigLink) { showConfigLink = req.isUserInRole(controller.adminRoleName); } model.put("showConfigLink", showConfigLink); // Also see if the portlet is configured // to permit users to delete messages boolean allowDelete = Boolean.valueOf(prefs.getValue(ALLOW_DELETE_PREFERENCE, "false")); model.put("allowDelete", allowDelete); MailStoreConfiguration config = controller.serviceBroker.getConfiguration(req); model.put("markMessagesAsRead", config.getMarkMessagesAsRead()); // Check if this mail server supports setting the READ/UNREAD flag model.put(SUPPORTS_TOGGLE_SEEN_KEY, config.supportsToggleSeen()); //Display message in a div model.put(MSG_CONTAINER, "div.message_infos"); model.put( MailPreferences.ALLOW_RENDERING_EMAIL_CONTENT.getKey(), config.getAllowRenderingEmailContent()); return new ModelAndView(getKey(), model); } }; private final String key; public static View getInstance(String key) { for (View v : View.values()) { if (v.getKey().equals(key)) { return v; } } throw new RuntimeException("Unrecognized view: " + key); } private View(String key) { this.key = key; } public String getKey() { return key; } public abstract ModelAndView show( RenderRequest req, RenderResponse res, EmailSummaryController controller); } public void setAdminRoleName(String adminRoleName) { this.adminRoleName = adminRoleName; } /* * Action Phase */ @RequestMapping(params = "action=showRollup") public void switchToRollup(ActionRequest req, ActionResponse res) { PortletPreferences prefs = req.getPreferences(); try { prefs.setValue(EmailSummaryController.DEFAULT_VIEW_PREFERENCE, View.ROLLUP.getKey()); prefs.store(); } catch (Throwable t) { log.error( "Failed to update " + DEFAULT_VIEW_PREFERENCE + " for user " + req.getRemoteUser(), t); throw new RuntimeException(t); } } @RequestMapping(params = "action=showPreview") public void switchToPreview(ActionRequest req, ActionResponse res) { PortletPreferences prefs = req.getPreferences(); try { prefs.setValue(EmailSummaryController.DEFAULT_VIEW_PREFERENCE, View.PREVIEW.getKey()); prefs.store(); } catch (Throwable t) { log.error( "Failed to update " + DEFAULT_VIEW_PREFERENCE + " for user " + req.getRemoteUser(), t); throw new RuntimeException(t); } } /* * Render Phase */ @RequestMapping public ModelAndView chooseView(RenderRequest req, RenderResponse res) throws Exception { View showView = null; final MailStoreConfiguration config = serviceBroker.getConfiguration(req); final IAuthenticationService authService = authServiceRegistry.getAuthenticationService(config.getAuthenticationServiceKey()); if (authService == null || !authService.isConfigured(req, config)) { // Rule #1: If we're not configured for authentication, // show the 'welcome' view so the user knows what to do log.debug("Authentication service is not configured. Review the portlet configuration."); showView = View.WELCOME; } else if (req.getWindowState().equals(WindowState.MAXIMIZED)) { // Rule #2: We don't show the rollup in MAXIMIZED state showView = viewSelector.getEmailPreviewViewName(req); } else { // Rule #3: Use the defaultView preference; this setting gets updated // every time the user changes from one to the other (it's sticky) PortletPreferences prefs = req.getPreferences(); String viewName = prefs.getValue(DEFAULT_VIEW_PREFERENCE, View.ROLLUP.getKey()); showView = View.getInstance(viewName); } // Now render the choice... ModelAndView rslt = showView.show(req, res, this); // Add common model stuff... rslt.getModel().put("jsErrorMessages", jsErrorMessages); rslt.getModel().put("jsMessages", jsMessages); rslt.getModel().put("supportsEdit", req.isPortletModeAllowed(PortletMode.EDIT)); rslt.getModel().put("supportsHelp", req.isPortletModeAllowed(PortletMode.HELP)); return rslt; } /* * Other stuff */ @ModelAttribute("inboxUrl") public String getInboxUrl(PortletRequest req) { String rslt = null; // default final MailStoreConfiguration config = serviceBroker.getConfiguration(req); final IEmailLinkService linkService = linkServiceRegistry.getEmailLinkService(config.getLinkServiceKey()); if (linkService != null) { rslt = linkService.getInboxUrl(config); } return rslt; } }