/*
 * 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 java.util.concurrent.ConcurrentHashMap;

import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.slee.SLEEException;
import javax.slee.profile.UnrecognizedProfileTableNameException;

import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.apache.commons.pool.impl.GenericObjectPoolFactory;
import org.apache.log4j.Logger;
import org.mobicents.slee.container.SleeContainer;
import org.mobicents.slee.container.transaction.SleeTransactionManager;
import org.mobicents.slee.container.transaction.TransactionalAction;

/**
 *
 * Manages profile object pools in the SLEE container.
 *
 * @author martins
 *
 */
public class ProfileObjectPoolManagement implements ProfileObjectPoolManagementMBean {

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

	private final ConcurrentHashMap<String, ProfileObjectPool> pools;
	private final SleeContainer sleeContainer;

	private GenericObjectPool.Config config;

	public ProfileObjectPoolManagement(SleeContainer sleeContainer) {
		this.sleeContainer = sleeContainer;
		// create pool config mbean with default pool configuration
		config = new GenericObjectPool.Config();
		config.maxActive = -1;
		config.maxIdle = 50;
		config.maxWait = -1;
		config.minEvictableIdleTimeMillis = 60000;
		config.minIdle = 0;
		config.numTestsPerEvictionRun = -1;
		config.testOnBorrow = true;
		config.testOnReturn = true;
		config.testWhileIdle = false;
		config.timeBetweenEvictionRunsMillis = 300000;
		config.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_FAIL;
		// create pools map
		pools = new ConcurrentHashMap<String, ProfileObjectPool>();
	}

	/**
	 * Retrieves the current pool configuration
	 *
	 * @return
	 */
	public GenericObjectPool.Config getPoolConfig() {
		return config;
	}

	/**
	 * Defines the current pool configuration
	 */
	public void setPoolConfig(GenericObjectPool.Config config) {
		this.config = config;
	}

	/**
	 * Retrieves the object pool for the specified profile table.
	 * @param profileTable
	 * @return
	 */
	public ProfileObjectPool getObjectPool(String profileTableName) {
		return pools.get(profileTableName);
	}

	/**
	 * Creates an object pool for the specified profile table. If a
	 * transaction manager is used then, and if the tx rollbacks, the pool will
	 * be removed.
	 *
	 * @param
	 * @param sleeTransactionManager
	 */
	public void createObjectPool(final ProfileTableImpl profileTable,
			final SleeTransactionManager sleeTransactionManager) {

		if (logger.isTraceEnabled()) {
            logger.trace("Creating Pool for " + profileTable);
		}

		createObjectPool(profileTable);

		if (sleeTransactionManager != null) {
			// add a rollback action to remove sbb object pool
			TransactionalAction action = new TransactionalAction() {
				public void execute() {
					if (logger.isDebugEnabled()) {
						logger
								.debug("Due to tx rollback, removing pool for " + profileTable);
					}
					try {
						removeObjectPool(profileTable);
					} catch (Throwable e) {
						logger.error("Failed to remove table's " + profileTable + " object pool", e);
					}
				}
			};
			sleeTransactionManager.getTransactionContext().getAfterRollbackActions().add(action);
		}
	}

	/**
	 *
	 * @param profileTable
	 */
	private void createObjectPool(final ProfileTableImpl profileTable) {
		// create the pool
		GenericObjectPoolFactory poolFactory = new GenericObjectPoolFactory(
				new ProfileObjectPoolFactory(profileTable), config);
		final ObjectPool objectPool = poolFactory.createPool();
		final ProfileObjectPool oldObjectPool = pools.put(profileTable.getProfileTableName(),
				new ProfileObjectPool(objectPool));
		if (oldObjectPool != null) {
			// there was an old pool, close it
			try {
				oldObjectPool.close();
			} catch (Exception e) {
				if (logger.isDebugEnabled()) {
					logger.debug("Failed to close old pool for " + profileTable);
				}
			}
		}
		if (logger.isDebugEnabled()) {
			logger.debug("Created Pool for " + profileTable);
		}
	}

	/**
	 * Removes the object pool for the specified profile table. If a
	 * transaction manager is used then the removal is only after the tx commit.
	 *
	 * @param sleeTransactionManager
	 * @throws Exception
	 */
	public void removeObjectPool(final ProfileTableImpl profileTable,
			final SleeTransactionManager sleeTransactionManager) {

		TransactionalAction action = new TransactionalAction() {
			public void execute() {
				if (logger.isTraceEnabled()) {
		            logger.trace("Removing Pool for " + profileTable);
				}

				removeObjectPool(profileTable);
			}
		};

		if (sleeTransactionManager != null) {
			sleeTransactionManager.getTransactionContext().getAfterCommitActions().add(action);
		}
		else {
			action.execute();
		}
	}

	/**
	 * Removes the pool for the specified ids
	 *
	 * @param serviceID
	 * @param sbbID
	 * @throws Exception
	 */
	private void removeObjectPool(final ProfileTableImpl profileTable) {
		final ProfileObjectPool objectPool = pools.remove(profileTable.getProfileTableName());
		if (objectPool != null) {
			try {
				objectPool.close();
			} catch (Exception e) {
				logger.error("failed to close pool",e);
			}
		}
		if (logger.isDebugEnabled()) {
			logger.debug("Removed Pool for " + profileTable);
		}
	}

	// ---- MBEAN METHODS

	public void register() {
		MBeanServer mBeanServer = sleeContainer.getMBeanServer();
		try {
			mBeanServer.registerMBean(this, new ObjectName(MBEAN_NAME));
		} catch (Exception e) {
			logger.error("Failed to register", e);
		}
	}

	public void unregister() {
		try {
			sleeContainer.getMBeanServer().unregisterMBean(
					new ObjectName(MBEAN_NAME));
		} catch (Exception e) {
			logger.error("Failed to unregister", e);
		}
	}

	public int getMaxActive() {
		return config.maxActive;
	}

	public void setMaxActive(int maxActive) {
		config.maxActive = maxActive;
	}

	public int getMaxIdle() {
		return config.maxIdle;
	}

	public void setMaxIdle(int maxIdle) {
		config.maxIdle = maxIdle;
	}

	public int getMinIdle() {
		return config.minIdle;
	}

	public void setMinIdle(int minIdle) {
		config.minIdle = minIdle;
	}

	public long getMaxWait() {
		return config.maxWait;
	}

	public void setMaxWait(long maxWait) {
		config.maxWait = maxWait;
	}

	public long getMinEvictableIdleTimeMillis() {
		return config.minEvictableIdleTimeMillis;
	}

	public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
		config.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
	}

	public int getNumTestsPerEvictionRun() {
		return config.numTestsPerEvictionRun;
	}

	public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
		config.numTestsPerEvictionRun = numTestsPerEvictionRun;
	}

	public boolean getTestOnBorrow() {
		return config.testOnBorrow;
	}

	public void setTestOnBorrow(boolean testOnBorrow) {
		config.testOnBorrow = testOnBorrow;
	}

	public boolean getTestOnReturn() {
		return config.testOnReturn;
	}

	public void setTestOnReturn(boolean testOnReturn) {
		config.testOnReturn = testOnReturn;
	}

	public boolean getTestWhileIdle() {
		return config.testWhileIdle;
	}

	public void setTestWhileIdle(boolean testWhileIdle) {
		config.testWhileIdle = testWhileIdle;
	}

	public long getTimeBetweenEvictionRunsMillis() {
		return config.timeBetweenEvictionRunsMillis;
	}

	public void setTimeBetweenEvictionRunsMillis(
			long timeBetweenEvictionRunsMillis) {
		config.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
	}

	public byte getWhenExhaustedAction() {
		return config.whenExhaustedAction;
	}

	public void setWhenExhaustedAction(byte whenExhaustedAction) {
		config.whenExhaustedAction = whenExhaustedAction;
	}

	public void reconfig() {
		for (String key : pools.keySet()) {
			ProfileTableImpl profileTable;
			try {
				profileTable = (ProfileTableImpl) sleeContainer.getSleeProfileTableManager().getProfileTable(key);
			} catch (UnrecognizedProfileTableNameException e) {
				throw new SLEEException(e.getMessage(),e);
			}
			createObjectPool(profileTable);
		}
	}

	@Override
	public String toString() {
		return "Profile Object Pool Management: "
			+ "\n+-- Pools: " + pools.keySet();
	}

}


/*
 * 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.sbbentity;

import org.apache.log4j.Logger;
import org.infinispan.notifications.Listener;
import org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved;
import org.infinispan.notifications.cachelistener.event.CacheEntryRemovedEvent;
import org.infinispan.tree.Fqn;
import org.infinispan.tree.impl.NodeKey;
import org.mobicents.slee.container.SleeContainer;
import org.mobicents.slee.container.sbbentity.SbbEntityID;
import org.restcomm.cache.MobicentsCache;

import javax.slee.ServiceID;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

/**
 *
 * @author martins
 *
 */
@Listener
public class SbbEntityLockFacility {

	private static final Logger logger = Logger.getLogger(SbbEntityLockFacility.class);
	private boolean doTraceLogs = logger.isTraceEnabled();
	private boolean doInfoLogs = logger.isInfoEnabled();

	/**
	 *
	 */
	private final ConcurrentHashMap<SbbEntityID,ReentrantLock> locks = new ConcurrentHashMap<SbbEntityID, ReentrantLock>();

	/**
	 *
	 */

	public SbbEntityLockFacility(SleeContainer container) {
		//container.getCluster().addDataRemovalListener(new DataRemovaClusterListener());
		MobicentsCache cache = container.getCluster().getMobicentsCache();
		if (!cache.isLocalMode()) {
			// SergeyLee: test
			cache.getJBossCache().getCache().addListener(this);
		}
	}

	/**
	 *
	 * @param sbbEntityId
	 * @return
	 */
	public ReentrantLock get(SbbEntityID sbbEntityId) {
		ReentrantLock lock = locks.get(sbbEntityId);
		if (lock == null) {
			final ReentrantLock newLock = new ReentrantLock();
			lock = locks.putIfAbsent(sbbEntityId, newLock);
			if (lock == null) {
				if(doInfoLogs) {
					logger.info(Thread.currentThread()+" put of lock "+newLock+" for "+sbbEntityId);
				}
				lock = newLock;
			}
		}
		return lock;
	}

	/**
	 *
	 * @param sbbEntityId
	 * @return
	 */
	public ReentrantLock remove(SbbEntityID sbbEntityId) {
		if(doInfoLogs) {
			logger.info(Thread.currentThread()+" removed lock for "+sbbEntityId);
		}
		return locks.remove(sbbEntityId);
	}

	/**
	 *
	 * @return
	 */
	public Set<SbbEntityID> getSbbEntitiesWithLocks() {
		return locks.keySet();
	}

	// FIXME this does not work in the new sbbe tree model, ensure cluster framework gets such feature
	/*
	private class DataRemovaClusterListener implements DataRemovalListener {

		private final Fqn<?> baseFqn = null;

		@SuppressWarnings("unchecked")
		public void dataRemoved(Fqn arg0) {
			final SbbEntityID sbbEntityId = (SbbEntityID) arg0.getLastElement();
			if(locks.remove(sbbEntityId) != null) {
				if(doTraceLogs) {
					logger.trace("Remotely removed lock for "+sbbEntityId);
				}
			}
		}

		@SuppressWarnings("unchecked")
		public Fqn getBaseFqn() {
			return baseFqn;
		}

	}*/

	@CacheEntryRemoved
	public void onNodeRemovedEvent(CacheEntryRemovedEvent event) {
		if(!event.isOriginLocal() && !event.isPre()) {
			// remote node removal
			Fqn fqn = ((NodeKey)event.getKey()).getFqn();
			if (fqn != null) {
				if(doInfoLogs) {
					logger.info("onNodeRemovedEvent( fqn = "+fqn+", size = "+fqn.size()+" )");
				}
				if (fqn.get(0).equals(SbbEntityFactoryCacheData.SBB_ENTITY_FACTORY_FQN_NAME)) {
					// is child of sbb entity factory cache data, i.e., /sbbe
					int fqnSize = fqn.size();
					if (fqnSize < 3) {
						return;
					}
					SbbEntityID sbbEntityID = null;
					if (fqnSize == 3) {
						// /sbbe/serviceid/convergenceName root sbb entity
						ServiceID serviceID = (ServiceID) fqn.get(1);
						String convergenceName = (String) fqn.get(2);
						sbbEntityID = new RootSbbEntityID(serviceID, convergenceName);
						if (doInfoLogs) {
							logger.info("Root sbb entity " + sbbEntityID + " was remotely removed, ensuring there is no local lock");
						}
					} else {
						// must end as /chd/chdRelationName/childId
						if (!fqn.get(fqnSize - 3).equals(SbbEntityCacheData.CHILD_RELATIONs_CHILD_NODE_NAME)) {
							return;
						}
						// let get the party started and rebuild the sbb entity id!
						ServiceID serviceID = (ServiceID) fqn.get(1);
						String convergenceName = (String) fqn.get(2);
						sbbEntityID = new RootSbbEntityID(serviceID, convergenceName);
						int i = 3;
						while (fqnSize >= i + 3) {
							// fqn get(i) is chd, skip
							String childRelationName = (String) fqn.get(i + 1);
							String childId = (String) fqn.get(i + 2);
							sbbEntityID = new NonRootSbbEntityID(sbbEntityID, childRelationName, childId);
							i += 3;
						}
						if (doInfoLogs) {
							logger.info("Non root sbb entity " + sbbEntityID + " was remotely removed, ensuring there is no local lock");
						}
					}
					if (locks.remove(sbbEntityID) != null) {
						if (doInfoLogs) {
							logger.info("Remotely removed lock for " + sbbEntityID);
						}
					}
				}
			}
		}
	}

 }


/*
 * 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;

import java.util.List;

import org.mobicents.slee.container.component.SleeComponentWithUsageParametersInterface;
import org.mobicents.slee.container.component.UsageParameterDescriptor;

public abstract class AbstractSleeComponentWithUsageParametersInterface extends AbstractSleeComponent implements SleeComponentWithUsageParametersInterface {

	/**
	 * the usage parameters interface
	 */
	private Class<?> usageParametersInterface;

	/**
	 * the concrete usage parameters class, generated by SLEE
	 */
	private Class<?> usageParametersConcreteClass;

	/**
	 * the concrete usage parameters mbean interface, generated by SLEE
	 */
	private Class<?> usageParametersMBeanConcreteInterface;

	/**
	 * the concrete usage parameters mbean impl class, generated by SLEE
	 */
	private Class<?> usageParametersMBeanImplConcreteClass;

	/**
	 * the concrete usage notification manager mbean interface, generated by SLEE
	 */
	private Class<?> usageNotificationManagerMBeanConcreteInterface;

	/**
	 * the concrete usage notification manager mbean impl class, generated by SLEE
	 */
	private Class<?> usageNotificationManagerMBeanImplConcreteClass;

	/**
	 * Retrieves the usage parameters interface
	 *
	 * @return
	 */
	public Class<?> getUsageParametersInterface() {
		return usageParametersInterface;
	}

	/**
	 * Sets the usage parameters interface
	 *
	 * @param usageParametersInterface
	 */
	public void setUsageParametersInterface(Class<?> usageParametersInterface) {
		this.usageParametersInterface = usageParametersInterface;
	}

	/**
	 * Retrieves the concrete usage parameters class, generated by SLEE
	 * @return
	 */
	public Class<?> getUsageParametersConcreteClass() {
		return usageParametersConcreteClass;
	}

	/**
	 * Sets the concrete usage parameters class, generated by SLEE
	 * @param usageParametersConcreteClass
	 */
	public void setUsageParametersConcreteClass(
			Class<?> usageParametersConcreteClass) {
		this.usageParametersConcreteClass = usageParametersConcreteClass;
	}

	/**
	 * Retrieves the concrete usage parameters mbean interface, generated by SLEE
	 * @return
	 */
	public Class<?> getUsageParametersMBeanConcreteInterface() {
		return usageParametersMBeanConcreteInterface;
	}

	/**
	 * Sets the concrete usage parameters mbean interface, generated by SLEE
	 * @param usageParametersMBeanConcreteInterface
	 */
	public void setUsageParametersMBeanConcreteInterface(
			Class<?> usageParametersMBeanConcreteInterface) {
		this.usageParametersMBeanConcreteInterface = usageParametersMBeanConcreteInterface;
	}

	/**
	 * Retrieves the concrete usage parameters mbean impl class, generated by SLEE
	 * @return
	 */
	public Class<?> getUsageParametersMBeanImplConcreteClass() {
		return usageParametersMBeanImplConcreteClass;
	}

	/**
	 * Sets the concrete usage parameters mbean impl class, generated by SLEE
	 * @param usageParametersMBeanImplConcreteClass
	 */
	public void setUsageParametersMBeanImplConcreteClass(
			Class<?> usageParametersMBeanImplConcreteClass) {
		this.usageParametersMBeanImplConcreteClass = usageParametersMBeanImplConcreteClass;
	}

	/**
	 * Retrieves the concrete usage notification manager mbean interface, generated by SLEE
	 * @return
	 */
	public Class<?> getUsageNotificationManagerMBeanConcreteInterface() {
		return usageNotificationManagerMBeanConcreteInterface;
	}

	/**
	 * Sets the concrete usage notification manager mbean interface, generated by SLEE
	 * @param usageNotificationManagerMBeanConcreteInterface
	 */
	public void setUsageNotificationManagerMBeanConcreteInterface(
			Class<?> usageNotificationManagerMBeanConcreteInterface) {
		this.usageNotificationManagerMBeanConcreteInterface = usageNotificationManagerMBeanConcreteInterface;
	}

	/**
	 * Retrieves the concrete usage notification manager mbean impl class, generated by SLEE
	 * @return
	 */
	public Class<?> getUsageNotificationManagerMBeanImplConcreteClass() {
		return usageNotificationManagerMBeanImplConcreteClass;
	}

	/**
	 * Sets the concrete usage notification manager mbean impl class, generated by SLEE
	 * @param usageNotificationManagerMBeanImplConcreteClass
	 */
	public void setUsageNotificationManagerMBeanImplConcreteClass(
			Class<?> usageNotificationManagerMBeanImplConcreteClass) {
		this.usageNotificationManagerMBeanImplConcreteClass = usageNotificationManagerMBeanImplConcreteClass;
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.core.component.SleeComponentWithUsageParametersInterface#getUsageParametersList()
	 */
	public abstract List<UsageParameterDescriptor> getUsageParametersList();

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.container.component.AbstractSleeComponent#undeployed()
	 */
	@Override
	public void undeployed() {
		super.undeployed();
		usageNotificationManagerMBeanConcreteInterface = null;
		usageNotificationManagerMBeanImplConcreteClass = null;
		usageParametersConcreteClass = null;
		usageParametersInterface = null;
		usageParametersMBeanConcreteInterface = null;
		usageParametersMBeanImplConcreteClass = null;
	}
}


package org.restcomm.slee.container.build.as7.extension;

import org.jboss.as.connector.subsystems.datasources.DataSourceReferenceFactoryService;
import org.jboss.as.controller.*;
import org.jboss.as.controller.registry.Resource;
import org.jboss.as.controller.services.path.PathManager;
import org.jboss.as.controller.services.path.PathManagerService;
import org.jboss.as.jmx.MBeanServerService;
import org.jboss.as.naming.ManagedReferenceFactory;
import org.jboss.as.server.AbstractDeploymentChainStep;
import org.jboss.as.server.DeploymentProcessorTarget;
import org.jboss.as.txn.service.TransactionManagerService;
import org.jboss.dmr.ModelNode;
import org.jboss.logging.Logger;
import org.jboss.msc.service.ServiceBuilder;
import org.jboss.msc.service.ServiceController;
import org.jboss.msc.service.ServiceController.Mode;
import org.jboss.msc.service.ServiceTarget;
import org.restcomm.slee.container.build.as7.deployment.SleeDeploymentInstallProcessor;
import org.restcomm.slee.container.build.as7.deployment.SleeDeploymentParseProcessor;
import org.restcomm.slee.container.build.as7.service.SleeContainerService;
import org.restcomm.slee.container.build.as7.service.SleeServiceNames;

import javax.management.MBeanServer;
import javax.transaction.TransactionManager;
import java.util.List;

class SleeSubsystemAdd extends AbstractBoottimeAddStepHandler {

    static final SleeSubsystemAdd INSTANCE = new SleeSubsystemAdd();

    private final Logger log = Logger.getLogger(SleeSubsystemAdd.class);

    private SleeSubsystemAdd() {
    }

    /** {@inheritDoc} */
    @Override
    protected void populateModel(ModelNode operation, ModelNode model) throws OperationFailedException {
        log.info("Populating the model");
        //model.setEmptyObject();
        for (AttributeDefinition ad : SleeSubsystemDefinition.ATTRIBUTES) {
            ad.validateAndSet(operation, model);
        }
    }

    /** {@inheritDoc} */
    @Override
    public void performBoottime(OperationContext context, ModelNode operation, ModelNode model,
            ServiceVerificationHandler verificationHandler, List<ServiceController<?>> newControllers)
            throws OperationFailedException {

        // Add deployment processors here
        // Remove this if you don't need to hook into the deployers, or you can add as many as you like
        // see SubDeploymentProcessor for explanation of the phases
        context.addStep(new AbstractDeploymentChainStep() {
            public void execute(DeploymentProcessorTarget processorTarget) {
                processorTarget.addDeploymentProcessor(SleeExtension.SUBSYSTEM_NAME,
                        SleeDeploymentParseProcessor.PHASE,
                        SleeDeploymentParseProcessor.PRIORITY,
                        new SleeDeploymentParseProcessor());
                processorTarget.addDeploymentProcessor(SleeExtension.SUBSYSTEM_NAME,
                        SleeDeploymentInstallProcessor.PHASE,
                        SleeDeploymentInstallProcessor.PRIORITY,
                        new SleeDeploymentInstallProcessor());
            }
        }, OperationContext.Stage.RUNTIME);

        ModelNode fullModel = Resource.Tools.readModel(context.readResource(PathAddress.EMPTY_ADDRESS));

        final ModelNode cacheConfigModel = SleeSubsystemDefinition.CACHE_CONFIG.resolveModelAttribute(context, model);
        final String cacheConfig = cacheConfigModel.isDefined() ? cacheConfigModel.asString() : null;

    	// Installs the msc service which builds the SleeContainer instance and its modules
        final ServiceTarget target = context.getServiceTarget();
        final SleeContainerService sleeContainerService = new SleeContainerService(fullModel, cacheConfig);

        String dbConfigMBean = getPropertyString(fullModel, "ProfileManagement", "dbConfigMBean", "H2DBConfig");
        String datasourceServiceName = getPropertyString(fullModel, dbConfigMBean, "datasourceServiceName", "ExampleDS");

        final ServiceBuilder<?> sleeContainerServiceBuilder = target
                .addService(SleeServiceNames.SLEE_CONTAINER, sleeContainerService)
                .addDependency(PathManagerService.SERVICE_NAME, PathManager.class, sleeContainerService.getPathManagerInjector())
                .addDependency(MBeanServerService.SERVICE_NAME, MBeanServer.class, sleeContainerService.getMbeanServer())
                .addDependency(TransactionManagerService.SERVICE_NAME, TransactionManager.class, sleeContainerService.getTransactionManager())
                .addDependency(DataSourceReferenceFactoryService.SERVICE_NAME_BASE.append(datasourceServiceName),
                        ManagedReferenceFactory.class, sleeContainerService.getManagedReferenceFactory());

        newControllers.add(sleeContainerServiceBuilder.setInitialMode(Mode.ACTIVE).install());
    }

    private ModelNode peek(ModelNode node, String... args) {
        for (String arg : args) {
            if (!node.hasDefined(arg)) { return null; }
            node = node.get(arg);
        }
        return node;
    }

    private String getPropertyString(ModelNode model, String mbeanName, String propertyName, String defaultValue) {
        String result = defaultValue;
        ModelNode propertyNode = peek(model, "mbean", mbeanName, "property", propertyName);
        if (propertyNode != null && propertyNode.isDefined()) {
            result = propertyNode.get("value").asString();
        }
        return (result == null) ? defaultValue : result;
    }

}


package javax.slee.usage;

import javax.management.Notification;
import javax.management.NotificationFilter;
import javax.slee.InvalidArgumentException;
import javax.slee.SbbID;
import javax.slee.ServiceID;
import javax.slee.management.NotificationSource;

/**
 * A notification filter that only allows through {@link UsageNotification}s where the
 * notification source and usage parameter name match specified values, and the value of
 * the usage parameter contained in the notification falls outside a specified range.
 *

 * If the notification contains usage information for some other notification source or
 * usage parameter, or the value of the usage parameter falls within the specified range,
 * the notification is suppressed.
 *

 * Notifications that are not instances of {@link UsageNotification} are suppressed
 * by this filter.
 */
public class UsageOutOfRangeFilter implements NotificationFilter {
    /**
     * Create a UsageOutOfRangeFilter.  A filter created using this constructor
     * will only allow SLEE 1.0-compliant usage notifications to pass through where they
     * otherwise satisfy the filtering criteria.
     * @param service the component identifier of the Service whose usage parameter
     *        should be monitored.
     * @param sbb the component identifier of the SBB whose usage parameter should be
     *        monitored.
     * @param paramName the name of a usage parameter defined by the SBB.
     * @param lowValue the lower bound of the range.  Notifications are allowed through
     *        this filter if the value of the specified usage parameter is less than
     *        this value.
     * @param highValue the upper bound of the range.  Notifications are allowed through
     *        this filter if the value of the specified usage parameter is greater than
     *        this value.
     * @throws NullPointerException if service, sbb, or
     *        paramName is null.
     * @throws InvalidArgumentException if highValue < lowValue.
     * @deprecated Replaced with {@link #UsageOutOfRangeFilter(NotificationSource, String, long, long)}
     *        as usage collecting has been expanded to include SLEE components other than SBBs.
     */
    public UsageOutOfRangeFilter(ServiceID service, SbbID sbb, String paramName, long lowValue, long highValue) throws NullPointerException, InvalidArgumentException {
        if (service == null) throw new NullPointerException("service is null");
        if (sbb == null) throw new NullPointerException("sbb is null");
        if (paramName == null) throw new NullPointerException("paramName is null");

        if (highValue < lowValue) throw new InvalidArgumentException("highValue < lowValue");

        this.service = service;
        this.sbb = sbb;
        this.paramName = paramName;
        this.lowValue = lowValue;
        this.highValue = highValue;

        // forward compatibiltiy
        this.notificationSource = null;
    }

    /**
     * Create a UsageOutOfRangeFilter.  A filter created using this constructor
     * will only allow SLEE 1.0-compliant usage notifications to pass through where they
     * otherwise satisfy the filtering criteria.
     * @param notificationSource the notification source whose usage parameter should be
     *        monitored.
     * @param paramName the name of a usage parameter defined by the SBB.
     * @param lowValue the lower bound of the range.  Notifications are allowed through
     *        this filter if the value of the specified usage parameter is less than
     *        this value.
     * @param highValue the upper bound of the range.  Notifications are allowed through
     *        this filter if the value of the specified usage parameter is greater than
     *        this value.
     * @throws NullPointerException if notificationSource or paramName
     *        is null.
     * @throws InvalidArgumentException if highValue < lowValue.
     */
    public UsageOutOfRangeFilter(NotificationSource notificationSource, String paramName, long lowValue, long highValue) throws NullPointerException, InvalidArgumentException {
        if (notificationSource == null) throw new NullPointerException("notificationSource is null");
        if (paramName == null) throw new NullPointerException("paramName is null");

        if (highValue < lowValue) throw new InvalidArgumentException("highValue < lowValue");

        this.notificationSource = notificationSource;
        this.paramName = paramName;
        this.lowValue = lowValue;
        this.highValue = highValue;

        // backward compatibiltiy
        this.service = null;
        this.sbb = null;
    }

    /**
     * Determine whether the specified notification should be delivered to notification
     * listeners using this notification filter.
     * @param notification the notification to be sent.
     * @return true if the notification should be delivered to notification
     *        listeners, false otherwise.  This method always returns
     *        false if notification is not an instance of
     *        {@link UsageNotification}.
     */
    public boolean isNotificationEnabled(Notification notification) {
        if (!(notification instanceof UsageNotification)) return false;

        UsageNotification usageNotification = (UsageNotification)notification;
        if (service != null) {
            // SLEE 1.0 comparison
            return service.equals(usageNotification.getService())
                && sbb.equals(usageNotification.getSbb())
                && paramName.equals(usageNotification.getUsageParameterName())
                && (usageNotification.getValue() < lowValue || usageNotification.getValue() > highValue);
        }
        else {
            // SLEE 1.1 comparison
            return notificationSource.equals(usageNotification.getNotificationSource())
                && paramName.equals(usageNotification.getUsageParameterName())
                && (usageNotification.getValue() < lowValue || usageNotification.getValue() > highValue);
        }
    }

    private final ServiceID service;
    private final SbbID sbb;
    private final NotificationSource notificationSource;
    private final String paramName;
    private final long lowValue;
    private final long highValue;
}


package javax.slee;

import java.io.Serializable;
import java.io.StreamCorruptedException;

/**
 * This class defines an enumerated type that encapsulates the values available for
 * address presentation to other call parties.  The user application uses an address
 * presentation attribute to determine whether an address is to be presented to end
 * users.
 *

 * A singleton instance of each enumerated value is guaranteed (via an implementation
 * of readResolve() - refer {@link java.io.Serializable java.io.Serializable}),
 * so that equality tests using == are always evaluated correctly.  (This
 * equality test is only guaranteed if this class is loaded in the application's boot class
 * path, rather than dynamically loaded at runtime.)
 * @see Address
 */
public final class AddressPresentation implements Serializable{
    /**
     * An integer representation of {@link #UNDEFINED}.
     */
    public static final int ADDRESS_PRESENTATION_UNDEFINED = 0;

    /**
     * An integer representation of {@link #ALLOWED}.
     */
    public static final int ADDRESS_PRESENTATION_ALLOWED = 1;

    /**
     * An integer representation of {@link #RESTRICTED}.
     */
    public static final int ADDRESS_PRESENTATION_RESTRICTED = 2;

    /**
     * An integer representation of {@link #ADDRESS_NOT_AVAILABLE}.
     */
    public static final int ADDRESS_PRESENTATION_ADDRESS_NOT_AVAILABLE = 3;

    /**
     * A string representation of {@link #UNDEFINED}.
     */
    public static final String UNDEFINED_STRING = "Undefined";

    /**
     * A string representation of {@link #ALLOWED}.
     */
    public static final String ALLOWED_STRING = "Allowed";

    /**
     * A string representation of {@link #RESTRICTED}.
     */
    public static final String RESTRICTED_STRING = "Restricted";

    /**
     * A string representation of {@link #ADDRESS_NOT_AVAILABLE}.
     */
    public static final String ADDRESS_NOT_AVAILABLE_STRING = "Address Not Available";

    /**
     * The UNDEFINED value indicates that the address presentation
     * is undefined.
     */
    public static final AddressPresentation UNDEFINED = new AddressPresentation(ADDRESS_PRESENTATION_UNDEFINED);

    /**
     * The ALLOWED value indicates that the address presentation
     * is allowed.
     */
    public static final AddressPresentation ALLOWED = new AddressPresentation(ADDRESS_PRESENTATION_ALLOWED);

    /**
     * The RESTRICTED value indicates that the address presentation
     * is restricted.
     */
    public static final AddressPresentation RESTRICTED = new AddressPresentation(ADDRESS_PRESENTATION_RESTRICTED);

    /**
     * The ADDRESS_NOT_AVAILABLE value indicates that the address
     * is not available for presentation.
     */
    public static final AddressPresentation ADDRESS_NOT_AVAILABLE = new AddressPresentation(ADDRESS_PRESENTATION_ADDRESS_NOT_AVAILABLE);

    /**
     * Get an AddressPresentation object from an integer value.
     * @param value the address presentation value as an integer.
     * @return an AddressPresentation object corresponding to value.
     * @throws IllegalArgumentException if value is not a valid
     *        address presentation value.
     */
    public static AddressPresentation fromInt(int value) throws IllegalArgumentException {
        switch (value) {
            case ADDRESS_PRESENTATION_UNDEFINED: return UNDEFINED;
            case ADDRESS_PRESENTATION_ALLOWED: return ALLOWED;
            case ADDRESS_PRESENTATION_RESTRICTED: return RESTRICTED;
            case ADDRESS_PRESENTATION_ADDRESS_NOT_AVAILABLE: return ADDRESS_NOT_AVAILABLE;
            default: throw new IllegalArgumentException("Invalid value: " + value);
        }
    }

    /**
     * Get an AddressPresentation object from a string value.
     * @param value the address presentation as a string, for example as returned by the
              {@link #toString()} method (case insensitive).
     * @return an AddressPresentation object corresponding to value.
     * @throws NullPointerException if value is null.
     * @throws IllegalArgumentException if value is not a valid
     *        address presentation value.
     * @since SLEE 1.1
     */
    public static AddressPresentation fromString(String value) throws NullPointerException, IllegalArgumentException {
        if (value == null) throw new NullPointerException("value is null");
        if (value.equalsIgnoreCase(UNDEFINED_STRING)) return UNDEFINED;
        if (value.equalsIgnoreCase(ALLOWED_STRING)) return ALLOWED;
        if (value.equalsIgnoreCase(RESTRICTED_STRING)) return RESTRICTED;
        if (value.equalsIgnoreCase(ADDRESS_NOT_AVAILABLE_STRING)) return ADDRESS_NOT_AVAILABLE;
        throw new IllegalArgumentException("Invalid value: " + value);
    }

    /**
     * Get an integer value representation for this AddressPresentation object.
     * @return an integer value representation for this AddressPresentation object.
     */
    public int toInt() {
        return value;
    }

    /**
     * Determine if this AddressPresentation object represents the UNDEFINED address
     * presentation value.
     *

     * This method is effectively equivalent to the conditional test:
     * (this == UNDEFINED), ie. the code:
     *

     *     if (presentation.isUndefined()) ...
     *

     * is interchangeable with the code:
     *

     *    if (presentation == AddressPresentation.UNDEFINED) ...
     *

     * @return true if this object represents the UNDEFINED address presentation
     *       value, false otherwise.
     */
    public boolean isUndefined() {
        return value == ADDRESS_PRESENTATION_UNDEFINED;
    }

    /**
     * Determine if this AddressPresentation object represents the ALLOWED address
     * presentation value.
     *

     * This method is effectively equivalent to the conditional test:
     * (this == ALLOWED), ie. the code:
     *

     *     if (presentation.isAllowed()) ...
     *

     * is interchangeable with the code:
     *

     *    if (presentation == AddressPresentation.ALLOWED) ...
     *

     * @return true if this object represents the ALLOWED address presentation
     *       value, false otherwise.
     */
    public boolean isAllowed() {
        return value == ADDRESS_PRESENTATION_ALLOWED;
    }

    /**
     * Determine if this AddressPresentation object represents the RESTRICTED address
     * presentation value.
     *

     * This method is effectively equivalent to the conditional test:
     * (this == RESTRICTED), ie. the code:
     *

     *     if (presentation.isRestricted()) ...
     *

     * is interchangeable with the code:
     *

     *    if (presentation == AddressPresentation.RESTRICTED) ...
     *

     * @return true if this object represents the RESTRICTED address presentation
     *       value, false otherwise.
     */
    public boolean isRestricted() {
        return value == ADDRESS_PRESENTATION_RESTRICTED;
    }

    /**
     * Determine if this AddressPresentation object represents the ADDRESS_NOT_AVAILABLE address
     * presentation value.
     *

     * This method is effectively equivalent to the conditional test:
     * (this == ADDRESS_NOT_AVAILABLE), ie. the code:
     *

     *     if (presentation.isAddressNotAvailable()) ...
     *

     * is interchangeable with the code:
     *

     *    if (presentation == AddressPresentation.ADDRESS_NOT_AVAILABLE) ...
     *

     * @return true if this object represents the ADDRESS_NOT_AVAILABLE address presentation
     *       value, false otherwise.
     */
    public boolean isAddressNotAvailable() {
        return value == ADDRESS_PRESENTATION_ADDRESS_NOT_AVAILABLE ;
    }

    /**
     * Compare this address presentation for equality with another.
     * @param obj the object to compare this with.
     * @return true if obj is an instance of this class
     *        representing the same address presentation value as this,
     *        false otherwise.
     */
    public boolean equals(Object obj) {
        if (obj == this) return true;

        return (obj instanceof AddressPresentation)
            && ((AddressPresentation)obj).value == value;
    }

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

    /**
     * Get the textual representation of the address presentation object.
     * @return the textual representation of the address presentation object.
     */
    public String toString() {
        switch (value) {
            case ADDRESS_PRESENTATION_UNDEFINED: return UNDEFINED_STRING;
            case ADDRESS_PRESENTATION_ALLOWED: return ALLOWED_STRING;
            case ADDRESS_PRESENTATION_RESTRICTED: return RESTRICTED_STRING;
            case ADDRESS_PRESENTATION_ADDRESS_NOT_AVAILABLE: return ADDRESS_NOT_AVAILABLE_STRING;
            default: return "AddressPresentation in Unknown and Invalid State";
        }
    }

    /**
     * Private constructor to prevent unauthorized object creation.
     */
    private AddressPresentation(int value) {
        this.value = value;
    }

    /**
     * Resolve deserialisation references so that the singleton property of each
     * enumerated object is preserved.
     */
    private Object readResolve() throws StreamCorruptedException {
        try {
            return fromInt(value);
        }
        catch (IllegalArgumentException iae) {
            throw new StreamCorruptedException("Invalid internal state found");
        }
    }

    private final int value;
}


/*
 * 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 JSLEE Platform      *
 *                                                 *
 *  Distributable under LGPL license.              *
 *  See terms of license at gnu.org.               *
 *                                                 *
 ***************************************************
 *
 * Created on Nov 18, 2004
 *
 * AlarmMBeanImpl.java
 *
 */
package org.mobicents.slee.container.management.jmx;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

import javax.management.MBeanNotificationInfo;
import javax.management.ObjectName;
import javax.slee.ComponentID;
import javax.slee.SbbID;
import javax.slee.UnrecognizedComponentException;
import javax.slee.facilities.AlarmFacility;
import javax.slee.facilities.AlarmLevel;
import javax.slee.facilities.Level;
import javax.slee.management.Alarm;
import javax.slee.management.AlarmNotification;
import javax.slee.management.ManagementException;
import javax.slee.management.NotificationSource;
import javax.slee.management.UnrecognizedNotificationSourceException;

import org.apache.log4j.Logger;
import org.mobicents.slee.container.SleeContainer;
import org.mobicents.slee.container.facilities.NotificationSourceWrapper;
import org.mobicents.slee.container.management.AlarmManagement;
import org.mobicents.slee.container.transaction.TransactionalAction;
import org.mobicents.slee.runtime.facilities.DefaultAlarmFacilityImpl;

/**
 * Implementation of the Alarm MBean: The implementation of the JMX interface to
 * the SLEE alarm facility
 *
 * @author baranowb
 * @author Tim
 *
 */
@SuppressWarnings("deprecation")
public class AlarmMBeanImpl extends MobicentsServiceMBeanSupport implements AlarmManagement,AlarmMBeanImplMBean {

	private static Logger log = Logger.getLogger(AlarmMBeanImpl.class);

	private Map<AlarmPlaceHolder, NotificationSource> placeHolderToNotificationSource = new ConcurrentHashMap<AlarmPlaceHolder, NotificationSource>();
	private Map<String, AlarmPlaceHolder> alarmIdToAlarm = new ConcurrentHashMap<String, AlarmPlaceHolder>();

	private final TraceMBeanImpl traceMBean;

	/**
	 * @param traceMBean
	 */
	public AlarmMBeanImpl(TraceMBeanImpl traceMBean) {
		super();
		this.traceMBean = traceMBean;
	}

	/* (non-Javadoc)
	 * @see org.mobicents.slee.container.management.AlarmManagement#newAlarmFacility(javax.slee.management.NotificationSource)
	 */
	public AlarmFacility newAlarmFacility(NotificationSource notificationSource) {
		return new DefaultAlarmFacilityImpl(notificationSource, this);
	}

	/* (non-Javadoc)
	 * @see org.mobicents.slee.container.SleeContainerModule#setSleeContainer(org.mobicents.slee.container.SleeContainer)
	 */
	public void setSleeContainer(SleeContainer sleeContainer) {
		this.sleeContainer = sleeContainer;
	}

	/*
	 * (non-Javadoc)
	 * @see javax.slee.management.AlarmMBean#clearAlarm(java.lang.String)
	 */
	public boolean clearAlarm(String alarmID) throws NullPointerException, ManagementException {
		if (alarmID == null) {
			throw new NullPointerException("AlarmID must not be null");
		}

		AlarmPlaceHolder aph = alarmIdToAlarm.remove(alarmID);
		placeHolderToNotificationSource.remove(aph);
		if (aph == null) {
			return false;
		} else {
			// we clear?
			try {
				generateNotification(aph, true);
			} catch (Exception e) {
				throw new ManagementException("Failed to clear alarm due to: " + e);
			}
			return true;
		}

	}

	/*
	 * (non-Javadoc)
	 * @see javax.slee.management.AlarmMBean#clearAlarms(javax.slee.management.NotificationSource)
	 */
	public int clearAlarms(NotificationSource notificationSource) throws NullPointerException, UnrecognizedNotificationSourceException, ManagementException {
		if (notificationSource == null) {
			throw new NullPointerException("NotificationSource must not be null");
		}

		mandateSource(notificationSource);

		int count = 0;
		try {

			for (Map.Entry<AlarmPlaceHolder, NotificationSource> e : placeHolderToNotificationSource.entrySet()) {
				if (e.getValue().equals(notificationSource)) {
					if (clearAlarm(e.getKey().getAlarm().getAlarmID())) {
						count++;
					}
				}
			}

		} catch (Exception e) {
			throw new ManagementException("Failed to get alarm id list due to: ", e);
		}

		return count;
	}

	/*
	 * (non-Javadoc)
	 * @see javax.slee.management.AlarmMBean#clearAlarms(javax.slee.management.NotificationSource, java.lang.String)
	 */
	public int clearAlarms(NotificationSource notificationSource, String alarmType) throws NullPointerException, UnrecognizedNotificationSourceException, ManagementException {
		if (notificationSource == null) {
			throw new NullPointerException("NotificationSource must not be null");
		}

		if (alarmType == null) {
			throw new NullPointerException("AlarmType must not be null");
		}

		mandateSource(notificationSource);

		int count = 0;
		try {

			for (Map.Entry<AlarmPlaceHolder, NotificationSource> e : placeHolderToNotificationSource.entrySet()) {
				if (e.getValue().equals(notificationSource) && e.getKey().getAlarmType().equals(alarmType)) {
					if (clearAlarm(e.getKey().getAlarm().getAlarmID())) {
						count++;
					}
				}
			}

		} catch (Exception e) {
			throw new ManagementException("Failed to get alarm id list due to: ", e);
		}

		return count;
	}

	/*
	 * (non-Javadoc)
	 * @see javax.slee.management.AlarmMBean#getAlarms()
	 */
	public String[] getAlarms() throws ManagementException {
		try {
			Set<String> ids = new HashSet<String>();
			ids.addAll(alarmIdToAlarm.keySet());
			return ids.toArray(new String[ids.size()]);
		} catch (Exception e) {
			throw new ManagementException("Failed to get list of active alarms due to.", e);
		}
	}

	/*
	 * (non-Javadoc)
	 * @see javax.slee.management.AlarmMBean#getAlarms(javax.slee.management.NotificationSource)
	 */
	public String[] getAlarms(NotificationSource notificationSource) throws NullPointerException, UnrecognizedNotificationSourceException, ManagementException {
		if (notificationSource == null) {
			throw new NullPointerException("NotificationSource must not be null");
		}

		mandateSource(notificationSource);

		try {
			Set<String> ids = new HashSet<String>();
			for (Map.Entry<AlarmPlaceHolder, NotificationSource> e : placeHolderToNotificationSource.entrySet()) {
				if (e.getValue().equals(notificationSource)) {
					ids.add(e.getKey().getAlarm().getAlarmID());
				}
			}
			return ids.toArray(new String[ids.size()]);
		} catch (Exception e) {
			throw new ManagementException("Failed to get alarm id list due to: ", e);
		}
	}

	/*
	 * (non-Javadoc)
	 * @see javax.slee.management.AlarmMBean#getDescriptor(java.lang.String)
	 */
	public Alarm getDescriptor(String alarmID) throws NullPointerException, ManagementException {
		if (alarmID == null) {
			throw new NullPointerException("AlarmID must not be null");
		}
		AlarmPlaceHolder aph = this.alarmIdToAlarm.get(alarmID);
		if (aph == null)
			return null;
		return aph.getAlarm();
	}

	/*
	 * (non-Javadoc)
	 * @see javax.slee.management.AlarmMBean#getDescriptors(java.lang.String[])
	 */
	public Alarm[] getDescriptors(String[] alarmIDs) throws NullPointerException, ManagementException {
		if (alarmIDs == null) {
			throw new NullPointerException("AlarmID[] must not be null");
		}

		Set<Alarm> alarms = new HashSet<Alarm>();

		try {
			for (String id : alarmIDs) {
				Alarm a = getDescriptor(id);
				if (a != null)
					alarms.add(a);
			}
			return alarms.toArray(new Alarm[alarms.size()]);

		} catch (Exception e) {
			throw new ManagementException("Failed to get desciptors.", e);
		}
	}

	/*
	 * (non-Javadoc)
	 * @see javax.slee.management.AlarmMBean#isActive(java.lang.String)
	 */
	public boolean isActive(String alarmID) throws NullPointerException, ManagementException {
		return this.alarmIdToAlarm.containsKey(alarmID);
	}

	// NON MBEAN - used only internal, those methods are not exposed via jmx

	public boolean isSourceOwnerOfAlarm(NotificationSourceWrapper notificationSource, String alarmID) {
		AlarmPlaceHolder aph = this.alarmIdToAlarm.get(alarmID);
		if (aph == null)
			return false;

		return aph.getNotificationSource().getNotificationSource().equals(notificationSource.getNotificationSource());
	}

	public boolean isAlarmAlive(String alarmID) {
		return this.alarmIdToAlarm.containsKey(alarmID);
	}

	public boolean isAlarmAlive(NotificationSourceWrapper notificationSource, String alarmType, String instanceID) {

		AlarmPlaceHolder aph = new AlarmPlaceHolder(notificationSource, alarmType, instanceID);
		// return this.placeHolderToAlarm.containsKey(aph);

		return this.alarmIdToAlarm.containsValue(aph);
	}

	public String getAlarmId(NotificationSourceWrapper notificationSource, String alarmType, String instanceID) {
		AlarmPlaceHolder localAPH = new AlarmPlaceHolder(notificationSource, alarmType, instanceID);
		Alarm a = null;
		for (Map.Entry<String, AlarmPlaceHolder> e : this.alarmIdToAlarm.entrySet()) {
			if (e.getValue().equals(localAPH)) {
				a = e.getValue().getAlarm();
				break;
			}

		}
		if (a != null)
			return a.getAlarmID();
		else
			return null;
	}

	/**
	 * THis methods raises alarm. It MUST not receive AlarmLevel.CLEAR, it has
	 * to be filtered.
	 *
	 * @param notificationSource
	 * @param alarmType
	 * @param instanceID
	 * @param level
	 * @param message
	 * @param cause
	 * @return - AlarmId
	 */
	public String raiseAlarm(NotificationSourceWrapper notificationSource, String alarmType, String instanceID, AlarmLevel level, String message, Throwable cause) {

		synchronized (notificationSource) {
			if (isAlarmAlive(notificationSource, alarmType, instanceID)) {
				// Alarm a = this.placeHolderToAlarm.get(new
				// AlarmPlaceHolder(notificationSource, alarmType, instanceID));

				Alarm a = null;
				// unconveniant....
				try {
					AlarmPlaceHolder localAPH = new AlarmPlaceHolder(notificationSource, alarmType, instanceID);
					for (Map.Entry<String, AlarmPlaceHolder> e : this.alarmIdToAlarm.entrySet()) {
						if (e.getValue().equals(localAPH)) {
							a = e.getValue().getAlarm();
							break;
						}
					}
				} catch (Exception e) {
					// ignore
				}

				if (a != null) {

					return a.getAlarmID();
				} else {
					return this.raiseAlarm(notificationSource, alarmType, instanceID, level, message, cause);
				}
			} else {
				Alarm a = new Alarm(UUID.randomUUID().toString(), notificationSource.getNotificationSource(), alarmType, instanceID, level, message, cause, System.currentTimeMillis());
				AlarmPlaceHolder aph = new AlarmPlaceHolder(notificationSource, alarmType, instanceID, a);
				this.alarmIdToAlarm.put(a.getAlarmID(), aph);
				// this.placeHolderToAlarm.put(aph, a);
				this.placeHolderToNotificationSource.put(aph, aph.getNotificationSource().getNotificationSource());
				generateNotification(aph, false);
				return a.getAlarmID();
			}
		}

	}

	private void generateNotification(AlarmPlaceHolder aph, boolean isCleared) {
		Alarm alarm = aph.getAlarm();
		AlarmLevel generalLevel = isCleared ? AlarmLevel.CLEAR : alarm.getAlarmLevel();

		AlarmNotification notification = new AlarmNotification(aph.getNotificationSource().getNotificationSource().getAlarmNotificationType(), this, alarm.getAlarmID(), aph.getNotificationSource()
				.getNotificationSource(), alarm.getAlarmType(), alarm.getInstanceID(), generalLevel, alarm.getMessage(), alarm.getCause(), aph.getNotificationSource().getNextSequence(), System
				.currentTimeMillis());
		super.sendNotification(notification);
	}

	/**
	 * This method is requried - in case component is removed on call to method with its noti source we must throw unknown notification source exception - even thought alarms MAY be present?
	 * @throws UnrecognizedNotificationSourceException
	 */
	private void mandateSource(NotificationSource src) throws UnrecognizedNotificationSourceException
	{
		if(!traceMBean.isNotificationSourceDefined(src))
		{
			throw new UnrecognizedNotificationSourceException("Notification source is not present: "+src);
		}
	}

	class AlarmPlaceHolder {
		private NotificationSourceWrapper notificationSource;
		private String alarmType;
		private String instanceID;
		private Alarm alarm;

		public AlarmPlaceHolder(NotificationSourceWrapper notificationSource, String alarmType, String instanceID) {
			super();
			this.notificationSource = notificationSource;
			this.alarmType = alarmType;
			this.instanceID = instanceID;
		}

		public AlarmPlaceHolder(NotificationSourceWrapper notificationSource, String alarmType, String instanceID, Alarm a) {
			this.notificationSource = notificationSource;
			this.alarmType = alarmType;
			this.instanceID = instanceID;
			this.alarm = a;
		}

		public NotificationSourceWrapper getNotificationSource() {
			return notificationSource;
		}

		public String getAlarmType() {
			return alarmType;
		}

		public String getInstanceID() {
			return instanceID;
		}

		public Alarm getAlarm() {
			return alarm;
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + getOuterType().hashCode();
			result = prime * result + ((alarmType == null) ? 0 : alarmType.hashCode());
			result = prime * result + ((instanceID == null) ? 0 : instanceID.hashCode());
			result = prime * result + ((notificationSource == null) ? 0 : notificationSource.hashCode());
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			AlarmPlaceHolder other = (AlarmPlaceHolder) obj;
			if (!getOuterType().equals(other.getOuterType()))
				return false;
			if (alarmType == null) {
				if (other.alarmType != null)
					return false;
			} else if (!alarmType.equals(other.alarmType))
				return false;
			if (instanceID == null) {
				if (other.instanceID != null)
					return false;
			} else if (!instanceID.equals(other.instanceID))
				return false;
			if (notificationSource == null) {
				if (other.notificationSource != null)
					return false;
			} else if (!notificationSource.equals(other.notificationSource))
				return false;
			return true;
		}

		private AlarmMBeanImpl getOuterType() {
			return AlarmMBeanImpl.this;
		}

	}

	// 1.0 part, required for compatibility.
	/**
	 * Represents a component registered with the alarm facility. Basically just
	 * stores notification sequence number
	 *
	 * @author Tim
	 */
	static class RegisteredComp {
		public AtomicLong seqNo = new AtomicLong(0);

		public long getSeqNo() {
			return seqNo.getAndIncrement();
		}
	}

	private Map<ComponentID, RegisteredComp> registeredComps = new ConcurrentHashMap<ComponentID, RegisteredComp>();

	// 1.0 methods

	public boolean isRegisteredAlarmComponent(ComponentID alarmSource) {
		// FIXME: in 1.0 we allow only SbbID as componetns
		return this.registeredComps.containsKey(alarmSource);
	}

	public void createAlarm(ComponentID alarmSource, Level alarmLevel, String alarmType, String message, Throwable cause, long timestamp) throws UnrecognizedComponentException {
		if (log.isDebugEnabled()) {
			log.debug("alarmSource:" + alarmSource + " alarmLevel:" + alarmLevel + " alarmType:" + alarmType + " message:" + message + " cause:" + cause + " timeStamp:" + timestamp);
		}
		if (alarmSource == null || alarmLevel == null || alarmType == null || message == null)
			throw new NullPointerException("Null parameter");
		if (alarmLevel.isOff())
			throw new IllegalArgumentException("Invalid alarm level");

		RegisteredComp comp = registeredComps.get(alarmSource);
		if (comp == null)
			throw new UnrecognizedComponentException("Component not registered");

		// TODO I'm not sure if we should log the alarm too

		// Add the notication type if not already in set. See note in
		// declaration about why we are using a map, not a set
		// if (!this.notificationTypes.containsKey(alarmType))
		// this.notificationTypes.put(alarmType, alarmType);

		// Create the alarm notification and propagate to the Alarm MBean

		AlarmNotification notification = new AlarmNotification(this, alarmType, alarmSource, alarmLevel, message, cause, comp.getSeqNo(), timestamp);
		super.sendNotification(notification);

	}

	public void registerComponent(final SbbID sbbID) {
		if (log.isDebugEnabled()) {
			log.debug("Registering component with alarm facility: " + sbbID);
		}

		registeredComps.put(sbbID, new RegisteredComp());

		TransactionalAction action = new TransactionalAction() {
			public void execute() {
				registeredComps.remove(sbbID);
			}
		};
		sleeContainer.getTransactionManager().getTransactionContext().getAfterRollbackActions().add(action);

	}

	public void unRegisterComponent(final SbbID sbbID) {
		final RegisteredComp registeredComp = this.registeredComps.remove(sbbID);
		if (registeredComp != null) {
			TransactionalAction action = new TransactionalAction() {
				public void execute() {
					registeredComps.put(sbbID, registeredComp);
				}
			};
			sleeContainer.getTransactionManager().getTransactionContext().getAfterRollbackActions().add(action);
		}

	}

	/* (non-Javadoc)
	 * @see org.mobicents.slee.container.management.AlarmManagement#getAlarmMBeanObjectName()
	 */
	public ObjectName getAlarmMBeanObjectName() {
		return getObjectName();
	}

	// NOTIFICATION PART
	/*
	 * (non-Javadoc)
	 *
	 * @see javax.management.NotificationBroadcaster#getNotificationInfo()
	 */
	public MBeanNotificationInfo[] getNotificationInfo() {

		return null;
	}

	@Override
	public void sleeInitialization() {
	}

	@Override
	public void sleeStarting() {

	}

	@Override
	public void sleeRunning() {

	}

	@Override
	public void sleeStopping() {

	}

	@Override
	public void sleeStopped() {

	}

	@Override
	public void sleeShutdown() {

	}

}


/*
 * 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 javax.slee.SLEEException;
import javax.slee.profile.ProfileID;
import javax.slee.profile.UnrecognizedProfileTableNameException;
import javax.slee.usage.UnrecognizedUsageParameterSetNameException;

import org.apache.log4j.Logger;
import org.mobicents.slee.container.SleeContainer;
import org.mobicents.slee.container.management.ProfileManagementImpl;
import org.mobicents.slee.container.transaction.SleeTransactionManager;

/**
 *
 * ProfileManagementHandler.java
 *
 *

 * Project: restcomm

 * 3:26:16 PM Apr 3, 2009

 *
 * @author  Bartosz Baranowski
 * @author  Alexandre Mendonca
 */
public class ProfileManagementHandler {

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

	public static boolean isProfileDirty(ProfileObjectImpl profileObject) {
		if (logger.isDebugEnabled()) {
			logger.info("[isProfileDirty] @ " + profileObject);
		}

		return profileObject.getProfileEntity().isDirty();
	}

	public static boolean isProfileValid(ProfileObject profileObject,
			ProfileID profileId) throws NullPointerException, SLEEException {
		if (logger.isDebugEnabled()) {
			logger.info("[isProfileValid(" + profileId + ")] @ "
					+ profileObject);
		}

		if (profileId == null) {
			throw new NullPointerException("null profile id");
		}

		final SleeContainer sleeContainer = SleeContainer.lookupFromJndi();
		final SleeTransactionManager txManager = sleeContainer.getTransactionManager();

		boolean terminateTx = txManager.requireTransaction();
		try {
			ProfileTableImpl profileTable = ((ProfileManagementImpl)sleeContainer.getSleeProfileTableManager()).getProfileTable(profileId.getProfileTableName());
			return profileTable.profileExists(profileId.getProfileName());
		}
		catch (UnrecognizedProfileTableNameException e) {
			return false;
		}
		catch (Throwable e) {
			throw new SLEEException(e.getMessage(),e);
		}
		finally {
			try {
				txManager.requireTransactionEnd(terminateTx, false);
			} catch (Throwable e) {
				logger.error(e.getMessage(),e);
			}
		}
	}

	public static void markProfileDirty(ProfileObjectImpl profileObject) {
		if (logger.isDebugEnabled()) {
			logger.info("[markProfileDirty] @ " + profileObject);
		}

		profileObject.getProfileEntity().setDirty(true);
	}

	// Usage methods. Here we can be static for sure. Rest must be tested.
	public static Object getUsageParameterSet(ProfileObjectImpl profileObject,
			String name) throws UnrecognizedUsageParameterSetNameException {
		if (logger.isDebugEnabled()) {
			logger.info("[getUsageParameterSet(" + name + ")] @ "
					+ profileObject);
		}

		if (name == null) {
			throw new NullPointerException(
					"UsageParameterSet name must not be null.");
		}
		ProfileTableImpl profileTable = profileObject
				.getProfileTable();
		Object result = profileTable.getProfileTableUsageMBean()
				.getInstalledUsageParameterSet(name);
		if (result == null) {
			throw new UnrecognizedUsageParameterSetNameException();
		}
		else {
			return result;
		}
	}

	public static Object getDefaultUsageParameterSet(
			ProfileObjectImpl profileObject) {

		if (logger.isDebugEnabled()) {
			logger.info("[getDefaultUsageParameterSet] @ "
					+ profileObject);
		}
		ProfileTableImpl profileTable = profileObject
				.getProfileTable();
		return profileTable.getProfileTableUsageMBean().getDefaultInstalledUsageParameterSet();
	}

	private static ClassLoader switchContextClassLoader(
			ClassLoader newClassLoader) {
		Thread t = Thread.currentThread();
		ClassLoader oldClassLoader = t.getContextClassLoader();
		t.setContextClassLoader(newClassLoader);

		return oldClassLoader;
	}

}


/*
 * 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.facilities.nullactivity;

import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

import org.mobicents.slee.container.activity.ActivityContextHandle;
import org.mobicents.slee.container.activity.ActivityType;
import org.mobicents.slee.container.facilities.nullactivity.NullActivityHandle;

/**
 * @author martins
 *
 */
public class NullActivityContextHandle implements ActivityContextHandle {

	/**
	 *
	 */
	private static final long serialVersionUID = 1L;

	private NullActivityHandle activityHandle;
	private NullActivityImpl activityObject;

	/**
	 * not to be used, needed due to externalizable
	 */
	public NullActivityContextHandle() {

	}

	/**
	 *
	 */
	public NullActivityContextHandle(NullActivityHandle activityHandle) {
		this.activityHandle = activityHandle;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.mobicents.slee.runtime.activity.ActivityContextHandle#getActivityHandle
	 * ()
	 */
	public NullActivityHandle getActivityHandle() {
		return activityHandle;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.mobicents.slee.runtime.activity.ActivityContextHandle#getActivityObject
	 * ()
	 */
	public Object getActivityObject() {
		if (activityObject == null) {
			activityObject = new NullActivityImpl(activityHandle);
		}
		return activityObject;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.mobicents.slee.runtime.activity.ActivityContextHandle#getActivityType
	 * ()
	 */
	public ActivityType getActivityType() {
		return ActivityType.NULL;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (obj.getClass() == this.getClass()) {
			final NullActivityContextHandle other = (NullActivityContextHandle) obj;
			return other.activityHandle.equals(this.activityHandle);
		} else {
			return false;
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		return activityHandle.hashCode();
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return new StringBuilder("ACH=").append(getActivityType()).append('>')
				.append(activityHandle).toString();
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see java.io.Externalizable#readExternal(java.io.ObjectInput)
	 */
	@Override
	public void readExternal(ObjectInput in) throws IOException,
			ClassNotFoundException {
		this.activityHandle = new NullActivityHandleImpl(in.readUTF());
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
	 */
	@Override
	public void writeExternal(ObjectOutput out) throws IOException {
		out.writeUTF(((NullActivityHandleImpl) activityHandle).getId());
	}

}


/*
 * 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:00:44:47 2009-02-04

 * Project: restcomm-jainslee-server-core

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

import java.util.Comparator;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.slee.ComponentID;
import javax.slee.EventTypeID;
import javax.slee.ServiceID;
import javax.slee.management.ComponentDescriptor;
import javax.slee.management.DependencyException;
import javax.slee.management.DeploymentException;
import javax.slee.management.LibraryID;

import org.mobicents.slee.container.component.deployment.jaxb.descriptors.EventTypeDescriptorImpl;
import org.mobicents.slee.container.component.event.EventTypeComponent;
import org.mobicents.slee.container.component.service.ServiceComponent;

/**
 * Start time:00:44:47 2009-02-04

 * Project: restcomm-jainslee-server-core

 *
 * @author baranowb - Bartosz Baranowski
 *
 * @author  Alexandre Mendonca
 */
public class EventTypeComponentImpl extends AbstractSleeComponent implements EventTypeComponent {

	/**
	 * the event type descriptor
	 */
	private final EventTypeDescriptorImpl descriptor;

	/**
	 * the event type class
	 */
	private Class<?> eventTypeClass = null;

	/**
	 * the JAIN SLEE specs event type descriptor
	 */
	private javax.slee.management.EventTypeDescriptor specsDescriptor = null;

	/**
	 * the ordered set of active {@link ServiceComponentImpl} which define this event as initial
	 */
	private SortedSet<ServiceComponent> activeServicesWhichDefineEventAsInitial = new TreeSet<ServiceComponent>(new ActiveServicesWhichDefineEventAsInitialComparator());

	private static class ActiveServicesWhichDefineEventAsInitialComparator implements Comparator<ServiceComponent> {
		public int compare(ServiceComponent o1, ServiceComponent o2) {
			if (o1 == o2) {
				return 0;
			}
			int result = o2.getDescriptor().getDefaultPriority() - o1.getDescriptor().getDefaultPriority();
			if (result == 0) {
				// older wins
				result = (int) (o1.getCreationTime() - o2.getCreationTime());
				if (result == 0) {
					// id string comparation, cause a 0 result means one entity is not added to set
					result = o1.getServiceID().compareTo(o2.getServiceID());
				}
			}
			return result;
		}
	}
	/**
	 *
	 * @param descriptor
	 */
	public EventTypeComponentImpl(EventTypeDescriptorImpl descriptor) {
		this.descriptor = descriptor;
	}

	/**
	 * Retrieves the event type class
	 * @return
	 */
	public Class<?> getEventTypeClass() {
		return eventTypeClass;
	}

	/**
	 * Sets the event type class
	 * @param eventTypeClass
	 */
	public void setEventTypeClass(Class<?> eventTypeClass) {
		this.eventTypeClass = eventTypeClass;
	}

	/**
	 * Retrieves the event type id
	 * @return
	 */
	public EventTypeID getEventTypeID() {
		return descriptor.getEventTypeID();
	}

	/**
	 * Retrieves the event type descriptor
	 * @return
	 */
	public EventTypeDescriptorImpl getDescriptor() {
		return descriptor;
	}

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

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

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

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

	@Override
	public boolean validate() throws DependencyException, DeploymentException {
		// nothing to validate
		return true;
	}

	/**
	 * Retrieves the JAIN SLEE specs event type descriptor
	 * @return
	 */
	public javax.slee.management.EventTypeDescriptor getSpecsDescriptor() {
		if (specsDescriptor == null) {
			specsDescriptor = new javax.slee.management.EventTypeDescriptor(getEventTypeID(),getDeployableUnit().getDeployableUnitID(),getDeploymentUnitSource(),descriptor.getLibraryRefs().toArray(new LibraryID[descriptor.getLibraryRefs().size()]),getDescriptor().getEventClassName());
		}
		return specsDescriptor;
	}

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

	/**
	 * Retrieves the set of active {@link ServiceComponentImpl} which define this event as initial
	 * @return
	 */
	public Set<ServiceComponent> getActiveServicesWhichDefineEventAsInitial() {
		return activeServicesWhichDefineEventAsInitial;
	}

	/**
	 * Signals that the specified {@link ServiceComponentImpl} which define this event as initial was activated
	 * @param serviceComponent
	 */
	public void activatedServiceWhichDefineEventAsInitial(ServiceComponent serviceComponent) {
		// create new ordered set
		SortedSet<ServiceComponent> activeServicesWhichDefineEventAsInitial = new TreeSet<ServiceComponent>(new ActiveServicesWhichDefineEventAsInitialComparator());
		// add all existent active services, except old version, this allows smooth service upgrade
		ServiceID oldVersion = serviceComponent.getOldVersion();
		if (oldVersion == null) {
			activeServicesWhichDefineEventAsInitial.addAll(this.activeServicesWhichDefineEventAsInitial);
		}
		else {
			for (ServiceComponent existentServiceComponent : this.activeServicesWhichDefineEventAsInitial) {
				if(!existentServiceComponent.getServiceID().equals(oldVersion)) {
					activeServicesWhichDefineEventAsInitial.add(existentServiceComponent);
				}
			}
		}
		// add new service
		activeServicesWhichDefineEventAsInitial.add(serviceComponent);
		// replace old set
		this.activeServicesWhichDefineEventAsInitial = activeServicesWhichDefineEventAsInitial;
	}

	/**
	 * Signals that the specified {@link ServiceComponentImpl} which define this event as initial was deactivated
	 * @param serviceComponent
	 */
	public void deactivatedServiceWhichDefineEventAsInitial(ServiceComponent serviceComponent) {
		// create new ordered set
		SortedSet<ServiceComponent> activeServicesWhichDefineEventAsInitial = new TreeSet<ServiceComponent>(new ActiveServicesWhichDefineEventAsInitialComparator());
		// add all existent active services, except one deactivated
		for (ServiceComponent existentServiceComponent : this.activeServicesWhichDefineEventAsInitial) {
			if(!existentServiceComponent.equals(serviceComponent)) {
				activeServicesWhichDefineEventAsInitial.add(existentServiceComponent);
			}
		}
		// replace old set
		this.activeServicesWhichDefineEventAsInitial = activeServicesWhichDefineEventAsInitial;
	}

	@Override
	public void processSecurityPermissions() throws DeploymentException {
		//Do nothing

	}

	@Override
	public void undeployed() {
		super.undeployed();
		eventTypeClass = null;
		if (activeServicesWhichDefineEventAsInitial != null) {
			activeServicesWhichDefineEventAsInitial.clear();
			activeServicesWhichDefineEventAsInitial = null;
		}
	}
}


/*
 * 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.deployment.jboss;

import org.apache.log4j.Logger;
import org.mobicents.slee.container.component.du.DeployableUnitDescriptor;
import org.mobicents.slee.container.component.du.DeployableUnitDescriptorFactory;

import javax.slee.InvalidStateException;
import javax.slee.management.DependencyException;
import javax.slee.management.DeploymentException;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * This is the Deployer main class where the AS will invoke the lifecycle
 * methods for new deployments.
 *
 * @author Alexandre Mendonça
 * @author martins
 * @version 1.0
 */
@SuppressWarnings("deprecation")
public class SLEESubDeployer implements
		SLEESubDeployerMBean {

	// Constants -----------------------------------------------------

	// The Logger.
	private static Logger logger = Logger.getLogger(SLEESubDeployer.class);

	// Attributes ----------------------------------------------------

	// The DIs to be accepted by this deployer.
	private ConcurrentHashMap<String, DeployableUnitWrapper> toAccept = new ConcurrentHashMap<String, DeployableUnitWrapper>();

	// Deployable Units present.
	private ConcurrentHashMap<String, DeployableUnit> deployableUnits = new ConcurrentHashMap<String, DeployableUnit>();

	private CopyOnWriteArrayList<String> undeploys = new CopyOnWriteArrayList<String>();

	private final SleeContainerDeployerImpl sleeContainerDeployer;

	public SLEESubDeployer(SleeContainerDeployerImpl sleeContainerDeployer) {
		this.sleeContainerDeployer = sleeContainerDeployer;
	}

	// Constructors
	// -------------------------------------------------------------

	/**
	 * Method for deciding whether or not to accept the file.
	 */
	public boolean accepts(URL deployableUnitURL, String deployableUnitName) {
		DeployableUnitWrapper du = new DeployableUnitWrapper(deployableUnitURL, deployableUnitName);

		URL url = du.getUrl();

		if (logger.isTraceEnabled()) {
			logger.trace("Method accepts called for " + url + " [DU: " + deployableUnitName + "]");
		}

		try {
			String fullPath = url.getFile();
			String fileName = fullPath.substring(fullPath.lastIndexOf('/') + 1,
					fullPath.length());

			// Is it in the toAccept list ? Direct accept.
			if (toAccept.containsKey(fileName)) {
				if (logger.isTraceEnabled()) {
					logger.trace("Accepting " + url.toString() + ".");
				}

				return true;
			}
			// If not it the accept list but it's a jar might be a DU jar...
			else if (fileName.endsWith(".jar")) {
				JarFile duJarFile = null;

				try {
					// Try to obtain the DU descriptor, if we got it, we're
					// accepting it!
					if (du.getEntry("META-INF/deployable-unit.xml") != null) {
						if (logger.isTraceEnabled()) {
							logger.trace("Accepting " + url.toString() + ".");
						}

						return true;
					}
				} finally {
					// Clean up!
					if (duJarFile != null) {
						try {
							duJarFile.close();
						} catch (IOException ignore) {
						} finally {
							duJarFile = null;
						}
					}
				}
			}
		} catch (Exception ignore) {
			// Ignore.. will reject.
		}

		// Uh-oh.. looks like it will stay outside.
		return false;
	}

	/**
	 * Initializer method for accepted files. Will parse descriptors at this
	 * point.
	 */
	public void init(URL deployableUnitURL, String deployableUnitName) throws DeploymentException {
		URL url = deployableUnitURL;
		DeployableUnitWrapper du = new DeployableUnitWrapper(deployableUnitURL, deployableUnitName);

		if (logger.isTraceEnabled()) {
			logger.trace("Method init called for " + deployableUnitURL + " [DU: " + deployableUnitName + "]");
		}

		// Get the full path and filename for this du
		String fullPath = du.getFullPath();
		String fileName = du.getFileName();

		try {
			DeployableUnitWrapper duWrapper = null;

			// If we're able to remove it from toAccept was because it was
			// there!
			if ((duWrapper = toAccept.remove(fileName)) != null) {
				// Create a new Deployable Component from this DI.
				DeployableComponent dc = new DeployableComponent(du, url,
						fileName, sleeContainerDeployer);

				// Also get the deployable unit for this (it exists, we've
				// checked!)
				DeployableUnit deployerDU = deployableUnits.get(duWrapper
						.getFileName());

				for (DeployableComponent subDC : dc.getSubComponents()) {
					// Add the sub-component to the DU object.
					deployerDU.addComponent(subDC);
				}
			}
			// If the DU for this component doesn't exists.. it's a new DU!
			else if (fileName.endsWith(".jar")) {
				JarFile duJarFile = null;

				try {
					// Get a reference to the DU jar file
					duJarFile = new JarFile(fullPath);

					// Try to get the Deployable Unit descriptor
					JarEntry duXmlEntry = duJarFile
							.getJarEntry("META-INF/deployable-unit.xml");

					// Got descriptor?
					if (duXmlEntry != null) {
						// Create a new Deployable Unit object.
						DeployableUnit deployerDU = new DeployableUnit(du,sleeContainerDeployer);

						// Let's parse the descriptor to see what we've got...
						DeployableUnitDescriptorFactory dudf = sleeContainerDeployer
								.getSleeContainer().getComponentManagement()
								.getDeployableUnitManagement()
								.getDeployableUnitDescriptorFactory();
						DeployableUnitDescriptor duDesc = dudf.parse(duJarFile
								.getInputStream(duXmlEntry));

						// If the filename is present, an undeploy in on the way... let's wait
						while(deployableUnits.containsKey(fileName)) {
							Thread.sleep(getWaitTimeBetweenOperations());
						}

						// Add it to the deployable units map.
						deployableUnits.put(fileName, deployerDU);

						// Go through each jar entry in the DU descriptor
						for (String componentJarName : duDesc.getJarEntries()) {
							// Might have path... strip it!
							int beginIndex;

							if ((beginIndex = componentJarName.lastIndexOf('/')) == -1)
								beginIndex = componentJarName.lastIndexOf('\\');

							beginIndex++;

							// Got a clean jar name, no paths.
							componentJarName = componentJarName.substring(
									beginIndex, componentJarName.length());

							// Put it in the accept list.
							toAccept.put(componentJarName, du);
						}

						// Do the same as above... but for services
						for (String serviceXMLName : duDesc.getServiceEntries()) {
							// Might have path... strip it!
							int beginIndex;

							if ((beginIndex = serviceXMLName.lastIndexOf('/')) == -1)
								beginIndex = serviceXMLName.lastIndexOf('\\');

							beginIndex++;

							// Got a clean XML filename
							serviceXMLName = serviceXMLName.substring(
									beginIndex, serviceXMLName.length());

							// Add it to the accept list.
							toAccept.put(serviceXMLName, du);
						}
					}
				} finally {
					// Clean up!
					if (duJarFile != null) {
						try {
							duJarFile.close();
						} catch (IOException ignore) {
						} finally {
							duJarFile = null;
						}
					}
				}
			}
		} catch (Exception e) {
			// Something went wrong...
			logger.error("Deployment of " + fileName + " failed. ", e);

			return;
		}
	}

	/**
	 * This is where the fun begins. Time to deploy!
	 */
	public void start(URL deployableUnitURL, String deployableUnitName) throws DeploymentException {
		DeployableUnitWrapper du = new DeployableUnitWrapper(deployableUnitURL, deployableUnitName);

		if (logger.isTraceEnabled()) {
			logger.trace("Method start called for " + du.getUrl() + " [DU: " + deployableUnitName + "]");
		}

		try {
			// Get the deployable unit object
			DeployableUnit realDU = deployableUnits.get(du.getFileName());

			// If it exists, install it.
			if (realDU != null) {
				while (isInUndeployList(du.getFileName())) {
					Thread.sleep(getWaitTimeBetweenOperations());
				}
				sleeContainerDeployer.getDeploymentManager().installDeployableUnit(realDU);
			}
		} catch (Exception e) {
			logger.error("", e);
		}
	}

	/**
	 * Fun has ended. Time to undeploy.
	 */
	public void stop(URL deployableUnitURL, String deployableUnitName) throws DeploymentException {

		if (logger.isTraceEnabled()) {
			logger.trace("stop( deployableUnitURL = : " + deployableUnitURL+" )");
		}

		DeployableUnitWrapper du = new DeployableUnitWrapper(deployableUnitURL, deployableUnitName);

		DeployableUnit realDU = null;

		String fileName = du.getFileName();

		if ((realDU = deployableUnits.get(du.getFileName())) != null) {
			if (logger.isTraceEnabled()) {
				logger.trace("Got DU: " + realDU.getDeploymentInfoShortName());
			}

			if (!isInUndeployList(fileName)) {
				addToUndeployList(fileName);
			}

			try {
				// Uninstall it
				sleeContainerDeployer.getDeploymentManager().uninstallDeployableUnit(realDU);
				// Remove it from list if successful
				deployableUnits.remove(fileName);
				removeFromUndeployList(fileName);
			} catch (DependencyException e) {
				// ignore, will be tried again once there is another undeployment
			} catch (Exception e) {
				Throwable cause = e.getCause();
				if (cause instanceof InvalidStateException) {
					logger.warn(cause.getLocalizedMessage() + "... WAITING ...");
				} else if (e instanceof DeploymentException) {
					throw new IllegalStateException(e.getLocalizedMessage(), e);
				} else {
					logger.error(e.getMessage(), e);
				}
			}
		}
	}

	// MBean Operations
	// ---------------------------------------------------------

	/**
	 * MBean operation for getting Deployer status.
	 */
	public String showStatus() throws DeploymentException {
		String output = "";

		output += "
Deployable Units List:
";

		for (String key : deployableUnits.keySet()) {
			output += "<" + key + "> [" + deployableUnits.get(key)
					+ "]
";

			for (String duComponent : deployableUnits.get(key).getComponents()) {
				output += "+-- " + duComponent + "
";
			}
		}

		output += "
To Accept List:
";

		for (String key : toAccept.keySet()) {
			output += "<" + key + "> [" + toAccept.get(key) + "]
";
		}

		output += "
Undeployments running:
";

		for (String undeploy : undeploys) {
			output += "+-- " + undeploy + "
";
		}

		output += "
Deployment Manager Status
";

		output += sleeContainerDeployer.getDeploymentManager().showStatus();

		return output;
	}

	/**
	 * MBean WaitTimeBetweenOperations property getter
	 */
	public long getWaitTimeBetweenOperations() {
		return sleeContainerDeployer.getDeploymentManager().waitTimeBetweenOperations;
	}

	/**
	 * MBean WaitTimeBetweenOperations property getter
	 */
	public void setWaitTimeBetweenOperations(long waitTime) {
		sleeContainerDeployer.getDeploymentManager().waitTimeBetweenOperations = waitTime;
	}

	// Aux Functions
	// ------------------------------------------------------------

	private boolean addToUndeployList(String du) {
		if (logger.isTraceEnabled()) {
			logger.trace("Adding " + du + " to running undeployments list ...");
			logger.trace("Current Undeploy List: " + undeploys.toString());
		}
		boolean added = undeploys.add(du);
		if (logger.isTraceEnabled()) {
			logger.trace("Added  " + du + " to running undeployments list = "
					+ added);
			logger.trace("Current Undeploy List: " + undeploys.toString());
		}
		return added;
	}

	private boolean removeFromUndeployList(String du) {
		if (logger.isTraceEnabled()) {
			logger.trace("Removing " + du
					+ " from running undeployments list ...");
			logger.trace("Current Undeploy List: " + undeploys.toString());
		}
		boolean removed = undeploys.remove(du);
		if (logger.isTraceEnabled()) {
			logger.trace("Removed  " + du
					+ " from running undeployments list = " + removed);
			logger.trace("Current Undeploy List: " + undeploys.toString());
		}
		return removed;
	}

	private boolean isInUndeployList(String du) {
		if (logger.isTraceEnabled()) {
			logger.trace("Checking if " + du
					+ " is in running undeployments list ...");
			logger.trace("Current Undeploy List: " + undeploys.toString());
		}
		boolean contains = undeploys.contains(du);
		if (logger.isTraceEnabled()) {
			logger.trace("Checked  if " + du
					+ " is in running undeployments list = " + contains);
			logger.trace("Current Undeploy List: " + undeploys.toString());
		}
		return contains;
	}

}