All Downloads are FREE. Search and download functionalities are using the official Maven repository.
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.activitystreams.listener.api.AbstractActivityStreamProvider Maven / Gradle / Ivy
/*************************************************************************
*
* 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.cq.social.activitystreams.listener.api;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.apache.commons.lang3.StringUtils;
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.felix.scr.annotations.References;
import org.apache.sling.api.resource.LoginException;
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.jcr.api.SlingRepository;
import org.apache.sling.jcr.resource.JcrResourceConstants;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.adobe.cq.social.activitystreams.api.SocialActivityManager;
import com.adobe.cq.social.activitystreams.impl.Activator;
import com.adobe.cq.social.activitystreams.listener.impl.ComparableStreamProviderExtension;
import com.adobe.cq.social.scf.core.SocialEvent;
import com.adobe.granite.activitystreams.Activity;
import com.adobe.granite.activitystreams.ActivityException;
import com.adobe.granite.activitystreams.ActivityStream;
/**
* Base class of the ActivityStreamProvider.
*/
@Component(componentAbstract = true, label = "%abstractactivitystreamprovider.name")
@References({
@Reference(name = "extensionProvider", referenceInterface = ActivityStreamProviderExtension.class,
bind = "bindExtension", unbind = "unbindExtension", cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
policy = ReferencePolicy.DYNAMIC),
@Reference(name = "listenerExtension", referenceInterface = EventListenerExtension.class,
bind = "bindListenerExtension", unbind = "unbindListenerExtension",
cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, policy = ReferencePolicy.DYNAMIC)})
public abstract class AbstractActivityStreamProvider implements ActivityStreamProvider {
protected static final String UGC_WRITER = "ugc-writer";
/**
* Eventually remove SLING_SERVICE_SUBSERVICE once we can update the dependencies to get this from
* ResourceResolverFactory and not make the unit tests fail.
*/
protected static final String SLING_SERVICE_SUBSERVICE = "sling.service.subservice";
/**
* The logger.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractActivityStreamProvider.class);
/**
* Reference to ResourceResolverFactory. Can't remove this it is API, but internally it is not used.
*/
@Reference
protected ResourceResolverFactory resourceResolverFactory;
@Reference
protected SocialActivityManager activityManager;
@Reference
protected final SlingRepository repository = null;
String servicePid;
/** The context. */
private volatile ComponentContext context;
/** The bound extension. */
private final List boundExtensions =
new LinkedList();
/**
* The list of extensions
*/
private final CopyOnWriteArrayList extensions =
new CopyOnWriteArrayList();
/**
* Because this is an abstract component we can't just add @Reference without bumping the package API major
* version. So we avoid using Declarative Services and just use the next layer down directly.
*/
private com.adobe.cq.social.serviceusers.internal.ServiceUserWrapper serviceUserWrapper;
/**
* Using this one lets us configure the service user with the symbolic name of *this* bundle, not the symbolic
* name of each bundle implementing a concrete version of this component.
*/
private ResourceResolverFactory privateResourceResolverFactory;
public com.adobe.cq.social.serviceusers.internal.ServiceUserWrapper getServiceUserWrapper() {
if (serviceUserWrapper == null) {
serviceUserWrapper =
Activator.getService(com.adobe.cq.social.serviceusers.internal.ServiceUserWrapper.class);
}
return serviceUserWrapper;
}
public ResourceResolverFactory getPrivateResourceResolverFactory() {
if (privateResourceResolverFactory == null) {
privateResourceResolverFactory = Activator.getService(ResourceResolverFactory.class);
}
return privateResourceResolverFactory;
}
@Override
public void append(final Activity activity) throws ActivityException {
if (activityManager == null) {
return;
}
ResourceResolver ugcResolver = null;
try {
ugcResolver =
getServiceUserWrapper().getServiceResourceResolver(getPrivateResourceResolverFactory(),
Collections.singletonMap(SLING_SERVICE_SUBSERVICE, (Object) UGC_WRITER));
final ActivityStream stream = getStream(activity, ugcResolver);
if (stream != null) {
stream.append(activity);
}
} catch (final LoginException le) {
LOGGER.error("Can't obtain resolver for service user", le);
return;
} finally {
if (ugcResolver != null && ugcResolver.isLive()) {
ugcResolver.close();
}
}
}
protected abstract ActivityStream getStream(Activity activity, ResourceResolver resolver)
throws ActivityException;
/**
* Get the session to be used by the stream
* @return Session the admin session or null if there is an error.
* @throws RepositoryException RepositoryException
*/
protected abstract Session getAdminSession() throws RepositoryException;
/**
* Activate this service. Subclass component needs to call this method in its activate method.
* @param ctx ComponentContext
* @throws LoginException LoginException
*/
protected void activate(final ComponentContext ctx) throws LoginException {
LOGGER.debug("Activating " + this.getClass().getName());
servicePid = (String) ctx.getProperties().get("service.pid");
this.context = ctx;
final List extensionsCopy;
synchronized (this.boundExtensions) {
extensionsCopy = new ArrayList(this.boundExtensions);
this.boundExtensions.clear();
}
for (final ActivityStreamProviderExtension extension : extensionsCopy) {
this.addExtension(extension);
}
}
/**
* Deactivate this service. Subclass component needs to call this method in its deactivate method.
* @param context OSGi component context
*/
protected void deactivate(final ComponentContext context) {
LOGGER.debug("Deactivating " + this.getClass().getName());
activityManager = null;
this.context = null;
}
protected ResourceResolver getServiceResourceResolver(final Session session) throws LoginException {
final Map authInfo = new HashMap();
authInfo.put(JcrResourceConstants.AUTHENTICATION_INFO_SESSION, session);
return resourceResolverFactory.getResourceResolver(authInfo);
}
public void bindExtension(final ActivityStreamProviderExtension extension) {
LOGGER.debug("Binding : {} activated: {}", extension.getName(), (context == null));
if (this.context == null) {
synchronized (this.boundExtensions) {
if (this.context == null) {
this.boundExtensions.add(extension);
} else {
addExtension(extension);
}
}
} else {
addExtension(extension);
}
}
private synchronized void addExtension(final ActivityStreamProviderExtension extension) {
if (!hasExtension(extension) && validateExtension(extension)) {
final int ranking = extension.getRanking();
final ComparableStreamProviderExtension cextension =
new ComparableStreamProviderExtension(extension, ranking);
final int index = Collections.binarySearch(extensions, cextension);
final int insertAt;
if (index < 0) {
insertAt = -(index + 1);
} else {
// this should never happen in our use case since we don't have duplicate item in the list.
insertAt = index + 1;
}
extensions.add(insertAt, cextension);
}
}
public void bindListenerExtension(final EventListenerExtension extension) {
LOGGER.debug("Binding : {} activated:{}", extension.getName(), (this.context == null));
if (this.context == null) {
synchronized (this.boundExtensions) {
if (this.context == null) {
this.boundExtensions.add(new ActivityStreamProviderExtensionWrapper(extension));
} else {
addExtension(new ActivityStreamProviderExtensionWrapper(extension));
}
}
} else {
addExtension(new ActivityStreamProviderExtensionWrapper(extension));
}
}
public void unbindListenerExtension(final EventListenerExtension extension) {
LOGGER.debug("Unbinding {} activated:{}", extension.getName(), (this.context == null));
unbindExtension(extension.getName());
}
private boolean validateExtension(final ActivityStreamProviderExtension extension) {
String streams[] = extension.getStreamProviderPid();
if (streams.length == 1 && StringUtils.equals(streams[0], "*")) {
return true;
}
for (String name : streams) {
if (StringUtils.equals(name, this.servicePid)) {
return true;
}
}
return false;
}
private boolean hasExtension(final ActivityStreamProviderExtension extension) {
for (ActivityStreamProviderExtension e : extensions) {
if (extension.getName().equals(e.getName())) {
return true;
}
}
return false;
}
public void unbindExtension(final ActivityStreamProviderExtension extension) {
LOGGER.debug("Unbind extension {} activated {}", extension.getName(), (context == null));
unbindExtension(extension.getName());
}
private synchronized void unbindExtension(final String name) {
int index = 0;
for (final ActivityStreamProviderExtension ext : extensions) {
if (ext.getName().equals(name)) {
extensions.remove(index);
break;
} else {
index++;
}
}
}
@Override
public List getExtensions() {
return new CopyOnWriteArrayList(extensions);
}
/**
* Wrapping old EventListenerExtension to support existing implementation.
* @author thuynh
*/
@SuppressWarnings("deprecation")
protected class ActivityStreamProviderExtensionWrapper implements ActivityStreamProviderExtension {
private EventListenerExtension eventListenerExtension;
private final String[] STREAM_PROVIDER_PID = {"*"};
public ActivityStreamProviderExtensionWrapper(final EventListenerExtension eventListenerExtension) {
this.eventListenerExtension = eventListenerExtension;
}
@Override
public String getName() {
return eventListenerExtension.getName();
}
@Override
public String[] getStreamProviderPid() {
return STREAM_PROVIDER_PID;
}
@Override
public boolean evaluate(SocialEvent event, Resource resource) {
return eventListenerExtension.evaluate(event, resource);
}
@Override
public int getRanking() {
return eventListenerExtension.getRanking();
}
@Override
public Map getActivityProperties(SocialEvent event, Resource resource) {
return eventListenerExtension.getActivityProperties(event, resource);
}
@Override
public Map getObjectProperties(SocialEvent event, Resource resource) {
return eventListenerExtension.getObjectProperties(event, resource);
}
@Override
public Map getActorProperties(SocialEvent event, Resource resource) {
return eventListenerExtension.getActorProperties(event, resource);
}
@Override
public Map getTargetProperties(SocialEvent event, Resource resource) {
return eventListenerExtension.getTargetProperties(event, resource);
}
}
}