/*
 * TeleStax, Open Source Cloud Communications
 * Copyright 2011-2014, Telestax Inc and individual contributors
 * by the @authors tag.
 *
 * This program is free software: you can redistribute it and/or modify
 * under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 *
 * This file incorporates work covered by the following copyright contributed under the GNU LGPL : Copyright 2007-2011 Red Hat.
 */

package org.mobicents.slee.runtime.transaction;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.slee.SLEEException;
import javax.slee.TransactionRequiredLocalException;
import javax.slee.transaction.CommitListener;
import javax.slee.transaction.RollbackListener;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.InvalidTransactionException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.Status;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;

import org.apache.log4j.Logger;
import org.mobicents.slee.container.AbstractSleeContainerModule;
import org.mobicents.slee.container.transaction.SleeTransaction;
import org.mobicents.slee.container.transaction.SleeTransactionManager;
import org.mobicents.slee.container.transaction.TransactionContext;

import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple;
import org.mobicents.slee.util.concurrent.SleeThreadFactory;

/**
 * Implementation of SLEE Tx manager.
 *
 * @author Tim Fox - Complete re-write.
 * @author M. Ranganathan
 * @author J. Deruelle
 * @author Ralf Siedow
 * @author Ivelin Ivanov
 * @author Eduardo Martins version 2
 *
 */
public class SleeTransactionManagerImpl extends AbstractSleeContainerModule implements SleeTransactionManager {

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

    private final static SleeThreadFactory SLEE_THREAD_FACTORY = new SleeThreadFactory("SLEE-TransactionManager");

    /**
	 * the underlying JTA tx manager
	 */
	private final TransactionManager transactionManager;

	/**
	 * an executor service for async operations invoked on {@link SleeTransaction}
	 */
	private ExecutorService executorService;

	private static final boolean doTraceLogs = logger.isTraceEnabled();

	/**
	 *
	 * @param transactionManager
	 */
	public SleeTransactionManagerImpl(TransactionManager transactionManager) {
		this.transactionManager = transactionManager;
	}

	/**
	 *
	 * @return
	 */
	ExecutorService getExecutorService() {
		if (executorService == null) {
			executorService = Executors.newCachedThreadPool(SLEE_THREAD_FACTORY);
		}
		return executorService;
	}

	/* (non-Javadoc)
	 * @see org.mobicents.slee.runtime.transaction.SleeTransactionManager#getRealTransactionManager()
	 */
	public TransactionManager getRealTransactionManager() {
		return transactionManager;
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.runtime.transaction.SleeTransactionManager#getRollbackOnly()
	 */
	public boolean getRollbackOnly() throws SystemException {
		return getStatus() == Status.STATUS_MARKED_ROLLBACK;
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.runtime.transaction.SleeTransactionManager#mandateTransaction()
	 */
	public void mandateTransaction() throws TransactionRequiredLocalException {

		try {
			final Transaction tx = getTransaction();
			if (tx == null)
				throw new TransactionRequiredLocalException(
						"Transaction Mandatory");
			final int status = tx.getStatus();
			if (status != Status.STATUS_ACTIVE && status != Status.STATUS_MARKED_ROLLBACK) {
				throw new IllegalStateException(
						"There is no active tx, tx is in state: "
						+ status);
			}
		} catch (SystemException e) {
			throw new SLEEException(e.getMessage(),e);
		}
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.runtime.transaction.SleeTransactionManager#requireTransaction()
	 */
	public boolean requireTransaction() {

		try {
			final Transaction tx = getTransaction();
			if (tx == null) {
				begin();
				return true;
			}
			else {
				final int status = tx.getStatus();
				if (status != Status.STATUS_ACTIVE && status != Status.STATUS_MARKED_ROLLBACK) {
					begin();
					return true;
				}
			}
		} catch (NotSupportedException e) {
			logger.error("Exception creating transaction", e);
		} catch (SystemException e) {
			logger.error("Caught SystemException in checking transaction", e);
		}
		return false;
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.runtime.transaction.SleeTransactionManager#requireTransactionEnd(boolean, boolean)
	 */
	public void requireTransactionEnd(boolean terminateTx, boolean doRollback) throws IllegalStateException, SecurityException, SystemException, RollbackException, HeuristicMixedException, HeuristicRollbackException {
		if (terminateTx) {
			if (doRollback) {
				rollback();
			}
			else {
				commit();
			}
		}
		else {
			if (doRollback) {
				setRollbackOnly();
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * @see javax.slee.transaction.SleeTransactionManager#asyncCommit(javax.slee.transaction.CommitListener)
	 */
	public void asyncCommit(CommitListener commitListener) throws IllegalStateException,
			SecurityException {

		if (doTraceLogs) {
			logger.trace("asyncCommit( commitListener = "+commitListener+" )");
		}

		try {
			final SleeTransaction sleeTransaction = getSleeTransaction();
			if (sleeTransaction == null) {
				throw new IllegalStateException("no transaction");
			}
			else {
				sleeTransaction.asyncCommit(commitListener);
			}
		} catch (SystemException e) {
			if (commitListener != null) {
				commitListener.systemException(e);
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * @see javax.slee.transaction.SleeTransactionManager#asyncRollback(javax.slee.transaction.RollbackListener)
	 */
	public void asyncRollback(RollbackListener rollbackListener)
			throws IllegalStateException, SecurityException {

		if (doTraceLogs) {
			logger.trace("asyncRollback( rollbackListener = "+rollbackListener+" )");
		}

		try {
			final SleeTransaction sleeTransaction = getSleeTransaction();
			if (sleeTransaction == null) {
				throw new IllegalStateException("no transaction");
			}
			else {
				sleeTransaction.asyncRollback(rollbackListener);
			}
		} catch (SystemException e) {
			if (rollbackListener != null) {
				rollbackListener.systemException(e);
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * @see javax.transaction.TransactionManager#begin()
	 */
	public void begin() throws NotSupportedException, SystemException {
		// begin transaction
		transactionManager.begin();
		// get tx does the rest
		getAsSleeTransaction(transactionManager.getTransaction(),true);
	}

	/*
	 * (non-Javadoc)
	 * @see javax.slee.transaction.SleeTransactionManager#beginSleeTransaction()
	 */
	public SleeTransaction beginSleeTransaction() throws NotSupportedException,
			SystemException {
		// begin transaction
		transactionManager.begin();
		// get tx does the rest
		return getAsSleeTransaction(transactionManager.getTransaction(),true);
	}

	public SleeTransaction getTransaction() throws SystemException {
		return getAsSleeTransaction(transactionManager.getTransaction(),false);
	}

	/*
	 * (non-Javadoc)
	 * @see javax.slee.transaction.SleeTransactionManager#getSleeTransaction()
	 */
	public SleeTransaction getSleeTransaction() throws SystemException {
		return getAsSleeTransaction(transactionManager.getTransaction(),false);
	}

	private SleeTransaction getAsSleeTransaction(Transaction transaction, boolean transactionCreation) throws SystemException {
		if (transaction != null) {
			TransactionContext transactionContext = null;
			if (transactionCreation) {
				transactionContext = bindToTransaction(transaction);
				if (logger.isDebugEnabled()) {
					logger.debug("Started tx "+transaction);
				}
			}
			else {
				transactionContext = TransactionContextThreadLocal.getTransactionContext();
				if (transactionContext == null && transaction.getStatus() == Status.STATUS_ACTIVE) {
					// we need to bind to tx, this is edge case for a tx that was created directly in the underlying tx manager
					transactionContext = bindToTransaction(transaction);
				}
			}
			return new SleeTransactionImpl((TransactionImple)transaction,transactionContext,this);
		}
		else {
			return null;
		}
	}

	private TransactionContext bindToTransaction(Transaction tx) throws IllegalStateException, SystemException {
		final TransactionContextImpl txContext = new TransactionContextImpl();
		// register for call-backs
		try {
			tx.registerSynchronization(new SleeTransactionSynchronization(tx,txContext));
		} catch (RollbackException e) {
			throw new IllegalStateException("Unable to register listener for created transaction. Error: "+e.getMessage());
		}
		// store tx context in thread
		TransactionContextThreadLocal.setTransactionContext(txContext);
		return txContext;
	}

	/*
	 * (non-Javadoc)
	 * @see javax.slee.transaction.SleeTransactionManager#asSleeTransaction(javax.transaction.Transaction)
	 */
	public SleeTransaction asSleeTransaction(Transaction transaction)
			throws NullPointerException, IllegalArgumentException,
			SystemException {
		if (transaction == null) {
			throw new NullPointerException("null transaction");
		}
		if (transaction.getClass() == SleeTransactionImpl.class) {
			return (SleeTransaction) transaction;
		}
		if (transaction instanceof TransactionImple) {
			return new SleeTransactionImpl((TransactionImple) transaction,getTransactionContext(),this);
		}
		throw new IllegalArgumentException("unexpected transaction class type "+transaction.getClass());
	}

	/*
	 * (non-Javadoc)
	 * @see javax.transaction.TransactionManager#commit()
	 */
	public void commit() throws RollbackException, HeuristicMixedException,
			HeuristicRollbackException, SecurityException,
			IllegalStateException, SystemException {
		if (doTraceLogs) {
			logger.trace("Starting commit of tx "+transactionManager.getTransaction());
		}
		transactionManager.commit();
	}

	/*
	 * (non-Javadoc)
	 * @see javax.transaction.TransactionManager#getStatus()
	 */
	public int getStatus() throws SystemException {
		return transactionManager.getStatus();
	}

	/*
	 * (non-Javadoc)
	 * @see javax.transaction.TransactionManager#resume(javax.transaction.Transaction)
	 */
	public void resume(Transaction transaction) throws InvalidTransactionException,
			IllegalStateException, SystemException {
		if (transaction.getClass() == SleeTransactionImpl.class) {
			final SleeTransactionImpl sleeTransactionImpl = (SleeTransactionImpl) transaction;
			if (doTraceLogs) {
				logger.trace("Resuming tx "+sleeTransactionImpl.getWrappedTransaction());
			}
			// resume wrapped tx
			transactionManager.resume(sleeTransactionImpl.getWrappedTransaction());
			// store tx context in thread
			TransactionContextThreadLocal.setTransactionContext(sleeTransactionImpl.getTransactionContext());
		}
		else {
			throw new InvalidTransactionException();
		}
	}

	/*
	 * (non-Javadoc)
	 * @see javax.transaction.TransactionManager#rollback()
	 */
	public void rollback() throws IllegalStateException, SecurityException,
			SystemException {
		if (doTraceLogs) {
			logger.trace("Starting rollback of tx "+transactionManager.getTransaction());
		}
		transactionManager.rollback();
	}

	/*
	 * (non-Javadoc)
	 * @see javax.transaction.TransactionManager#setRollbackOnly()
	 */
	public void setRollbackOnly() throws IllegalStateException, SystemException {
		if (logger.isDebugEnabled()) {
			logger.debug("Marking tx "
					+ transactionManager.getTransaction()+" for rollback.");
		}
		transactionManager.setRollbackOnly();
	}

	/*
	 * (non-Javadoc)
	 * @see javax.transaction.TransactionManager#setTransactionTimeout(int)
	 */
	public void setTransactionTimeout(int seconds) throws SystemException {
		transactionManager.setTransactionTimeout(seconds);
	}

	/*
	 * (non-Javadoc)
	 * @see javax.transaction.TransactionManager#suspend()
	 */
	public Transaction suspend() throws SystemException {
		if (doTraceLogs) {
			logger.trace("Suspending tx "+transactionManager.getTransaction());
		}
		final Transaction tx = getAsSleeTransaction(transactionManager.suspend(),false);
		if (tx != null) {
			// remove tx context from thread
			TransactionContextThreadLocal.setTransactionContext(null);
			return tx;
		}
		else {
			return null;
		}
	}

	// --- TX CONTEXT AND ACTION METHODS

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.runtime.transaction.SleeTransactionManager#getTransactionContext()
	 */
	public TransactionContext getTransactionContext() {
		TransactionContext txContext = TransactionContextThreadLocal.getTransactionContext();
		if (txContext == null) {
			try {
				final Transaction tx = transactionManager.getTransaction();
				if (tx != null && tx.getStatus() == Status.STATUS_ACTIVE) {
					// a tx was started with the real tx manager, lets try to hook the sync handler and a new tx context
					txContext = bindToTransaction(tx);
				}
			}
			catch (Throwable e) {
				throw new SLEEException(e.getMessage(), e);
			}
		}
		return txContext;
	}

}


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

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import org.mobicents.slee.container.eventrouter.EventRoutingTransactionData;
import org.mobicents.slee.container.sbbentity.SbbEntityID;
import org.mobicents.slee.container.transaction.TransactionContext;
import org.mobicents.slee.container.transaction.TransactionalAction;

/**
 *
 * The local context of a transaction.
 *
 * Provides a {@link Map} to store data in the transaction.
 *
 * Provides various {@link List}s for {@link TransactionalAction}s to be added. Those lists can be:
 *
 *   + Before Commit Action, an action to execute before the transaction is committed
 *
 *   + After Commit Priority Action, an action to execute first after the transaction is committed
 *
 *   + After Commit Action, an action to execute after the transaction is committed and the priority actions execution
 *
 *   + After Rollback Action, an action to execute after the transaction rollbacks
 *
 * @author ?
 * @author martins
 *
 */
public class TransactionContextImpl implements TransactionContext {

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

	/**
	 * {@link TransactionalAction}s which should be executed first after transaction commit succeeds
	 */
	private List<TransactionalAction> afterCommitPriorityActions;

	/**
	 * {@link TransactionalAction}s which should be executed after transaction commit succeeds
	 */
	private List<TransactionalAction> afterCommitActions;

	/**
	 * {@link TransactionalAction}s which should be executed after transaction rollback
	 */
	private List<TransactionalAction> afterRollbackActions;

	/**
	 * {@link TransactionalAction}s which should be executed before transaction commits
	 */
	private List<TransactionalAction> beforeCommitActions;

	/**
	 * {@link TransactionalAction}s which should be executed before transaction commits at first
	 */
	private List<TransactionalAction> beforeCommitPriorityActions;

	/**
	 * transaction data
	 */
	@SuppressWarnings("rawtypes")
	private Map data;

	/**
	 * place holder for event routing data related with a tx
	 */
	private EventRoutingTransactionData eventRoutingTransactionData;

	/**
	 * indicates if the tx context should do traces or not
	 */
	private final static boolean trace = logger.isTraceEnabled();

	/**
	 * Retrieves the list of actions which should be executed after commit succeeds
	 * @return
	 */
	public List<TransactionalAction> getAfterCommitActions() {
		if (afterCommitActions == null) {
			afterCommitActions = new ArrayList<TransactionalAction>();
		}
		return afterCommitActions;
	}

	/**
	 * Retrieves the list of actions which should be executed first after commit succeeds
	 * @return
	 */
	public List<TransactionalAction> getAfterCommitPriorityActions() {
		if (afterCommitPriorityActions == null) {
			afterCommitPriorityActions = new ArrayList<TransactionalAction>();
		}
		return afterCommitPriorityActions;
	}

	/**
	 * Retrieves the list of actions which should be executed after rollback
	 * @return
	 */
	public List<TransactionalAction> getAfterRollbackActions() {
		if (afterRollbackActions == null) {
			afterRollbackActions = new ArrayList<TransactionalAction>();
		}
		return afterRollbackActions;
	}

	/**
	 * Retrieves the list of actions which should be executed before commit
	 * @return
	 */
	public List<TransactionalAction> getBeforeCommitActions() {
		if (beforeCommitActions == null) {
			beforeCommitActions = new ArrayList<TransactionalAction>();
		}
		return beforeCommitActions;
	}

	/**
	 * Retrieves the list of actions which should be executed before commit at first
	 * @return
	 */
	public List<TransactionalAction> getBeforeCommitPriorityActions() {
		if (beforeCommitPriorityActions == null) {
			beforeCommitPriorityActions = new ArrayList<TransactionalAction>();
		}
		return beforeCommitPriorityActions;
	}

	// ------- DATA MANAGEMENT

	@SuppressWarnings("rawtypes")
	public Map getData() {
		if (data == null) {
			data = new HashMap();
		}
		return data;
	}

	// ------- ACTIONS EXECUTION

	/**
	 * Executes actions scheduled after commit succeeds
	 */
	protected void executeAfterCommitActions() {
		if (afterCommitActions != null) {
			if (trace) {
				logger.trace("Executing after commit actions");
			}
			executeActions(afterCommitActions,trace);
			afterCommitActions = null;
		}
	}

	/**
	 * Executes actions scheduled to run first after commit succeeds
	 */
	protected void executeAfterCommitPriorityActions() {
		if (afterCommitPriorityActions != null) {
			if (trace) {
				logger.trace("Executing after commit priority actions");
			}
			executeActions(afterCommitPriorityActions,trace);
			afterCommitPriorityActions = null;
		}
	}

	/**
	 * Executes actions scheduled for after a rollback
	 */
	protected void executeAfterRollbackActions() {
		if (afterRollbackActions != null) {
			if (trace) {
				logger.trace("Executing rollback actions");
			}
			executeActions(afterRollbackActions,trace);
			afterRollbackActions = null;
		}
	}

	/**
	 * Executes actions scheduled for before commit
	 */
	protected void executeBeforeCommitActions() {
		if (beforeCommitActions != null) {
			if (trace) {
				logger.trace("Executing before commit actions");
			}
			executeActions(beforeCommitActions,trace);
			beforeCommitActions = null;
		}
	}

	/**
	 * Executes actions scheduled for before commit at first
	 */
	protected void executeBeforeCommitPriorityActions() {
		if (beforeCommitPriorityActions != null) {
			if (trace) {
				logger.trace("Executing before commit priority actions");
			}
			executeActions(beforeCommitPriorityActions,trace);
			beforeCommitPriorityActions = null;
		}
	}

	private void executeActions(List<TransactionalAction> actions,boolean trace) {
		for (TransactionalAction action : actions) {
			if (trace)
				logger.trace("Executing action:" + action);
			action.execute();
		}
	}

	/**
	 * Cleanups any state the entry has created.
	 */
	protected void cleanup() {
		data = null;
		eventRoutingTransactionData = null;
		invokedSbbEntities = null;
	}

	public EventRoutingTransactionData getEventRoutingTransactionData() {
		return eventRoutingTransactionData;
	}

	public void setEventRoutingTransactionData(EventRoutingTransactionData eventRoutingTransactionData) {
		this.eventRoutingTransactionData = eventRoutingTransactionData;
	}

	/**
	 * a linked list with the non reentrant sbb entities in the call tree, since the event was
	 * passed to the event handler method
	 */
	private Set<SbbEntityID> invokedSbbEntities = null;

	/**
	 * Retrieves a set with the non reentrant sbb entities in the call tree, since the
	 * event was passed to the event handler method
	 *
	 * @return
	 */
	public Set<SbbEntityID> getInvokedNonReentrantSbbEntities() {
		if (invokedSbbEntities == null) {
			invokedSbbEntities = new HashSet<SbbEntityID>();
		}
		return invokedSbbEntities;
	}

}


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

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.slee.InvalidArgumentException;
import javax.slee.facilities.TraceLevel;
import javax.slee.facilities.Tracer;
import javax.slee.management.NotificationSource;

import org.mobicents.slee.container.management.jmx.TraceMBeanImpl;

/**
 * This class holds tracers for sources. By default it create root tracer. It
 * implicitly creates ancestor tracers for requested name. It holds reference
 * TraceName->TracerImpl. It also associates parent to a child.

 * Start time:19:20:19 2009-03-09

 * Project: restcomm-jainslee-server-core

 *
 * @author  Bartosz Baranowski
 *
 */
public class TracerStorage {

	private final ConcurrentHashMap<String, TracerImpl> tracers = new ConcurrentHashMap<String, TracerImpl>();

	private final NotificationSourceWrapperImpl notificationSource;

	private final TraceMBeanImpl traceFacility;
	private TracerImpl rootTracer;

	public TracerStorage(NotificationSource notificationSource, TraceMBeanImpl traceFacility) {
		super();
		this.notificationSource = new NotificationSourceWrapperImpl(notificationSource);
		this.traceFacility = traceFacility;
		this.rootTracer = new TracerImpl("",null,this.notificationSource, this.traceFacility);
		tracers.put(rootTracer.getTracerName(), rootTracer);
	}

	public void syncTracersWithLog4J()  {
		for (TracerImpl tracer : tracers.values()) {
			tracer.syncLevelWithLog4j();
		}
	}

	public void setTracerLevel(TraceLevel lvl, String tracerName) throws InvalidArgumentException {
		// FIXME: JDOC of TraceMBean - description of class show example
		// that setTraceLevel creates tracer, we handle creation elswhere
		if (!isTracerDefined(tracerName)) {
			throw new InvalidArgumentException("No tracer definition with name: " + tracerName + ", for notification source: " + this.notificationSource + ". See section 13.3 of JSLEE 1.1 specs");
		}
		TracerImpl tracer = this.tracers.get(tracerName);
		if (tracer.getParentTracerName() == null) {
			throw new InvalidArgumentException("Can not set root tracer level for source: " + this.notificationSource + ". See section 13.3 of JSLEE 1.1 specs");
		}
		tracer.setTraceLevel(lvl);

	}

	public void unsetTracerLevel(String tracerName) throws InvalidArgumentException {
		if (!isTracerDefined(tracerName)) {
			throw new InvalidArgumentException("No tracer definition with name: " + tracerName + ", for notification source: " + this.notificationSource + ". See section 13.3 of JSLEE 1.1 specs");
		}
		TracerImpl tracer = this.tracers.get(tracerName);
		if (tracer.getParentTracerName() == null) {
			throw new InvalidArgumentException("Can not unset root tracer level for source: " + this.notificationSource + ". See section 13.3 of JSLEE 1.1 specs");
		}
		tracer.unsetTraceLevel();
	}

	public TraceLevel getTracerLevel(String tracerName) throws InvalidArgumentException {
		if (!isTracerDefined(tracerName)) {
			throw new InvalidArgumentException("No tracer definition with name: " + tracerName + ", for notification source: " + this.notificationSource + ". See section 13.3 of JSLEE 1.1 specs");
		}
		TracerImpl tracer = this.tracers.get(tracerName);

		return tracer.getTraceLevel();
	}

	/**
	 * This method raturns tracer names of tracers that have been requested
	 * directly from NotificationSource (like through SbbContext, RAContext,
	 * etc)
	 *
	 * @return
	 */
	public String[] getRequestedTracerNames() {
		Set<String> names = new HashSet<String>();
		for (TracerImpl t : this.tracers.values()) {
			if (t.isRequestedBySource())
				names.add(t.getTracerName());
		}
		if(names.isEmpty())
			return new String[0];
		return names.toArray(new String[names.size()]);
	}

	/**
	 * This method returns tracer names that have been defined explicitly via
	 * setTraceLevel from TraceMBean
	 *
	 * @return
	 */
	public String[] getDefinedTracerNames() {
		Set<String> names = new HashSet<String>();
		for (TracerImpl t : this.tracers.values()) {
			if (t.isExplicitlySetTracerLevel())
				names.add(t.getTracerName());
		}
		if(names.isEmpty())
			return new String[0];
		return names.toArray(new String[names.size()]);
	}

	/**
	 * This method can be called multiple times.
	 *
	 * @param tracerName
	 * @param requestedBySource
	 * @return
	 */
	public Tracer createTracer(String tracerName, boolean requestedBySource) {

		TracerImpl tparent = null;
		TracerImpl t = tracers.get(tracerName);
		if (t == null) {
			String[] split = tracerName.split("\\.");
			String currentName = "";
			for (String s : split) {
				if (tparent == null) {
					// first loop
					tparent = rootTracer;
					currentName = s;
				} else {
					currentName = currentName + "." + s;
				}
				t = tracers.get(currentName);
				if (t == null) {
					t = new TracerImpl(currentName, tparent, this.notificationSource, this.traceFacility);
					final TracerImpl u = tracers.putIfAbsent(t.getTracerName(), t);
					if (u != null) {
						t = u;
					}
				}
				tparent = t;
			}
		}

		if (requestedBySource)
			t.setRequestedBySource(requestedBySource);
		return t;
	}

	public boolean isTracerDefined(String tracerName) {
		return tracers.containsKey(tracerName);
	}
}


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

import java.util.Map;

import javax.slee.ActivityContextInterface;
import javax.slee.TransactionRequiredLocalException;
import javax.slee.facilities.FacilityException;
import javax.slee.facilities.NameAlreadyBoundException;
import javax.slee.facilities.NameNotBoundException;

import org.apache.log4j.Logger;
import org.mobicents.slee.container.AbstractSleeContainerModule;
import org.mobicents.slee.container.activity.ActivityContext;
import org.mobicents.slee.container.activity.ActivityContextHandle;
import org.mobicents.slee.container.facilities.ActivityContextNamingFacility;

/*
 * Ranga - Initial and refactored for Tx isolation.
 * Tim
 */

/**
 * Activity Context Naming facility implementation.
 *
 * @author M. Rangananthan.
 * @author Tim
 * @author martins
 *
 *
 */
public class ActivityContextNamingFacilityImpl extends AbstractSleeContainerModule implements
        ActivityContextNamingFacility {

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

    private ActivityContextNamingFacilityCacheData cacheData;

    @Override
    public void sleeInitialization() {
    }

    @Override
    public void sleeStarting() {
    	cacheData = new ActivityContextNamingFacilityCacheData(sleeContainer.getCluster());
    	cacheData.create();
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.slee.facilities.ActivityContextNamingFacility#bind(javax.slee.ActivityContextInterface,
     *      java.lang.String)
     */
    public void bind(ActivityContextInterface aci, String aciName)
            throws NullPointerException, IllegalArgumentException,
            TransactionRequiredLocalException, NameAlreadyBoundException,
            FacilityException {
        // Check if we are in the context of a transaction.

    	sleeContainer.getTransactionManager().mandateTransaction();

        if (aciName == null)
            throw new NullPointerException("null aci name");
        else if (aciName.equals(""))
            throw new IllegalArgumentException("empty name");
        else if (aci == null )
            throw new NullPointerException ("Null ACI! ");

        try {
        	org.mobicents.slee.container.activity.ActivityContextInterface sleeAci = (org.mobicents.slee.container.activity.ActivityContextInterface)aci;
        	ActivityContext ac = sleeAci.getActivityContext();
        	ActivityContextHandle ach = ac.getActivityContextHandle();
        	cacheData.bindName(ach,aciName);
	        ac.addNameBinding(aciName);
	        if (log.isDebugEnabled()) {
	        	log.debug("aci name "+aciName+" bound to "+ach+" . Tx is "+sleeContainer.getTransactionManager().getTransaction());
	        }
        } catch (NameAlreadyBoundException ex) {
            if (log.isDebugEnabled()) {
                log.debug("name already bound " + aciName);
            }
            throw ex;
        } catch (Exception e) {
        	throw new FacilityException("Failed to put ac name binding in cache", e);
        }

    }

    /*
     * (non-Javadoc)
     *
     * @see javax.slee.facilities.ActivityContextNamingFacility#unbind(java.lang.String)
     */
    public void unbind(String aciName) throws NullPointerException,
            TransactionRequiredLocalException, NameNotBoundException,
            FacilityException {
        //Check if we are in the context of a transaction.

    	sleeContainer.getTransactionManager().mandateTransaction();

        if (aciName == null)
            throw new NullPointerException("null activity context name!");

        try {

        	ActivityContextHandle ach = (ActivityContextHandle) cacheData.unbindName(aciName);
            ActivityContext ac = sleeContainer.
            	getActivityContextFactory().getActivityContext(ach);
            if ( ac != null )
                ac.removeNameBinding(aciName);
            if (log.isDebugEnabled()) {
	        	log.debug("aci name "+aciName+" unbound from "+ach+" . Tx is "+sleeContainer.getTransactionManager().getTransaction());
	        }
        } catch ( NameNotBoundException ex) {
            if (log.isDebugEnabled()) {
                log.debug("Name not bound " + aciName);
            }
            throw ex;
        } catch (Exception e) {
        	throw new FacilityException("Failed to remove ac name binding from cache", e);
        }

    }

    public void removeName(String aciName) throws NameNotBoundException {
    	if (log.isDebugEnabled()) {
    		log.debug("Removing name from facility: aci " + aciName);
    	}
    	cacheData.unbindName(aciName);
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.slee.facilities.ActivityContextNamingFacility#lookup(java.lang.String)
     */
    public ActivityContextInterface lookup(String acName)
            throws NullPointerException, TransactionRequiredLocalException,
            FacilityException {

    	sleeContainer.getTransactionManager().mandateTransaction();

        if (acName == null)
            throw new NullPointerException("null ac name");

        try {

	        ActivityContextHandle ach = (ActivityContextHandle) cacheData.lookupName(acName);

	        if (log.isDebugEnabled()) {
	        	log.debug("lookup of aci name "+acName+" result is "+ach+" . Tx is "+sleeContainer.getTransactionManager().getTransaction());
	        }

            if (ach == null) {
        		return null;
        	}
        	ActivityContext ac = sleeContainer.getActivityContextFactory().getActivityContext(ach);
        	if (ac == null) {
        		cacheData.unbindName(acName);
        		throw new FacilityException("name found but unable to retrieve activity context");
        	}

        	return ac.getActivityContextInterface();

        } catch (Exception e) {
        	throw new FacilityException("Failed to look-up ac name binding", e);
        }

    }

	@SuppressWarnings("rawtypes")
	public Map getBindings() {

    	try {
    		return cacheData.getNameBindings();
		} catch (Exception e) {
			log.error(e.getMessage(),e);
		}

		return null;
    }

    @Override
	public String toString() {
		return 	"Activity context Naming Facility: " +
				"\n+-- Names: " + getBindings().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.container.deployment.profile;

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

import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.NotFoundException;

import javax.slee.InvalidStateException;
import javax.slee.SLEEException;
import javax.slee.management.DeploymentException;
import javax.slee.management.ManagementException;
import javax.slee.profile.ProfileImplementationException;

import org.apache.log4j.Logger;
import org.mobicents.slee.container.component.ClassPool;
import org.mobicents.slee.container.component.profile.ProfileSpecificationComponent;
import org.mobicents.slee.container.component.profile.ProfileSpecificationDescriptor;
import org.mobicents.slee.container.profile.AbstractProfileMBean;
import org.mobicents.slee.container.profile.AbstractProfileMBeanImpl;

public class ConcreteProfileMBeanGenerator {

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

	private ProfileSpecificationComponent component = null;
	private String cmpProfileInterfaceName = null;

	private String profileManagementInterfaceName = null;
	private ClassPool pool = null;
	private CtClass cmpProfileInterface = null;
	private CtClass profileManagementInterface = null;
	private CtClass profileMBeanConcreteClass = null;
	private CtClass profileMBeanConcreteInterface = null;

	/**
	 * holds all cmp acessor methods to copy to mbean interface and implement in mbean impl
	 */
	private Set<CtMethod> mBeanCmpAcessorMethods = new HashSet<CtMethod>();
	/**
	 * holds all management methods to copy to mbean interface and implement in mbean impl
	 */
	private Set<CtMethod> mBeanManagementMethods = new HashSet<CtMethod>();

	public ConcreteProfileMBeanGenerator(ProfileSpecificationComponent component) {
		this.component = component;
		ProfileSpecificationDescriptor descriptor = component.getDescriptor();
		this.cmpProfileInterfaceName = descriptor.getProfileCMPInterface().getProfileCmpInterfaceName();
		this.profileManagementInterfaceName = descriptor.getProfileManagementInterface() == null ? null : descriptor.getProfileManagementInterface();
		this.pool = component.getClassPool();
	}

	/**
	 * Generates the Profile MBean interface
	 *
	 * @return the interface generated
	 */
	public void generateProfileMBeanInterface() throws Exception {

		if (SleeProfileClassCodeGenerator.checkCombination(component) == -1) {
			throw new DeploymentException("Profile Specification doesn't match any combination " + "from the JSLEE spec 1.0 section 10.5.2");
		}

		String profileMBeanConcreteInterfaceName = cmpProfileInterfaceName + "MBean";

		profileMBeanConcreteInterface = pool.makeInterface(profileMBeanConcreteInterfaceName);

		try {
			cmpProfileInterface = pool.get(cmpProfileInterfaceName);
			profileManagementInterface = profileManagementInterfaceName != null ? pool.get(profileManagementInterfaceName) : null;
		}
		catch (NotFoundException nfe) {
			throw new DeploymentException("Failed to locate CMP/Management Interface for " + component, nfe);
		}

		// set interface
		try {
			profileMBeanConcreteInterface.addInterface(pool.get(AbstractProfileMBean.class.getName()));
		}
		catch (Throwable e) {
			throw new SLEEException(e.getMessage(),e);
		}

		// gather exceptions that the mbean methods may throw
		CtClass[] managementMethodExceptions = new CtClass[3];
		try {
			managementMethodExceptions[0] = pool.get(ManagementException.class.getName());
			managementMethodExceptions[1] = pool.get(InvalidStateException.class.getName());
			managementMethodExceptions[2] = pool.get(ProfileImplementationException.class.getName());
		}
		catch (NotFoundException e) {
			throw new SLEEException(e.getMessage(),e);
		}
		CtClass[] cmpGetAcessorMethodExceptions = new CtClass[] {managementMethodExceptions[0]};
		CtClass[] cmpSetAcessorMethodExceptions = new CtClass[] {managementMethodExceptions[0],managementMethodExceptions[1]};

		// gather all Object class methods, we don't want those in the mbean
		Set<CtMethod> objectMethods = new HashSet<CtMethod>();
		try {
			CtClass objectClass = pool.get(Object.class.getName());
			for (CtMethod ctMethod : objectClass.getMethods()) {
				objectMethods.add(ctMethod);
			}
		}
		catch (NotFoundException e) {
			throw new SLEEException(e.getMessage(),e);
		}

		// gather methods to copy
		Set<CtMethod> cmpAcessorMethods = new HashSet<CtMethod>();
		Set<CtMethod> managementMethods = new HashSet<CtMethod>();
		if (profileManagementInterface != null) {
			// If the Profile Specification defines a Profile Management Interface, the profileMBean interface has the same methods
			// 1. gather all methods from management interface
			for (CtMethod ctMethod : profileManagementInterface.getMethods()) {
				if (!objectMethods.contains(ctMethod)) {
					managementMethods.add(ctMethod);
				}
			}
			// 2. gather all methods present also in cmp interface, removing those from the ones gather from management interface
			for (CtMethod ctMethod : cmpProfileInterface.getMethods()) {
				if (!objectMethods.contains(ctMethod)) {
					if (managementMethods.remove(ctMethod)) {
						cmpAcessorMethods.add(ctMethod);
					}
				}
			}
		}
		else {
			for (CtMethod ctMethod : cmpProfileInterface.getMethods()) {
				if (!objectMethods.contains(ctMethod)) {
					cmpAcessorMethods.add(ctMethod);
				}
			}
		}

		// copy cmp acessor & mngt methods
		for (CtMethod ctMethod : cmpAcessorMethods) {
			// copy method
			CtMethod methodCopy = new CtMethod(ctMethod, profileMBeanConcreteInterface, null);
			// set exceptions
			CtClass[] exceptions = null;
			if(ctMethod.getName().startsWith("set")) {
				exceptions = cmpSetAcessorMethodExceptions;
			}
			else if(ctMethod.getName().startsWith("get")) {
				exceptions = cmpGetAcessorMethodExceptions;
			}
			else {
				throw new DeploymentException("unexpected method in profile cmp interface "+ctMethod);
			}
			methodCopy.setExceptionTypes(exceptions);
			// add to class
			profileMBeanConcreteInterface.addMethod(methodCopy);
			// store in set to be used in mbean impl
			mBeanCmpAcessorMethods.add(methodCopy);
		}
		for (CtMethod ctMethod : managementMethods) {
			// copy method
			CtMethod methodCopy = new CtMethod(ctMethod, profileMBeanConcreteInterface, null);
			// set exceptions
			methodCopy.setExceptionTypes(managementMethodExceptions);
			// add to class
			profileMBeanConcreteInterface.addMethod(methodCopy);
			// store in set to be used in mbean impl
			mBeanManagementMethods.add(methodCopy);

		}

		// write class file
		try {
			profileMBeanConcreteInterface.writeFile(this.component.getDeploymentDir().getAbsolutePath());
		}
		catch (Throwable e) {
			throw new SLEEException(e.getMessage(), e);
		}
		finally {
			profileMBeanConcreteInterface.defrost();
		}

		// and load it to the component
		try {
			this.component.setProfileMBeanConcreteInterfaceClass(Thread.currentThread().getContextClassLoader().loadClass(profileMBeanConcreteInterfaceName));
		}
		catch (Throwable e) {
			throw new SLEEException(e.getMessage(), e);
		}
	}

	/**
	 * This method generates concrete class of MBean impl
	 */
	public void generateProfileMBean() throws Exception
	{
		if (SleeProfileClassCodeGenerator.checkCombination(component) == -1)
		{
			throw new DeploymentException("Profile Specification doesn't match any combination " + "from the JSLEE spec 1.0 section 10.5.2");
		}

		String profileMBeanConcreteClassName = profileMBeanConcreteInterface.getName() + "Impl";

		profileMBeanConcreteClass = pool.makeClass(profileMBeanConcreteClassName);

		// set interface & super class
		try {
			profileMBeanConcreteClass.setInterfaces(new CtClass[] {profileMBeanConcreteInterface});
			profileMBeanConcreteClass.setSuperclass(pool.get(AbstractProfileMBeanImpl.class.getName()));
		}
		catch (NotFoundException e) {
			throw new SLEEException(e.getMessage(),e);
		}

		// implement cmp acessor & management methods gather in the mbean interface building
		for (CtMethod method : mBeanCmpAcessorMethods) {

			// copy method & remove abstract modifier
			CtMethod newMethod = CtNewMethod.copy( method, profileMBeanConcreteClass, null );
			// generate body
			String body = null;
			if (method.getName().startsWith("set")) {
				body = 	"{ " +
						"	beforeSetCmpField();" +
						"	try { " +
						"		(("+component.getProfileCmpConcreteClass().getName()+")getProfileObject().getProfileConcrete())." + method.getName()+"($1);" +
						"	} finally {" +
						"		afterSetCmpField();" +
						"	}" +
						"}";
			}
			else {
				body = 	"{ " +
						"	boolean activatedTransaction = beforeGetCmpField();" +
						"	try { " +
						"		return ($r) (("+component.getProfileCmpConcreteClass().getName()+")getProfileObject().getProfileConcrete())." + method.getName()+"();" +
						"	} finally {" +
						"		afterGetCmpField(activatedTransaction);" +
						"	}" +
						"}";
			}
			if(logger.isTraceEnabled()) {
				logger.trace("Implemented profile mbean method named "+method.getName()+", with body:\n"+body);
			}
			newMethod.setBody(body);
			profileMBeanConcreteClass.addMethod(newMethod);
		}

		for (CtMethod method : mBeanManagementMethods) {

			// copy method & remove abstract modifier
			CtMethod newMethod = CtNewMethod.copy( method, profileMBeanConcreteClass, null );

			// generate body
			boolean voidReturnType = newMethod.getReturnType().equals(CtClass.voidType);

			String body = "{ boolean activatedTransaction = beforeManagementMethodInvocation(); try { ";
			if (!voidReturnType) {
				body += "return ($r) ";
			}
			body += "(("+component.getProfileCmpConcreteClass().getName()+")getProfileObject().getProfileConcrete())." + method.getName()+"($$); } catch(Throwable t) { throwableOnManagementMethodInvocation(t); } finally { afterManagementMethodInvocation(activatedTransaction); }";
			if (!voidReturnType) {
				body += "throw new "+SLEEException.class.getName()+"(\"bad code generated\");";
			}
			body += " }";

			if(logger.isTraceEnabled()) {
				logger.trace("Implemented profile mbean method named "+method.getName()+", with body:\n"+body);
			}
			newMethod.setBody(body);
			profileMBeanConcreteClass.addMethod(newMethod);
		}

		try {
			profileMBeanConcreteClass.writeFile(this.component.getDeploymentDir().getAbsolutePath());
		}
		catch (Throwable e) {
			throw new SLEEException(e.getMessage(),e);
		}
		finally {
			profileMBeanConcreteClass.defrost();
		}

		try {
			component.setProfileMBeanConcreteImplClass(Thread.currentThread().getContextClassLoader().loadClass(profileMBeanConcreteClassName));
		}
		catch (Throwable e) {
			throw new SLEEException(e.getMessage(),e);
		}
	}

}


/*
 * 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.mobicents.slee.container.SleeContainer;

import java.io.Serializable;

/**
 * Implementation of the fault tolerant ra context.
 *
 * @author martins
 *
 */
public class FaultTolerantResourceAdaptorContextImpl<K extends Serializable, V extends Serializable>
		implements FaultTolerantResourceAdaptorContext<K, V> {

	private static final String REPLICATED_DATA_WITH_FAILOVER_NAME = "ra-data-fo";
	private static final String REPLICATED_DATA_NAME = "ra-data";

	private ReplicatedDataWithFailoverImpl<K, V> replicatedDataWithFailover = null;
	private ReplicatedDataImpl<K, V> replicatedData = null;

	private final String raEntity;
	private final SleeContainer sleeContainer;
	private final FaultTolerantResourceAdaptor<K, V> ra;

	private FaultTolerantTimerImpl timer;

	/**
	 * @param raEntity
	 * @param sleeContainer
	 * @param ra
	 */
	public FaultTolerantResourceAdaptorContextImpl(String raEntity,
			SleeContainer sleeContainer, FaultTolerantResourceAdaptor<K, V> ra) {
		this.raEntity = raEntity;
		this.sleeContainer = sleeContainer;
		this.ra = ra;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptorContext
	 * #getReplicatedDataWithFailover(boolean)
	 */
	public ReplicatedDataWithFailover<K, V> getReplicatedDataWithFailover(
			boolean activateDataRemovedCallback) {
		if (replicatedDataWithFailover == null) {
			replicatedDataWithFailover = new ReplicatedDataWithFailoverImpl<K, V>(
					REPLICATED_DATA_WITH_FAILOVER_NAME, raEntity,
					sleeContainer.getCluster(), ra, activateDataRemovedCallback);
		}
		return replicatedDataWithFailover;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptorContext
	 * #getReplicateData(boolean)
	 */
	public ReplicatedData<K, V> getReplicateData(
			boolean activateDataRemovedCallback) {
		if (replicatedData == null) {
			replicatedData = new ReplicatedDataImpl<K, V>(REPLICATED_DATA_NAME,
					raEntity, sleeContainer.getCluster(), ra,
					activateDataRemovedCallback);
		}
		return replicatedData;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptorContext
	 * #isLocal()
	 */
	public boolean isLocal() {
		return sleeContainer.getCluster().getMobicentsCache().isLocalMode();
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptorContext
	 * #isHeadMember()
	 */
	public boolean isHeadMember() {
		return sleeContainer.getCluster().isHeadMember();
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptorContext
	 * #isSingleMember()
	 */
	public boolean isSingleMember() {
		return sleeContainer.getCluster().isSingleMember();
	}

	private static final Address[] EMPTY_ADDRESS_ARRAY = {};

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptorContext
	 * #getMembers()
	 */
	public MemberAddress[] getMembers() {
		final Address[] addresses = sleeContainer.getCluster()
				.getClusterMembers().toArray(EMPTY_ADDRESS_ARRAY);
		final MemberAddressImpl[] members = new MemberAddressImpl[addresses.length];
		for (int i = 0; i < members.length; i++) {
			members[i] = new MemberAddressImpl(addresses[i]);
		}
		return members;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptorContext
	 * #getLocalAddress()
	 */
	public MemberAddress getLocalAddress() {
		Address localAddress = sleeContainer.getCluster().getLocalAddress();
		return localAddress != null ? new MemberAddressImpl(localAddress)
				: null;
	}

	/**
	 * Removes all replicated data
	 */
	public void removeReplicateData() {
		if (replicatedDataWithFailover != null) {
			replicatedDataWithFailover.remove();
			replicatedDataWithFailover = null;
		}
		if (replicatedData != null) {
			replicatedData.remove();
			replicatedData = null;
		}
	}

	@Override
	public FaultTolerantTimer getFaultTolerantTimer() {
		if (timer == null) {
			timer = new FaultTolerantTimerImpl(sleeContainer, raEntity);
		}
		return timer;
	}

	public void shutdown() {
		if (timer != null) {
			timer.shutdown();
		}
	}
}


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

import java.beans.PropertyEditorManager;

import javax.slee.Address;
import javax.slee.ComponentID;
import javax.slee.EventTypeID;
import javax.slee.SbbID;
import javax.slee.ServiceID;
import javax.slee.facilities.Level;
import javax.slee.facilities.TraceLevel;
import javax.slee.management.DeployableUnitID;
import javax.slee.management.LibraryID;
import javax.slee.management.NotificationSource;
import javax.slee.management.ResourceAdaptorEntityState;
import javax.slee.management.ServiceState;
import javax.slee.profile.ProfileSpecificationID;
import javax.slee.resource.ConfigProperties;
import javax.slee.resource.ResourceAdaptorID;
import javax.slee.resource.ResourceAdaptorTypeID;

/**
 * Handles registration of jmx property editors.
 *
 * @author martins
 *
 */
@SuppressWarnings("deprecation")
public class SleePropertyEditorRegistrator {

	/**
	 * Register the property editors for jboss jmx console, so non string SLEE api types can be used in specs mbeans methods as args
	 */
	public void register() {

		PropertyEditorManager.registerEditor(ComponentID.class,
				ComponentIDPropertyEditor.class);
		PropertyEditorManager.registerEditor(EventTypeID.class,
				ComponentIDPropertyEditor.class);
		PropertyEditorManager.registerEditor(LibraryID.class,
				ComponentIDPropertyEditor.class);
		PropertyEditorManager.registerEditor(ProfileSpecificationID.class,
				ComponentIDPropertyEditor.class);
		PropertyEditorManager.registerEditor(ResourceAdaptorID.class,
				ComponentIDPropertyEditor.class);
		PropertyEditorManager.registerEditor(ResourceAdaptorTypeID.class,
				ComponentIDPropertyEditor.class);
		PropertyEditorManager.registerEditor(SbbID.class,
				ComponentIDPropertyEditor.class);
		PropertyEditorManager.registerEditor(ServiceID.class,
				ComponentIDPropertyEditor.class);

		PropertyEditorManager.registerEditor(ComponentID[].class,
				ComponentIDArrayPropertyEditor.class);
		PropertyEditorManager.registerEditor(EventTypeID[].class,
				ComponentIDArrayPropertyEditor.class);
		PropertyEditorManager.registerEditor(LibraryID[].class,
				ComponentIDArrayPropertyEditor.class);
		PropertyEditorManager.registerEditor(ProfileSpecificationID[].class,
				ComponentIDArrayPropertyEditor.class);
		PropertyEditorManager.registerEditor(ResourceAdaptorID[].class,
				ComponentIDArrayPropertyEditor.class);
		PropertyEditorManager.registerEditor(ResourceAdaptorTypeID[].class,
				ComponentIDArrayPropertyEditor.class);
		PropertyEditorManager.registerEditor(SbbID[].class,
				ComponentIDArrayPropertyEditor.class);
		PropertyEditorManager.registerEditor(ServiceID[].class,
				ComponentIDArrayPropertyEditor.class);

		PropertyEditorManager.registerEditor(DeployableUnitID.class,
				DeployableUnitIDPropertyEditor.class);

		PropertyEditorManager.registerEditor(Level.class,
				LevelPropertyEditor.class);
		PropertyEditorManager.registerEditor(TraceLevel.class,
				TraceLevelPropertyEditor.class);

		PropertyEditorManager.registerEditor(ConfigProperties.class,
				ConfigPropertiesPropertyEditor.class);

		PropertyEditorManager.registerEditor(NotificationSource.class,
				NotificationSourcePropertyEditor.class);

		PropertyEditorManager.registerEditor(Object.class,
				ObjectPropertyEditor.class);

		PropertyEditorManager.registerEditor(ServiceState.class,
				ServiceStatePropertyEditor.class);
		PropertyEditorManager.registerEditor(ResourceAdaptorEntityState.class,
				ResourceAdaptorEntityStatePropertyEditor.class);
		PropertyEditorManager.registerEditor(Address.class,
				AddressPropertyEditor.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.container.deployment;

import javax.slee.management.DeploymentException;

import org.apache.log4j.Logger;
import org.mobicents.slee.container.component.ClassPool;
import org.mobicents.slee.container.component.SleeComponentWithUsageParametersInterface;

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

	private static final Logger LOGGER = Logger.getLogger(SleeComponentWithUsageParametersClassCodeGenerator.class);

	/**
	 * Generates classes for a slee component, which defines usage parameters
	 * @param component
	 * @throws DeploymentException
	 */
	public void process(SleeComponentWithUsageParametersInterface component) throws DeploymentException {

		ClassPool classPool = component.getClassPool();
		String deploymentDir = component.getDeploymentDir().getAbsolutePath();
		Class<?> usageParametersInterface = component
				.getUsageParametersInterface();
		if (usageParametersInterface != null) {
			try {
				// generate the concrete usage param set class
				component
						.setUsageParametersConcreteClass(new ConcreteUsageParameterClassGenerator(
								usageParametersInterface.getName(),
								deploymentDir, classPool)
								.generateConcreteUsageParameterClass());
				if (LOGGER.isDebugEnabled()) {
					LOGGER.debug("Generated usage parameter impl class for "+component);
		        }
				// generate the mbeans
				new ConcreteUsageParameterMBeanGenerator(component)
						.generateConcreteUsageParameterMBean();

				if (LOGGER.isDebugEnabled()) {
					LOGGER.debug("Generated usage mbean (interface and impl) for "+component);
		        }

			} catch (DeploymentException ex) {
				throw ex;
			} catch (Exception ex) {
				throw new DeploymentException(
						"Failed to generate "+component+" usage parameter class", ex);
			}
		}

	}
}


package javax.slee;

import java.io.Serializable;

/**
 * The ComponentID class is the common base class for all component
 * identifiers.  All deployable components installed in the SLEE have some
 * component identity, specified as a derivitive class of ComponentID.
 */
public abstract class ComponentID implements Comparable, Serializable, Cloneable {
    /**
     * Create a new component identifier.
     * @param name the name of the component.
     * @param vendor the vendor of the component.
     * @param version the version of the component.
     * @throws NullPointerException if any argument is null.
     */
    protected ComponentID(String name, String vendor, String version) {
        if (name == null) throw new NullPointerException("name is null");
        if (vendor == null) throw new NullPointerException("vendor is null");
        if (version == null) throw new NullPointerException("version is null");
        this.name = name;
        this.vendor = vendor;
        this.version = version;

        String className = getClassName();
        componentType = className.substring(className.lastIndexOf('.') + 1);

        hash = className.hashCode() ^
            rotateLeft(name.hashCode(), 3) ^
            rotateLeft(vendor.hashCode(), 12) ^
            rotateLeft(version.hashCode(), 21);
    }

    /**
     * Get the name of the component.
     * @return the name of the component.
     */
    public final String getName() { return name; }

    /**
     * Get the vendor of the component.
     * @return the vendor of the component.
     */
    public final String getVendor() { return vendor; }

    /**
     * Get the version of the component.
     * @return the version of the component.
     */
    public final String getVersion() { return version; }

    /**
     * Compare this component identifier for equality with another object.
     * @param obj the object to compare this with.
     * @return true if obj is a component identifier
     *        of the same class as this, and has the same name, vendor, and
     *        version as this, false otherwise.
     * @see Object#equals(Object)
     */
    public final boolean equals(Object obj) {
        return (obj == this) || (obj instanceof ComponentID && compareTo(obj) == 0);
    }

    /**
     * Get a hash code value for this component identifier.
     * @return a hash code value for this identifier.
     * @see Object#hashCode()
     */
    public final int hashCode() {
        return hash;
    }

    /**
     * Get a string representation for this component identifier.
     * @return a string representation for this component identifier.
     * @see Object#toString()
     */
    public final String toString() {
        StringBuffer buf = new StringBuffer();
        buf.append(componentType).
            append("[name=").append(name).
            append(",vendor=").append(vendor).
            append(",version=").append(version).
            append(']');
        return buf.toString();
    }

    /**
     * Compare this component identifier 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.
     *

     * Component ordering is determined by comparing the component identifier
     * attributes in the following order:
     *

     *
component type (nb. any subclass of ComponentID may
     *       be safely compared without causing a ClassCastException)
     *
component name
     *
component vendor
     *
component version
     *

     * @param obj the object to compare this with.
     * @return a negative integer, zero, or a positive integer if this component
     *        identifier is considered less than, equal to, or greater than the
     *        specified object.
     * @see Comparable#compareTo(Object)
     */
    public abstract int compareTo(Object obj);

    // protected

    /**
     * Compare this component identifier with the specified component identifier
     * 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.
     *

     * Component ordering is determined by comparing the component identifier
     * attributes in the following order:
     *

     *
component type (nb. any subclass of ComponentID may
     *       be safely compared without causing a ClassCastException)
     *
component name
     *
component vendor
     *
component version
     *

     * @param thisClassName the class name of this component identifier.
     * @param that the component identifier to compare this with.
     * @return a negative integer, zero, or a positive integer if this component
     *        identifier is considered less than, equal to, or greater than the
     *        specified object.
     * @see Comparable#compareTo(Object)
     */
    protected final int compareTo(String thisClassName, ComponentID that) {
        int typeComparison = thisClassName.compareTo(that.getClassName());
        if (typeComparison != 0) return typeComparison;

        int nameComparison = this.name.compareTo(that.name);
        if (nameComparison != 0) return nameComparison;

        int vendorComparison = this.vendor.compareTo(that.vendor);
        if (vendorComparison != 0) return vendorComparison;

        return this.version.compareTo(that.version);
    }

    /**
     * Get the class name of this component identifier.  More efficient than
     * getClass().getName().
     * @return the class name of this component identifier.
     */
    protected abstract String getClassName();

    // private

    private int rotateLeft(int value, int bits) {
        long l = value & 0x00000000ffffffffL;
        l <<= bits;
        return (int)l | (int)(l >> 32);
    }

    private final String name;
    private final String vendor;
    private final String version;
    private final String componentType;
    private final int hash;
}


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

import java.util.concurrent.ConcurrentHashMap;

import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.slee.SbbID;
import javax.slee.ServiceID;

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.component.sbb.SbbComponent;
import org.mobicents.slee.container.transaction.SleeTransactionManager;
import org.mobicents.slee.container.transaction.TransactionalAction;

/**
 *
 * Manages sbb object pools in the SLEE container.
 *
 * @author martins
 *
 */
public class SbbObjectPoolManagementImpl implements SbbObjectPoolManagementImplMBean {

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

	private final ConcurrentHashMap<ObjectPoolMapKey, SbbObjectPoolImpl> pools;
	private final SleeContainer sleeContainer;

	private GenericObjectPool.Config config;

	public SbbObjectPoolManagementImpl(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 = 1;
		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<ObjectPoolMapKey, SbbObjectPoolImpl>();
	}

	/**
	 * 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 sbb and service.
	 * @param serviceID
	 * @param sbbID
	 * @return
	 */
	public SbbObjectPoolImpl getObjectPool(ServiceID serviceID, SbbID sbbID) {
		return pools.get(new ObjectPoolMapKey(serviceID,sbbID));
	}

	/**
	 * Creates an object pool for the specified service and sbb. If a
	 * transaction manager is used then, and if the tx rollbacks, the pool will
	 * be removed.
	 *
	 * @param
	 * @param sleeTransactionManager
	 */
	public void createObjectPool(final ServiceID serviceID, final SbbComponent sbbComponent,
			final SleeTransactionManager sleeTransactionManager) {

		if (logger.isTraceEnabled()) {
            logger.trace("Creating Pool for  " + serviceID +" and "+ sbbComponent);
		}

		createObjectPool(serviceID,sbbComponent);

		if (sleeTransactionManager != null && sleeTransactionManager.getTransactionContext() != 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 " + serviceID +" and "+ sbbComponent);
					}
					try {
						removeObjectPool(serviceID,sbbComponent.getSbbID());
					} catch (Throwable e) {
						logger.error("Failed to remove " + serviceID +" and "+ sbbComponent + " object pool", e);
					}
				}
			};
			sleeTransactionManager.getTransactionContext().getAfterRollbackActions().add(action);
		}
	}

	/**
	 *
	 * @param serviceID
	 * @param sbbID
	 */
	private void createObjectPool(final ServiceID serviceID, final SbbComponent sbbComponent) {
		// create the pool for the given SbbID
		GenericObjectPoolFactory poolFactory = new GenericObjectPoolFactory(
				new SbbObjectPoolFactory(serviceID,sbbComponent), config);
		final ObjectPool objectPool = poolFactory.createPool();
		final SbbObjectPoolImpl oldObjectPool = pools.put(new ObjectPoolMapKey(serviceID,sbbComponent.getSbbID()),
				new SbbObjectPoolImpl(sbbComponent,serviceID,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 " + serviceID + "and " + sbbComponent);
				}
			}
		}
		if (logger.isDebugEnabled()) {
			logger.debug("Created Pool for " + serviceID + "and " + sbbComponent);
		}
	}

	/**
	 * Removes the object pool for the sbb with the specified component and the specified service. If a
	 * transaction manager is used then, and if the tx rollbacks, the pool will
	 * be restored.
	 *
	 * @param sbbDescriptor
	 * @param sleeTransactionManager
	 * @throws Exception
	 */
	public void removeObjectPool(final ServiceID serviceID, final SbbComponent sbbComponent,
			final SleeTransactionManager sleeTransactionManager) {

		if (logger.isTraceEnabled()) {
            logger.trace("Removing Pool for " + serviceID + "and " + sbbComponent);
		}

		removeObjectPool(serviceID,sbbComponent.getSbbID());

		if (sleeTransactionManager != null) {
			// restore object pool if tx rollbacks
			TransactionalAction action = new TransactionalAction() {
				public void execute() {
					if (logger.isDebugEnabled()) {
						logger
								.debug("Due to tx rollback, restoring pool for " + serviceID + "and " + sbbComponent);
					}
					createObjectPool(serviceID,sbbComponent);
				}
			};
			sleeTransactionManager.getTransactionContext().getAfterRollbackActions().add(action);
		}
	}

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

	// ---- 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 (ObjectPoolMapKey key : pools.keySet()) {
			final SbbComponent sbbComponent = sleeContainer.getComponentRepository().getComponentByID(key.sbbID);
			createObjectPool(key.serviceID,sbbComponent);
		}
	}

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

	private static class ObjectPoolMapKey {

		private final ServiceID serviceID;
		private final SbbID sbbID;

		public ObjectPoolMapKey(ServiceID serviceID, SbbID sbbID) {
			this.serviceID = serviceID;
			this.sbbID = sbbID;
		}

		@Override
		public int hashCode() {
			return serviceID.hashCode()*31+sbbID.hashCode();
		}

		@Override
		public boolean equals(Object obj) {
			if (obj != null && obj.getClass() == this.getClass()) {
				ObjectPoolMapKey other = (ObjectPoolMapKey) obj;
				return this.serviceID.equals(other.serviceID) && this.sbbID.equals(other.sbbID);
			}
			else {
				return false;
			}
		}

		@Override
		public String toString() {
			return serviceID.toString() + " & "+sbbID.toString();
		}
	}
}


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

/*
 * ServiceActivityContextInterfaceFactoryImpl.java
 *
 * Created on Oct 5, 2004
 *
 * Created by: M. Ranganathan
 *
 * The Open SLEE project
 *
 * A SLEE for the people!
 *
 * The source code contained in this file is in in the public domain.
 * It can be used in any project or product without prior permission,
 * license or royalty payments. There is  NO WARRANTY OF ANY KIND,
 * EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION,
 * THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
 * AND DATA ACCURACY.  We do not warrant or make any representations
 * regarding the use of the software or the  results thereof, including
 * but not limited to the correctness, accuracy, reliability or
 * usefulness of the software.
 */

package org.mobicents.slee.container.service;

import javax.slee.ActivityContextInterface;
import javax.slee.FactoryException;
import javax.slee.TransactionRequiredLocalException;
import javax.slee.UnrecognizedActivityException;
import javax.slee.serviceactivity.ServiceActivity;
import javax.slee.serviceactivity.ServiceActivityContextInterfaceFactory;

import org.mobicents.slee.container.SleeContainer;
import org.mobicents.slee.container.activity.ActivityContext;
import org.mobicents.slee.container.activity.ActivityContextHandle;

/**
 * Service Activity Context Factory Implementation.
 *
 * @author Eduardo Martins
 *
 */
public class ServiceActivityContextInterfaceFactoryImpl implements
		ServiceActivityContextInterfaceFactory {

	public static String JNDI_NAME = "activitycontextinterfacefactory";

	private final SleeContainer sleeContainer;

	/**
	 * @param acFactory
	 */
	public ServiceActivityContextInterfaceFactoryImpl(
			SleeContainer sleeContainer) {
		this.sleeContainer = sleeContainer;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see javax.slee.serviceactivity.ServiceActivityContextInterfaceFactory#getActivityContextInterface(javax.slee.serviceactivity.ServiceActivity)
	 */
	public ActivityContextInterface getActivityContextInterface(
			ServiceActivity serviceActivityImpl) throws NullPointerException,
			TransactionRequiredLocalException, UnrecognizedActivityException,
			FactoryException {

		ActivityContextHandle ach = new ServiceActivityContextHandle(new ServiceActivityHandleImpl(((ServiceActivityImpl) serviceActivityImpl).getServiceID()));
		ActivityContext ac = sleeContainer.getActivityContextFactory().getActivityContext(ach);
		if (ac == null) {
			throw new UnrecognizedActivityException(serviceActivityImpl);
		}
		return ac.getActivityContextInterface();

	}

}


/*
 * 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 javax.slee.resource.ActivityHandle;
import javax.slee.resource.UnrecognizedActivityHandleException;

import org.mobicents.slee.container.SleeContainer;
import org.mobicents.slee.container.transaction.SleeTransaction;

/**
 *
 * @author martins
 *
 */
public class SleeEndpointEndActivityNotTransactedExecutor extends
		SleeEndpointOperationNotTransactedExecutor {

	/**
	 *
	 * @param sleeContainer
	 * @param sleeEndpoint
	 */
	public SleeEndpointEndActivityNotTransactedExecutor(
			SleeContainer sleeContainer, SleeEndpointImpl sleeEndpoint) {
		super(sleeContainer, sleeEndpoint);
	}

	/**
	 * Executes a non transacted End Activity operation.
	 *
	 * @param handle
	 * @throws UnrecognizedActivityHandleException
	 */
	void execute(final ActivityHandle handle)
			throws UnrecognizedActivityHandleException {

		final SleeTransaction tx = super.suspendTransaction();
		try {
			sleeEndpoint._endActivity(handle,tx);
		} finally {
			if (tx != null) {
				super.resumeTransaction(tx);
			}
		}
	}
}