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.remondis.limbus.monitoring.MonitoringRegistry Maven / Gradle / Ivy
Go to download
API to create and process monitoring information using extendable interfaces for consumers and producers.
package com.remondis.limbus.monitoring;
import static com.remondis.limbus.monitoring.Conventions.denyInvalidPublisherImplementation;
import static com.remondis.limbus.monitoring.Conventions.isValidPublisherInterface;
import static com.remondis.limbus.monitoring.InvalidConfigurationException.duplicatePublisher;
import static com.remondis.limbus.monitoring.InvalidConfigurationException.duplicatePublisherId;
import static com.remondis.limbus.utils.ReflectionUtil.getAllInterfaces;
import static com.remondis.limbus.utils.ReflectionUtil.getClassLoader;
import static com.remondis.limbus.utils.ReflectionUtil.newInstance;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentHashMap.KeySetView;
import com.remondis.limbus.IInitializable;
import com.remondis.limbus.utils.ObjectCreateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class defines the monitoring registry. It maps the configured monitoring client patterns to available
* publisher interfaces. The available interfaces are mapped to the set of configured publisher implementations.
*
* @author schuettec
*
*/
/**
* @author schuettec
*
*/
public class MonitoringRegistry {
private static final Logger log = LoggerFactory.getLogger(MonitoringRegistry.class);
/**
* Holds the patterns with specifity descending.
*/
protected List orderedPatterns;
protected List> lifecycleObjects;
protected Map, Set>> patternToPublisher;
public MonitoringRegistry(MonitoringConfiguration configuration)
throws InvalidConfigurationException, SecurityException, ObjectCreateException {
super();
this.lifecycleObjects = new LinkedList>();
this.patternToPublisher = createPatternToPublisherMapping(configuration);
}
/**
* This method returns the set of configured publishers for the specified pattern and publisher interface. The pattern
* is evaluated against the list of known patterns starting with the most specific pattern. The first matching and
* most specific pattern will be chosen.
*
* @param clientName
* The name of the client publishing records. Configured patterns are evaluated against this name to search
* publishers for this client.
* @param publisherInterface
* The specified publisher type.
* @return Returns the set of configured publisher instances or an empty set if no publisher was found.
*/
public Set getPublishers(String clientName, Class> publisherInterface) {
Pattern pattern = getFirstMatchingPattern(clientName);
if (pattern == null) {
if (log.isTraceEnabled()) {
log.trace("No matching pattern found for client '{}'.", clientName);
}
return Collections.emptySet();
}
if (patternToPublisher.containsKey(pattern)) {
Map, Set> interfaceToPublishersMap = patternToPublisher.get(pattern);
if (interfaceToPublishersMap.containsKey(publisherInterface)) {
return interfaceToPublishersMap.get(publisherInterface);
} else {
if (log.isTraceEnabled()) {
log.trace("The specified publisher interface '{}' was not found - requesting client was '{}'.",
publisherInterface.getName(), clientName);
}
return Collections.emptySet();
}
} else {
if (log.isTraceEnabled()) {
log.trace("The matching pattern '{}' is not known by the publisher mapping - this is an implementation fault.",
pattern.getPattern());
}
return Collections.emptySet();
}
}
private Pattern getFirstMatchingPattern(String clientName) {
for (Pattern p : orderedPatterns) {
String pattern = p.getPattern();
if (clientName.startsWith(pattern)) {
return p;
}
}
return null;
}
protected List orderPatternsSpecifityDescending(List pattern) {
Collections.sort(pattern, Collections.reverseOrder(new PatternSpecifityComparator()));
return pattern;
}
protected Object createPublisher(String clazz) throws ObjectCreateException, SecurityException {
try {
ClassLoader classLoader = getClassLoader(MonitoringFactory.class);
Class> publisherImpl = classLoader.loadClass(clazz);
denyInvalidPublisherImplementation(publisherImpl);
Object newInstance = newInstance(publisherImpl);
return newInstance;
} catch (SecurityException e) {
throw e;
} catch (ClassNotFoundException e) {
throw new ObjectCreateException("Cannot create publisher instance - class was not found.", e);
}
}
protected Map, Set>> createPatternToPublisherMapping(MonitoringConfiguration config)
throws InvalidConfigurationException, ObjectCreateException, SecurityException {
Map, Set>> patternToPublishers = new ConcurrentHashMap, Set>>();
Map idToPublisher = createIdToPublisherMapping(config);
List patterns = config.getPatterns();
denyDuplicatePatterns(patterns);
orderedPatterns = orderPatternsSpecifityDescending(patterns);
// Now we can iterate over the patterns starting with the most specific pattern.
for (Pattern p : orderedPatterns) {
List publisherIDs = p.getPublishers();
for (String pubId : publisherIDs) {
// For every publisher id, get the publisher and its corresponding publisher interface
denyUnknownPublisherId(idToPublisher, pubId);
Object object = idToPublisher.get(pubId);
Set> publisherInterfaces = getPublisherInterfacesForImplementation(object.getClass());
for (Class> pubInterface : publisherInterfaces) {
addPatternToPublishersMapping(patternToPublishers, p, pubInterface, object);
}
}
}
return patternToPublishers;
}
protected void addPatternToPublishersMapping(Map, Set>> patternToPublishers, Pattern p,
Class> pubInterface, Object object) {
Map, Set> interfaceToPublishers = getOrCreateInterfacesToPublishersMap(patternToPublishers, p);
Set publishers = getOrCreatePublishersSet(interfaceToPublishers, pubInterface);
publishers.add(object);
}
protected Set getOrCreatePublishersSet(Map, Set> interfaceToPublishers,
Class> pubInterface) {
if (interfaceToPublishers.containsKey(pubInterface)) {
return interfaceToPublishers.get(pubInterface);
} else {
KeySetView newKeySet = ConcurrentHashMap.newKeySet();
interfaceToPublishers.put(pubInterface, newKeySet);
return newKeySet;
}
}
protected Map, Set> getOrCreateInterfacesToPublishersMap(
Map, Set>> patternToPublishers, Pattern p) {
if (patternToPublishers.containsKey(p)) {
return patternToPublishers.get(p);
} else {
ConcurrentHashMap, Set> map = new ConcurrentHashMap, Set>();
patternToPublishers.put(p, map);
return map;
}
}
protected void denyUnknownPublisherId(Map idToPublisher, String publisherId)
throws InvalidConfigurationException {
if (!idToPublisher.containsKey(publisherId)) {
throw InvalidConfigurationException.unknownPublisherId(publisherId);
}
}
protected void denyDuplicatePatterns(List patterns) throws InvalidConfigurationException {
HashSet cleaned = new HashSet<>(patterns);
if (cleaned.size() != patterns.size()) {
List delta = new LinkedList<>(patterns);
delta.removeAll(cleaned);
throw InvalidConfigurationException.duplicatePatterns(delta);
}
}
protected Set> getPublisherInterfacesForImplementation(Class> implementation) {
List> allInterfaces = getAllInterfaces(implementation);
Set> validInterfaces = new HashSet>();
Iterator> it = allInterfaces.iterator();
while (it.hasNext()) {
Class> pubInterface = it.next();
if (isValidPublisherInterface(pubInterface)) {
validInterfaces.add(pubInterface);
}
}
if (allInterfaces.isEmpty()) {
throw InvalidPublisherException.noPublisherInterfaces(implementation);
} else {
return validInterfaces;
}
}
protected String monitoringConfigurationAsString() {
StringBuilder b = new StringBuilder();
String format = "%-40s | %-40s | %-40s";
b.append(String.format(format, "Pattern", "Publisher Interface", "Publisher Implementation"))
.append("\n");
Iterator it = patternToPublisher.keySet()
.iterator();
while (it.hasNext()) {
Pattern p = it.next();
String pattern = shortString(p.getPattern());
Map, Set> interfaceToImpls = patternToPublisher.get(p);
Iterator> interfaces = interfaceToImpls.keySet()
.iterator();
while (interfaces.hasNext()) {
Class> pubInt = interfaces.next();
Set impls = interfaceToImpls.get(pubInt);
for (Object impl : impls) {
String interfaceName = shortString(pubInt.getName());
String implName = shortString(impl.getClass()
.getName());
b.append(String.format(format, pattern, interfaceName, implName))
.append("\n");
pattern = "";
}
}
}
return b.toString();
}
protected String shortString(String string) {
return shortString(40, string);
}
protected String shortString(int maxChars, String string) {
String shortener = "...";
String newString = string;
int actual = newString.length();
if (actual > maxChars) {
int diff = (actual - maxChars) + shortener.length();
newString = shortener + newString.substring(diff, actual);
}
return newString;
}
/**
* Creates the configured publishers.
*
* @param config
* The configuration.
* @return Returns the mapping of declared publisher id to publisher instance.
* @throws InvalidConfigurationException
* Thrown if a duplicate publisher id was detected.
* @throws ObjectCreateException
* Thrown if a publisher could not be created.
* @throws SecurityException
* Thrown on missing permissions.
*/
protected Map createIdToPublisherMapping(MonitoringConfiguration config)
throws InvalidConfigurationException, SecurityException, ObjectCreateException {
Map mapping = new HashMap<>();
Set addedPublisherClassNames = new HashSet<>();
List publishers = config.getPublishers();
Iterator it = publishers.iterator();
while (it.hasNext()) {
PublisherConfig p = it.next();
String id = p.getId();
Object instance = p.getInstance();
Class> clazz = instance.getClass();
if (mapping.containsKey(id)) {
throw duplicatePublisherId(id);
} else if (addedPublisherClassNames.contains(clazz.getName())) {
throw duplicatePublisher(clazz);
} else {
initializeOnDemand(instance);
mapping.put(id, instance);
addedPublisherClassNames.add(clazz.getName());
}
}
return mapping;
}
/**
* If the publisher instance is an {@link IInitializable} call the initialize lifecycle method.
*
* @param instance
* The instance to initialize.
*/
private void initializeOnDemand(Object instance) throws ObjectCreateException {
if (instance instanceof IInitializable>) {
IInitializable> iInitializable = (IInitializable>) instance;
try {
iInitializable.initialize();
lifecycleObjects.add(iInitializable);
} catch (Exception e) {
throw new ObjectCreateException(String
.format("Could not initialized IInitializable publisher implementation '%s'.", iInitializable.getClass()
.getName()),
e);
}
}
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return monitoringConfigurationAsString();
}
public void clear() {
finishPublishers();
this.lifecycleObjects.clear();
this.lifecycleObjects = null;
this.orderedPatterns.clear();
this.orderedPatterns = null;
this.patternToPublisher.clear();
this.patternToPublisher = null;
}
private void finishPublishers() {
Iterator> it = lifecycleObjects.iterator();
while (it.hasNext()) {
IInitializable> toFinish = it.next();
try {
toFinish.finish();
} catch (Exception e) {
log.warn("Finishing of an IInitializable was expected to be silent but threw an exception.", e);
}
}
}
}