Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.adobe.cq.social.group.client.endpoints.AbstractCommunityGroupOperationService Maven / Gradle / Ivy
/*************************************************************************
*
* ADOBE CONFIDENTIAL
* __________________
*
* Copyright 2013 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.cq.social.group.client.endpoints;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.activation.DataSource;
import javax.annotation.Nullable;
import javax.jcr.Binary;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.servlet.http.HttpServletResponse;
import com.adobe.cq.social.commons.FunctionValidationUtil;
import com.adobe.cq.social.commons.exception.FunctionValidationException;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.ReferencePolicy;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.request.RequestParameter;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.ModifiableValueMap;
import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.wrappers.ValueMapDecorator;
import org.apache.sling.commons.json.JSONArray;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.apache.sling.commons.osgi.OsgiUtil;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.jcr.resource.JcrResourceConstants;
import org.apache.sling.settings.SlingSettingsService;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.adobe.cq.social.blueprint.api.SiteActivationService;
import com.adobe.cq.social.blueprint.api.SiteBlueprintConstants;
import com.adobe.cq.social.blueprint.api.TemplateRolloutService;
import com.adobe.cq.social.commons.CollabUtil;
import com.adobe.cq.social.commons.CommentSystem;
import com.adobe.cq.social.community.api.CommunityConstants;
import com.adobe.cq.social.community.api.CommunityContext;
import com.adobe.cq.social.community.api.CommunityUserGroup;
import com.adobe.cq.social.communityfunctions.api.CommunityFunction;
import com.adobe.cq.social.console.utils.api.FunctionDefinitionUtils;
import com.adobe.cq.social.console.utils.api.internal.PropertiesUtils;
import com.adobe.cq.social.group.api.GroupConstants;
import com.adobe.cq.social.group.api.GroupException;
import com.adobe.cq.social.group.api.GroupService;
import com.adobe.cq.social.group.api.GroupUtil;
import com.adobe.cq.social.group.bundleactivator.impl.Activator;
import com.adobe.cq.social.group.client.api.CommunityGroup;
import com.adobe.cq.social.group.client.api.CommunityGroupCollection;
import com.adobe.cq.social.group.client.api.CommunityGroupConstants;
import com.adobe.cq.social.group.client.api.CommunityGroupFolder;
import com.adobe.cq.social.group.client.api.CommunityGroupService;
import com.adobe.cq.social.scf.ClientUtilities;
import com.adobe.cq.social.scf.Operation;
import com.adobe.cq.social.scf.OperationException;
import com.adobe.cq.social.scf.SocialComponent;
import com.adobe.cq.social.scf.SocialComponentFactory;
import com.adobe.cq.social.scf.SocialComponentFactoryManager;
import com.adobe.cq.social.serviceusers.internal.ServiceUserWrapper;
import com.adobe.cq.social.site.api.CommunitySiteConstants;
import com.adobe.cq.social.site.api.CommunitySiteService;
import com.adobe.cq.social.site.endpoints.AbstractPublishOperationService;
import com.adobe.cq.social.site.endpoints.SiteOperationUtils;
import com.adobe.cq.social.ugcbase.AsyncReverseReplicator;
import com.adobe.cq.social.ugcbase.SocialUtils;
import com.day.cq.commons.LanguageUtil;
import com.adobe.granite.confmgr.Conf;
import com.day.cq.commons.jcr.JcrUtil;
import com.day.cq.replication.ReplicationActionType;
import com.day.cq.wcm.api.NameConstants;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import com.day.cq.wcm.api.WCMException;
import com.day.text.Text;
/**
* Provides abstract implementation of community group operations. This class can be extended to implement create
* operations for any component that extends the community group.
* @param is a {@link CommunityGroupOperationExtension} that will be used as hooks by the extending class.
* @param is a {@link Operation} that is being provided by the extending class.
*/
@Component(metatype = false, componentAbstract = true)
public abstract class AbstractCommunityGroupOperationService
extends AbstractPublishOperationService implements CommunityGroupOperations {
private static final String MSM_SERVICE = "msm-service";
private static final Logger LOG = LoggerFactory.getLogger(AbstractCommunityGroupOperationService.class);
private static final String PROPERTY_IMAGE_NAME = "image";
private static final String PROPERTY_BANNER_IMAGE_NAME = "pagebanner";
private static final int PARAM_NAME_INDEX = 0;
private static final int PARAM_CLASS_INDEX = 1;
private static final int PARAM_REQUIRED_INDEX = 2;
private static final Object requestParams[][] =
{{CommunityGroupConstants.PROP_COMMUNITY_GROUP_DESCRIPTION, String.class, Boolean.FALSE},
{CommunityGroupConstants.PROP_COMMUNITY_GROUP_NAME, String.class, Boolean.TRUE},
{CommunityGroupConstants.PROP_COMMUNITY_GROUP_TITLE, String.class, Boolean.FALSE},
{CommunityGroupConstants.PROP_COMMUNITY_GROUP_TYPE, String.class, Boolean.FALSE},
{CommunityGroupConstants.PROP_COMMUNITY_GROUP_INVITE, String[].class, Boolean.FALSE},
{CommunityGroupConstants.PROP_COMMUNITY_GROUP_INCLUDE_SITE_MODERATORS, Boolean.class, Boolean.FALSE},
{CommunityGroupConstants.PROP_COMMUNITY_GROUP_MODERATOR, String[].class, Boolean.FALSE},
{CommunityGroupConstants.PROP_COMMUNITY_GROUP_ADMINS, String[].class, Boolean.FALSE},
{CommunityGroupConstants.PROP_COMMUNITY_INITIALLANGUAGES, String[].class, Boolean.FALSE},
{CommunityGroupConstants.PROP_COMMUNITY_COMPLETE_TABLE_DATA, String[].class, Boolean.FALSE},
{CommunitySiteConstants.PROP_FUNCTIONS, String.class, Boolean.FALSE},
{CommunitySiteConstants.PROP_THEME_ID, String.class, Boolean.FALSE},
{CommunityGroupConstants.PROP_COMMUNITY_GROUP_BLUEPRINT_ID, String.class, Boolean.TRUE}};
private static final String specialParams[] =
{CommunityGroupConstants.PROP_COMMUNITY_GROUP_FILE, CommunityGroupConstants.REQUEST_ATTACHMENT_PAGEBANNER};
// list of parameters that are excluded from update
private static final String unchangeableParams[] = {CommunityGroupConstants.PROP_COMMUNITY_GROUP_NAME,
CommunityGroupConstants.PROP_COMMUNITY_GROUP_FILE, CommunityGroupConstants.REQUEST_ATTACHMENT_PAGEBANNER};
private static final int ATTACHMENT_FILE_LIMIT = Integer.MAX_VALUE;
private static final List WHITE_LIST = new ArrayList();
private static final String[] BLACK_LIST = new String[0];
private static final String USER_ADMIN = "communities-user-admin";
// Reuse old paths for back comp
private static final String DEFAULT_GROUP_ROOTTEMPLATE_ROOT = "/etc/community/templates/groups";
private static final String DEFAULT_GROUP_TEMPLATE_ROOT =
DEFAULT_GROUP_ROOTTEMPLATE_ROOT + CommunityConstants.REFERENCE_SUBPATH;
private static final String CUSTOM_GROUP_TEMPLATE_ROOT =
DEFAULT_GROUP_ROOTTEMPLATE_ROOT + CommunityConstants.CUSTOM_SUBPATH;
private static final String DEFAULT_GROUP_ROOTTEMPLATE_RELATIVIEPATH_ROOT = "community/templates/groups";
private static final String CUSTOM_GROUP_TEMPLATE_ROOT_CONF =
"/conf/global/settings/" + DEFAULT_GROUP_ROOTTEMPLATE_RELATIVIEPATH_ROOT;
private static final String CUSTOM_GROUP_TEMPLATE_ROOT_LIBS =
"/libs/settings/" + DEFAULT_GROUP_ROOTTEMPLATE_RELATIVIEPATH_ROOT;
private static final String PATH = "path";
private static final String NAME = "name";
private static final String NODE_PROPERTY_COMMENTATTACHMENT = "cq:CommentAttachment";
protected ClientUtilities clientUtils;
/**
* The name of the property that holds a white list of form field names added as additional properties to the
* comment.
*/
public static final String PROPERTY_FIELD_WHITELIST = "fieldWhitelist";
// delimiters to split the invited id list
private final String delimiters = "[\\s,;]";
/** Social Component Factory Manager. */
@Reference
private SocialComponentFactoryManager componentFactoryManager;
@Reference
private AsyncReverseReplicator replicator;
@Reference
private GroupService groupService;
@Reference
private CommunityGroupService communityGroupService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY, policy = ReferencePolicy.STATIC)
private SlingRepository repository;
@Reference
private ServiceUserWrapper serviceUserWrapper;
@Reference
private ResourceResolverFactory resourceResolverFactory;
@Reference
protected SlingSettingsService settingsService;
@Reference
CommunitySiteService siteService;
@Reference
SiteActivationService activationService;
@Reference
private SocialUtils socialUtils;
@Reference
private FunctionDefinitionUtils funcDefUtils;
@Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY, policy = ReferencePolicy.DYNAMIC)
private TemplateRolloutService siteBlueprintService;
/**
* White list field.
*/
protected String[] fieldWhitelist;
private void cleanupFailure(final Session session) {
try {
if (LOG.isDebugEnabled()) {
LOG.debug("Failure cleanup invoked.", new Throwable());
}
session.refresh(false);
} catch (final RepositoryException e) {
LOG.info("Failed to refresh the session", e);
}
}
@Override
protected ResourceResolverFactory getBundleLocalResourceResolverFactory() {
if (resourceResolverFactory == null) {
resourceResolverFactory = Activator.getService(ResourceResolverFactory.class);
}
return resourceResolverFactory;
}
@Override
protected ServiceUserWrapper getServiceUserWrapper() {
if (serviceUserWrapper == null) {
serviceUserWrapper = Activator.getService(ServiceUserWrapper.class);
}
return serviceUserWrapper;
}
@Override
public Resource create(final SlingHttpServletRequest request) throws OperationException {
final Resource resource = request.getResource();
final ResourceResolver resolver = resource.getResourceResolver();
final Session session = resource.getResourceResolver().adaptTo(Session.class);
// Validate group root
boolean validPath = false;
CommunityGroupCollection groupCollection = null;
ArrayList returnresourceList = new ArrayList();
// post to groupcollection node
if (resource.isResourceType(CommunityGroupCollection.RESOURCE_TYPE)) {
validPath = true;
groupCollection = getCommunityGroupCollectionForResource(resource, request);
} else {
final PageManager pm = resolver.adaptTo(PageManager.class);
final Page page = pm.getPage(resource.getPath());
if (page != null) {
// post to a group collection page
Resource r =
resolver.getResource(resource.getPath() + "/" + CommunityGroupFolder.FOLDER_CONFIG_NODE_NAME);
if (r != null) {
validPath = true;
groupCollection = getCommunityGroupCollectionForResource(resource, request);
} else {
// post to a site page or a group page, currently we don't support this case
r = resolver.getResource(resource.getPath() + "/" + CommunityGroupConstants.CONFIG_NODE_NAME);
if (r != null) {
validPath = true;
}
}
}
}
if (!validPath) {
throw new OperationException("Invalid Group Path:" + resource.getPath(),
HttpServletResponse.SC_BAD_REQUEST);
}
if (groupCollection != null && !groupCollection.isCanAdd()) {
throw new OperationException("No permission to create a community group.",
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
if (!this.isPublishMode() && !siteService.mayPost(request, session)) {
throw new OperationException("Access violation.", HttpServletResponse.SC_FORBIDDEN);
}
// Get the other definition/configuration properties of the site
final Map props = new HashMap();
try {
getDefaultProperties(request, props, true);
getCustomProperties(request, props, session);
} catch (final RepositoryException e) {
throw new OperationException("Failed to obtain community group parameters.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
final U createOperation = getCreateOperation();
getExtensionParameters(createOperation, request, props);
// add creator to the invite list
String invites = (String) props.get(CommunityGroupConstants.PROP_COMMUNITY_GROUP_INVITE);
props.put(CommunityGroupConstants.PROP_COMMUNITY_GROUP_INVITE, invites);
props.put(CommunityGroupConstants.PROP_COMMUNITY_GROUP_CREATOR, session.getUserID());
// Get the name of the new group
String name = null;
name = (String) props.get(CommunityGroupConstants.PROP_COMMUNITY_GROUP_NAME);
final PageManager pm = resolver.adaptTo(PageManager.class);
final Page groupPage = pm.getContainingPage(resource);
String root = groupPage.getPath();
Resource groupPageResource = resolver.getResource(root);
Resource firstGroupPageResource = groupPageResource;
if (!GroupUtil.validateGroupName(resolver, name, root)) {
throw new OperationException("Community group name is badly formatted " + name,
HttpServletResponse.SC_BAD_REQUEST);
}
// get the attachment images
final List attachments =
getAttachmentsFromRequest(request, CommunityGroupConstants.PROP_COMMUNITY_GROUP_FILE);
// get the banner images
final List banner =
getAttachmentsFromRequest(request, CommunityGroupConstants.REQUEST_ATTACHMENT_PAGEBANNER);
// get the css file
final List cssFiles =
getAttachmentsFromRequest(request, CommunitySiteConstants.REQUEST_ATTACHMENT_PAGECSS);
// create the community group
// need to open a userAdminSession, since we allow every login user to create groups
ResourceResolver userAdminResolver = null;
try {
userAdminResolver =
getServiceUserWrapper().getServiceResourceResolver(getBundleLocalResourceResolverFactory(),
Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, (Object) USER_ADMIN));
returnresourceList.add(create(groupPageResource, name, props, attachments, banner, cssFiles,
userAdminResolver.adaptTo(Session.class)));
if (this.isPublishMode()) { // we don't need to create locale based groups on publish
return groupPageResource;
}
String initialLanguage = (String) props.get(CommunityGroupConstants.PROP_COMMUNITY_INITIALLANGUAGES);
if(initialLanguage != null){
String[] initialLangLen = initialLanguage.split(",");
String pathmk = null;
LanguageUtil languageCode = new LanguageUtil();
int i = 0;
for (i = 0; i < initialLangLen.length; i++) {
String languageCodePath = languageCode.getLanguageRoot(root);
int codelanPath = languageCodePath.length();
int rootlanPath = root.length();
pathmk = root.substring(codelanPath, rootlanPath);
String currentLanguage = initialLangLen[i];
String relativeparent = Text.getRelativeParent(languageCodePath, 1);
root = relativeparent.concat("/" + currentLanguage + pathmk);
groupPageResource = resolver.getResource(root);
// check if a group with the given name already exists for multi language group creation process
final Page group = pm.getPage(root + "/" + name);
if (group != null) {
LOG.info("Group {} already exists in {}", name, root);
continue;
}
if (!GroupUtil.validateGroupName(resolver, name, root)) {
throw new OperationException("Community group name is badly formatted " + name,
HttpServletResponse.SC_BAD_REQUEST);
}
if(groupPageResource!=null){
userAdminResolver =
getServiceUserWrapper().getServiceResourceResolver(getBundleLocalResourceResolverFactory(),
Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, (Object) USER_ADMIN));
returnresourceList.add(create(groupPageResource, name, props, attachments, banner, cssFiles,
userAdminResolver.adaptTo(Session.class)));
userAdminResolver.close();
}
}
}
return firstGroupPageResource;
} catch (final LoginException e) {
cleanupFailure(session);
throw new OperationException("Failed to join community group.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} finally {
if (userAdminResolver != null && userAdminResolver.isLive()) {
userAdminResolver.close();
}
}
}
// TODO : create a hash map from next time
protected Resource create(final Resource root, final String name, final Map properties,
final List attachments, final Session session) throws OperationException {
return create(root, name, properties, attachments, Collections.emptyList(),
Collections.emptyList(), session);
}
protected Resource create(final Resource root, final String name, final Map properties,
final List attachments, final List banner, final Session session)
throws OperationException {
return create(root, name, properties, attachments, banner, Collections.emptyList(), session);
}
protected Resource create(final Resource root, final String name, final Map properties,
final List attachments, final List banner, final List cssFiles,
final Session session) throws OperationException {
try {
final Map authInfo = new HashMap();
authInfo.put(JcrResourceConstants.AUTHENTICATION_INFO_SESSION, session);
final ResourceResolver resolver = resourceResolverFactory.getResourceResolver(authInfo);
final U createOperation = getCreateOperation();
performBeforeActions(createOperation, session, root, properties);
final String groupPath = root.getPath() + "/" + name;
final CommunityContext context = root.adaptTo(CommunityContext.class);
String nuggetRoot = context != null ? context.getSitePayloadPath() : "/var/community/publish";
nuggetRoot = StringUtils.replace(nuggetRoot, CommunityGroupConstants.ROOT_FOR_PUBLISH_COMMUNITY_NUGGETS,
CommunityGroupConstants.ROOT_FOR_CREATE_COMMUNITY_NUGGETS);
final String nuggetPath = nuggetRoot + groupPath;
final Node folder = JcrUtil.createPath(nuggetPath, "sling:Folder", session);
final Node nugget =
folder.addNode(SiteActivationService.REPLICATE_NODE_NAME, SiteActivationService.REPLICATE_NODE_TYPE);
nugget.setProperty(SiteActivationService.REPLICATE_PROPERTY_PATH, root.getPath());
nugget.setProperty(SiteActivationService.REPLICATE_PROPERTY_ACTION,
CommunityGroupConstants.ACTION_TYPE_CREATE_COMMUNITY_GROUP);
nugget.setProperty(GroupConstants.PROPERTY_FORM_PAYLOAD, nuggetPath);
for (final Entry property : properties.entrySet()) {
final String key = property.getKey();
if (!isSpecialRequestParam(key)) {
JcrUtil.setProperty(nugget, key, property.getValue());
}
}
// add image node if one has been uploaded
if (attachments != null && !attachments.isEmpty()) {
final DataSource ds = attachments.get(0);
addImage(nuggetPath, resolver, ds.getInputStream(), ds.getContentType(), PROPERTY_IMAGE_NAME,
ds.getName());
} else {
// add default image if no image has been uploaded
ResourceResolver serviceResolver = null;
try {
serviceResolver =
getServiceUserWrapper().getServiceResourceResolver(getBundleLocalResourceResolverFactory(),
Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, (Object) MSM_SERVICE));
} catch (final LoginException e) {
LOG.error("Unable to add default group image", e);
}
if (serviceResolver != null) {
final Resource image =
serviceResolver.getResource(CommunityGroupConstants.DEFAULT_STREAMABLE_IMAGE_PATH);
if (image != null) {
addImage(nuggetPath, resolver, image.adaptTo(InputStream.class),
CommunityGroupConstants.DEFAULT_IMAGE_CONTENT_TYPE, PROPERTY_IMAGE_NAME,
CommunityGroupConstants.DEFAULT_IMAGE_NAME);
} else {
LOG.error("Unable to find default group image");
}
serviceResolver.close();
}
}
// add banner image node if one has been uploaded
final boolean hasBanner = banner != null && !banner.isEmpty();
if (hasBanner) {
final DataSource ds = banner.get(0);
addImage(nuggetPath, resolver, ds.getInputStream(), ds.getContentType(), PROPERTY_BANNER_IMAGE_NAME,
ds.getName());
}
final boolean hasCSS = cssFiles != null && !cssFiles.isEmpty();
if (hasCSS) {
final DataSource ds = cssFiles.get(0);
addCSS(nuggetPath, resolver, ds.getInputStream(), ds.getContentType(),
CommunitySiteConstants.PROP_THEME_ID, ds.getName());
}
boolean publishRunMode = this.isPublishMode();
nugget.setProperty(SiteActivationService.REPLICATE_PUBLISH_RUN_MODE, Boolean.toString(publishRunMode));
session.save();
// reverse replicate nugget node
if (resolver.getResource(nuggetPath) != null && publishRunMode) {
final List paths = new ArrayList(2);
paths.add(nuggetPath);
paths.add(nuggetPath + "/" + PROPERTY_IMAGE_NAME);
if (hasBanner) {
paths.add(nuggetPath + "/" + PROPERTY_BANNER_IMAGE_NAME);
}
if (hasCSS) {
paths.add(nuggetPath + "/" + CommunitySiteConstants.PROP_THEME_ID);
}
replicator.reverseReplicate(ReplicationActionType.ACTIVATE, paths);
}
/* Perform the wait with the msm-service as the user admin session we have can't read content. */
ResourceResolver msmResolver = null;
try {
msmResolver =
getServiceUserWrapper().getServiceResourceResolver(getBundleLocalResourceResolverFactory(),
Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, (Object) MSM_SERVICE));
GroupUtil.waitForPageCreation(msmResolver, groupPath, 120 * 1000, 15 * 1000);
} finally {
if (msmResolver != null) {
msmResolver.close();
}
}
final Resource communityGroupResource =
root.getResourceResolver().resolve(groupPath + "/" + CommunityGroupConstants.CONFIG_NODE_NAME);
final SocialComponentFactory factory =
componentFactoryManager.getSocialComponentFactory(communityGroupResource);
final CommunityGroup communityGroup =
(CommunityGroup) ((factory != null) ? factory.getSocialComponent(communityGroupResource) : null);
performAfterActions(createOperation, session, communityGroup, properties);
return communityGroupResource;
} catch (final OperationException e) {
cleanupFailure(session);
throw e;
} catch (final Exception e) {
cleanupFailure(session);
throw new OperationException("Failed to create community group.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
@Override
public Resource update(final SlingHttpServletRequest request) throws OperationException {
final Resource resource = request.getResource();
final Session session = resource.getResourceResolver().adaptTo(Session.class);
final CommunityContext context = resource.adaptTo(CommunityContext.class);
if (context.getCommunityGroupId() == null) {
throw new OperationException("Not a valid Group resource", HttpServletResponse.SC_BAD_REQUEST);
}
if (!siteService.mayPost(resource, session)) {
throw new OperationException("Access violation.", HttpServletResponse.SC_FORBIDDEN);
}
String name;
CommunityGroup group = (CommunityGroup) this.getCommunityGroupComponentForResource(resource, request);
if (group != null) {
name = group.getUrl();
} else {
name = resource.getName();
}
final Map props = new HashMap();
final JSONArray functions;
try {
getDefaultProperties(request, props, false);
getCustomProperties(request, props, session);
final String structureString = (String) props.get(CommunitySiteConstants.PROP_FUNCTIONS);
if (!validateFunctionValue(structureString)){
LOG.error("Malformed Function property "+ structureString);
throw new OperationException("Malformed Function property ", HttpServletResponse.SC_BAD_REQUEST);
}
final JSONObject structure = new JSONObject(structureString);
functions = structure.getJSONArray(CommunitySiteConstants.PROP_FUNCTIONS);
} catch (final RepositoryException e) {
throw new OperationException("Failed to obtain community group properties.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (JSONException e1) {
throw new OperationException("Failed to create community site.", e1,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
try {
FunctionValidationUtil.validateFunctions(resource.getParent(), functions );
} catch (FunctionValidationException e) {
LOG.error("Community functions malformed", e);
// checkstyle ignore:line
throw new OperationException("Community functions malformed\n" + e.getMessage(),
HttpServletResponse.SC_CONFLICT);
}
// get the attachment images
final List attachments =
getAttachmentsFromRequest(request, CommunityGroupConstants.PROP_COMMUNITY_GROUP_FILE);
if (attachments != null && !attachments.isEmpty()) {
props.put(CommunityGroupConstants.PROP_COMMUNITY_GROUP_FILE, attachments);
}
// get the banner images
final List banner =
getAttachmentsFromRequest(request, CommunityGroupConstants.REQUEST_ATTACHMENT_PAGEBANNER);
final List groupCSS =
getAttachmentsFromRequest(request, CommunitySiteConstants.REQUEST_ATTACHMENT_PAGECSS);
final List groupThumbnail =
getAttachmentsFromRequest(request, CommunitySiteConstants.REQUEST_ATTACHMENT_THUMBNAIL);
if (banner != null && !banner.isEmpty())
props.put(CommunityGroupConstants.REQUEST_ATTACHMENT_PAGEBANNER, banner);
final U updateOperation = getUpdateOperation();
getExtensionParameters(updateOperation, request, props);
// update the site
ResourceResolver msmResolver = null;
ResourceResolver userManagerResolver = null;
// ResourceResolver aclResolver = null;
try {
msmResolver = serviceUserWrapper.getServiceResourceResolver(resourceResolverFactory,
Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, (Object) MSM_SERVICE));
userManagerResolver = serviceUserWrapper.getServiceResourceResolver(resourceResolverFactory,
Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, (Object) USER_ADMIN));
// aclResolver =
// serviceUserWrapper.getServiceResourceResolver(resourceResolverFactory,
// Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, (Object) ACL_MANAGER));
return update(siteBlueprintService, resource, group, props, banner, groupThumbnail, groupCSS, session,
msmResolver, userManagerResolver, funcDefUtils);
} catch (final LoginException e) {
LOG.error("Failed to login as service user.", e);
throw new OperationException(e, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} finally {
if (msmResolver != null) {
msmResolver.close();
}
if (userManagerResolver != null) {
userManagerResolver.close();
}
}
}
// this method does not validate access right.
protected Resource update(final TemplateRolloutService siteBlueprintService, final Resource root,
final CommunityGroup group, final Map properties, final List attachments,
final List groupThumbnail, final List groupCSS, final Session session,
final ResourceResolver msmResolver, final ResourceResolver userManagerResolver,
final FunctionDefinitionUtils funcDefUtils) throws OperationException {
if (ResourceUtil.isNonExistingResource(root)) {
throw new OperationException("Invalid group resource '" + root.getPath() + "'",
HttpServletResponse.SC_BAD_REQUEST);
}
if (group == null) {
throw new OperationException("Invalid community group " + root.getPath(),
HttpServletResponse.SC_BAD_REQUEST);
}
try {
final U updateOperation = getUpdateOperation();
performBeforeActions(updateOperation, session, root, properties);
final Resource siteRoot = updateGroup(siteBlueprintService, group, attachments, groupThumbnail, groupCSS,
properties, msmResolver, userManagerResolver, funcDefUtils);
if (msmResolver.hasChanges()) {
msmResolver.commit();
}
final SocialComponentFactory factory = componentFactoryManager.getSocialComponentFactory(root);
final CommunityGroup updatedGroup =
(CommunityGroup) ((factory != null) ? factory.getSocialComponent(root) : null);
// siteConfigurator.setSiteLevelConfiguration(updatedSite, msmResolver, aclResolver, userManagerResolver);
performAfterActions(updateOperation, session, updatedGroup, properties);
return siteRoot;
} catch (final OperationException e) {
cleanupFailure(session);
throw e;
} catch (final Exception e) {
cleanupFailure(session);
throw new OperationException("Failed to update community site.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
private boolean validateFunctionValue(final String structureString) {
if (StringUtils.isBlank(structureString)) {
return false;
}
try {
final JSONObject structure = new JSONObject(structureString);
final JSONArray functions = structure.getJSONArray(CommunitySiteConstants.PROP_FUNCTIONS);
return functions.length() > 0;
} catch (JSONException e) {
LOG.debug("Malformed json for Function property {}", structureString, e);
return false;
}
}
private void updateGroupStructure(final TemplateRolloutService siteBlueprintService, final Node configNode,
final Resource site, final String structureString, final ResourceResolver resolver,
final FunctionDefinitionUtils funcDefUtils)
throws JSONException, RepositoryException, PersistenceException, WCMException, OperationException {
final JSONObject structure = new JSONObject(structureString);
if (structure.has(CommunitySiteConstants.PROP_FUNCTIONS)) {
final PageManager pageMgr = resolver.adaptTo(PageManager.class);
final JSONArray functions = structure.getJSONArray(CommunitySiteConstants.PROP_FUNCTIONS);
final JSONArray newStructure = new JSONArray();
final List deletedPages = new ArrayList(3);
if (functions.length() > 0) {
SiteOperationUtils groupOperationUtils = SiteOperationUtils.getInstance();
groupOperationUtils.applyActions(siteBlueprintService, site, resolver, funcDefUtils, functions,
newStructure);
groupOperationUtils.reorderFunctions(siteBlueprintService, functions, site, resolver,
configNode.getProperty(CommunitySiteConstants.PROP_SITE_BLUEPRINT_ID).getString(), deletedPages);
final Node functionsNode = funcDefUtils.createFunctions(newStructure, configNode, resolver);
groupOperationUtils.deleteFunctions(functionsNode, deletedPages, site, pageMgr, resolver);
groupOperationUtils.applyConfigurations(siteBlueprintService, functionsNode, site, resolver);
}
}
}
// this method does not validate access right.
protected Resource updateGroup(final TemplateRolloutService siteBlueprintService, final CommunityGroup group,
final List attachments, final List groupThumbnail, final List siteCSS,
final Map properties, final ResourceResolver msmResolver,
final ResourceResolver userManagerResolver, final FunctionDefinitionUtils funcDefUtils)
throws OperationException {
final ResourceResolver resolver = group.getResource().getResourceResolver();
final Session session = resolver.adaptTo(Session.class);
try {
final Session msmSession = msmResolver.adaptTo(Session.class);
final Session userManagerSession = userManagerResolver.adaptTo(Session.class);
String siteName = (String) properties.get(CommunitySiteConstants.PROP_SITE_NAME);
final CommunityContext context = group.getResource().adaptTo(CommunityContext.class);
/**
* The resource is pointing to the configuration node.
*/
final Node configNode = msmSession.getNode(group.getResource().getPath());
String title = (String) properties.get(CommunityGroupConstants.PROP_COMMUNITY_GROUP_TITLE);
final String description =
(String) properties.get(CommunityGroupConstants.PROP_COMMUNITY_GROUP_DESCRIPTION);
final String type = (String) properties.get(CommunityGroupConstants.PROP_COMMUNITY_GROUP_TYPE);
if (StringUtils.isBlank(siteName)) {
siteName = (String) properties.get(CommunitySiteConstants.PROP_SITE_URL_NAME);
}
String currentThemeId = "";
if (configNode.hasProperty(CommunitySiteConstants.PROP_THEME_ID)) {
currentThemeId = configNode.getProperty(CommunitySiteConstants.PROP_THEME_ID).getString();
}
if (StringUtils.isBlank(currentThemeId)) {
currentThemeId = CommunitySiteConstants.DEFAULT_CONFIG_THEME;
}
final U operation = getUpdateOperation();
final Resource groupRoot = msmResolver.getResource(group.getResource().getPath()).getParent();
for (final Entry property : properties.entrySet()) {
final String key = property.getKey();
if (isConfigurationParameter(operation, key)
&& isUpdatedParameter(key, property.getValue(), configNode)) {
if (!ArrayUtils.contains(fieldWhitelist, key)) {
if (StringUtils.equals(CommunitySiteConstants.PROP_FUNCTIONS, key)) {
if (validateFunctionValue((String) property.getValue())) { // don't want to store corrupt
// value of functions
JcrUtil.setProperty(configNode, key, property.getValue());
}
} else {
JcrUtil.setProperty(configNode, key, property.getValue());
}
} else {
// Have to do this when a string value is replaced by multivalue prop
// This is possible when a person enters one tag first and later adds another
// In the above situation initially its stores as string and later it needs to be changed
// multivalue
if (configNode.hasProperty(key)) {
if (!configNode.getProperty(key).getClass().equals(property.getValue().getClass())) {
configNode.getProperty(key).remove();
JcrUtil.setProperty(configNode, key, property.getValue());
} else {
JcrUtil.setProperty(configNode, key, property.getValue());
}
} else {
JcrUtil.setProperty(configNode, key, property.getValue());
}
}
}
}
ValueMap props = new ValueMapDecorator(properties);
props.put(CommunityGroupConstants.PROP_COMMUNITY_GROUP_BLUEPRINT_ID,
configNode.getProperty(CommunitySiteConstants.PROP_SITE_BLUEPRINT_ID).getString());
//CQ-4220011 Need not change the group unique id of the group
props.put(CommunityGroupConstants.PROP_GROUP_ID, configNode.getProperty(CommunityGroupConstants.PROP_GROUP_ID).getString());
// do not change invite list, so read it from configuration node
if (configNode.hasProperty(CommunityGroupConstants.PROP_COMMUNITY_GROUP_INVITE)) {
props.put(CommunityGroupConstants.PROP_COMMUNITY_GROUP_INVITE,
configNode.getProperty(CommunityGroupConstants.PROP_COMMUNITY_GROUP_INVITE).getString());
}
// do not change group type, so read it from configuration node
props.put(CommunityGroupConstants.PROP_COMMUNITY_GROUP_TYPE,
configNode.getProperty(CommunityGroupConstants.PROP_COMMUNITY_GROUP_TYPE).getString());
props.put(CommunityGroupConstants.PROP_COMMUNITY_GROUP_NAME,
configNode.getProperty(CommunityGroupConstants.PROP_COMMUNITY_GROUP_NAME).getString());
props.put(CommunityGroupConstants.PROP_COMMUNITY_GROUP_CREATOR,
configNode.getProperty(CommunityGroupConstants.PROP_COMMUNITY_GROUP_CREATOR).getString());
communityGroupService.prepareUserGroups(userManagerResolver, groupRoot, groupRoot.getParent().getPath(),
props);
final String structureString = (String) properties.get(CommunitySiteConstants.PROP_FUNCTIONS);
if (!org.apache.commons.lang3.StringUtils.isEmpty(structureString)) {
try {
updateGroupStructure(siteBlueprintService, configNode, group.getResource().getParent(),
structureString, msmResolver.getResource(group.getResource().getPath()).getResourceResolver(), funcDefUtils);
// overwrite the title property for root page of sites
final ModifiableValueMap pageProps = userManagerResolver.getResource(group.getResource().getParent().getPath()).getChild(NameConstants.NN_CONTENT).adaptTo(ModifiableValueMap.class);
pageProps.put(NameConstants.PN_TITLE, siteName);
pageProps.put(NameConstants.PN_PAGE_TITLE, siteName);
} catch (final JSONException e) {
throw new OperationException("Malformed group structure", e, HttpServletResponse.SC_BAD_REQUEST);
}
}
communityGroupService.setCommunityGroupConfigure(msmResolver, groupRoot.getPath(), props);
// Take care of theme and theme images
// TODO: Hack this to get the blueprint to work. Move it to the site
// photo folder.
final Node photoFolder;
if (configNode.getParent().hasNode("photos")) {
photoFolder = configNode.getParent().getNode("photos");
} else {
photoFolder = configNode.getParent().addNode("photos", "sling:Folder");
}
final String themeId =
PropertiesUtils.get(properties, CommunitySiteConstants.PROP_THEME_ID, currentThemeId);
if (group.isUsingCustomCSS()) {
if (!themeId.equals(currentThemeId)) {
try {
final Node themeNode = session.getNode(currentThemeId);
if (themeNode != null) {
themeNode.remove();
}
} catch (PathNotFoundException e) {
LOG.error("Path not found", e);
}
}
}
Node image = null;
String photoFolderPath = photoFolder.getPath();
for (final DataSource ds : groupThumbnail) {
image = addThemeAsset(userManagerResolver, context, photoFolderPath, ds.getName(),
resolver.adaptTo(Session.class).getValueFactory().createBinary(ds.getInputStream()),
ds.getContentType());
}
final Node groupThumbnailImage = createThumbnailAsset(groupThumbnail, groupRoot, userManagerResolver, context);
final Node groupCSSNode = createCSSAsset(siteCSS, userManagerSession, context);
if (groupCSSNode != null) {
JcrUtil.setProperty(configNode, CommunitySiteConstants.PROP_THEME_ID, groupCSSNode.getPath());
} else {
final String themeProp = PropertiesUtils.get(properties, CommunitySiteConstants.PROP_THEME_ID,
CommunitySiteConstants.DEFAULT_CONFIG_THEME);
JcrUtil.setProperty(configNode, CommunitySiteConstants.PROP_THEME_ID, themeProp);
}
// Take care of banner
updateImage(groupRoot, attachments, CommunityGroupConstants.REQUEST_ATTACHMENT_PAGEBANNER);
updateImage(groupRoot,
(List) properties.get(CommunityGroupConstants.PROP_COMMUNITY_GROUP_FILE),
GroupConstants.PROPERTY_IMAGE_NAME);
// Add last modified
JcrUtil.setProperty(configNode, JcrConstants.JCR_LASTMODIFIED, Calendar.getInstance());
session.save();
return resolver.getResource(configNode.getPath());
} catch (final Exception e) {
LOG.error("Error updating Community site.", e);
throw new OperationException("Error updating community site.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
@Nullable
private Node createCSSAsset(final List siteThumbnail, final Session session,
final CommunityContext context) throws RepositoryException, IOException {
final String absolutePath = context.getPageThemePath();
final String nodeType = "cq:ClientLibraryFolder";
for (final DataSource cssFile : siteThumbnail) {
final boolean isCss = cssFile.getContentType().equalsIgnoreCase(CommunitySiteConstants.CSS_MIMETYPE);
if (isCss) {
final String assetName = JcrUtil.createValidName(cssFile.getName());
// Create node /etc/designs/tenants/tenant_id/site_id/sitethemes
// or
// /etc/designs/site_id/sitethemes
final Node assetRootNode =
JcrUtil.createPath(absolutePath, false, CommunitySiteConstants.SITES_ROOT_NODETYPE,
CommunitySiteConstants.SITES_ROOT_NODETYPE, session, false);
final Node assetNode = JcrUtil.createUniqueNode(assetRootNode, assetName, nodeType, session);
final Node cssNode = JcrUtils.putFile(assetNode, assetName, CommunitySiteConstants.CSS_MIMETYPE,
cssFile.getInputStream());
// TODO: Move to ugc community?
String themeCategoryName = CommunitySiteConstants.CUSTOM_THEME_PREFIX
+ context.getCommunityGroupUniqueId() + "." + assetNode.getName();
if (context.isMultiTenantSupported()) {
themeCategoryName = CommunitySiteConstants.CUSTOM_THEME_PREFIX + context.getTenantId() + "."
+ context.getSiteId() + "." + assetNode.getName();
}
JcrUtil.setProperty(assetNode, CommunitySiteConstants.PROP_THEME_CATEGORIES,
new String[]{themeCategoryName});
JcrUtils.putFile(assetNode, "css.txt", CommunitySiteConstants.TEXT_MIMETYPE,
new ByteArrayInputStream(cssNode.getName().getBytes()));
return assetNode;
}
}
return null;
}
/**
* Add a theme asset for the specified tenant
* @param resolver ResourceResolver
* @param context CommunityContext
* @param photoFolderPath folder for storing image
* @param name Name
* @param data binary data
* @param contentType type of the content
* @return node value
* @throws OperationException if theme is not added properly
*/
protected static Node addThemeAsset(final ResourceResolver resolver, final CommunityContext context,
final String photoFolderPath, final String name, final Binary data, final String contentType)
throws OperationException {
final Session session = resolver.adaptTo(Session.class);
try {
final Node photoRootNode =
JcrUtils.getOrCreateByPath(photoFolderPath,CommunitySiteConstants.SITES_ROOT_NODETYPE,resolver.adaptTo(Session.class));
if (photoRootNode.hasNode(PROPERTY_IMAGE_NAME)) {
photoRootNode.getNode(PROPERTY_IMAGE_NAME).remove();
}
final String assetRootName;
return createFile(resolver, PROPERTY_IMAGE_NAME, data, contentType, photoRootNode,
"", name, context);
} catch (final RepositoryException e) {
try {
session.refresh(false);
} catch (final RepositoryException e1) {
LOG.error("Repository error while adding theme asset.");
throw new OperationException("Repository error while adding theme asset.",
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
LOG.error("Repository error while adding theme asset.");
throw new OperationException("Repository error while adding theme asset.",
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
private Node createThumbnailAsset(final List siteThumbnail, final Resource site,
final ResourceResolver resolver, final CommunityContext context) throws RepositoryException, IOException {
if (siteThumbnail != null && !siteThumbnail.isEmpty()) {
final Node siteNode = site.getChild(JcrConstants.JCR_CONTENT).adaptTo(Node.class);
if (siteNode.hasNode(CommunitySiteConstants.IMAGE_NODENAME)) {
// Hack to generate a newer thumbnail
// Thumbnail doesnt get updated when creating a new file
final Node fileNode = siteNode.getNode(CommunitySiteConstants.IMAGE_NODENAME);
fileNode.remove();
resolver.adaptTo(Session.class).save();
}
for (final DataSource ds : siteThumbnail) {
return createFile(resolver, CommunitySiteConstants.FILE_NODENAME,
resolver.adaptTo(Session.class).getValueFactory().createBinary(ds.getInputStream()),
ds.getContentType(), siteNode, CommunitySiteConstants.IMAGE_NODENAME, ds.getName(), context);
}
}
return null;
}
protected static Node createFile(final ResourceResolver resolver, final String name, final Binary data,
final String contentType, final Node themeIdNode, final String assetRootName, final String fileNameProperty,
final CommunityContext context) throws RepositoryException {
final Session session = resolver.adaptTo(Session.class);
final boolean isCss = contentType.equalsIgnoreCase(CommunitySiteConstants.CSS_MIMETYPE);
final String nodeType = JcrConstants.NT_UNSTRUCTURED;
final boolean createUniqueLeaf = false;
final String aRootName = assetRootName;
final Node assetRootNode = JcrUtil.createPath(themeIdNode, aRootName, createUniqueLeaf, // createUniqueLeaf
JcrConstants.NT_UNSTRUCTURED, // intermediateNodeType
nodeType, // nodeType
session, false // autoSave
);
Node assetNode;
Node resNode;
String assetName = name;
if (assetName == null) {
assetName = "a" + System.currentTimeMillis() + ".bin";
} else {
int pos = assetName.lastIndexOf('/');
if (pos < 0) {
pos = assetName.lastIndexOf('\\');
}
if (pos >= 0) {
assetName = name.substring(pos + 1);
}
}
String assetContentType = contentType;
if (assetContentType == null) {
assetContentType = "application/octet-stream";
}
// check if content-type has a charset
final int pos = assetContentType.indexOf(';');
if (pos > 0) {
// for now, just snip off
assetContentType = assetContentType.substring(0, pos);
}
String fileNameWithoutExtension = FilenameUtils.getBaseName(assetName);
final String fileNameExtension = FilenameUtils.getExtension(assetName);
fileNameWithoutExtension = JcrUtil.isValidName(fileNameWithoutExtension) ? fileNameWithoutExtension
: JcrUtil.createValidName(fileNameWithoutExtension);
String fileName = "";
if (StringUtils.isBlank(fileNameExtension)) {
fileName = fileNameWithoutExtension;
} else {
fileName = fileNameWithoutExtension + "." + fileNameExtension;
}
if (assetRootNode.hasNode(fileName)) {
assetNode = assetRootNode.getNode(fileName);
resNode = assetNode.getNode(JcrConstants.JCR_CONTENT);
} else {
// TODO: Do we want to use comment attachment node type?
assetNode = assetRootNode.addNode(fileName, CommentSystem.COMMENT_ATTACHMENT_NODETYPE);
resNode = assetNode.addNode(JcrConstants.JCR_CONTENT, JcrConstants.NT_RESOURCE);
}
resNode.setProperty(JcrConstants.JCR_MIMETYPE, assetContentType);
resNode.setProperty(JcrConstants.JCR_DATA, data);
resNode.setProperty(JcrConstants.JCR_LASTMODIFIED, Calendar.getInstance());
assetNode.setProperty(CommunitySiteConstants.PROP_SITE_NAME, fileNameProperty);
return assetNode;
}
private Node getThemeNode(final CommunityContext context, final String themeId, final Session session)
throws PathNotFoundException, RepositoryException {
final String themePath = context.getSiteThemePath() + +CommunityConstants.FORWARDSLASH_CHAR + themeId;
return session.getNode(themePath);
}
protected void updateImage(final Resource groupRoot, final List dataSources, final String name)
throws OperationException {
if (dataSources != null && !dataSources.isEmpty()) {
Resource imgResource = groupRoot.getChild(SiteBlueprintConstants.PROPERTY_IMAGE_PATH + "/" + name);
DataSource dataSource = dataSources.get(0);
try {
if (imgResource != null) {
final Node bannerNode = imgResource.adaptTo(Node.class);
if (bannerNode != null && StringUtils.isNotBlank(dataSource.getName())) {
bannerNode.setProperty(NAME, dataSource.getName());
}
final Node imageContentNode = bannerNode.getNode(JcrConstants.JCR_CONTENT);
final Binary data = groupRoot.getResourceResolver().adaptTo(Session.class).getValueFactory()
.createBinary(dataSource.getInputStream());
imageContentNode.setProperty(JcrConstants.JCR_MIMETYPE, dataSource.getContentType());
imageContentNode.setProperty(JcrConstants.JCR_DATA, data);
imageContentNode.setProperty(JcrConstants.JCR_LASTMODIFIED, Calendar.getInstance());
} else {
// new content
Resource photos = groupRoot.getChild(SiteBlueprintConstants.PROPERTY_IMAGE_PATH);
if (photos == null) {
Node groupRootNode = groupRoot.adaptTo(Node.class);
groupRootNode.addNode(SiteBlueprintConstants.PROPERTY_IMAGE_PATH,
JcrResourceConstants.NT_SLING_FOLDER);
}
addImage(groupRoot.getPath() + "/" + SiteBlueprintConstants.PROPERTY_IMAGE_PATH,
groupRoot.getResourceResolver(), dataSource.getInputStream(), dataSource.getContentType(),
name, dataSource.getName());
}
} catch (RepositoryException e) {
throw new OperationException("Failed to create image " + name, e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (IOException e) {
throw new OperationException("Failed to read image " + name, e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
}
protected boolean isConfigurationParameter(final U operation, final String parameterName)
throws OperationException {
for (final String key : unchangeableParams) {
if (key.equals(parameterName)) {
return false;
}
}
if (this.extensionProviders.containsKey(operation)) {
for (final T extension : this.extensionProviders.get(operation)) {
try {
return extension.isConfigurationParameter(operation, parameterName);
} catch (final NoSuchMethodError e) {
} // Catch these exceptions just in case there are extensions which implements the old SiteOperation
// interface.
catch (final AbstractMethodError e) {
}
}
}
return true;
}
@Override
protected void getExtensionParameters(final U operation, final SlingHttpServletRequest request,
final Map requestParameters) throws OperationException {
if (this.extensionProviders.containsKey(operation)) {
for (final T extension : this.extensionProviders.get(operation)) {
try {
extension.getExtensionRequestParameters(operation, request, requestParameters);
} catch (final NoSuchMethodError e) {
} // Catch these exceptions just in case there are extensions which implements the old SiteOperation
// interface.
catch (final AbstractMethodError e) {
}
}
}
}
private boolean isUpdatedParameter(final String key, final Object value, final Node configNode)
throws RepositoryException {
if (configNode.hasProperty(key)) {
final Property prop = configNode.getProperty(key);
if (!prop.isMultiple()) {
final Value currentValue = prop.getValue();
final Value newValue = JcrUtil.createValue(value, configNode.getSession());
if (newValue != null) {
return !newValue.equals(currentValue);
} else {
return true;
}
} else {
return true;
}
} else {
return true;
}
}
@Override
public boolean isPublishMode() {
return settingsService != null && settingsService.getRunModes().contains("publish");
}
@Override
public boolean approveJoin(final ResourceResolver resolver, final CommunityGroup group)
throws OperationException {
// anonymous cannot join
final Session session = resolver.adaptTo(Session.class);
if (StringUtils.endsWithIgnoreCase(session.getUserID(), "anonymous")) {
return false;
}
// auto approve the request to join open community groups
if (group != null && GroupConstants.TYPE_OPEN.equals(group.getType())) {
return true;
}
// currently reject all other requests
return false;
}
@Override
public Resource join(final SlingHttpServletRequest request) throws OperationException {
final Resource resource = request.getResource();
final ResourceResolver resolver = resource.getResourceResolver();
final Session session = resource.getResourceResolver().adaptTo(Session.class);
final String groupUrl = request.getParameter(CommunityGroupConstants.PROP_COMMUNITY_GROUP_PATH);
if (StringUtils.isBlank(groupUrl)) {
return null;
}
final Resource groupPageResource = resolver.resolve(groupUrl);
final CommunityGroup group =
(CommunityGroup) this.getCommunityGroupComponentForResource(groupPageResource, request);
return join(resolver, group, session);
}
protected Resource join(final ResourceResolver resolver, final CommunityGroup group, final Session session)
throws OperationException {
if (resolver == null || group == null || session == null) {
return null;
}
if (!approveJoin(resolver, group)) {
throw new OperationException(
"Deny " + session.getUserID() + "'s request to join community group " + group.getName(),
HttpServletResponse.SC_NOT_ACCEPTABLE);
}
ResourceResolver userAdminResolver = null;
try {
final String authorizableId = session.getUserID();
userAdminResolver =
getServiceUserWrapper().getServiceResourceResolver(getBundleLocalResourceResolverFactory(),
Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, (Object) USER_ADMIN));
groupService.addGroupMember(userAdminResolver, group.getMemberGroupId(), authorizableId);
resolver.adaptTo(Session.class).refresh(false);
resolver.refresh();
} catch (final LoginException e) {
cleanupFailure(session);
throw new OperationException("Failed to login as user admin.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (final GroupException e) {
cleanupFailure(session);
throw new OperationException("Failed to join community group.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (final RepositoryException e) {
cleanupFailure(session);
throw new OperationException("Failed to join community group.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} finally {
if (userAdminResolver != null) {
userAdminResolver.close();
}
}
return group.getResource();
}
@Override
public Resource leave(final SlingHttpServletRequest request) throws OperationException {
final Resource resource = request.getResource();
final ResourceResolver resolver = resource.getResourceResolver();
final Session session = resource.getResourceResolver().adaptTo(Session.class);
final String groupUrl = request.getParameter(CommunityGroupConstants.PROP_COMMUNITY_GROUP_PATH);
if (StringUtils.isBlank(groupUrl)) {
return null;
}
final Resource groupPageResource = resolver.resolve(groupUrl);
final CommunityGroup group =
(CommunityGroup) this.getCommunityGroupComponentForResource(groupPageResource, request);
return leave(resolver, group, session);
}
protected Resource leave(final ResourceResolver resolver, final CommunityGroup group, final Session session)
throws OperationException {
if (resolver == null || group == null || session == null) {
return null;
}
ResourceResolver userAdminResolver = null;
try {
final String authorizableId = session.getUserID();
userAdminResolver =
getServiceUserWrapper().getServiceResourceResolver(getBundleLocalResourceResolverFactory(),
Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, (Object) USER_ADMIN));
groupService.removeGroupMember(userAdminResolver, group.getMemberGroupId(), authorizableId);
resolver.adaptTo(Session.class).refresh(false);
resolver.refresh();
} catch (final LoginException e) {
cleanupFailure(session);
throw new OperationException("Failed to login as user admin.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (final GroupException e) {
cleanupFailure(session);
throw new OperationException("Failed to join community group.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (final RepositoryException e) {
cleanupFailure(session);
throw new OperationException("Failed to join community group.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} finally {
if (userAdminResolver != null) {
userAdminResolver.close();
}
}
return group.getResource();
}
@Override
public Resource invite(final SlingHttpServletRequest request) throws OperationException {
final Resource resource = request.getResource();
final ResourceResolver resolver = resource.getResourceResolver();
final Session session = resource.getResourceResolver().adaptTo(Session.class);
final String[] inviteList = request.getParameterValues(CommunityGroupConstants.PROP_COMMUNITY_GROUP_USERS);
final CommunityContext context = resource.adaptTo(CommunityContext.class);
final Resource groupPageResource = resolver.resolve(context.getCommunityGroupPath());
final CommunityGroup group =
(CommunityGroup) this.getCommunityGroupComponentForResource(groupPageResource, request);
invite(resolver, group, inviteList, context, session);
return resource;
}
protected void invite(final ResourceResolver resolver, final CommunityGroup group, final String[] inviteList,
final CommunityContext context, final Session session) throws OperationException {
if (resolver == null || group == null || session == null) {
return;
}
ResourceResolver userAdminResolver = null;
try {
userAdminResolver =
getServiceUserWrapper().getServiceResourceResolver(getBundleLocalResourceResolverFactory(),
Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, (Object) USER_ADMIN));
UserManager um = ((JackrabbitSession)userAdminResolver.adaptTo(Session.class)).getUserManager();
if (!GroupUtil.canInviteGroupMember(resolver, context, serviceUserWrapper, repository, um)) {
throw new OperationException(
"Deny " + session.getUserID() + "'s request to invite users to community group " + group.getName(),
HttpServletResponse.SC_NOT_ACCEPTABLE);
}
groupService.addGroupMembers(userAdminResolver, group.getMemberGroupId(), inviteList);
session.refresh(false);
resolver.refresh();
} catch (final LoginException e) {
cleanupFailure(session);
throw new OperationException("Failed to login as user admin.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (final GroupException e) {
cleanupFailure(session);
throw new OperationException("Failed to join community group.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (final RepositoryException e) {
cleanupFailure(session);
throw new OperationException("Failed to join community group.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} finally {
if (userAdminResolver != null) {
userAdminResolver.close();
}
}
}
@Override
public Resource uninvite(final SlingHttpServletRequest request) throws OperationException {
final Resource resource = request.getResource();
final ResourceResolver resolver = resource.getResourceResolver();
final Session session = resource.getResourceResolver().adaptTo(Session.class);
final String invite = request.getParameter(CommunityGroupConstants.PROP_COMMUNITY_GROUP_USERS);
if (StringUtils.isEmpty(invite)) {
return null;
}
final String[] inviteList = invite.split(delimiters);
final CommunityContext context = resource.adaptTo(CommunityContext.class);
final Resource groupPageResource = resolver.resolve(context.getCommunityGroupPath());
final CommunityGroup group =
(CommunityGroup) this.getCommunityGroupComponentForResource(groupPageResource, request);
uninvite(resolver, group, inviteList, context, session);
return resource;
}
protected void uninvite(final ResourceResolver resolver, final CommunityGroup group, final String[] inviteList,
final CommunityContext context, final Session session) throws OperationException {
if (resolver == null || group == null || session == null) {
return;
}
ResourceResolver userAdminResolver = null;
try {
userAdminResolver =
getServiceUserWrapper().getServiceResourceResolver(getBundleLocalResourceResolverFactory(),
Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, (Object) USER_ADMIN));
UserManager um = ((JackrabbitSession)userAdminResolver.adaptTo(Session.class)).getUserManager();
if (!GroupUtil.canInviteGroupMember(resolver, context, serviceUserWrapper, repository, um)) {
throw new OperationException(
"Deny " + session.getUserID() + "'s request to invite users to community group " + group.getName(),
HttpServletResponse.SC_NOT_ACCEPTABLE);
}
groupService.removeGroupMembers(userAdminResolver, group.getMemberGroupId(), inviteList);
session.refresh(false);
resolver.refresh();
} catch (final LoginException e) {
cleanupFailure(session);
throw new OperationException("Failed to login as user admin.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (final GroupException e) {
cleanupFailure(session);
throw new OperationException("Failed to uninvite member from community group.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (final RepositoryException e) {
cleanupFailure(session);
throw new OperationException("Failed to uninvite member from community group.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} finally {
if (userAdminResolver != null) {
userAdminResolver.close();
}
}
}
@Override
public Resource promoteMember(final SlingHttpServletRequest request) throws OperationException {
final Resource resource = request.getResource();
final ResourceResolver resolver = resource.getResourceResolver();
final Session session = resource.getResourceResolver().adaptTo(Session.class);
final String[] inviteList = request.getParameterValues(CommunityGroupConstants.PROP_COMMUNITY_GROUP_USERS);
final CommunityContext context = resource.adaptTo(CommunityContext.class);
final Resource groupPageResource = resolver.resolve(context.getCommunityGroupPath());
final CommunityGroup group =
(CommunityGroup) this.getCommunityGroupComponentForResource(groupPageResource, request);
LOG.debug("promoteMember: resource {} groupPageResource {}", resource, groupPageResource);
LOG.debug("promoteMember: communityGroupPath {}", context.getCommunityGroupPath());
promoteMember(resolver, group, context, inviteList, session);
return resource;
}
protected void promoteMember(final ResourceResolver resolver, final CommunityGroup group,
final CommunityContext context, final String[] inviteList, final Session session) throws OperationException {
final String groupAdminID = context.getSiteUserGroupName(CommunityUserGroup.GROUP_ADMIN);
if (LOG.isDebugEnabled()) {
LOG.debug("promoteMember: {} to {}", Arrays.asList(inviteList), groupAdminID);
}
if (resolver == null) {
throw new IllegalArgumentException("resolver not allowed to be null");
}
if (group == null) {
throw new IllegalArgumentException("group not allowed to be null");
}
if (session == null) {
throw new IllegalArgumentException("session not allowed to be null");
}
LOG.debug("promoteMember: {} is authorized.", resolver.getUserID());
ResourceResolver userAdminResolver = null;
try {
userAdminResolver =
getServiceUserWrapper().getServiceResourceResolver(getBundleLocalResourceResolverFactory(),
Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, (Object) USER_ADMIN));
UserManager um = ((JackrabbitSession)userAdminResolver.adaptTo(Session.class)).getUserManager();
if (!GroupUtil.canPromoteGroupMember(resolver, context, serviceUserWrapper, repository, um)) {
throw new OperationException(
"Deny " + session.getUserID() + "'s request to invite users to community group " + group.getName(),
HttpServletResponse.SC_NOT_ACCEPTABLE);
}
LOG.debug("promoteMember: calling addGroupMembers adding {} to {}.", Arrays.asList(inviteList),
groupAdminID);
groupService.addGroupMembers(userAdminResolver, groupAdminID, inviteList);
session.refresh(false);
resolver.refresh();
} catch (final LoginException e) {
cleanupFailure(session);
throw new OperationException("Failed to login as user admin.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (final GroupException e) {
cleanupFailure(session);
throw new OperationException("Failed to join community group.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (final RepositoryException e) {
cleanupFailure(session);
throw new OperationException("Failed to join community group.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} finally {
if (userAdminResolver != null) {
userAdminResolver.close();
}
}
}
@Override
public Resource demoteMember(final SlingHttpServletRequest request) throws OperationException {
final Resource resource = request.getResource();
final ResourceResolver resolver = resource.getResourceResolver();
final Session session = resource.getResourceResolver().adaptTo(Session.class);
final String[] inviteList = request.getParameterValues(CommunityGroupConstants.PROP_COMMUNITY_GROUP_USERS);
final CommunityContext context = resource.adaptTo(CommunityContext.class);
final Resource groupPageResource = resolver.resolve(context.getCommunityGroupPath());
final CommunityGroup group =
(CommunityGroup) this.getCommunityGroupComponentForResource(groupPageResource, request);
demoteMember(resolver, group, context, inviteList, session);
return resource;
}
protected void demoteMember(final ResourceResolver resolver, final CommunityGroup group,
final CommunityContext context, final String[] inviteList, final Session session) throws OperationException {
if (resolver == null || group == null || session == null) {
return;
}
final String groupAdminID = context.getSiteUserGroupName(CommunityUserGroup.GROUP_ADMIN);
ResourceResolver userAdminResolver = null;
try {
userAdminResolver =
getServiceUserWrapper().getServiceResourceResolver(getBundleLocalResourceResolverFactory(),
Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, (Object) USER_ADMIN));
UserManager um = ((JackrabbitSession)userAdminResolver.adaptTo(Session.class)).getUserManager();
if (!GroupUtil.canPromoteGroupMember(resolver, context, serviceUserWrapper, repository, um)) {
throw new OperationException(
"Deny " + session.getUserID() + "'s request to invite users to community group " + group.getName(),
HttpServletResponse.SC_NOT_ACCEPTABLE);
}
groupService.removeGroupMembers(userAdminResolver, groupAdminID, inviteList);
groupService.addGroupMembers(userAdminResolver, group.getMemberGroupId(), inviteList);
session.refresh(false);
resolver.refresh();
} catch (final LoginException e) {
cleanupFailure(session);
throw new OperationException("Failed to login as user admin.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (final GroupException e) {
cleanupFailure(session);
throw new OperationException("Failed to join community group.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (final RepositoryException e) {
cleanupFailure(session);
throw new OperationException("Failed to join community group.", e,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} finally {
if (userAdminResolver != null) {
userAdminResolver.close();
}
}
}
private boolean isSpecialRequestParam(final String paramName) {
for (int i = 0; i < specialParams.length; i++) {
if (paramName.equals(specialParams[i])) {
return true;
}
}
return false;
}
protected void addCSS(final String path, final ResourceResolver resolver, final InputStream imageStream,
final String contentType, final String nodeName, final String nameProperty)
throws OperationException, RepositoryException {
try {
if (imageStream != null && imageStream.available() > 0) {
final Resource folder = ResourceUtil.getOrCreateResource(resolver, path,
CommunityGroupConstants.FOLDER_NODETYPE, null, true);
final Node folderNode = folder.adaptTo(Node.class);
final Node groupthemesFolder = folderNode.addNode(GroupConstants.PROPERTY_GROUPTHEMES);
final Node cssNode = groupthemesFolder.addNode(nameProperty);
final Node cssFiles =
JcrUtils.putFile(cssNode, nameProperty, CommunitySiteConstants.CSS_MIMETYPE, imageStream);
JcrUtils.putFile(cssNode, "css.txt", CommunitySiteConstants.TEXT_MIMETYPE,
new ByteArrayInputStream(cssFiles.getName().getBytes()));
}
} catch (final IOException e) {
throw new OperationException("IO failure", e, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
protected void addImage(final String path, final ResourceResolver resolver, final InputStream imageStream,
final String contentType, final String nodeName, final String nameProperty)
throws OperationException, RepositoryException {
try {
if (imageStream != null && imageStream.available() > 0) {
final Resource folder = ResourceUtil.getOrCreateResource(resolver, path,
CommunityGroupConstants.FOLDER_NODETYPE, null, true);
final Node folderNode = folder.adaptTo(Node.class);
final Node imageNode = folderNode.addNode(nodeName, NODE_PROPERTY_COMMENTATTACHMENT);
JcrUtil.setProperty(imageNode, NAME, nameProperty);
final Node imageContentNode = imageNode.addNode(JcrConstants.JCR_CONTENT, JcrConstants.NT_RESOURCE);
final Binary data = resolver.adaptTo(Session.class).getValueFactory().createBinary(imageStream);
imageContentNode.setProperty(JcrConstants.JCR_MIMETYPE, contentType);
imageContentNode.setProperty(JcrConstants.JCR_DATA, data);
imageContentNode.setProperty(JcrConstants.JCR_LASTMODIFIED, Calendar.getInstance());
}
} catch (final IOException e) {
throw new OperationException("IO failure", e, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
// NOTE: caller should save the new image node
}
protected void replaceImage(final Resource root, final String name, final ResourceResolver resolver,
final InputStream imageStream, final String contentType) throws OperationException, RepositoryException {
try {
if (imageStream != null && imageStream.available() > 0) {
final Resource folder = root.getChild(CommunityGroupConstants.FOLDER_NODETYPE);
final Node folderNode = folder.adaptTo(Node.class);
final Node imageNode = folderNode.getNode(name);
final Node imageContentNode = imageNode.addNode(JcrConstants.JCR_CONTENT, JcrConstants.NT_RESOURCE);
final Binary data = resolver.adaptTo(Session.class).getValueFactory().createBinary(imageStream);
imageContentNode.setProperty(JcrConstants.JCR_MIMETYPE, contentType);
imageContentNode.setProperty(JcrConstants.JCR_DATA, data);
imageContentNode.setProperty(JcrConstants.JCR_LASTMODIFIED, Calendar.getInstance());
}
} catch (final IOException e) {
throw new OperationException("IO failure", e, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
// NOTE: caller should save the new image node
}
protected List getAttachmentsFromRequest(final SlingHttpServletRequest request,
final String requestParameterName) {
final RequestParameter[] fileRequestParameters = request.getRequestParameters(requestParameterName);
if (fileRequestParameters != null) {
// Didn't find equivalent in SocialUitl
return CollabUtil.getAttachmentsFromRequest(fileRequestParameters, ATTACHMENT_FILE_LIMIT, WHITE_LIST,
BLACK_LIST);
}
return Collections.emptyList();
}
/**
* Extract the default site properties from the specified {@link SlingHttpServletRequest} into the specified.
* {@link Map}
* @param request SlingHttpServletRequest
* @param props map of values
* @param validateRequired gives validation status
* @throws RepositoryException - thrown if unable to get props.
* @throws OperationException - thrown if unable to get props
*/
protected void getDefaultProperties(final SlingHttpServletRequest request, final Map props,
final boolean validateRequired) throws RepositoryException, OperationException {
for (int i = 0; i < requestParams.length; i++) {
final Object params[] = requestParams[i];
final Class clazz = (Class) params[PARAM_CLASS_INDEX];
final String name = (String) params[PARAM_NAME_INDEX];
if (clazz.isArray()) {
final String values[] = request.getParameterValues(name);
if (validateRequired && values == null && ((Boolean) params[PARAM_REQUIRED_INDEX])) {
throw new OperationException("Community group value '" + name + "' is empty",
HttpServletResponse.SC_BAD_REQUEST);
}
if (clazz == String[].class) {
if (values != null) {
props.put(name, StringUtils.join(values, ","));
}
}
// TODO: Handle other array types
} else {
final String value = request.getParameter(name);
if (validateRequired && value == null && ((Boolean) params[PARAM_REQUIRED_INDEX])) {
throw new OperationException("Community group value '" + name + "' is empty",
HttpServletResponse.SC_BAD_REQUEST);
}
if (value != null) {
props.put(name, GroupUtil.toObject(value, clazz));
}
}
}
}
/**
* Extract the custom site properties from the specified {@link SlingHttpServletRequest} into the specified.
* {@link Map}
* @param request SlingHttpServletRequest
* @param props map of values
* @param session Session
* @throws RepositoryException - thrown if unable to get props.
* @throws OperationException - thrown if unable to get props.
*/
protected void getCustomProperties(final SlingHttpServletRequest request, final Map props,
final Session session) throws RepositoryException, OperationException {
// TODO
}
private void addAllowedTemplate(final String path, final List allowedTemplates,
final ResourceResolver resolver) {
final Resource res = resolver.resolve(path);
addAllowedTemplate(res, allowedTemplates, resolver);
}
private void addAllowedTemplate(final Resource res, final List allowedTemplates,
final ResourceResolver resolver) {
if (res != null && !ResourceUtil.isNonExistingResource(res)) {
final ValueMap v = res.adaptTo(ValueMap.class);
final boolean isDisabled = v.get(CommunityFunction.PROPERTY_BLUEPRINT_ENABLED, false);
if (!isDisabled) {
final Map data = new HashMap();
data.put(PATH, res.getPath());
data.put(NAME, v.get("jcr:title"));
allowedTemplates.add(data);
}
}
}
private void addTemplatesUnderResource(final String path, final List allowedTemplates,
final ResourceResolver userAdminResolver) {
Iterator resourceIterator = null;
if (path.startsWith("/")) {
final Resource templates = userAdminResolver.resolve(path);
if (templates != null && templates.hasChildren()) {
resourceIterator = templates.getChildren().iterator();
}
} else {
Resource resource = userAdminResolver.getResource(CUSTOM_GROUP_TEMPLATE_ROOT_LIBS);
Conf confMgr = resource.adaptTo(Conf.class);
List list = confMgr.getListResources(path);
if (list != null) {
resourceIterator = list.iterator();
}
}
if (resourceIterator != null) {
while (resourceIterator.hasNext()) {
final Resource res = resourceIterator.next();
if (res != null && !ResourceUtil.isNonExistingResource(res)) {
final ValueMap v = res.adaptTo(ValueMap.class);
final Map data = new HashMap();
data.put(PATH, res.getPath());
data.put(NAME, v.get("jcr:title"));
allowedTemplates.add(data);
}
}
}
}
@Override
public List getAllowedTemplateForEveryone(final String[] paths) {
final List allowedTemplates = new ArrayList();
ResourceResolver msmResolver = null;
try {
msmResolver = getServiceUserWrapper().getServiceResourceResolver(getBundleLocalResourceResolverFactory(),
Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, (Object) MSM_SERVICE));
if (paths != null && paths.length > 0) {
for (int i = 0; i < paths.length; i++) {
addAllowedTemplate(paths[i], allowedTemplates, msmResolver);
}
} else {
if (msmResolver.getResource(DEFAULT_GROUP_TEMPLATE_ROOT) != null) {
// for backcomp
addTemplatesUnderResource(CUSTOM_GROUP_TEMPLATE_ROOT, allowedTemplates, msmResolver);
addTemplatesUnderResource(DEFAULT_GROUP_TEMPLATE_ROOT, allowedTemplates, msmResolver);
} else {
addTemplatesUnderResource(DEFAULT_GROUP_ROOTTEMPLATE_RELATIVIEPATH_ROOT, allowedTemplates,
msmResolver);
}
}
} catch (final LoginException e) {
LOG.error("Failed to login as user admin.", e);
} finally {
if (msmResolver != null) {
msmResolver.close();
}
}
return allowedTemplates;
}
private CommunityGroupCollection getCommunityGroupCollectionForResource(final Resource groupCollection,
final SlingHttpServletRequest request) {
String path = groupCollection.getPath();
if (!path.endsWith(CommunityGroupConstants.CONFIG_NODE_NAME)) {
path = path + "/" + CommunityGroupConstants.CONFIG_NODE_NAME;
}
final Resource resource = request.getResourceResolver().getResource(path);
if (resource == null) {
LOG.debug("getCommunityGroupCollectionForResource: Resource at {} not found with resolver for user {}",
path, request.getResourceResolver().getUserID());
return null;
}
final SocialComponentFactory factory = componentFactoryManager.getSocialComponentFactory(resource);
if (factory == null) {
LOG.debug("getCommunityGroupCollectionForResource: SocialComponentFactory responsible for {} not found.",
resource.getPath());
return null;
}
final CommunityGroupCollection sc = (CommunityGroupCollection) factory.getSocialComponent(resource, request);
if (sc == null) {
LOG.debug("getCommunityGroupCollectionForResource: SocialComponentFactory {} returned null for {}.", sc,
resource.getPath());
}
return sc;
}
/**
* Get the SocialComponent
for the specified {@link Resource} and {@link SlingHttpServletRequest}.
* @param communityGroup the target community group
* @param request the client request
* @return the {@link SocialComponent}
*/
@Override
public SocialComponent getCommunityGroupComponentForResource(final Resource communityGroup,
final SlingHttpServletRequest request) {
String path = communityGroup.getPath();
if (!path.endsWith(CommunityGroupConstants.CONFIG_NODE_NAME)) {
path = path + "/" + CommunityGroupConstants.CONFIG_NODE_NAME;
}
final Resource resource = request.getResourceResolver().getResource(path);
if (resource == null) {
LOG.debug("getCommunityGroupComponentForResource: Resource at {} not found with resolver for user {}",
path, request.getResourceResolver().getUserID());
return null;
}
final SocialComponentFactory factory = componentFactoryManager.getSocialComponentFactory(resource);
if (factory == null) {
LOG.debug("getCommunityGroupComponentForResource: SocialComponentFactory responsible for {} not found.",
resource.getPath());
return null;
}
final SocialComponent sc = factory.getSocialComponent(resource, request);
if (sc == null) {
LOG.debug("getCommunityGroupComponentForResource: SocialComponentFactory {} returned null for {}.", sc,
resource.getPath());
}
return sc;
}
/**
* Get the SocialComponent
for the specified {@link Resource} and {@link SlingHttpServletRequest}.
* @param communityMembers the target community member list
* @param request the client request
* @return the {@link SocialComponent}
*/
@Override
public SocialComponent getCommunityMemberListComponentForResource(final Resource communityMembers,
final SlingHttpServletRequest request) {
final String path = communityMembers.getPath();
final Resource resource = request.getResourceResolver().getResource(path);
if (resource == null) {
return null;
}
final SocialComponentFactory factory = componentFactoryManager.getSocialComponentFactory(resource);
return (factory != null) ? factory.getSocialComponent(resource, request) : null;
}
protected CommunitySiteService getCommunitySiteService() {
return siteService;
}
@Override
protected SiteActivationService getActivationService() {
return activationService;
}
@Override
protected CommunityGroup getSocialComponent(Resource resource, SlingHttpServletRequest request) {
return (CommunityGroup) getCommunityGroupComponentForResource(resource, request);
}
/**
* Activate this component. Open the session and register event listeners.
* @param context The component context
*/
@Activate
protected void activate(final ComponentContext context) {
fieldWhitelist = OsgiUtil.toStringArray(context.getProperties().get(PROPERTY_FIELD_WHITELIST));
}
protected abstract U getCreateOperation();
protected abstract U getUpdateOperation();
protected abstract U getJoinOperation();
protected abstract U getLeaveOperation();
}