/*
* 2012-3 Red Hat Inc. and/or its affiliates and other contributors.
*
* Licensed 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 org.overlord.rtgov.activity.collector;
import java.util.Stack;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.transaction.Synchronization;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import org.overlord.commons.services.ServiceClose;
import org.overlord.commons.services.ServiceInit;
import org.overlord.commons.services.ServiceListener;
import org.overlord.commons.services.ServiceRegistryUtil;
import org.overlord.rtgov.activity.model.ActivityType;
import org.overlord.rtgov.activity.model.ActivityUnit;
import org.overlord.rtgov.activity.model.Origin;
import org.overlord.rtgov.activity.processor.InformationProcessorManager;
import org.overlord.rtgov.activity.validator.ActivityValidatorManager;
import org.overlord.rtgov.common.util.RTGovProperties;
/**
* This class provides an abstract implementation of the activity
* collector interface.
*
*/
public abstract class AbstractActivityCollector implements ActivityCollector, AbstractActivityCollectorMBean {
private static final Logger LOG=Logger.getLogger(AbstractActivityCollector.class.getName());
private static final boolean DEFAULT_COLLECTION_ENABLED=true;
private Boolean _enabled;
private CollectorContext _collectorContext=null;
private ActivityUnitLogger _activityLogger=null;
private InformationProcessorManager _infoProcessorManager=null;
private ActivityValidatorManager _activityValidatorManager=null;
private ThreadLocalStack<ActivityUnit> _activityUnit = new ThreadLocalStack<ActivityUnit>();
class ThreadLocalStack<T> {
private java.lang.ThreadLocal<java.util.Stack<T>> _threadLocalStack = new ThreadLocal<java.util.Stack<T>>();
public T get() {
Stack<T> stack = _threadLocalStack.get();
if (stack == null || stack.isEmpty()) {
return null;
}
return stack.peek();
}
public void set(T value) {
Stack<T> stack = _threadLocalStack.get();
if (stack == null) {
_threadLocalStack.set(new Stack<T>());
stack = _threadLocalStack.get();
}
stack.push(value);
}
public void remove() {
Stack<T> stack = _threadLocalStack.get();
if (stack == null) {
return;
}
stack.pop();
}
}
/**
* The default constructor.
*/
public AbstractActivityCollector() {
_enabled = RTGovProperties.getPropertyAsBoolean("ActivityCollector.enabled", DEFAULT_COLLECTION_ENABLED);
}
/**
* Initialize the activity collector.
*/
@ServiceInit
public void init() {
if (_infoProcessorManager == null) {
ServiceRegistryUtil.addServiceListener(InformationProcessorManager.class, new ServiceListener<InformationProcessorManager>() {
@Override
public void registered(InformationProcessorManager service) {
setInformationProcessorManager(service);
}
@Override
public void unregistered(InformationProcessorManager service) {
setInformationProcessorManager(null);
}
});
}
if (_activityValidatorManager == null) {
ServiceRegistryUtil.addServiceListener(ActivityValidatorManager.class, new ServiceListener<ActivityValidatorManager>() {
@Override
public void registered(ActivityValidatorManager service) {
setActivityValidatorManager(service);
}
@Override
public void unregistered(ActivityValidatorManager service) {
setActivityValidatorManager(null);
}
});
}
if (_collectorContext == null) {
ServiceRegistryUtil.addServiceListener(CollectorContext.class, new ServiceListener<CollectorContext>() {
@Override
public void registered(CollectorContext service) {
setCollectorContext(service);
}
@Override
public void unregistered(CollectorContext service) {
setCollectorContext(null);
}
});
}
if (_activityLogger == null) {
ServiceRegistryUtil.addServiceListener(ActivityUnitLogger.class, new ServiceListener<ActivityUnitLogger>() {
@Override
public void registered(ActivityUnitLogger service) {
setActivityUnitLogger(service);
}
@Override
public void unregistered(ActivityUnitLogger service) {
setActivityUnitLogger(null);
}
});
}
}
/**
* This method sets the collector context.
*
* @param cc The collector context
*/
public void setCollectorContext(CollectorContext cc) {
_collectorContext = cc;
}
/**
* This method gets the collector context.
*
* @return The collector context
*/
public CollectorContext getCollectorContext() {
return (_collectorContext);
}
/**
* This method indicates whether activity collection is
* currently enabled.
*
* @return Whether collection is enabled
*/
public boolean isCollectionEnabled() {
return (_enabled == null ? DEFAULT_COLLECTION_ENABLED : _enabled);
}
/**
* This method identifies whether the collection process should be
* enabled.
*
* @return Whether enabled
*/
public boolean getCollectionEnabled() {
return (isCollectionEnabled());
}
/**
* This method sets whether the collection process should be
* enabled.
*
* @param enabled Whether enabled
*/
public void setCollectionEnabled(boolean enabled) {
_enabled = enabled;
}
/**
* This method sets the activity logger.
*
* @param activityLogger The activity logger
*/
public void setActivityUnitLogger(ActivityUnitLogger activityLogger) {
_activityLogger = activityLogger;
}
/**
* This method gets the activity logger.
*
* @return The activity logger
*/
public ActivityUnitLogger getActivityUnitLogger() {
return (_activityLogger);
}
/**
* This method gets the information processor manager.
*
* @return The information processor manager
*/
public InformationProcessorManager getInformationProcessorManager() {
return (_infoProcessorManager);
}
/**
* This method sets the information processor manager.
*
* @param ipm The information processor manager
*/
public void setInformationProcessorManager(InformationProcessorManager ipm) {
_infoProcessorManager = ipm;
}
/**
* This method gets the activity validator manager.
*
* @return The activity validator manager
*/
public ActivityValidatorManager getActivityValidatorManager() {
return (_activityValidatorManager);
}
/**
* This method sets the activity validator manager.
*
* @param aim The activity validator manager
*/
public void setActivityValidatorManager(ActivityValidatorManager aim) {
_activityValidatorManager = aim;
}
/**
* This method generates a unique transaction id.
*
* @return The transaction id
*/
protected String createTransactionId() {
return (UUID.randomUUID().toString());
}
/**
* This method returns the current date/time.
*
* @return The timestamp
*/
protected long getTimestamp() {
return (System.currentTimeMillis());
}
/**
* {@inheritDoc}
*/
public void startScope() {
if (!isCollectionEnabled()) {
return;
}
ActivityUnit au=_activityUnit.get();
if (au != null) {
if (LOG.isLoggable(Level.FINEST)) {
LOG.finest("Starting nested scope");
}
}
startScope(createActivityUnit());
}
/**
* {@inheritDoc}
*/
public boolean isScopeActive() {
return (_activityUnit.get() != null);
}
/**
* This method starts the scope associated with the supplied activity unit.
*
* @param au The activity unit
*/
protected void startScope(ActivityUnit au) {
if (LOG.isLoggable(Level.FINEST)) {
LOG.finest("Start scope");
}
_activityUnit.set(au);
}
/**
* This method creates a new activity unit and
* initializes its origin based on the template
* supplied by the OriginInitializer, if
* available.
*
* @return The new activity unit
*/
protected ActivityUnit createActivityUnit() {
ActivityUnit ret=new ActivityUnit();
Origin origin=new Origin();
origin.setHost(_collectorContext.getHost());
origin.setNode(_collectorContext.getNode());
origin.setThread(Thread.currentThread().getName());
ret.setOrigin(origin);
return (ret);
}
/**
* {@inheritDoc}
*/
public void endScope() {
if (!isCollectionEnabled()) {
return;
}
ActivityUnit au=_activityUnit.get();
if (LOG.isLoggable(Level.FINEST)) {
LOG.finest("End scope for: "+au);
}
if (au != null) {
_activityLogger.log(au);
_activityUnit.remove();
} else {
LOG.severe(java.util.PropertyResourceBundle.getBundle(
"activity.Messages").getString("ACTIVITY-1"));
}
}
/**
* {@inheritDoc}
*/
public String processInformation(String processor, String type, Object info,
java.util.Map<String, Object> headers, ActivityType actType) {
if (_infoProcessorManager != null) {
return (_infoProcessorManager.process(processor, type, info, headers, actType));
} else if (LOG.isLoggable(Level.WARNING)) {
LOG.warning("Information processor manager not specified: "
+"unable to process type '"+type+"' info: "+info);
}
return (null);
}
/**
* {@inheritDoc}
*/
public void validate(ActivityType actType) throws Exception {
// Check if activity is of interest to validators
if (_activityValidatorManager != null) {
_activityValidatorManager.validate(actType);
}
}
/**
* {@inheritDoc}
*/
public void record(ActivityType actType) {
if (!isCollectionEnabled()) {
return;
}
ActivityUnit au=_activityUnit.get();
// Check if need to create a single event activity unit outside of transaction scope
boolean transactional=true;
if (au == null) {
au = createActivityUnit();
TransactionManager tm=_collectorContext.getTransactionManager();
if (tm != null) {
try {
Transaction txn=tm.getTransaction();
if (txn != null) {
txn.registerSynchronization(
new Synchronization() {
public void afterCompletion(int arg0) {
endScope();
}
public void beforeCompletion() {
}
});
startScope(au);
} else {
if (LOG.isLoggable(Level.FINEST)) {
LOG.finest("No transaction available");
}
transactional = false;
}
} catch (Exception e) {
LOG.log(Level.SEVERE, java.util.PropertyResourceBundle.getBundle(
"activity.Messages").getString("ACTIVITY-2"), e);
transactional = false;
}
} else {
if (LOG.isLoggable(Level.FINEST)) {
LOG.finest("No transaction manager available");
}
transactional = false;
}
}
// Set/override timestamp
actType.setTimestamp(getTimestamp());
au.getActivityTypes().add(actType);
if (!transactional) {
_activityLogger.log(au);
}
}
/**
* This method closes the activity collector.
*/
@ServiceClose
public void close() {
}
}