io.kestros.commons.osgiserviceutils.utils.OsgiServiceUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kestros-osgi-service-utils Show documentation
Show all versions of kestros-osgi-service-utils Show documentation
Foundational and utility logic for building OSGI Services on Kestros/Sling
instances.
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.kestros.commons.osgiserviceutils.utils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.osgi.service.component.ComponentContext;
import org.osgi.util.tracker.ServiceTracker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Utility methods for OSGI services.
*/
public class OsgiServiceUtils {
private static final Logger LOG = LoggerFactory.getLogger(OsgiServiceUtils.class);
private OsgiServiceUtils() {
}
/**
* Sets the specified resource resolver to a live service ResourceResolver, if it is not already
* live.
*
* @param serviceName Service to open ResourceResolver as.
* @param existingResourceResolver ResourceResolver to set live.
* @param resourceResolverFactory ResourceResolveFactory to get ResourceResolver from if
* needed.
* @param service Service the ResourceResolver will be used for.
*
* @return Newly opened service ResourceResolver or existing resourceResolver if it is still
* live.
*
* @throws LoginException ResourceResolver factory failed to login for the given service
* UserID.
*/
@Nonnull
public static ResourceResolver getOpenServiceResourceResolver(@Nonnull final String serviceName,
final ResourceResolver existingResourceResolver,
@Nonnull final ResourceResolverFactory resourceResolverFactory,
@Nonnull final Object service)
throws LoginException {
ResourceResolver resourceResolver = existingResourceResolver;
if (resourceResolver != null && resourceResolver.isLive()) {
LOG.info("Attempted to open ResourceResolver for service user {}, for service {}, but a live "
+ "ResourceResolver already exists.", serviceName.replaceAll("[\r\n]", ""),
service.getClass().getSimpleName().replaceAll("[\r\n]", ""));
} else {
final Map params = Collections.singletonMap(
ResourceResolverFactory.SUBSERVICE, serviceName);
if (resourceResolverFactory != null) {
resourceResolver = resourceResolverFactory.getServiceResourceResolver(params);
LOG.info("Opened service user {} resourceResolver for service {}.",
serviceName.replaceAll("[\r\n]", ""),
service.getClass().getSimpleName().replaceAll("[\r\n]", ""));
} else {
LOG.warn("Failed to open service user {} resourceResolver for service {}. "
+ "ResourceResolverFactory was null.",
serviceName.replaceAll("[\r\n]", ""),
service.getClass().getSimpleName().replaceAll("[\r\n]", ""));
throw new LoginException();
}
}
return resourceResolver;
}
/**
* Sets the specified resource resolver to a live service ResourceResolver, if it is not already
* live.
*
* @param serviceName Service to open ResourceResolver as.
* @param existingResourceResolver ResourceResolver to set live.
* @param resourceResolverFactory ResourceResolveFactory to get ResourceResolver from if
* needed.
* @param service Service the ResourceResolver will be used for.
*
* @return Newly opened service ResourceResolver or existing resourceResolver if it is still
* live.
*/
@Nullable
public static ResourceResolver getOpenServiceResourceResolverOrNullAndLogExceptions(
@Nonnull final String serviceName,
@Nonnull final ResourceResolver existingResourceResolver,
@Nonnull final ResourceResolverFactory resourceResolverFactory,
@Nonnull final Object service) {
try {
return getOpenServiceResourceResolver(serviceName, existingResourceResolver,
resourceResolverFactory, service);
} catch (final LoginException exception) {
LOG.error("Failed to log into service user {} resourceResolver for {}. {}",
serviceName.replaceAll("[\r\n]", ""),
service.getClass().getSimpleName().replaceAll("[\r\n]", ""),
exception.getMessage().replaceAll("[\r\n]", ""));
}
return null;
}
/**
* Closes a resource resolver if it is open.
*
* @param resourceResolver ResourceResolver to close.
* @param service Service the ResourceResolver is used for.
*/
public static void closeServiceResourceResolver(@Nonnull final ResourceResolver resourceResolver,
@Nonnull final Object service) {
LOG.trace("Checking if resourceResolver needs to be closed for {}",
service.getClass().getSimpleName().replaceAll("[\r\n]", ""));
if (resourceResolver != null && resourceResolver.isLive()) {
LOG.info("Closing resourceResolver for {}", service.getClass().getSimpleName().replaceAll(
"[\r\n]", ""));
resourceResolver.close();
}
}
/**
* Retrieves the top ranked service registered to a specified class.
*
* @param componentContext Component Context.
* @param type Service class to retrieve instances of.
* @param Generic Type.
*
* @return The top ranked service registered to a specified class.
*/
@Nullable
public static T getOsgiServiceOfType(@Nonnull ComponentContext componentContext,
@Nonnull Class type) {
final ServiceTracker serviceTracker = new ServiceTracker(componentContext.getBundleContext(),
type.getName(), null);
serviceTracker.open();
try {
T service = (T) serviceTracker.getService();
return service;
} finally {
serviceTracker.close();
}
}
/**
* Retrieves all Services which are registered to the specified service class.
*
* @param componentContext componentContext
* @param type Service class to retrieve instances of.
* @param Generic type.
*
* @return All Services which are registered to the specified service class.
*/
@SuppressWarnings("unchecked")
@Nonnull
public static List getAllOsgiServicesOfType(
@Nonnull final ComponentContext componentContext,
@Nonnull final Class type) {
final ServiceTracker serviceTracker = new ServiceTracker(componentContext.getBundleContext(),
type, null);
return getAllOsgiServicesOfType(type.getName(), serviceTracker);
}
/**
* Retrieves all Services which are registered to the specified service class.
*
* @param componentContext componentContext
* @param serviceClassName Service class name to retrieve instances of.
* @param Generic type.
*
* @return All Services which are registered to the specified service class.
*/
@SuppressWarnings("unchecked")
@Nonnull
public static List getAllOsgiServicesOfType(
@Nonnull final ComponentContext componentContext,
@Nonnull final String serviceClassName) {
final ServiceTracker serviceTracker = new ServiceTracker(componentContext.getBundleContext(),
serviceClassName, null);
return getAllOsgiServicesOfType(serviceClassName, serviceTracker);
}
@SuppressWarnings("unchecked")
@Nonnull
static List getAllOsgiServicesOfType(@Nonnull final String serviceName,
@Nonnull final ServiceTracker serviceTracker) {
serviceTracker.open();
final List osgiServices = new ArrayList<>();
final Object[] services = serviceTracker.getTracked().values().toArray();
if (services.length != 0) {
for (final Object service : services) {
osgiServices.add((T) service);
}
} else {
LOG.debug("No services found for '{}'.", serviceName.replaceAll("[\r\n]", ""));
}
serviceTracker.close();
return osgiServices;
}
}