/**
* 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.backgroundpreference;
import java.util.Arrays;
import javax.annotation.PostConstruct;
import javax.portlet.ActionRequest;
import javax.portlet.PortletPreferences;
import javax.portlet.PortletRequest;
import javax.servlet.ServletContext;
import org.apache.commons.lang.StringUtils;
import org.apereo.portal.spring.spel.IPortalSpELService;
import org.apereo.portal.spring.spel.PortalSpELServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
/**
* Determines set of images to display by checking to see if user is in a mobile user group as
* determined by the portal's security roles.
*
*/
@Component
public class RoleBasedBackgroundSetSelectionStrategy implements BackgroundSetSelectionStrategy {
private enum PreferenceNames {
DEFAULT("default"),
MOBILE("mobile");
/** <b>Must match</a> the name of the corresponding PAGS group perfectly. */
private static final String MOBILE_DEVICE_ROLE_NAME = "Mobile Device Access";
public static PreferenceNames getInstance(PortletRequest req) {
return req.isUserInRole(MOBILE_DEVICE_ROLE_NAME) ? MOBILE : DEFAULT;
}
private final String prefix;
private PreferenceNames(String prefix) {
this.prefix = prefix;
}
public String getImageSetPreferenceName() {
return prefix + "BackgroundImages";
}
public String getImageThumbnailSetPreferenceName() {
return prefix + "BackgroundThumbnailImages";
}
public String getSelectedBackgroundImagePreferenceName() {
return prefix + "SelectedBackgroundImage";
}
public String getBackgroundContainerSelectorPreferenceName() {
return prefix + "BackgroundContainerSelector";
}
/**
* The portlet-preference containing the image captions. This preference name will not
* change.
*/
public static final String IMAGE_CAPTIONS_PREFERENCE_NAME = "backgroundImageCaptions";
}
private static final String[] EMPTY_STRING_ARRAY = new String[0];
@Autowired private ServletContext servletContext;
@Autowired private IPortalSpELService portalSpELService;
final StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
@PostConstruct
public void init() {
final String contextPath = servletContext.getContextPath();
evaluationContext.setRootObject(new RootObjectImpl(contextPath));
}
@Override
public String[] getImageSet(PortletRequest req) {
final PreferenceNames names = PreferenceNames.getInstance(req);
final PortletPreferences prefs = req.getPreferences();
final String[] images =
prefs.getValues(names.getImageSetPreferenceName(), EMPTY_STRING_ARRAY);
for (int i = 0; i < images.length; i++) {
images[i] = evaluateImagePath(images[i]);
}
return images;
}
@Override
public String[] getImageThumbnailSet(PortletRequest req) {
PreferenceNames names = PreferenceNames.getInstance(req);
PortletPreferences prefs = req.getPreferences();
final String[] images = prefs.getValues(names.getImageThumbnailSetPreferenceName(), null);
for (int i = 0; i < images.length; i++) {
images[i] = evaluateImagePath(images[i]);
}
return images;
}
@Override
public String[] getImageCaptions(PortletRequest req) {
PreferenceNames names = PreferenceNames.getInstance(req);
PortletPreferences prefs = req.getPreferences();
return prefs.getValues(names.IMAGE_CAPTIONS_PREFERENCE_NAME, null);
}
@Override
public String getSelectedImage(PortletRequest req) {
// No evaluation required (already processed)
PreferenceNames names = PreferenceNames.getInstance(req);
PortletPreferences prefs = req.getPreferences();
return prefs.getValue(names.getSelectedBackgroundImagePreferenceName(), null);
}
@Override
public String getBackgroundContainerSelector(PortletRequest req) {
PreferenceNames names = PreferenceNames.getInstance(req);
PortletPreferences prefs = req.getPreferences();
return prefs.getValue(names.getBackgroundContainerSelectorPreferenceName(), null);
}
@Override
public void setSelectedImage(ActionRequest req, String backgroundImage) {
PreferenceNames names = PreferenceNames.getInstance(req);
PortletPreferences prefs = req.getPreferences();
if (StringUtils.isNotBlank(backgroundImage)) {
// We are trying to choose a background; first verify the requested image is actually in the set...
String[] images =
prefs.getValues(names.getImageSetPreferenceName(), EMPTY_STRING_ARRAY);
for (int i = 0; i < images.length; i++) {
images[i] = evaluateImagePath(images[i]);
}
if (Arrays.asList(images).contains(backgroundImage)) {
try {
prefs.setValue(
names.getSelectedBackgroundImagePreferenceName(), backgroundImage);
prefs.store();
} catch (Exception e) {
throw new RuntimeException(
"Failed to store the user's choice of background image", e);
}
}
} else {
// We are trying to clear a previous selection
try {
prefs.reset(names.getSelectedBackgroundImagePreferenceName());
prefs.store();
} catch (Exception e) {
throw new RuntimeException(
"Failed to reset the user's choice of background image", e);
}
}
}
/*
* Implementation
*/
private String evaluateImagePath(String pathBeforeProcessing) {
final Expression x =
portalSpELService.parseExpression(
pathBeforeProcessing, PortalSpELServiceImpl.TemplateParserContext.INSTANCE);
final String rslt = x.getValue(evaluationContext, String.class);
return rslt;
}
/*
* Nested Types
*/
/**
* Allows us to evaluate '${portalContext}' to '/uPortal' (or whatever it is) within image
* paths.
*/
private static final class RootObjectImpl {
private final String portalContext;
public RootObjectImpl(String portalContext) {
this.portalContext = portalContext;
}
@SuppressWarnings("unused")
public String getPortalContext() {
return portalContext;
}
}
}