com.adobe.granite.cloudsettings.CloudSettingsUtil Maven / Gradle / Ivy
Show all versions of aem-sdk-api Show documentation
/*************************************************************************
*
* ADOBE CONFIDENTIAL
* __________________
*
* Copyright 2014 Adobe Systems Incorporated
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Adobe Systems Incorporated and its suppliers,
* if any. The intellectual and technical concepts contained
* herein are proprietary to Adobe Systems Incorporated and its
* suppliers and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
**************************************************************************/
package com.adobe.granite.cloudsettings;
import java.util.Collections;
import java.util.Iterator;
import javax.jcr.RepositoryException;
import javax.jcr.query.Query;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import org.apache.commons.collections.Predicate;
import org.apache.commons.collections.iterators.FilterIterator;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.SyntheticResource;
import org.apache.sling.api.resource.ValueMap;
import com.adobe.granite.security.user.UserProperties;
import com.adobe.granite.security.user.UserPropertiesManager;
import com.adobe.granite.security.user.UserPropertiesService;
/**
* Utility methods utilized in the JSPs to retrieve and process data for displaying the cloudsettings UI
*/
public class CloudSettingsUtil {
/**
* JCR Mixin Type used to collect CloudsettingsConfigType candidates via search
*/
public static final String MIXIN_CLOUDSETTINGS_CONFIG_TYPE = "granite:CloudsettingsConfigType";
/**
* Property on a CloudSettingConfigType Resource to define to define the
* resourceTypes that can be used as child for a CloudSettingsConfig
* with this resourceType (subTypes are allowed as well)
*/
public static final String PROP_ALLOWED_CHILD_TYPES = "allowedChildTypes";
/**
* Property on a CloudSettingConfigType Resource to define to define the
* resourceTypes that a parent must have (subTypes are allowed as well)
* to create a CloudSettingsConfig with this resourceType
*/
public static final String PROP_ALLOWED_PARENT_TYPES = "allowedParentTypes";
/**
* Property on a CloudSettingConfigType Resource to define a unique name
* for the CloudSettingConfig Resource so that no sibling with the same name can be created
*
* Implementing ui has to take care of creating the CloudSettingConfig Resource with this name
*/
public static final String PROP_UNIQUE_NAME = "uniqueName";
/**
* Extract the output for display.
*
* @param resolver the resourceResolver for the lookup of profiles
* @param userId the userId candidate to be processed for displayName detection
* @return detected displayName
*/
public static String getPersonDisplayName(ResourceResolver resolver, String userId) {
String displayName = null;
if (!StringUtils.isEmpty(userId)) {
try {
InternetAddress[] addresses = InternetAddress.parse(userId);
if (addresses.length > 0) {
userId = addresses[0].getAddress();
displayName = addresses[0].getPersonal();
}
} catch (AddressException e) {
// ignore and try to retrieve from repo
}
// Even if we could extract the display name, we have to lookup the
// current display name because it could have changed (e.g. because of a wedding)
try {
UserPropertiesManager upm = resolver.adaptTo(UserPropertiesManager.class);
UserProperties profile = upm.getUserProperties(userId, UserPropertiesService.PROFILE_PATH);
if (profile != null) {
String profileDisplayName = profile.getDisplayName();
if (!StringUtils.isEmpty(profileDisplayName)) {
displayName = profileDisplayName;
}
}
} catch (RepositoryException e) {
// skip and return userId instead
}
}
if (StringUtils.isEmpty(displayName)) {
displayName = userId;
}
return displayName;
}
/**
* Performs a search for all available CloudSettingConfigTypes by mixin Type in
* the system.
*
* @param resolver
* the resolver to be used for CloudSettingConfigType search
* @return Iterator containing all CloudSettingsConfigTypes for the given
* parent
*/
@SuppressWarnings("unchecked")
public static Iterator getAllCloudSettingsConfigTypes(ResourceResolver resolver) {
Iterator searchIt = resolver.findResources("SELECT * FROM [" + MIXIN_CLOUDSETTINGS_CONFIG_TYPE + "]", Query.JCR_SQL2);
return (searchIt == null) ? Collections. emptyList().iterator() : searchIt;
}
/**
* Performs a search for available CloudSettingConfigTypes by mixin Type in
* the system and filters the resulting iterator them with {@link CloudSettingsConfigTypeFilter}
*
* @param resolver the resolver to be used for CloudSettingConfigType search
* @param parentResource the resource under which the returned CloudSettingConfigType are creatable
* @return filtered Iterator containing the valid CloudSettingsConfigTypes for the given parent
*/
@SuppressWarnings("unchecked")
public static Iterator getCloudSettingsConfigTypes(ResourceResolver resolver, Resource parentResource) {
Iterator resultIt = null;
Predicate predicate = new CloudSettingsConfigTypeFilter(parentResource);
Iterator searchIt = resolver.findResources("SELECT * FROM [" + MIXIN_CLOUDSETTINGS_CONFIG_TYPE + "]", Query.JCR_SQL2);
if (searchIt != null && searchIt.hasNext()) {
resultIt = (Iterator) new FilterIterator(searchIt, predicate);
}
return (resultIt == null) ? Collections. emptyList().iterator() : resultIt;
}
/**
* Predicate for a FilterIterator filtering the found resources based on the
* rules for CloudsettingsConfigTypes Evaluation is performed against a
* parentResource so rules defined for parentResource and for the candidate
* are taken into account.
*
*
* Rules for evaluation:
*
* - ConfigTypes must live under /libs or /apps (to prevent injection
* through content) * if a
*
- uniqueName is set for a ConfigType this candidate is invalid if
* parentResource already has a corresponding child
*
- allowParentTypes on the candidate restricts the resourceTypes the
* parentResource can have (respecting superTypeInheritance)
*
- allowChildTypes on the resourceType Resource of the parent defines
* restricts which type the candidate might be (respecting
* superTypeInheritance)
*
*/
private static class CloudSettingsConfigTypeFilter implements Predicate {
private Resource parentResource;
public CloudSettingsConfigTypeFilter(Resource parentResource) {
this.parentResource = parentResource;
}
/*
* (non-Javadoc)
* @see
* org.apache.commons.collections.Predicate#evaluate(java.lang.Object)
*/
public boolean evaluate(Object object) {
if (object instanceof Resource) {
Resource configType = (Resource) object;
/* make sure that node have a parent! */
if (configType.getParent() == null) {
return false;
}
// GRANITE-5179 - performing post filtering of resource path to ensure configs to be defined in libs or apps
if (!configType.getPath().startsWith("/apps") && !configType.getPath().startsWith("/libs")) {
return false;
}
ValueMap configTypeVm = ResourceUtil.getValueMap(configType);
// ensure no configs with unique names can be created if name already exists
String uniqueName = configTypeVm.get(PROP_UNIQUE_NAME, String.class);
if (StringUtils.isNotEmpty(uniqueName) && (parentResource.getChild(uniqueName) != null)) {
return false;
}
// ensure that childTypes with a different allowedParentType get filtered out
ResourceResolver resourceResolver = parentResource.getResourceResolver();
String[] allowedParentTypes = configTypeVm.get(PROP_ALLOWED_PARENT_TYPES, new String[] {});
boolean isParentAllowed = ArrayUtils.isEmpty(allowedParentTypes);
for (String allowedParentType : allowedParentTypes) {
isParentAllowed = resourceResolver.isResourceType(parentResource, allowedParentType);
if (isParentAllowed) {
break;
}
}
// ensure that childTypes not allowed by contentType are filtered out
String parentResType = parentResource.getResourceType();
Resource parentResTypeResource = resourceResolver.getResource(parentResType);
ValueMap parentTypeVm = ResourceUtil.getValueMap(parentResTypeResource);
String[] allowedChildTypes = parentTypeVm.get(PROP_ALLOWED_CHILD_TYPES, new String[] {});
boolean isChildAllowed = ArrayUtils.isEmpty(allowedChildTypes);
for (String allowedChildType : allowedChildTypes) {
Resource configTypeRes = new SyntheticResource(resourceResolver, "testRes", configType.getPath());
isChildAllowed = resourceResolver.isResourceType(configTypeRes, allowedChildType);
if (isChildAllowed) {
break;
}
}
return isParentAllowed && isChildAllowed;
}
return false;
}
}
}