/*
 * JBoss, Home of Professional Open Source
 * Copyright 2011, Red Hat, Inc. and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.mobicents.slee.resource;

import java.util.HashSet;
import java.util.Set;
import java.util.TimerTask;

import javax.slee.EventTypeID;
import javax.slee.InvalidArgumentException;
import javax.slee.InvalidStateException;
import javax.slee.SLEEException;
import javax.slee.ServiceID;
import javax.slee.TransactionRequiredLocalException;
import javax.slee.facilities.AlarmFacility;
import javax.slee.management.NotificationSource;
import javax.slee.management.ResourceAdaptorEntityNotification;
import javax.slee.management.ResourceAdaptorEntityState;
import javax.slee.management.SleeState;
import javax.slee.resource.ActivityFlags;
import javax.slee.resource.ActivityHandle;
import javax.slee.resource.ConfigProperties;
import javax.slee.resource.FireableEventType;
import javax.slee.resource.InvalidConfigurationException;
import javax.slee.resource.Marshaler;
import javax.slee.resource.ReceivableService;
import javax.slee.resource.ResourceAdaptor;
import javax.slee.resource.ResourceAdaptorID;
import javax.slee.resource.ResourceAdaptorTypeID;

import org.apache.log4j.Logger;
import org.mobicents.slee.container.SleeContainer;
import org.mobicents.slee.container.activity.ActivityContextHandle;
import org.mobicents.slee.container.activity.ActivityType;
import org.mobicents.slee.container.component.ra.ResourceAdaptorComponent;
import org.mobicents.slee.container.component.ratype.ResourceAdaptorTypeComponent;
import org.mobicents.slee.container.management.ResourceManagementImpl;
import org.mobicents.slee.container.management.jmx.ResourceUsageMBean;
import org.mobicents.slee.container.resource.ResourceAdaptorActivityContextHandle;
import org.mobicents.slee.container.resource.ResourceAdaptorEntity;
import org.mobicents.slee.container.resource.ResourceAdaptorObjectState;
import org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptor;
import org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptorContextImpl;

/**
 *
 * Implementation of the logical Resource Adaptor Entity and its life cycle.
 *
 * @author Eduardo Martins
 */
public class ResourceAdaptorEntityImpl implements ResourceAdaptorEntity {

	private static final Logger logger = Logger
			.getLogger(ResourceAdaptorEntity.class);

	/**
	 * the ra entity name
	 */
	private final String name;

	/**
	 * the ra component related to this entity
	 */
	private final ResourceAdaptorComponent component;

	/**
	 * the ra entity state
	 */
	private ResourceAdaptorEntityState state;

	/**
	 * the ra object
	 */
	private final ResourceAdaptorObjectImpl object;

	/**
	 * the slee container
	 */
	private final SleeContainer sleeContainer;

	/**
	 *
	 */
	private final ResourceManagementImpl resourceManagement;

	/**
	 * Notification source of this RA Entity
	 */
	private ResourceAdaptorEntityNotification notificationSource;

	/**
	 * Alarm facility serving this RA entity(notification source)
	 */
	private AlarmFacility alarmFacility;

	/**
	 * the resource usage mbean for this ra, may be null
	 */
	private final ResourceUsageMBean usageMbean;

	/**
	 * the ra context for this entity
	 */
	private final ResourceAdaptorContextImpl resourceAdaptorContext;

	/**
	 * the ra allowed event types, cached here for optimal runtime performance
	 */
	private final Set<EventTypeID> allowedEventTypes;

	private boolean setFTContext = true;

	@SuppressWarnings("rawtypes")
	private FaultTolerantResourceAdaptorContextImpl ftResourceAdaptorContext;

	/**
	 * Creates a new entity with the specified name, for the specified ra
	 * component and with the provided entity config properties. The entity
	 * creation is complete after instantianting the ra object, and then setting
	 * its ra context and configuration.
	 *
	 * @param name
	 * @param component
	 * @param entityProperties
	 * @param resourceManagement
	 * @throws InvalidConfigurationException
	 * @throws InvalidArgumentException
	 */
	public ResourceAdaptorEntityImpl(String name,
			ResourceAdaptorComponent component,
			ConfigProperties entityProperties, ResourceManagementImpl resourceManagement,
			ResourceAdaptorEntityNotification notificationSource, ResourceUsageMBean usageMbean)
			throws InvalidConfigurationException, InvalidArgumentException {
		this.name = name;
		this.component = component;
		this.resourceManagement = resourceManagement;
		this.sleeContainer = resourceManagement.getSleeContainer();
		this.notificationSource = notificationSource;
		this.usageMbean = usageMbean;
		this.alarmFacility = sleeContainer.getAlarmManagement().newAlarmFacility(notificationSource);
		// create ra object
		ClassLoader currentClassLoader = Thread.currentThread()
				.getContextClassLoader();
		try {
			Thread.currentThread().setContextClassLoader(
					component.getClassLoader());
			ResourceAdaptor ra = (ResourceAdaptor) this.component.getResourceAdaptorClass().newInstance();
			object = new ResourceAdaptorObjectImpl(this,ra, component
					.getDefaultConfigPropertiesInstance());
		} catch (Exception e) {
			throw new SLEEException(
					"unable to create instance of ra object for " + component,e);
		} finally {
			Thread.currentThread().setContextClassLoader(currentClassLoader);
		}
		// create ra context
		resourceAdaptorContext = new ResourceAdaptorContextImpl(this,
				sleeContainer);
		// cache runtime data
		if (!component.getDescriptor().getIgnoreRaTypeEventTypeCheck()) {
			// the slee endpoint will filter events fired, build a set with the
			// event types allowed
			allowedEventTypes = new HashSet<EventTypeID>();
			for (ResourceAdaptorTypeID raTypeID : resourceAdaptorContext
					.getResourceAdaptorTypes()) {
				ResourceAdaptorTypeComponent raTypeComponent = sleeContainer
						.getComponentRepository()
						.getComponentByID(raTypeID);
				for (EventTypeID eventTypeRef : raTypeComponent
						.getDescriptor().getEventTypeRefs()) {
					allowedEventTypes.add(eventTypeRef);
				}
			}
		} else {
			allowedEventTypes = null;
		}
		// set ra context
		try {
			object.setResourceAdaptorContext(resourceAdaptorContext);
		} catch (InvalidStateException e) {
			logger
					.error(
							"should not happen, setting ra context on ra entity creation",
							e);
			throw new SLEEException(e.getMessage(), e);
		}
		// configure
		object.raConfigure(entityProperties);
		// process to inactive state
		this.state = ResourceAdaptorEntityState.INACTIVE;
	}

	/**
	 * @return the sleeContainer
	 */
	public SleeContainer getSleeContainer() {
		return sleeContainer;
	}

	/**
	 * Retrieves ra component related to this entity
	 *
	 * @return
	 */
	public ResourceAdaptorComponent getComponent() {
		return component;
	}

	/**
	 * Retrieves the ra entity name
	 *
	 * @return
	 */
	public String getName() {
		return name;
	}

	/**
	 * Retrieves the ra entity state
	 *
	 * @return
	 */
	public ResourceAdaptorEntityState getState() {
		return state;
	}

	@Override
	public int hashCode() {
		return name.hashCode();
	}

	@Override
	public boolean equals(Object obj) {
		if (obj != null && obj.getClass() == this.getClass()) {
			return ((ResourceAdaptorEntityImpl) obj).name.equals(this.name);
		} else {
			return false;
		}
	}

	// --------- ra entity/object logic

	/**
	 * Updates the ra entity config properties
	 */
	public void updateConfigurationProperties(ConfigProperties properties)
			throws InvalidConfigurationException, InvalidStateException {
		if (!component.getDescriptor().getSupportsActiveReconfiguration()
				&& (sleeContainer.getSleeState() != SleeState.STOPPED)
				&& (state == ResourceAdaptorEntityState.ACTIVE || state == ResourceAdaptorEntityState.STOPPING)) {
			throw new InvalidStateException(
					"the value of the supports-active-reconfiguration attribute of the resource-adaptor-class element in the deployment descriptor of the Resource Adaptor of the resource adaptor entity is False and the resource adaptor entity is in the Active or Stopping state and the SLEE is in the Starting, Running, or Stopping state");
		} else {
			object.raConfigurationUpdate(properties);
		}
	}

	/**
	 * Signals that the container is in RUNNING state
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public void sleeRunning() throws InvalidStateException {
		// if entity is active then activate the ra object
		if (this.state.isActive()) {
			if (setFTContext) {
				setFTContext = false;
				if (object.isFaultTolerant()) {
					// set fault tolerant context, it is a ft ra
					try {
						this.ftResourceAdaptorContext = new FaultTolerantResourceAdaptorContextImpl(name,sleeContainer,(FaultTolerantResourceAdaptor) object.getResourceAdaptorObject());
						object.setFaultTolerantResourceAdaptorContext(ftResourceAdaptorContext);
					}
					catch (Throwable t) {
						logger.error("Got exception invoking setFaultTolerantResourceAdaptorContext(...) for entity "+name, t);
					}
				}
			}
			try {
				object.raActive();
			}
			catch (Throwable t) {
				logger.error("Got exception invoking raActive() for entity "+name, t);
			}
		}
	}

	/**
	 * Signals that the container is in STOPPING state
	 * @throws TransactionRequiredLocalException
	 */
	public void sleeStopping() throws InvalidStateException, TransactionRequiredLocalException {
		if (state != null && state.isActive()) {
			try {
				object.raStopping();
			}
			catch (Throwable t) {
				logger.error("Got exception from RA object",t);
			}
			scheduleAllActivitiesEnd();
		}
	}

	public void allActivitiesEnded() {

		logger.info("All activities ended for ra entity "+name);

		if (timerTask != null) {
			timerTask = null;
		}
		if (!this.state.isInactive()) {
			if (object.getState() == ResourceAdaptorObjectState.STOPPING) {
				try {
					object.raInactive();
				}
				catch (Throwable t) {
					logger.error("Got exception invoking raInactive() for entity "+name, t);
				}
			}
			if (state != null && state.isStopping()) {
				state = ResourceAdaptorEntityState.INACTIVE;
			}
		}
	}

	/**
	 * Activates the ra entity
	 *
	 * @throws InvalidStateException
	 *             if the entity is not in INACTIVE state
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public void activate() throws InvalidStateException {
		if (!this.state.isInactive()) {
			throw new InvalidStateException("entity " + name + " is in state: "
					+ this.state);
		}
		this.state = ResourceAdaptorEntityState.ACTIVE;
		// if slee is running then activate ra object
		if (sleeContainer.getSleeState() == SleeState.RUNNING) {
			if (setFTContext) {
				setFTContext = false;
				if (object.isFaultTolerant()) {
					// set fault tolerant context, it is a ft ra
					try {
						this.ftResourceAdaptorContext = new FaultTolerantResourceAdaptorContextImpl(name,sleeContainer,(FaultTolerantResourceAdaptor) object.getResourceAdaptorObject());
						object.setFaultTolerantResourceAdaptorContext(ftResourceAdaptorContext);
					}
					catch (Throwable t) {
						logger.error("Got exception invoking setFaultTolerantResourceAdaptorContext(...) for entity "+name, t);
					}
				}
			}
			try {
				object.raActive();
			}
			catch (Throwable t) {
				logger.error("Got exception invoking raActive() for entity "+name, t);
			}
		}
	}

	/**
	 * Deactivates the ra entity
	 *
	 * @throws InvalidStateException
	 *             if the entity is not in ACTIVE state
	 * @throws TransactionRequiredLocalException
	 */
	public void deactivate() throws InvalidStateException, TransactionRequiredLocalException {
		if (!this.state.isActive()) {
			throw new InvalidStateException("entity " + name + " is in state: "
					+ this.state);
		}
		this.state = ResourceAdaptorEntityState.STOPPING;
		if (object.getState() == ResourceAdaptorObjectState.ACTIVE) {
			object.raStopping();
		}
		// tck requires that the method returns with stopping state so do
		// all deactivation logic half a sec later
		TimerTask t = new TimerTask() {
			@Override
			public void run() {
				try {
					cancel();
					if (state == ResourceAdaptorEntityState.STOPPING) {
						if (object.getState() == ResourceAdaptorObjectState.STOPPING) {
							scheduleAllActivitiesEnd();
						}
						else {
							allActivitiesEnded();
						}
					}
				}
				catch (Throwable e) {
					logger.error(e.getMessage(),e);
				}
			}
		};
		resourceAdaptorContext.getTimer().schedule(t,500);
	}

	/**
	 * schedules the ending of all the entity activities, this is needed on ra
	 * entity deactivation or slee container stop, once the process ends it will
	 * invoke allActivitiesEnded to complete those processes
	 * @throws TransactionRequiredLocalException
	 */
	private void scheduleAllActivitiesEnd() throws TransactionRequiredLocalException {

		// schedule the end of all activities if the node is the single member of the cluster
		boolean skipActivityEnding = !sleeContainer.getCluster().isSingleMember();

		if (!skipActivityEnding && hasActivities()) {
			logger.info("RA entity "+name+" activities end scheduled.");
			timerTask = new EndAllActivitiesRAEntityTimerTask(this,sleeContainer);
		}
		else {
			allActivitiesEnded();
		}
	}

	/**
	 * Checks if the entity has activities besides the one passed as parameter (if not null).
	 * @param exceptHandle
	 * @return
	 */
	private boolean hasActivities() {
		try {
			for (ActivityContextHandle handle : sleeContainer
					.getActivityContextFactory()
					.getAllActivityContextsHandles()) {
				if (handle.getActivityType() == ActivityType.RA) {
					ResourceAdaptorActivityContextHandle raHandle = (ResourceAdaptorActivityContextHandle) handle;
					if (raHandle.getResourceAdaptorEntity().equals(this)) {

						logger.debug("**** AllActivityContextsHandles: "+sleeContainer
								.getActivityContextFactory()
								.getAllActivityContextsHandles());

						if (logger.isDebugEnabled()) {
							logger.debug("RA entity "+name+" has (at least) activity "+handle.getActivityHandle());
						}

						//return true;

						logger.warn("WORKAROUND USAGE: ENDING RESOURCE ADAPTOR ACTIVITIES");
						sleeContainer.getActivityContextFactory().WAremove("RA");
						return false;
					}
				}
			}
		} catch (Throwable e) {
			logger.error(e.getMessage(), e);
		}

		return false;
	}

	private EndAllActivitiesRAEntityTimerTask timerTask;

	/**
	 * Removes the entity, it will unconfigure and unset the ra context, the
	 * entity object can not be reused
	 *
	 * @throws InvalidStateException
	 */
	public void remove() throws InvalidStateException {
		if (!this.state.isInactive()) {
			throw new InvalidStateException("entity " + name + " is in state: "
						+ this.state);
		}
		object.raUnconfigure();
		if (object.isFaultTolerant()) {
			object.unsetFaultTolerantResourceAdaptorContext();
			ftResourceAdaptorContext.shutdown();
		}
		object.unsetResourceAdaptorContext();
		this.sleeContainer.getTraceManagement()
				.deregisterNotificationSource(this.getNotificationSource());
		state = null;
	}

	/**
	 * Retrieves the active config properties for the entity
	 *
	 * @return
	 */
	public ConfigProperties getConfigurationProperties() {
		return object.getConfigProperties();
	}

	/**
	 * Retrieves the id of the resource adaptor for this entity
	 *
	 * @return
	 */
	public ResourceAdaptorID getResourceAdaptorID() {
		return component.getResourceAdaptorID();
	}

	/**
	 * Retrieves the ra object
	 *
	 * @return
	 */
	public ResourceAdaptorObjectImpl getResourceAdaptorObject() {
		return object;
	}

	/**
	 * Retrieves the ra interface for this entity and the specified ra type
	 *
	 * @param raType
	 * @return
	 */
	public Object getResourceAdaptorInterface(ResourceAdaptorTypeID raType) {
		return object.getResourceAdaptorInterface(sleeContainer
				.getComponentRepository().getComponentByID(raType)
				.getDescriptor().getResourceAdaptorInterface());
	}

	/**
	 * Retrieves the marshaller from the ra object, if exists
	 *
	 * @return
	 */
	public Marshaler getMarshaler() {
		return object.getMarshaler();
	}

	/**
	 * Indicates a service was activated, the entity will forward this
	 * notification to the ra object.
	 *
	 * @param serviceInfo
	 */
	public void serviceActive(ServiceID serviceID) {
		try {
			ReceivableService receivableService = resourceAdaptorContext
					.getServiceLookupFacility().getReceivableService(serviceID);
			if (receivableService.getReceivableEvents().length > 0) {
				object.serviceActive(receivableService);
			}
		} catch (Throwable e) {
			logger.warn("invocation resulted in unchecked exception", e);
		}
	}

	/**
	 * Indicates a service is stopping, the entity will forward this
	 * notification to the ra object.
	 *
	 * @param serviceInfo
	 */
	public void serviceStopping(ServiceID serviceID) {
		try {
			ReceivableService receivableService = resourceAdaptorContext
					.getServiceLookupFacility().getReceivableService(serviceID);
			if (receivableService.getReceivableEvents().length > 0) {
				object.serviceStopping(receivableService);
			}
		} catch (Throwable e) {
			logger.warn("invocation resulted in unchecked exception", e);
		}
	}

	/**
	 * Indicates a service was deactivated, the entity will forward this
	 * notification to the ra object.
	 *
	 * @param serviceInfo
	 */
	public void serviceInactive(ServiceID serviceID) {
		try {
			ReceivableService receivableService = resourceAdaptorContext
					.getServiceLookupFacility().getReceivableService(serviceID);
			if (receivableService.getReceivableEvents().length > 0) {
				object.serviceInactive(receivableService);
			}
		} catch (Throwable e) {
			logger.warn("invocation resulted in unchecked exception", e);
		}
	}

	/**
	 * Return Notification source representing this RA Entity
	 *
	 * @return
	 */
	public NotificationSource getNotificationSource() {
		return this.notificationSource;
	}

	public AlarmFacility getAlarmFacility() {
		return alarmFacility;
	}

	/**
	 * Retrieves the resource usage mbean for this ra, may be null
	 *
	 * @return
	 */
	public ResourceUsageMBean getResourceUsageMBean() {
		return usageMbean;
	}

	/**
	 * Retrieves a set containing event types allowed to be fire by this entity
	 *
	 * @return null if the ra ignores event type checking
	 */
	public Set<EventTypeID> getAllowedEventTypes() {
		return allowedEventTypes;
	}

	public FireableEventType getFireableEventType(EventTypeID eventTypeID) {
		FireableEventType eventType = null;
		try {
			eventType = resourceAdaptorContext.getEventLookupFacility()
					.getFireableEventType(eventTypeID);
		} catch (Throwable e) {
			logger.error(e.getMessage(), e);
		}
		return eventType;
	}

	public ReceivableService getReceivableService(ServiceID serviceID) {
		ReceivableService receivableService = null;
		if (serviceID != null) {
			try {
				receivableService = resourceAdaptorContext
						.getServiceLookupFacility().getReceivableService(serviceID);
			} catch (Throwable e) {
				logger.error(e.getMessage(), e);
			}
		}
		return receivableService;
	}

	/**
	 * if it is a handle reference it gets the referred handle
	 * @param handle
	 * @return
	 */
	ActivityHandle derreferActivityHandle(ActivityHandle handle) {
		ActivityHandle ah = null;
		if (resourceManagement.getHandleReferenceFactory() != null && handle.getClass() == ActivityHandleReference.class) {
			ActivityHandleReference ahReference = (ActivityHandleReference) handle;
			ah = resourceManagement.getHandleReferenceFactory().getActivityHandle(ahReference);
		}
		else {
			ah = handle;
		}
		return ah;
	}

	/**
	 * Callback to notify the entity and possibly the ra object, informing activity handled ended.
	 * @param handle
	 * @param activityFlags
	 */
	public void activityEnded(final ActivityHandle handle, int activityFlags) {
		logger.trace("activityEnded( handle = " + handle + " )");
		ActivityHandle ah = null;
		if (handle instanceof ActivityHandleReference) {
			// handle is a ref, derrefer and remove the ref
			ah = resourceManagement.getHandleReferenceFactory().removeActivityHandleReference((ActivityHandleReference) handle);
		}
		else {
			// handle is not a reference
			ah = handle;
		}
		if (ah != null && ActivityFlags.hasRequestEndedCallback(activityFlags)) {
			object.activityEnded(ah);
		}
		if (object.getState() == ResourceAdaptorObjectState.STOPPING) {
			synchronized (this) {
				// the ra object is stopping, check if the timer task is still
				// needed
				if (!hasActivities()) {
					if (timerTask != null) {
						timerTask.cancel();
					}
					allActivitiesEnded();
				}
			}
		}
	}

	/* (non-Javadoc)
	 * @see org.mobicents.slee.resource.ResourceAdaptorEntity#getActivityContextHandle(javax.slee.resource.ActivityHandle)
	 */
	public ActivityContextHandle getActivityContextHandle(
			ActivityHandle activityHandle) {
		return new ResourceAdaptorActivityContextHandleImpl(this, activityHandle);
	}

	/**
	 *
	 * @return
	 */
	public ActivityHandleReferenceFactory getHandleReferenceFactory() {
		return resourceManagement.getHandleReferenceFactory();
	}
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2011, Red Hat, Inc. and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

/***************************************************
 *                                                 *
 *  Restcomm: The Open Source VoIP Platform       *
 *                                                 *
 *  Distributable under LGPL license.              *
 *  See terms of license at gnu.org.               *
 *                                                 *
 ***************************************************/

package org.mobicents.slee.container.management.jmx;

import javax.management.ObjectName;
import javax.slee.InvalidArgumentException;
import javax.slee.InvalidStateException;
import javax.slee.ServiceID;
import javax.slee.UnrecognizedServiceException;
import javax.slee.management.InvalidLinkNameBindingStateException;
import javax.slee.management.ManagementException;
import javax.slee.management.ServiceState;

import org.mobicents.slee.container.management.ServiceManagementImpl;

/**
 * Implementation of the ServiceManagementMBean
 *
 * @author M. Ranganathan
 * @author Eduardo Martins
 */
public class ServiceManagementMBeanImpl extends MobicentsServiceMBeanSupport implements
		ServiceManagementMBeanImplMBean {

	private final ServiceManagementImpl serviceManagement;

	public ServiceManagementMBeanImpl(ServiceManagementImpl serviceManagement) {
		super(serviceManagement.getSleeContainer());
		this.serviceManagement = serviceManagement;
	}

	/* (non-Javadoc)
	 * @see javax.slee.management.ServiceManagementMBean#activate(javax.slee.ServiceID)
	 */
	public void activate(ServiceID serviceID) throws NullPointerException,
			UnrecognizedServiceException, InvalidStateException,
			InvalidLinkNameBindingStateException, ManagementException {
		try {
			serviceManagement.activate(serviceID);
		}
		catch (NullPointerException e) {
			throw e;
		}
		catch (UnrecognizedServiceException e) {
			throw e;
		}
		catch (InvalidLinkNameBindingStateException e) {
			throw e;
		}
		catch (InvalidStateException e) {
			throw e;
		}
		catch (Throwable e) {
			throw new ManagementException(e.getMessage(),e);
		}
	}

	/* (non-Javadoc)
	 * @see javax.slee.management.ServiceManagementMBean#activate(javax.slee.ServiceID[])
	 */
	public void activate(ServiceID[] serviceIDs) throws NullPointerException,
	InvalidArgumentException, UnrecognizedServiceException,
	InvalidStateException, InvalidLinkNameBindingStateException,
	ManagementException {
		try {
			serviceManagement.activate(serviceIDs);
		}
		catch (NullPointerException e) {
			throw e;
		}
		catch (InvalidArgumentException e) {
			throw e;
		}
		catch (UnrecognizedServiceException e) {
			throw e;
		}
		catch (InvalidLinkNameBindingStateException e) {
			throw e;
		}
		catch (InvalidStateException e) {
			throw e;
		}
		catch (Throwable e) {
			throw new ManagementException(e.getMessage(),e);
		}
	}

	public void deactivate(ServiceID serviceID) throws NullPointerException,
			UnrecognizedServiceException, InvalidStateException,
			ManagementException {
		serviceManagement.deactivate(serviceID);
	}

	public void deactivate(ServiceID[] serviceIDs) throws NullPointerException,
			InvalidArgumentException, UnrecognizedServiceException,
			InvalidStateException, ManagementException {
		serviceManagement.deactivate(serviceIDs);
	}

	public void deactivateAndActivate(ServiceID arg0, ServiceID arg1)
			throws NullPointerException, InvalidArgumentException,
			UnrecognizedServiceException, InvalidStateException,
			ManagementException {
		serviceManagement.deactivateAndActivate(arg0, arg1);
	}

	public void deactivateAndActivate(ServiceID[] arg0, ServiceID[] arg1)
			throws NullPointerException, InvalidArgumentException,
			UnrecognizedServiceException, InvalidStateException,
			ManagementException {
		serviceManagement.deactivateAndActivate(arg0, arg1);
	}

	public ObjectName getServiceUsageMBean(ServiceID serviceID)
			throws NullPointerException, UnrecognizedServiceException,
			ManagementException {
		return serviceManagement.getServiceUsageMBean(serviceID);
	}

	public ServiceID[] getServices(ServiceState serviceState)
			throws NullPointerException, ManagementException {

		return serviceManagement.getServices(serviceState);
	}

	public ServiceState getState(ServiceID serviceID)
			throws NullPointerException, UnrecognizedServiceException,
			ManagementException {

		return serviceManagement.getState(serviceID);
	}

}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2011, Red Hat, Inc. and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.mobicents.slee.resource;

import java.io.Serializable;

import javax.slee.Address;
import javax.slee.InvalidStateException;
import javax.slee.resource.ActivityHandle;
import javax.slee.resource.ConfigProperties;
import javax.slee.resource.FailureReason;
import javax.slee.resource.FireableEventType;
import javax.slee.resource.InvalidConfigurationException;
import javax.slee.resource.Marshaler;
import javax.slee.resource.ReceivableService;
import javax.slee.resource.ResourceAdaptor;
import javax.slee.resource.ResourceAdaptorContext;

import org.apache.log4j.Logger;
import org.mobicents.slee.container.resource.ResourceAdaptorObject;
import org.mobicents.slee.container.resource.ResourceAdaptorObjectState;
import org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptor;
import org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptorContext;

/**
 * A wrapper for an ra object, managing its state and configuration
 *
 * @author Eduardo Martins
 *
 */
public class ResourceAdaptorObjectImpl implements ResourceAdaptorObject {

	/**
	 * the ra object
	 */
	private final ResourceAdaptor object;

	/**
	 * the state of the ra object
	 */
	private ResourceAdaptorObjectState state = null;

	/**
	 * the properties of the ra object/entity
	 */
	private ConfigProperties configProperties;

	private final ResourceAdaptorEntityImpl raEntity;

	private MarshallerWrapper marshaler;

	private final static Logger logger = Logger
			.getLogger(ResourceAdaptorObjectImpl.class);
	private static boolean doTraceLogs = logger.isTraceEnabled();

	/**
	 * Creates a new instance, for the specified ra object and with the
	 * specified configuration properties.
	 *
	 * @param raAdaptorEntity
	 * @param object
	 * @param configProperties
	 */
	public ResourceAdaptorObjectImpl(ResourceAdaptorEntityImpl raEntity,
			ResourceAdaptor object, ConfigProperties configProperties) {
		this.raEntity = raEntity;
		this.object = object;
		this.configProperties = configProperties;
	}

	/**
	 * Retrieves the current ra object configuration
	 *
	 * @return
	 */
	public ConfigProperties getConfigProperties() {
		return configProperties;
	}

	/**
	 * Retrieves the current ra object state
	 *
	 * @return
	 */
	public ResourceAdaptorObjectState getState() {
		return state;
	}

	// OPERATIONS ON RA OBJECT

	/*
	 * (non-Javadoc)
	 *
	 * @see org.mobicents.slee.container.resource.ResourceAdaptorObject#
	 * setResourceAdaptorContext(javax.slee.resource.ResourceAdaptorContext)
	 */
	public void setResourceAdaptorContext(ResourceAdaptorContext context)
			throws InvalidStateException {

		if (doTraceLogs) {
			logger.trace("setResourceAdaptorContext( context = " + context
					+ " )");
		}

		if (state == null) {
			state = ResourceAdaptorObjectState.UNCONFIGURED;
			object.setResourceAdaptorContext(context);
		} else {
			throw new InvalidStateException("ra object is in state " + state);
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.mobicents.slee.container.resource.ResourceAdaptorObject#
	 * setFaultTolerantResourceAdaptorContext
	 * (org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptorContext)
	 */
	@SuppressWarnings("unchecked")
	public void setFaultTolerantResourceAdaptorContext(
			FaultTolerantResourceAdaptorContext<Serializable, Serializable> context)
			throws IllegalArgumentException {

		if (doTraceLogs) {
			logger.trace("setFaultTolerantResourceAdaptorContext( context = "
					+ context + " )");
		}

		if (isFaultTolerant()) {
			((FaultTolerantResourceAdaptor<Serializable, Serializable>) this.object)
					.setFaultTolerantResourceAdaptorContext(context);
		} else {
			throw new IllegalArgumentException(
					"RA Object is not fault tolerant!");
		}

	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.mobicents.slee.container.resource.ResourceAdaptorObject#raConfigure
	 * (javax.slee.resource.ConfigProperties)
	 */
	public void raConfigure(ConfigProperties properties)
			throws InvalidConfigurationException {

		if (doTraceLogs) {
			logger.trace("raConfigure( properties = " + properties + " )");
		}

		verifyConfigProperties(properties);
		object.raConfigure(configProperties);
		if (state == ResourceAdaptorObjectState.UNCONFIGURED) {
			state = ResourceAdaptorObjectState.INACTIVE;
		}
	}

	/**
	 * Updates the ra configuration.
	 *
	 * @param properties
	 * @throws InvalidConfigurationException
	 *             if the configuration, after merging the specified properties
	 *             with the current properties values, results in an invalid
	 *             configuration
	 */
	public void raConfigurationUpdate(ConfigProperties properties)
			throws InvalidConfigurationException {

		if (doTraceLogs) {
			logger.trace("raConfigurationUpdate( properties = " + properties
					+ " )");
		}

		verifyConfigProperties(properties);
		object.raConfigurationUpdate(configProperties);
	}

	/**
	 * Merges the current properties values with the new ones and uses the ra to
	 * verify the configuration
	 *
	 * @param newProperties
	 * @throws InvalidConfigurationException
	 *             if the configuration, after merging the specified properties
	 *             with the current properties values, results in an invalid
	 *             configuration
	 */
	private void verifyConfigProperties(ConfigProperties newProperties)
			throws InvalidConfigurationException {

		if (doTraceLogs) {
			logger.trace("verifyConfigProperties( newProperties = "
					+ newProperties + " )");
		}

		// merge properties
		for (ConfigProperties.Property configProperty : configProperties
				.getProperties()) {
			if (newProperties.getProperty(configProperty.getName()) == null) {
				newProperties.addProperty(configProperty);
			}
		}
		// validate result
		for (ConfigProperties.Property entityProperty : newProperties
				.getProperties()) {
			if (entityProperty.getValue() == null) {
				throw new InvalidConfigurationException("the property "
						+ entityProperty.getName() + " has null value");
			}
		}
		// validate in ra object
		object.raVerifyConfiguration(newProperties);
		// ok, switch config
		configProperties = newProperties;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.mobicents.slee.container.resource.ResourceAdaptorObject#raActive()
	 */
	public void raActive() throws InvalidStateException {

		if (doTraceLogs) {
			logger.trace("raActive()");
		}

		if (state == ResourceAdaptorObjectState.INACTIVE) {
			state = ResourceAdaptorObjectState.ACTIVE;
			object.raActive();
		} else {
			throw new InvalidStateException("ra object is in state " + state);
		}
	}

	/**
	 * Requests the stopping of the ra object. If the operation succeeds the ra
	 * will transition to STOPPING state.
	 *
	 * @throws InvalidStateException
	 *             if the ra object is not in ACTIVE state
	 */
	public void raStopping() throws InvalidStateException {

		if (doTraceLogs) {
			logger.trace("raStopping()");
		}

		if (state == ResourceAdaptorObjectState.ACTIVE) {
			state = ResourceAdaptorObjectState.STOPPING;
			object.raStopping();
		} else {
			throw new InvalidStateException("ra object is in state " + state);
		}
	}

	/**
	 * Requests the deactivation of the ra object. If the operation succeeds the
	 * ra will transition to INACTIVE state.
	 *
	 * @throws InvalidStateException
	 *             if the ra object is not in STOPPING state
	 */
	public void raInactive() throws InvalidStateException {

		if (doTraceLogs) {
			logger.trace("raInactive()");
		}

		if (state == ResourceAdaptorObjectState.STOPPING) {
			state = ResourceAdaptorObjectState.INACTIVE;
			object.raInactive();
		} else {
			throw new InvalidStateException("ra object is in state " + state);
		}
	}

	/**
	 * Unconfigures the ra object
	 *
	 * @throws InvalidStateException
	 *             if the ra object is not in INACTIVE state
	 */
	public void raUnconfigure() throws InvalidStateException {

		if (doTraceLogs) {
			logger.trace("raUnconfigure()");
		}

		if (state == ResourceAdaptorObjectState.INACTIVE) {
			state = ResourceAdaptorObjectState.UNCONFIGURED;
			object.raUnconfigure();
		} else {
			throw new InvalidStateException("ra object is in state " + state);
		}
	}

	/**
	 * Unsets the context of the ra object.
	 *
	 * @throws InvalidStateException
	 *             if the ra object is not in UNCONFIGURED state
	 */
	public void unsetResourceAdaptorContext() throws InvalidStateException {

		if (doTraceLogs) {
			logger.trace("unsetResourceAdaptorContext()");
		}

		if (state == ResourceAdaptorObjectState.UNCONFIGURED) {
			object.unsetResourceAdaptorContext();
			state = null;
		} else {
			throw new InvalidStateException("ra object is in state " + state);
		}
	}

	/**
	 * Unsets the ft context of the ra object.
	 *
	 * @throws IllegalArgumentException
	 *             if the ra object is not in fault tolerant
	 */
	@SuppressWarnings("unchecked")
	public void unsetFaultTolerantResourceAdaptorContext()
			throws IllegalArgumentException {

		if (doTraceLogs) {
			logger.trace("unsetFaultTolerantResourceAdaptorContext()");
		}

		if (isFaultTolerant()) {
			((FaultTolerantResourceAdaptor<Serializable, Serializable>) this.object)
					.unsetFaultTolerantResourceAdaptorContext();
		} else {
			throw new IllegalArgumentException(
					"RA Object is not fault tolerant!");
		}
	}

	/**
	 * @see ResourceAdaptor#getResourceAdaptorInterface(ResourceAdaptorTypeID)
	 */
	public Object getResourceAdaptorInterface(String className) {

		if (doTraceLogs) {
			logger.trace("getResourceAdaptorInterface( className = "
					+ className + " )");
		}

		return object.getResourceAdaptorInterface(className);
	}

	/**
	 * @see ResourceAdaptor#getMarshaller()
	 */
	public Marshaler getMarshaler() {

		if (doTraceLogs) {
			logger.trace("getMarshaler()");
		}

		if (marshaler == null) {
			Marshaler realMarshaler = object.getMarshaler();
			marshaler = realMarshaler == null ? null : new MarshallerWrapper(
					realMarshaler, raEntity);
		}

		return marshaler;
	}

	/**
	 * @see ResourceAdaptor#serviceActive(ReceivableService)
	 * @param serviceInfo
	 */
	public void serviceActive(ReceivableService serviceInfo) {

		if (doTraceLogs) {
			logger.trace("serviceActive( serviceInfo = " + serviceInfo + " )");
		}

		object.serviceActive(serviceInfo);
	}

	/**
	 * @see ResourceAdaptor#serviceStopping(ReceivableService)
	 * @param serviceInfo
	 */
	public void serviceStopping(ReceivableService serviceInfo) {

		if (doTraceLogs) {
			logger.trace("serviceStopping( serviceInfo = " + serviceInfo + " )");
		}

		object.serviceStopping(serviceInfo);
	}

	/**
	 * @see ResourceAdaptor#serviceInactive(ReceivableService)
	 * @param serviceInfo
	 */
	public void serviceInactive(ReceivableService serviceInfo) {

		if (doTraceLogs) {
			logger.trace("serviceInactive( serviceInfo = " + serviceInfo + " )");
		}

		object.serviceInactive(serviceInfo);
	}

	/**
	 * @see ResourceAdaptor#getActivityHandle(Object)
	 * @param activity
	 * @return null if the activity does not belongs to this ra object
	 */
	public ActivityHandle getActivityHandle(Object activity) {

		if (doTraceLogs) {
			logger.trace("getActivityHandle( activity = " + activity + " )");
		}

		ActivityHandle activityHandle = object.getActivityHandle(activity);
		if (raEntity.getHandleReferenceFactory() != null
				&& activityHandle != null) {
			ActivityHandle reference = raEntity.getHandleReferenceFactory()
					.getReferenceTransacted(activityHandle);
			if (reference != null) {
				activityHandle = reference;
			}
		}
		return activityHandle;
	}

	/**
	 * @see ResourceAdaptor#getActivity(ActivityHandle)
	 * @param handle
	 */
	public Object getActivity(ActivityHandle handle) {

		if (doTraceLogs) {
			logger.trace("getActivity( handle = " + handle + " )");
		}

		final ActivityHandle origHandle = raEntity
				.derreferActivityHandle(handle);
		return origHandle != null ? object.getActivity(origHandle) : null;
	}

	/**
	 * @see ResourceAdaptor#activityEnded(ActivityHandle)
	 * @param handle
	 */
	public void activityEnded(ActivityHandle handle) {

		if (doTraceLogs) {
			logger.trace("activityEnded( handle = " + handle + " )");
		}

		object.activityEnded(handle);
	}

	/**
	 * @see ResourceAdaptor#administrativeRemove(ActivityHandle)
	 * @param handle
	 */
	public void administrativeRemove(ActivityHandle handle) {

		if (doTraceLogs) {
			logger.trace("administrativeRemove( handle = " + handle + " )");
		}

		object.administrativeRemove(raEntity.derreferActivityHandle(handle));
	}

	/**
	 * @see ResourceAdaptor#activityUnreferenced(ActivityHandle)
	 * @param handle
	 */
	public void activityUnreferenced(ActivityHandle handle) {

		if (doTraceLogs) {
			logger.trace("activityUnreferenced( handle = " + handle + " )");
		}

		object.activityUnreferenced(raEntity.derreferActivityHandle(handle));
	}

	/**
	 * @see ResourceAdaptor#queryLiveness(ActivityHandle)
	 * @param handle
	 */
	public void queryLiveness(ActivityHandle handle) {

		if (doTraceLogs) {
			logger.trace("queryLiveness( handle = " + handle + " )");
		}

		object.queryLiveness(raEntity.derreferActivityHandle(handle));
	}

	/**
	 * @see ResourceAdaptor#eventProcessingFailed(ActivityHandle,
	 *      FireableEventType, Object, Address, ReceivableService, int,
	 *      FailureReason)
	 * @param handle
	 * @param eventType
	 * @param event
	 * @param address
	 * @param service
	 * @param flags
	 * @param reason
	 */
	public void eventProcessingFailed(ActivityHandle handle,
			FireableEventType eventType, Object event, Address address,
			ReceivableService service, int flags, FailureReason reason) {

		if (doTraceLogs) {
			logger.trace("eventProcessingFailed( handle = " + handle
					+ " , eventType = " + eventType + " , event = " + event
					+ " , address = " + address + " , service = " + service
					+ " , flags = " + flags + " , reason = " + reason + " )");
		}

		object.eventProcessingFailed(handle, eventType, event, address,
				service, flags, reason);
	}

	/**
	 * @see ResourceAdaptor#eventProcessingSuccessful(ActivityHandle,
	 *      FireableEventType, Object, Address, ReceivableService, int)
	 * @param handle
	 * @param eventType
	 * @param event
	 * @param address
	 * @param service
	 * @param flags
	 */
	public void eventProcessingSuccessful(ActivityHandle handle,
			FireableEventType eventType, Object event, Address address,
			ReceivableService service, int flags) {

		if (doTraceLogs) {
			logger.trace("eventProcessingSuccessful( handle = " + handle
					+ " , eventType = " + eventType + " , event = " + event
					+ " , address = " + address + " , service = " + service
					+ " , flags = " + flags + " )");
		}

		if (this.state == ResourceAdaptorObjectState.ACTIVE
				|| this.state == ResourceAdaptorObjectState.STOPPING) {
			object.eventProcessingSuccessful(handle, eventType, event, address,
					service, flags);
		}
	}

	/**
	 * @see ResourceAdaptor#eventUnreferenced(ActivityHandle, FireableEventType,
	 *      Object, Address, ReceivableService, int)
	 * @param handle
	 * @param eventType
	 * @param event
	 * @param address
	 * @param service
	 * @param flags
	 */
	public void eventUnreferenced(ActivityHandle handle,
			FireableEventType eventType, Object event, Address address,
			ReceivableService service, int flags) {

		if (doTraceLogs) {
			logger.trace("eventUnreferenced( handle = " + handle
					+ " , eventType = " + eventType + " , event = " + event
					+ " , address = " + address + " , service = " + service
					+ " , flags = " + flags + " )");
		}

		if (this.state == ResourceAdaptorObjectState.ACTIVE
				|| this.state == ResourceAdaptorObjectState.STOPPING) {
			object.eventUnreferenced(handle, eventType, event, address,
					service, flags);
		}
	}

	public boolean isFaultTolerant() {
		return this.object instanceof FaultTolerantResourceAdaptor;
	}

	public ResourceAdaptor getResourceAdaptorObject() {
		return object;
	}
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2011, Red Hat, Inc. and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

/**
 * Start time:15:32:06 2009-02-02

 * Project: restcomm-jainslee-server-core

 *
 * @author baranowb - Bartosz Baranowski
 *
 * @author  Alexandre Mendonca
 */
package org.mobicents.slee.container.component;

import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.slee.ComponentID;
import javax.slee.facilities.AlarmFacility;
import javax.slee.management.ComponentDescriptor;
import javax.slee.management.DependencyException;
import javax.slee.management.DeploymentException;
import javax.slee.management.LibraryID;
import javax.slee.profile.ProfileSpecificationID;

import org.mobicents.slee.container.component.UsageParameterDescriptor;
import org.mobicents.slee.container.component.deployment.jaxb.descriptors.ProfileSpecificationDescriptorImpl;
import org.mobicents.slee.container.component.profile.ProfileAttribute;
import org.mobicents.slee.container.component.profile.ProfileAttributeImpl;
import org.mobicents.slee.container.component.profile.ProfileConcreteClassInfo;
import org.mobicents.slee.container.component.profile.ProfileConcreteClassInfoImpl;
import org.mobicents.slee.container.component.profile.ProfileIndexDescriptor;
import org.mobicents.slee.container.component.profile.cmp.ProfileCMPFieldDescriptor;
import org.mobicents.slee.container.component.security.PermissionHolderImpl;
import org.mobicents.slee.container.component.validator.ProfileSpecificationComponentValidator;
import org.mobicents.slee.container.profile.entity.ProfileEntityFramework;

/**
 * Start time:15:32:06 2009-02-02

 * Project: restcomm-jainslee-server-core

 *
 * @author baranowb - Bartosz Baranowski
 *
 * @author  Alexandre Mendonca
 *
 * @author martins
 */
public class ProfileSpecificationComponentImpl extends AbstractSleeComponentWithUsageParametersInterface implements org.mobicents.slee.container.component.profile.ProfileSpecificationComponent {

	/**
	 * the profile specification descriptor
	 */
	private final ProfileSpecificationDescriptorImpl descriptor;

	/**
	 * the profile abstract class
	 */
	private Class<?> profileAbstractClass = null;

	/**
	 * a map containing all attributes of the profile specification
	 */
	private Map<String, ProfileAttribute> profileAttributeMap;

	/**
	 * the profile cmp interface
	 */
	private Class<?> profileCmpInterfaceClass = null;

	/**
	 * the Profile CMP Slee 1.0 Wrapper, an object that implements the Profile CMP
	 * Interface, wrapping the SLEE 1.1 real profile concrete object in a SLEE 1.0
	 * compatible interface
	 */
	private Class<?> profileCmpSlee10WrapperClass;

	/**
	 * holds concrete class that implementeds all required interface and methods
	 */
	private Class<?> profileConcreteClass = null;

	/**
	 * the entity framework for the component
	 */
	private ProfileEntityFramework profileEntityFramework;

	/**
	 * the profile local interface
	 */
	private Class<?> profileLocalInterfaceClass = null;

	/**
	 *
	 */
	private Class<?> profileLocalObjectConcreteClass;

	/**
	 * the profile management interface
	 */
	private Class<?> profileManagementInterfaceClass = null;

	/**
	 * Holds refence to concrete MBean Impl for mgmt mbean for this profiel spec
	 */
	private Class<?> profileMBeanConcreteImplClass = null;

	/**
	 * holds reference to generate MBean interface class for this specification
	 */
	private Class<?> profileMBeanConcreteInterfaceClass = null;

	/**
	 * Dont know yet what it is? ;[
	 */
	private Class<?> profilePersistanceTransientStateConcreteClass;

	/**
	 * Class<?> object for profiel table.
	 */
	private Class<?> profileTableConcreteClass;

	/**
	 * the profile table interface
	 */
	private Class<?> profileTableInterfaceClass = null;

	/**
	 * the JAIN SLEE specs descriptor
	 */
	private javax.slee.profile.ProfileSpecificationDescriptor specsDescriptor = null;

	/**
	 * info about the profile concrete class
	 */
	private ProfileConcreteClassInfo profileConcreteClassInfo = new ProfileConcreteClassInfoImpl();

	/**
	 * the alarm facility for the profile spec
	 */
	private AlarmFacility alarmFacility;

	/**
	 *
	 * @param descriptor
	 */
	public ProfileSpecificationComponentImpl(ProfileSpecificationDescriptorImpl descriptor) {
		this.descriptor = descriptor;
	}

	@Override
	public boolean addToDeployableUnit() {
		return getDeployableUnit().getProfileSpecificationComponents().put(getProfileSpecificationID(), this) == null;
	}

	/**
	 * Builds the profile attribute map using the cmp interface class
	 * @throws DeploymentException
	 */
	private void buildProfileAttributeMap() throws DeploymentException {
		 HashMap<String, ProfileAttribute> map = new HashMap<String, ProfileAttribute>();
		 Class<?> cmpInterface = getProfileCmpInterfaceClass();
		 String attributeGetterMethodPrefix = "get";
		 for (Method method : cmpInterface.getMethods()) {
			 if (!method.getDeclaringClass().equals(Object.class) && method.getName().startsWith(attributeGetterMethodPrefix)) {
				 String attributeName = method.getName().substring(attributeGetterMethodPrefix.length());
				 switch (attributeName.length()) {
				 case 0:
					throw new DeploymentException("the profile cmp interface class has an invalid attribute getter method name > "+method.getName());
				 case 1:
					attributeName = attributeName.toLowerCase();
					break;
				 default:
					attributeName = attributeName.substring(0, 1).toLowerCase() + attributeName.substring(1);
				 	break;
				 }
				 ProfileAttributeImpl profileAttribute = null;
				 try {
					profileAttribute = new ProfileAttributeImpl(attributeName,method.getReturnType());
				 } catch (Throwable e) {
					throw new DeploymentException("Invalid profile cmp interface attribute getter method definition ( name = "+attributeName+" , type = "+method.getReturnType()+" )",e);
				 }
				 if (isSlee11()) {
					 for (ProfileCMPFieldDescriptor cmpField : getDescriptor().getProfileCMPInterface().getCmpFields()) {
						 if (cmpField.getCmpFieldName().equals(attributeName)) {
							 // TODO add index hints ?
							 profileAttribute.setUnique(cmpField.isUnique());
						 }
					 }
				 }
				 else {
					 for (ProfileIndexDescriptor profileIndex : getDescriptor().getIndexedAttributes()) {
						 if (profileIndex.getName().equals(attributeName)) {
							 profileAttribute.setIndex(true);
							 profileAttribute.setUnique(profileIndex.getUnique());
						 }
					 }
				 }
				 map.put(attributeName, profileAttribute);
			 }
		 }
		 profileAttributeMap = Collections.unmodifiableMap(map);
	}

	@Override
	public ComponentDescriptor getComponentDescriptor() {
		return getSpecsDescriptor();
	}

	@Override
	public ComponentID getComponentID() {
		return getProfileSpecificationID();
	}

	@Override
	public Set<ComponentID> getDependenciesSet() {
		return descriptor.getDependenciesSet();
	}

	/**
	 * Retrieves the profile specification descriptor
	 *
	 * @return
	 */
	public ProfileSpecificationDescriptorImpl getDescriptor() {
		return descriptor;
	}

	/**
	 * Retrieves the profile abstract class
	 *
	 * @return
	 */
	public Class<?> getProfileAbstractClass() {
		return profileAbstractClass;
	}

	/**
	 *
	 * @return the profileConcreteClassInfo
	 */
	public ProfileConcreteClassInfo getProfileConcreteClassInfo() {
		return profileConcreteClassInfo;
	}

	/**
	 * Retrieves a unmodifiable map of {@link ProfileAttribute}, the key of this map is the attribute name
	 * @return
	 */
	public Map<String, ProfileAttribute> getProfileAttributes() {
		return profileAttributeMap;
	}

	/**
	 * Returns class object representing concrete impl of cmp interface - it
	 * implements all required
	 *
	 * @return
	 */
	public Class<?> getProfileCmpConcreteClass() {
		return profileConcreteClass;
	}

	/**
	 * Retrieves the profile cmp interface
	 *
	 * @return
	 */
	public Class<?> getProfileCmpInterfaceClass() {
		return profileCmpInterfaceClass;
	}

	/**
	 * Retreives the Profile CMP Slee 1.0 Wrapper class, an object that implements the Profile CMP
	 * Interface, wrapping the SLEE 1.1 real profile concrete object in a SLEE 1.0
	 * compatible interface
	 * @return
	 */
	public Class<?> getProfileCmpSlee10WrapperClass() {
		return profileCmpSlee10WrapperClass;
	}

	/**
	 * Retrieves the entity framework for the component
	 * @return
	 */
	public ProfileEntityFramework getProfileEntityFramework() {
		return profileEntityFramework;
	}

	/**
	 * Retrieves the profile local interface
	 *
	 * @return
	 */
	public Class<?> getProfileLocalInterfaceClass() {
		return profileLocalInterfaceClass;
	}

	/**
	 * sget profile local object concrete class - this is instrumented class
	 * that handles runtime calls
	 *
	 * @return
	 */
	public Class<?> getProfileLocalObjectConcreteClass() {
		return this.profileLocalObjectConcreteClass;

	}

	/**
	 * Retrieves the profile management interface
	 *
	 * @return
	 */
	public Class<?> getProfileManagementInterfaceClass() {
		return profileManagementInterfaceClass;
	}

	/**
	 * returns concrete MBean impl that manages this profile spec
	 *
	 * @return
	 */
	public Class<?> getProfileMBeanConcreteImplClass() {
		return profileMBeanConcreteImplClass;
	}

	/**
	 * Returns concrete/generated mbean interface for this profile specs
	 *
	 * @return
	 */
	public Class<?> getProfileMBeanConcreteInterfaceClass() {
		return profileMBeanConcreteInterfaceClass;
	}

	public Class<?> getProfilePersistanceTransientStateConcreteClass() {
		return profilePersistanceTransientStateConcreteClass;
	}

	/**
	 * Retrieves the profile specification id
	 *
	 * @return
	 */
	public ProfileSpecificationID getProfileSpecificationID() {
		return descriptor.getProfileSpecificationID();
	}

	/**
	 * get profile table concrete class - its impl of profile table interface -
	 * either default or provided by dev - this is instrumented class that
	 * handles runtime calls
	 *
	 * @return
	 */
	public Class<?> getProfileTableConcreteClass() {
		return this.profileTableConcreteClass;

	}

	/**
	 * Retrieves the profile table interface
	 *
	 * @return
	 */
	public Class<?> getProfileTableInterfaceClass() {
		return profileTableInterfaceClass;
	}

	/**
	 * Retrieves the JAIN SLEE specs descriptor
	 *
	 * @return
	 */
	public javax.slee.profile.ProfileSpecificationDescriptor getSpecsDescriptor() {
		if (specsDescriptor == null) {
			final LibraryID[] libraryIDs = descriptor.getLibraryRefs().toArray(new LibraryID[descriptor.getLibraryRefs().size()]);
			final ProfileSpecificationID[] profileSpecs = new ProfileSpecificationID[descriptor.getProfileSpecRefs().size()];
			for (int i = 0; i < profileSpecs.length; i++) {
				profileSpecs[i] = descriptor.getProfileSpecRefs().get(i).getComponentID();
			}
			specsDescriptor = new javax.slee.profile.ProfileSpecificationDescriptor(getProfileSpecificationID(), getDeployableUnit().getDeployableUnitID(), getDeploymentUnitSource(), libraryIDs, profileSpecs,
					getDescriptor().getProfileCMPInterface().getProfileCmpInterfaceName());
		}
		return specsDescriptor;
	}

	@Override
	public boolean isSlee11() {
		return this.descriptor.isSlee11();
	}

	@Override
	public void processSecurityPermissions() throws DeploymentException {
		try {
			if (this.descriptor.getSecurityPermissions() != null) {
				super.permissions.add(new PermissionHolderImpl(super.getDeploymentDir().toURI(), this.descriptor.getSecurityPermissions()));
			}
		} catch (Exception e) {
			throw new DeploymentException("Failed to make permissions usable.", e);
		}
	}

	/**
	 * Sets the profile abstract class
	 *
	 * @param profileAbstractClass
	 */
	public void setProfileAbstractClass(Class<?> profileAbstractClass) {
		this.profileAbstractClass = profileAbstractClass;
	}

	/**
	 * Set class object representing concrete impl of cmp interface - it
	 * implements all required
	 *
	 * @param profileCmpConcreteClass
	 */
	public void setProfileCmpConcreteClass(Class<?> profileCmpConcreteClass) {
		this.profileConcreteClass = profileCmpConcreteClass;
	}

	/**
	 * Sets the profile cmp interface and builds the profile attribute map
	 *
	 * @param profileCmpInterfaceClass
	 * @throws DeploymentException
	 */
	public void setProfileCmpInterfaceClass(Class<?> profileCmpInterfaceClass) throws DeploymentException {
		this.profileCmpInterfaceClass = profileCmpInterfaceClass;
		buildProfileAttributeMap();
	}

	/**
	 * Sets the Profile CMP Slee 1.0 Wrapper class, an object that implements the Profile CMP
	 * Interface, wrapping the SLEE 1.1 real profile concrete object in a SLEE 1.0
	 * compatible interface
	 * @param clazz
	 */
	public void setProfileCmpSlee10WrapperClass(Class<?> clazz) {
		this.profileCmpSlee10WrapperClass = clazz;
	}

	/**
	 * Sets the entity framework for the component
	 * @param profileEntityFramework
	 */
	public void setProfileEntityFramework(
			ProfileEntityFramework profileEntityFramework) {
		this.profileEntityFramework = profileEntityFramework;
	}

	/**
	 * Sets the profile local interface
	 *
	 * @param profileLocalInterfaceClass
	 */
	public void setProfileLocalInterfaceClass(Class<?> profileLocalInterfaceClass) {
		this.profileLocalInterfaceClass = profileLocalInterfaceClass;
	}

	/**
	 * set profile local object concrete class - this is instrumented class that
	 * handles runtime calls
	 *
	 * @param clazz
	 */
	public void setProfileLocalObjectConcreteClass(Class<?> clazz) {
		this.profileLocalObjectConcreteClass = clazz;

	}

	/**
	 * Sets the profile management interface
	 *
	 * @param profileManagementInterfaceClass
	 */
	public void setProfileManagementInterfaceClass(Class<?> profileManagementInterfaceClass) {
		this.profileManagementInterfaceClass = profileManagementInterfaceClass;
	}

	/**
	 * sets concrete MBean impl that manages this profile spec
	 *
	 * @param profileMBeanConcreteImplClass
	 */
	public void setProfileMBeanConcreteImplClass(Class<?> profileMBeanConcreteImplClass) {
		this.profileMBeanConcreteImplClass = profileMBeanConcreteImplClass;
	}

	/**
	 * Sets concrete/generated mbean interface for this profile specs
	 *
	 * @param profileMBeanConcreteInterfaceClass
	 */
	public void setProfileMBeanConcreteInterfaceClass(Class<?> profileMBeanConcreteInterfaceClass) {
		this.profileMBeanConcreteInterfaceClass = profileMBeanConcreteInterfaceClass;
	}

	public void setProfilePersistanceTransientStateConcreteClass(Class<?> profilePersistanceTransientStateConcreteClass) {
		this.profilePersistanceTransientStateConcreteClass = profilePersistanceTransientStateConcreteClass;

	}

	/**
	 * set profile table concrete class - its impl of profile table interface -
	 * either default or provided by dev - this is instrumented class that
	 * handles runtime calls
	 *
	 * @param clazz
	 */
	public void setProfileTableConcreteClass(Class<?> clazz) {

		this.profileTableConcreteClass = clazz;
	}

	/**
	 * Sets the profile table interface
	 *
	 * @param profileTableInterfaceClass
	 */
	public void setProfileTableInterfaceClass(Class<?> profileTableInterfaceClass) {
		this.profileTableInterfaceClass = profileTableInterfaceClass;
	}

	@Override
	public boolean validate() throws DependencyException, DeploymentException {
		ProfileSpecificationComponentValidator validator = new ProfileSpecificationComponentValidator();
		validator.setComponent(this);
		validator.setComponentRepository(getDeployableUnit().getDeployableUnitRepository());
		return validator.validate();
	}

	@Override
	public void undeployed() {
		super.undeployed();
		specsDescriptor = null;
		profileAbstractClass = null;
		profileAttributeMap = null;
		profileCmpInterfaceClass = null;
		profileCmpSlee10WrapperClass = null;
		profileConcreteClass = null;
		profileEntityFramework = null;
		profileLocalInterfaceClass = null;
		profileLocalObjectConcreteClass = null;
		profileManagementInterfaceClass = null;
		profileMBeanConcreteImplClass = null;
		profileMBeanConcreteInterfaceClass = null;
		profilePersistanceTransientStateConcreteClass = null;
		profileTableConcreteClass = null;
		profileTableInterfaceClass = null;
	}

	/* (non-Javadoc)
	 * @see org.mobicents.slee.container.component.AbstractSleeComponentWithUsageParametersInterface#getUsageParametersList()
	 */
	@Override
	public List<UsageParameterDescriptor> getUsageParametersList() {
		return descriptor.getProfileUsageParameterInterface().getUsageParameter();
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.container.component.profile.ProfileSpecificationComponent#getAlarmFacility()
	 */
	public AlarmFacility getAlarmFacility() {
		return alarmFacility;
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.container.component.profile.ProfileSpecificationComponent#setAlarmFacility(javax.slee.facilities.AlarmFacility)
	 */
	public void setAlarmFacility(AlarmFacility alarmFacility) {
		this.alarmFacility = alarmFacility;
	}
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2011, Red Hat, Inc. and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

/**
 *
 */
package org.mobicents.slee.container.event;

import java.util.LinkedList;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import javax.slee.SLEEException;
import javax.slee.TransactionRequiredLocalException;
import javax.transaction.SystemException;
import javax.transaction.Transaction;

import org.apache.log4j.Logger;
import org.mobicents.slee.container.SleeContainer;
import org.mobicents.slee.container.transaction.TransactionContext;
import org.mobicents.slee.container.transaction.TransactionalAction;

/**
 * @author martins
 *
 */
public class EventContextSuspensionHandler {

	private final EventContextImpl event;

	private final SleeContainer sleeContainer;

	/**
	 *
	 */
	public EventContextSuspensionHandler(EventContextImpl eventContext) {
		this.event = eventContext;
		this.sleeContainer = eventContext.factory.getSleeContainer();
	}

	/**
	 * the transaction being used to deliver this event
	 */
	private Transaction transaction;

	/**
	 * a queue of {@link EventContext}s barried due to this context become
	 * suspended
	 */
	private LinkedList<EventContext> barriedEvents;

	/**
	 * indicates if the context is suspended or not
	 */
	private boolean suspended;

	/**
	 * the scheduled future for the task controlling the suspension timeout
	 */
	private ScheduledFuture<?> scheduledFuture;

	/**
	 * transactional action action to change state
	 */
	private EventContextStateChange transactionalAction;

	public void barrierEvent(EventContext eventContext) {
		barriedEvents.add(eventContext);
	}

	public boolean isSuspended() throws TransactionRequiredLocalException,
			SLEEException {
		sleeContainer.getTransactionManager().mandateTransaction();
		if (isSuspendedNotTransacted()) {
			// current committed state is suspended
			if (transactionalAction != null
					&& transactionalAction.op == EventContextStateChangeOp.resume) {
				// resume is the op queued for tx commit
				return false;
			} else {
				return true;
			}
		} else {
			// current committed state is not suspended
			if (transactionalAction != null
					&& transactionalAction.op == EventContextStateChangeOp.suspend) {
				// suspend is the op queued for tx commit
				return true;
			} else {
				return false;
			}
		}
	}

	public boolean isSuspendedNotTransacted() {
		return suspended;
	}

	public void resumeDelivery() throws IllegalStateException,
			TransactionRequiredLocalException, SLEEException {
		if (!isSuspended()) {
			throw new IllegalStateException();
		} else {
			if (transactionalAction == null) {
				transactionalAction = new EventContextStateChange();
				transactionalAction.op = EventContextStateChangeOp.resume;
				TransactionContext transactionContext = sleeContainer.getTransactionManager().getTransactionContext();
				transactionContext.getAfterCommitActions().add(transactionalAction);
				TransactionalAction rollbackAction = new TransactionalAction() {
					public void execute() {
						transactionalAction = null;
					}
				};
				transactionContext.getAfterRollbackActions().add(rollbackAction);
			}
			else {
				// tx action queued to suspend, lets cancel it
				transactionalAction.cancel();
				transactionalAction = null;
			}
		}
	}

	public void suspendDelivery(final int timeout)
			throws IllegalArgumentException, IllegalStateException,
			TransactionRequiredLocalException, SLEEException {

		if (timeout < 1) {
			throw new IllegalArgumentException();
		}

		if (isSuspended()) {
			throw new IllegalStateException();
		} else {
			if (transactionalAction == null) {
				try {
					transactionalAction = new EventContextStateChange();
					transactionalAction.op = EventContextStateChangeOp.suspend;
					transactionalAction.timeout = timeout;
					transactionalAction.tx = sleeContainer.getTransactionManager().getTransaction();
					TransactionContext transactionContext = sleeContainer.getTransactionManager().getTransactionContext();
					transactionContext.getAfterCommitActions().add(transactionalAction);
					TransactionalAction rollbackAction = new TransactionalAction() {
						public void execute() {
							transactionalAction = null;
						}
					};
					transactionContext.getAfterRollbackActions().add(rollbackAction);

				} catch (SystemException e) {
					transactionalAction = null;
					throw new SLEEException(
							"unable to add tx action to change event context state", e);
				}
			}
			else {
				throw new IllegalStateException();
			}
		}
	}

	/**
	 * the real logic to resume the event context
	 */
	private void resume() {

		// create runnable to resume the event context
		Runnable runnable = new Runnable() {
			public void run() {
				if (scheduledFuture == null) {
					// already resumed
					return;
				}
				// cancel timer task
				scheduledFuture.cancel(false);
				scheduledFuture = null;
				// send events frozen to event router again, will be processed only after this one ends (this one is already being executed)
				for (EventContext ec : barriedEvents) {
					ec.getLocalActivityContext().getExecutorService().routeEvent(ec);
				}
				barriedEvents = null;
				// remove barrier on activity event queue
				event.getLocalActivityContext().getEventQueueManager().removeBarrier(transaction);
				// remove suspension
				suspended = false;
				// continue routing the event related with this context
				event.getLocalActivityContext().getCurrentEventRoutingTask().run();
			}
		};
		// run it using the activity executor service to avoid thread concurrency
		event.getLocalActivityContext().getExecutorService().execute(runnable);
	}

	private class SuspensionTimerTask implements Runnable {
		public void run() {
			try {
				resume();
			}
			catch(Throwable t) {
				logger.error("failed to resume event context "+event,t);
			}
		}
	}

	// -------- TX ACTION TO SUSPEND/RESUME

	private enum EventContextStateChangeOp { suspend , resume }

	private class EventContextStateChange implements TransactionalAction {

		private EventContextStateChangeOp op;

		private int timeout;

		private Transaction tx;

		private boolean canceled;

		public void execute() {
			if(!canceled) {
				transactionalAction = null;
				switch (op) {
				case suspend:
					suspended = true;
					transaction = tx;
					// put a barrier in the event queue manager for this activity, to
					// freeze the event routing on this activity at that level
					event.getLocalActivityContext().getEventQueueManager().createBarrier(tx);
					// init queue to store events about to be routed (after this one),
					// which may have passed the barrier
					barriedEvents = new LinkedList<EventContext>();
					// set state as suspended
					suspended = true;
					// schedule task
					scheduledFuture = sleeContainer.getNonClusteredScheduler().schedule(new SuspensionTimerTask(),timeout,TimeUnit.MILLISECONDS);
					break;
				case resume:
					resume();
					break;

				default:
					throw new SLEEException("unxpected op type when executing event context state change");
				}
			}
		}

		public void cancel() {
			canceled = true;
		}
	}

	private static final Logger logger = Logger.getLogger(EventContextImpl.class);

}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2011, Red Hat, Inc. and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

/**
 *
 */
package org.mobicents.slee.resource.cluster;

import org.infinispan.remoting.transport.Address;
import org.infinispan.tree.Fqn;
import org.restcomm.cache.FqnWrapper;
import org.restcomm.cluster.cache.ClusteredCacheData;
import org.restcomm.cluster.election.ClientLocalListenerElector;

import java.io.Serializable;

/**
 * @author martins
 *
 */
public class FailOverListener<K extends Serializable, V extends Serializable>
		implements org.restcomm.cluster.FailOverListener {

	private final FaultTolerantResourceAdaptor<K, V> ra;
	private final ReplicatedDataCacheData<K, V> baseCacheData;

	/**
	 * @param ra
	 * @param baseCacheData
	 */
	public FailOverListener(FaultTolerantResourceAdaptor<K, V> ra,
			ReplicatedDataCacheData<K, V> baseCacheData) {
		this.ra = ra;
		this.baseCacheData = baseCacheData;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.restcomm.cluster.ClientLocalListener#failOverClusterMember(org.jgroups
	 * .Address)
	 */
	public void failOverClusterMember(Address address) {
		// nothing to do
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.restcomm.cluster.ClientLocalListener#getBaseFqn()
	 */
	@SuppressWarnings("unchecked")
	public FqnWrapper getBaseFqn() {
		return new FqnWrapper(baseCacheData.getNodeFqn());
	}

	/*
	 * (non-Javadoc)
	 * @see org.restcomm.cluster.FailOverListener#getElector()
	 */
	public ClientLocalListenerElector getElector() {
		return null;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.restcomm.cluster.ClientLocalListener#getPriority()
	 */
	public byte getPriority() {
		return 0;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.restcomm.cluster.ClientLocalListener#lostOwnership(org.mobicents
	 * .cluster.cache.ClusteredCacheData)
	 */
	public void lostOwnership(ClusteredCacheData clusteredCacheData) {
		// nothing to do
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.restcomm.cluster.ClientLocalListener#wonOwnership(org.mobicents.
	 * cluster.cache.ClusteredCacheData)
	 */
	@SuppressWarnings("unchecked")
	public void wonOwnership(ClusteredCacheData clusteredCacheData) {
		ra.failOver((K) clusteredCacheData.getNodeFqn().getLastElement());
	}
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2011, Red Hat, Inc. and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.mobicents.slee.runtime.activity;

import java.util.Collections;
import java.util.Set;

import org.infinispan.tree.Fqn;
import org.infinispan.tree.Node;
import org.restcomm.cache.CacheData;
import org.restcomm.cache.FqnWrapper;
import org.restcomm.cluster.MobicentsCluster;
import org.mobicents.slee.container.activity.ActivityContextHandle;

/**
 *
 * Proxy object for activity context factory data management through JBoss Cache
 *
 * @author martins
 *
 */

public class ActivityContextFactoryCacheData extends CacheData {

	/**
	 * the fqn of the node that holds all activity context cache child nodes
	 */
	final static Fqn NODE_FQN = Fqn.fromElements(ActivityContextCacheData.parentNodeFqn);

	/**
	 *
	 * @param cluster
	 */
	public ActivityContextFactoryCacheData(MobicentsCluster cluster) {
		super(new FqnWrapper(NODE_FQN), cluster.getMobicentsCache());
	}

	/**
	 * Retrieves a set containing all activity context handles in the factory's
	 * cache data
	 *
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public Set<ActivityContextHandle> getActivityContextHandles() {
		final Node node = getNode();
		return node != null ? node.getChildrenNames() : Collections.emptySet();
	}

	public void WAremove(String type) {
		final Node node = getNode();
		if (node != null) {
			if (!node.getChildren().isEmpty()) {
				for (Object cho : node.getChildren()) {
					if (type != "") {
						if (cho instanceof Node) {
							Node chn = (Node) cho;
							if (chn.getFqn().getLastElementAsString().startsWith(type)) {
								node.removeChild(chn.getFqn());
							}
						}
					}
				}
				if (type == "") {
					node.removeChildren();
				}
			}
		}
	}

}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2011, Red Hat, Inc. and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.mobicents.slee.resource.cluster;

import org.restcomm.timers.TimerTask;
import org.restcomm.timers.TimerTaskData;
import org.restcomm.timers.TimerTaskFactory;

/**
 * Wrapps the FT RA Timer task factory into the factory used by Mobicents
 * Cluster framework.
 *
 * @author martins
 *
 */
public class FaultTolerantTimerTaskFactoryWrapper implements TimerTaskFactory {

	/**
	 *
	 */
	private final FaultTolerantTimerTaskFactory taskFactory;

	/**
	 *
	 * @param taskFactory
	 */
	public FaultTolerantTimerTaskFactoryWrapper(
			FaultTolerantTimerTaskFactory taskFactory) {
		this.taskFactory = taskFactory;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.restcomm.timers.TimerTaskFactory#newTimerTask(org.restcomm.timers
	 * .TimerTaskData)
	 */
	@Override
	public TimerTask newTimerTask(TimerTaskData data) {
		FaultTolerantTimerTaskDataWrapper dataWrapper = (FaultTolerantTimerTaskDataWrapper) data;
		FaultTolerantTimerTask task = taskFactory.getTask(dataWrapper
				.getWrappedData());
		return new FaultTolerantTimerTaskWrapper(task, dataWrapper);
	}

}


package javax.slee.management;

/**
 * This class identifies a notification such as an {@link AlarmNotification alarm} or
 * {@link TraceNotification trace} notification as being generated in response to
 * some action performed by a profile object on behalf of a profile.  For example,
 * if a profile object generates a traceable trace message using a
 * {@link javax.slee.facilities.Tracer Tracer} object, a trace notification will be
 * generated containing a ProfileTableNotification object that identifies
 * the profile table containing the profile.
 * @since SLEE 1.1
 */
public final class ProfileTableNotification extends AbstractNotificationSource implements NotificationSource {
    /**
     * The JMX notification type of alarm notifications that are generated in response
     * to a profile object interacting with the {@link javax.slee.facilities.AlarmFacility}.
     *

     * The notification type is equal to the string "javax.slee.management.alarm.profiletable".
     */
    public static final String ALARM_NOTIFICATION_TYPE = "javax.slee.management.alarm.profiletable";

    /**
     * The JMX notification type of trace notifications that are generated in response
     * to a profile object interacting with a {@link javax.slee.facilities.Tracer} object.
     *

     * The notification type is equal to the string "javax.slee.management.trace.profiletable".
     */
    public static final String TRACE_NOTIFICATION_TYPE = "javax.slee.management.trace.profiletable";

    /**
     * The JMX notification type of usage notifications that are generated by a
     * {@link javax.slee.usage.UsageMBean} containing a ProfileTableNotification
     * as a notification source.
     *

     * The notification type is equal to the string "javax.slee.management.usage.profiletable".
     */
    public static final String USAGE_NOTIFICATION_TYPE = "javax.slee.management.usage.profiletable";

    /**
     * The JMX Object Name property key that identifies the name of the profile table
     * in a Usage MBean whose {@link javax.slee.usage.UsageMBean#NOTIFICATION_SOURCE_KEY}
     * property has a value equal to {@link #USAGE_NOTIFICATION_TYPE}.  This key is
     * equal to the string "profileTableName".
     * @see javax.slee.usage.UsageMBean#BASE_OBJECT_NAME
     * @see javax.slee.usage.UsageMBean#NOTIFICATION_SOURCE_KEY
     * @since SLEE 1.1
     */
    public static final String PROFILE_TABLE_NAME_KEY = "profileTableName";

    /**
     * Create a new ProfileTableNotification object that uniquely identifies a
     * profile table.
     * @param profileTableName the name of the profile table..
     * @throws NullPointerException if profileTableName is null.
     */
    public ProfileTableNotification(String profileTableName) {
        if (profileTableName == null) throw new NullPointerException("entityName is null");
        this.profileTableName = profileTableName;
    }

    /**
     * Get the name of the profile table of this notification source.
     * @return the name of the profile table.
     */
    public String getProfileTableName() {
        return profileTableName;
    }

    /**
     * Get the JMX notification type of alarm notifications generated in response
     * to a profile object interacting with the Alarm Facility.
     * @return the string defined by {@link #ALARM_NOTIFICATION_TYPE}.
     */
    public String getAlarmNotificationType() {
        return ALARM_NOTIFICATION_TYPE;
    }

    /**
     * Get the JMX notification type of trace notifications generated in response
     * to a profile object interacting with the Trace Facility.
     * @return the string defined by {@link #TRACE_NOTIFICATION_TYPE}.
     */
    public String getTraceNotificationType() {
        return TRACE_NOTIFICATION_TYPE;
    }

    /**
     * Get the JMX notification type of usage notifications generated in response
     * to a profile object interacting with its usage parameters.
     * @return the string defined by {@link #USAGE_NOTIFICATION_TYPE}.
     */
    public String getUsageNotificationType() {
        return USAGE_NOTIFICATION_TYPE;
    }

    /**
     * Compare this notification source for equality with another object.
     * @param obj the object to compare this with.
     * @return true if obj is an instance of this class and
     *        contains the same profile table name as this, false otherwise.
     */
    public boolean equals(Object obj) {
        if (obj == this) return true;
        if (!(obj instanceof ProfileTableNotification)) return false;

        return this.profileTableName.equals(((ProfileTableNotification)obj).profileTableName);
    }

    /**
     * Get a hash code value for this notification source.
     * @return a hash code value for this notification source.
     */
    public int hashCode() {
        return profileTableName.hashCode();
    }

    /**
     * Get a string representation for this notification source.
     * @return a string representation for this notification source.
     * @see Object#toString()
     */
    public String toString() {
        StringBuffer buf = new StringBuffer();
        buf.append("ProfileTableNotification[table=").append(profileTableName).append(']');
        return buf.toString();
    }

    /**
     * Compare this notification source with the specified object for order.
     * Returns a negative integer, zero, or a positive integer if this object
     * is less than, equal to, or greater than the specified object.
     *

     * If obj is a ProfileTableNotification, order is
     * determined by comparing the encapsulated profile table name.  Otherwise, if
     * obj is a NotificationSource, ordering is determined
     * by comparing the class name of this class with the class name of obj.
     * @param obj the object to compare this with.
     * @return a negative integer, zero, or a positive integer if this notification
     *        source is considered less than, equal to, or greater than the
     *        specified object.
     * @throws ClassCastException if obj does not implement the
     *        {@link NotificationSource} interface.
     * @see Comparable#compareTo(Object)
     */
    public int compareTo(Object obj) {
        // can't compare with null
        if (obj == null) throw new NullPointerException("obj is null");
        if (obj == this) return 0;

        if (obj instanceof ProfileTableNotification) {
            // compare the profile table name
            ProfileTableNotification that = (ProfileTableNotification)obj;
            return this.profileTableName.compareTo(that.profileTableName);
        }
        else {
            return super.compareTo(TYPE, obj);
        }
    }

    // protected

    protected String getClassName() {
        return TYPE;
    }

    private final String profileTableName;

    // constant to avoid expensive getClass() invocations at runtime
    private static final String TYPE = ProfileTableNotification.class.getName();
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2011, Red Hat, Inc. and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.mobicents.slee.container.profile;

import org.apache.commons.pool.PoolableObjectFactory;
import org.apache.log4j.Logger;

/**
 * Implements the methods invoked by the object pool to create new PRofile Objects
 * Object
 *
 * @author Eduardo Martins
 */
public class ProfileObjectPoolFactory implements PoolableObjectFactory {

	private static Logger logger = Logger.getLogger(ProfileObjectPoolFactory.class);

	private final ProfileTableImpl profileTable;

    public ProfileObjectPoolFactory(ProfileTableImpl profileTable) {
    	this.profileTable = profileTable;
    }

    public void activateObject(Object obj) throws java.lang.Exception {

    }

    public void destroyObject(Object obj) throws java.lang.Exception {

    	if (logger.isTraceEnabled()) {
			logger.trace("destroyObject() for "+obj);
        }

    	ProfileObjectImpl profileObject = (ProfileObjectImpl) obj;
       profileObject.unsetProfileContext();
    }

    /**
     * Create a new instance of this object and set the SbbContext This places
     * it into the object pool.
     */
    public Object makeObject() {

    	if (logger.isTraceEnabled()) {
			logger.trace("makeObject()");
        }

    	ProfileObjectImpl profileObject = new ProfileObjectImpl(profileTable);
		profileObject.setProfileContext(new ProfileContextImpl(profileTable));
        return profileObject;
    }

    public void passivateObject(Object obj) throws java.lang.Exception {

    }

    public boolean validateObject(Object obj) {
    	return ((ProfileObjectImpl) obj).getState() == ProfileObjectState.POOLED;
    }

}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2011, Red Hat, Inc. and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.mobicents.slee.container.component.deployment.jaxb.descriptors;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.slee.SLEEException;
import javax.slee.management.DeploymentException;

import org.mobicents.slee.container.component.deployment.jaxb.descriptors.common.MSecurityPermissions;
import org.mobicents.slee.container.component.deployment.jaxb.descriptors.library.MLibrary;
import org.mobicents.slee.container.component.deployment.jaxb.descriptors.library.MLibraryJar;
import org.mobicents.slee.container.component.library.LibraryDescriptorFactory;

/**
 *
 * Factory to build {@link LibraryDescriptorImpl} objects.
 *
 * @author  Alexandre Mendonca
 * @author  Bartosz Baranowski
 */
public class LibraryDescriptorFactoryImpl extends AbstractDescriptorFactory implements LibraryDescriptorFactory {

  /*
   * (non-Javadoc)
   * @see org.mobicents.slee.core.component.library.LibraryDescriptorFactory#parse(java.io.InputStream)
   */
  public List<LibraryDescriptorImpl> parse(InputStream inputStream) throws DeploymentException {

    Object jaxbPojo = buildJAXBPojo(inputStream);

    List<LibraryDescriptorImpl> result = new ArrayList<LibraryDescriptorImpl>();

    // Only exists in JAIN SLEE 1.1
    boolean isSlee11 = true;

    MLibraryJar mLibraryJar = null;
    if (jaxbPojo instanceof org.mobicents.slee.container.component.deployment.jaxb.slee11.library.LibraryJar )
    {
      mLibraryJar = new MLibraryJar((org.mobicents.slee.container.component.deployment.jaxb.slee11.library.LibraryJar)jaxbPojo);
    }
    else {
      throw new SLEEException("unexpected class of jaxb pojo built: "+(jaxbPojo != null ? jaxbPojo.getClass() : null));
    }

    MSecurityPermissions securityPermissions = mLibraryJar.getSecurityPermissions();
    for (MLibrary mLibrary : mLibraryJar.getLibrary())
    {
      result.add(new LibraryDescriptorImpl(mLibrary, securityPermissions, isSlee11));
    }

    return result;
  }
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2011, Red Hat, Inc. and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.mobicents.slee.container.management;

import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;

import org.mobicents.slee.container.AbstractSleeContainerModule;
import org.mobicents.slee.container.component.profile.ProfileSpecificationComponent;
import org.mobicents.slee.container.component.ra.ResourceAdaptorComponent;
import org.mobicents.slee.container.component.service.ServiceComponent;
import org.mobicents.slee.container.management.jmx.ProfileTableUsageMBean;
import org.mobicents.slee.container.management.jmx.ProfileTableUsageMBeanImpl;
import org.mobicents.slee.container.management.jmx.ResourceUsageMBean;
import org.mobicents.slee.container.management.jmx.ResourceUsageMBeanImpl;
import org.mobicents.slee.container.management.jmx.ServiceUsageMBean;
import org.mobicents.slee.container.management.jmx.ServiceUsageMBeanImpl;

/**
 * @author martins
 *
 */
public class UsageParametersManagementImpl extends AbstractSleeContainerModule
		implements UsageParametersManagement {

	/*
	 * (non-Javadoc)
	 *
	 * @seeorg.mobicents.slee.container.management.UsageParametersManagement#
	 * newProfileTableUsageMBean(java.lang.String,
	 * org.mobicents.slee.core.component.profile.ProfileSpecificationComponent)
	 */
	public ProfileTableUsageMBean newProfileTableUsageMBean(
			String profileTableName, ProfileSpecificationComponent component)
			throws NotCompliantMBeanException, MalformedObjectNameException,
			NullPointerException {
		return new ProfileTableUsageMBeanImpl(profileTableName, component,
				sleeContainer);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @seeorg.mobicents.slee.container.management.UsageParametersManagement#
	 * newResourceUsageMBean(java.lang.String,
	 * org.mobicents.slee.core.component.ra.ResourceAdaptorComponent)
	 */
	public ResourceUsageMBean newResourceUsageMBean(String entityName,
			ResourceAdaptorComponent component)
			throws NotCompliantMBeanException, MalformedObjectNameException,
			NullPointerException {
		return new ResourceUsageMBeanImpl(entityName, component, sleeContainer);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @seeorg.mobicents.slee.container.management.UsageParametersManagement#
	 * newServiceUsageMBean
	 * (org.mobicents.slee.core.component.service.ServiceComponent)
	 */
	public ServiceUsageMBean newServiceUsageMBean(ServiceComponent component)
			throws NotCompliantMBeanException, MalformedObjectNameException,
			NullPointerException {
		return new ServiceUsageMBeanImpl(component, sleeContainer);
	}

}