/** * 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.apereo.portal.portlets.jsp; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.portlet.PortletPreferences; import javax.portlet.PortletRequest; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import org.apache.commons.lang.StringUtils; import org.apereo.portal.security.IPerson; import org.apereo.portal.security.IPersonManager; import org.apereo.portal.url.IPortalRequestUtils; import org.apereo.portal.url.IPortalUrlProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.support.PortalPropertySourcesPlaceholderConfigurer; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.portlet.ModelAndView; import org.springframework.web.portlet.bind.annotation.RenderMapping; /** * Provides a very simple, Spring Portlet MVC portlet implementation that renders a JSP at a * location specified in the portlet definition (publish time). This feature is very similar to the * SimpleJspPortlet in the jasig-widget-portlets project, except portlets based on tech (1) are * framework portlets, and (2) may access the native {@link IPortalUrlProvider} API. */ @Controller @RequestMapping("VIEW") public final class JspInvokerPortletController implements ApplicationContextAware { private static final String CONTROLLER_PREFERENCE_PREFIX = JspInvokerPortletController.class.getSimpleName() + "."; private static final String VIEW_LOCATION_PREFERENCE = CONTROLLER_PREFERENCE_PREFIX + "viewLocation"; private static final String BEANS_PREFERENCE = CONTROLLER_PREFERENCE_PREFIX + "beans"; public static final String PREF_SECURITY_ROLE_NAMES = CONTROLLER_PREFERENCE_PREFIX + "securityRolesToTest"; private ApplicationContext applicationContext; private final Logger logger = LoggerFactory.getLogger(getClass()); @Autowired() private PortalPropertySourcesPlaceholderConfigurer properties; @Autowired() private IPortalUrlProvider portalUrlProvider; @Autowired() private IPortalRequestUtils portalRequestUtils; @Autowired private IPersonManager personManager; @Override public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } public void setProperties(PortalPropertySourcesPlaceholderConfigurer props) { this.properties = props; } @RenderMapping protected ModelAndView render(RenderRequest req, RenderResponse res) { final Map<String, Object> model = new HashMap<String, Object>(); @SuppressWarnings("unchecked") final Map<String, String> userInfo = (Map<String, String>) req.getAttribute(PortletRequest.USER_INFO); model.put("userInfo", userInfo); logger.debug("Invoking with userInfo={}", userInfo); // Can access property values in JSP using ${properties.getProperty('propertyName')} model.put("properties", properties.getPropertyResolver()); // Determine if guest user. IPerson person = personManager.getPerson(portalRequestUtils.getPortletHttpRequest(req)); model.put("authenticated", !person.isGuest()); model.putAll(getBeans(req)); model.putAll(getPreferences(req)); addSecurityRoleChecksToModel(req, model); final String viewLocation = getViewLocation(req); return new ModelAndView(viewLocation, model); } private Map<String, Object> getBeans(PortletRequest req) { Map<String, Object> rslt = new HashMap<String, Object>(); // default PortletPreferences prefs = req.getPreferences(); String[] beanNames = prefs.getValues(BEANS_PREFERENCE, new String[] {}); for (String name : beanNames) { Object bean = applicationContext.getBean(name); rslt.put(name, bean); } logger.debug("Invoking with beans={}", (Object[]) beanNames); return rslt; } private Map<String, List<String>> getPreferences(PortletRequest req) { Map<String, List<String>> rslt = new HashMap<String, List<String>>(); // default PortletPreferences prefs = req.getPreferences(); List<String> names = Collections.list(prefs.getNames()); for (String name : names) { if (!name.startsWith(CONTROLLER_PREFERENCE_PREFIX)) { // Pass it along in the model List<String> values = Arrays.asList(prefs.getValues(name, new String[] {})); rslt.put(name, values); } } logger.debug("Invoking with preferences={}", rslt); return rslt; } private String getViewLocation(PortletRequest req) { String rslt; PortletPreferences prefs = req.getPreferences(); String preferenceViewLocation = prefs.getValue(VIEW_LOCATION_PREFERENCE, null); if (StringUtils.isNotBlank(preferenceViewLocation)) { rslt = preferenceViewLocation; } else { throw new RuntimeException( "Portlet preference '" + VIEW_LOCATION_PREFERENCE + "' not set"); } logger.debug("Invoking with viewLocation={}", rslt); return rslt; } /** * Run through the list of configured security roles and add an "is"+Rolename to the model. The * security roles must also be defined with a <code><security-role-ref></code> element in * the portlet.xml. * * @param req Portlet request * @param model Model object to add security indicators to */ private void addSecurityRoleChecksToModel(PortletRequest req, Map<String, Object> model) { PortletPreferences prefs = req.getPreferences(); String[] securityRoles = prefs.getValues(PREF_SECURITY_ROLE_NAMES, new String[] {}); for (int i = 0; i < securityRoles.length; i++) { model.put( "is" + securityRoles[i].replace(" ", "_"), req.isUserInRole(securityRoles[i])); } } }