/*
 * 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.concurrent.atomic.AtomicBoolean;

import javax.slee.transaction.CommitListener;
import javax.slee.transaction.RollbackListener;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.RollbackException;
import javax.transaction.Status;
import javax.transaction.Synchronization;
import javax.transaction.SystemException;
import javax.transaction.xa.XAResource;

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

import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple;

/**
 * Implementation of the {@link SleeTransaction}.
 * @author martins
 *
 */
public class SleeTransactionImpl implements SleeTransaction {

	/**
	 * the wrapped JBossTS transaction
	 */
	private final TransactionImple transaction;

	/**
	 * caching the wrapped transaction id
	 */
	private final String transactionId;

	/**
	 * the transaction manager
	 */
	private final SleeTransactionManagerImpl transactionManager;

	/**
	 * the tx context, stored here too to support suspend/resume op
	 */
	private final TransactionContext txContext;

	/**
	 * controls thread access safety
	 */
	private AtomicBoolean asyncOperationInitiated = new AtomicBoolean(false);

	/**
	 *
	 * @param transaction
	 * @param txContext
	 * @param transactionManager
	 */
	public SleeTransactionImpl(TransactionImple transaction,
			TransactionContext txContext, SleeTransactionManagerImpl transactionManager) {
		this.transaction = transaction;
		this.transactionId = transaction.get_uid().toString();
		this.txContext = txContext;
		this.transactionManager = transactionManager;
	}

	/**
	 * Retrieves the tx context.
	 * @return
	 */
	public TransactionContext getTransactionContext() {
		return txContext;
	}

	/**
	 * Retrieves the real jta transaction
	 * @return
	 */
	TransactionImple getWrappedTransaction() {
		return transaction;
	}

	/**
	 * Some operations require that the transaction be suspended
	 * @throws SystemException
	 */
	private void suspendIfAssoaciatedWithThread() throws SystemException {
		// if there is a tx associated with this thread and it is this one
		// then suspend it to dissociate the thread (dumb feature?!?! of jboss ts)
		final SleeTransaction currentThreadTransaction = transactionManager
				.getSleeTransaction();
		if (currentThreadTransaction != null
				&& currentThreadTransaction.equals(this)) {
			// lets use the real tx manager directly, to avoid any other procedures
			transactionManager.getRealTransactionManager().suspend();
		}
	}

	/**
	 * Verifies if the wrapped transaction is active and if dissociates it from
	 * the thread if needed
	 *
	 * @throws IllegalStateException
	 * @throws SecurityException
	 */
	private void beforeAsyncOperation() throws IllegalStateException,
			SecurityException {
		try {
			int status = transaction.getStatus();
			if (asyncOperationInitiated.getAndSet(true) || (status != Status.STATUS_ACTIVE
					&& status != Status.STATUS_MARKED_ROLLBACK)) {
				throw new IllegalStateException(
						"There is no active tx, tx is in state: " + status);
			}
			suspendIfAssoaciatedWithThread();
		} catch (SystemException e) {
			throw new IllegalStateException(e);
		}
	}

	/*
	 * (non-Javadoc)
	 * @see javax.slee.transaction.SleeTransaction#asyncCommit(javax.slee.transaction.CommitListener)
	 */
	public void asyncCommit(CommitListener commitListener)
			throws IllegalStateException, SecurityException {
		beforeAsyncOperation();
		transactionManager.getExecutorService().submit(new AsyncTransactionCommitRunnable(
				commitListener, transaction));
	}

	/*
	 * (non-Javadoc)
	 * @see javax.slee.transaction.SleeTransaction#asyncRollback(javax.slee.transaction.RollbackListener)
	 */
	public void asyncRollback(RollbackListener rollbackListener)
			throws IllegalStateException, SecurityException {
		beforeAsyncOperation();
		transactionManager.getExecutorService().submit(new AsyncTransactionRollbackRunnable(
				rollbackListener, transaction));
	}

	/*
	 * (non-Javadoc)
	 * @see javax.slee.transaction.SleeTransaction#delistResource(javax.transaction.xa.XAResource, int)
	 */
	public boolean delistResource(XAResource arg0, int arg1)
			throws IllegalStateException, SystemException {
		return transaction.delistResource(arg0, arg1);
	}

	/*
	 * (non-Javadoc)
	 * @see javax.slee.transaction.SleeTransaction#enlistResource(javax.transaction.xa.XAResource)
	 */
	public boolean enlistResource(XAResource arg0)
			throws IllegalStateException, RollbackException {
		try {
			return transaction.enlistResource(arg0);
		} catch (SystemException e) {
			// this should be a bug in slee 1.1 api, the exceptions thrown
			// should match jta transaction interface
			throw new RuntimeException(e);
		}
	}

	/*
	 * (non-Javadoc)
	 * @see javax.transaction.Transaction#commit()
	 */
	public void commit() throws RollbackException, HeuristicMixedException,
			HeuristicRollbackException, SecurityException,
			IllegalStateException, SystemException {
		if (asyncOperationInitiated.get()) {
			throw new IllegalStateException();
		}
		try {
			transaction.commit();
		}
		finally {
			suspendIfAssoaciatedWithThread();
		}
	}

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

	/*
	 * (non-Javadoc)
	 * @see javax.transaction.Transaction#registerSynchronization(javax.transaction.Synchronization)
	 */
	public void registerSynchronization(Synchronization sync)
			throws RollbackException, IllegalStateException, SystemException {
		transaction.registerSynchronization(sync);
	}

	/*
	 * (non-Javadoc)
	 * @see javax.transaction.Transaction#rollback()
	 */
	public void rollback() throws IllegalStateException, SystemException {
		if (asyncOperationInitiated.get()) {
			throw new IllegalStateException();
		}
		try {
			transaction.rollback();
		}
		finally {
			suspendIfAssoaciatedWithThread();
		}
	}

	/*
	 * (non-Javadoc)
	 * @see javax.transaction.Transaction#setRollbackOnly()
	 */
	public void setRollbackOnly() throws IllegalStateException, SystemException {
		transaction.setRollbackOnly();
	}

	@Override
	public String toString() {
		return transactionId;
	}

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

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

}


package javax.slee.management;

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

/**
 * This class defines an enumerated type that encapsulates the state of a Resource Adaptor Entity.
 *

 * 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.)
 * @since SLEE 1.1
 */
public final class ResourceAdaptorEntityState implements Serializable {
    /**
     * An integer representation of the {@link #INACTIVE} state.
     */
    public static final int ENTITY_INACTIVE = 0;

    /**
     * An integer representation of the {@link #ACTIVE} state.
     */
    public static final int ENTITY_ACTIVE = 1;

    /**
     * An integer representation of the {@link #STOPPING} state.
     */
    public static final int ENTITY_STOPPING = 2;

    /**
     * A string representation of the {@link #INACTIVE} state.
     */
    public static final String INACTIVE_STRING = "Inactive";

    /**
     * A string representation of the {@link #ACTIVE} state.
     */
    public static final String ACTIVE_STRING = "Active";

    /**
     * A string representation of the {@link #STOPPING} state.
     */
    public static final String STOPPING_STRING = "Stopping";

    /**
     * The INACTIVE state indicates that the resource adaptor entity has been successfully
     * created and configured.  All required files and parameters have been set up, so that
     * the resource adaptor entity may be connected to the underlying resource, but it is
     * not currently producing events.
     */
    public static final ResourceAdaptorEntityState INACTIVE = new ResourceAdaptorEntityState(ENTITY_INACTIVE);

    /**
     * The ACTIVE state indicates that the resource adaptor entity has been activated and
     * it is able to deliver events from the underlying resource to the SLEE.
     */
    public static final ResourceAdaptorEntityState ACTIVE = new ResourceAdaptorEntityState(ENTITY_ACTIVE);

    /**
     * The STOPPING state indicates that an active resource adaptor entity has been
     * deactivated but some activities created by the resource adaptor entity still exist.
     * Once all activities have completed, the resource adaptor entity state spontaneously
     * returns to the INACTIVE state.
     */
    public static final ResourceAdaptorEntityState STOPPING = new ResourceAdaptorEntityState(ENTITY_STOPPING);

    /**
     * Get a ResourceAdaptorEntityState object from an integer value.
     * @param state the state as an integer.
     * @return a ResourceAdaptorEntityState object corresponding to state.
     * @throws IllegalArgumentException if state is not a valid resource
     *        adaptor entity state value.
     */
    public static ResourceAdaptorEntityState fromInt(int state) throws IllegalArgumentException {
        switch (state) {
            case ENTITY_INACTIVE: return INACTIVE;
            case ENTITY_ACTIVE: return ACTIVE;
            case ENTITY_STOPPING: return STOPPING;
            default: throw new IllegalArgumentException("Invalid state: " + state);
        }
    }

    /**
     * Get a ResourceAdaptorEntityState object from a string value.
     * @param state the state as a string, for example as returned by the {@link #toString()}
     *        method (case insensitive).
     * @return a ResourceAdaptorEntityState object corresponding to state.
     * @throws NullPointerException if state is null.
     * @throws IllegalArgumentException if state is not a valid resource
     *        adaptor entity state string.
     */
    public static ResourceAdaptorEntityState fromString(String state) throws NullPointerException, IllegalArgumentException {
        if (state == null) throw new NullPointerException("state is null");
        if (state.equalsIgnoreCase(INACTIVE_STRING)) return INACTIVE;
        if (state.equalsIgnoreCase(ACTIVE_STRING)) return ACTIVE;
        if (state.equalsIgnoreCase(STOPPING_STRING)) return STOPPING;
        throw new IllegalArgumentException("Invalid state: " + state);
    }

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

    /**
     * Determine if this ResourceAdaptorEntityState object represents the INACTIVE state of
     * a resource adaptor entity.
     *

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

     *     if (state.isInactive()) ...
     *

     * is interchangeable with the code:
     *

     *    if (state == ResourceAdaptorEntityState.INACTIVE) ...
     *

     * @return true if this object represents the INACTIVE state of a resource
     *       adaptor entity, false otherwise.
     */
    public boolean isInactive() {
        return state == ENTITY_INACTIVE;
    }

    /**
     * Determine if this ResourceAdaptorEntityState object represents the ACTIVE state of
     * a resource adaptor entity.
     *

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

     *     if (state.isActive()) ...
     *

     * is interchangeable with the code:
     *

     *    if (state == ResourceAdaptorEntityState.ACTIVE) ...
     *

     * @return true if this object represents the ACTIVE state of a resource
     *       adaptor entity, false otherwise.
     */
    public boolean isActive() {
        return state == ENTITY_ACTIVE;
    }

    /**
     * Determine if this ResourceAdaptorEntityState object represents the STOPPING state of
     * a resource adaptor entity.
     *

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

     *     if (state.isStopping()) ...
     *

     * is interchangeable with the code:
     *

     *    if (state == ResourceAdaptorEntityState.STOPPING) ...
     *

     * @return true if this object represents the STOPPING state of a
     *       resource adaptor entity, false otherwise.
     */
    public boolean isStopping() {
        return state == ENTITY_STOPPING;
    }

    /**
     * Compare this resource adaptor state 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 resource adaptor state as this, false
     *        otherwise.
     */
    public boolean equals(Object obj) {
        if (obj == this) return true;

        return (obj instanceof ResourceAdaptorEntityState)
            && ((ResourceAdaptorEntityState)obj).state == state;
    }

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

    /**
     * Get the textual representation of the ResourceAdaptorEntityState object.
     * @return the textual representation of the ResourceAdaptorEntityState object.
     */
    public String toString() {
        switch (state) {
            case ENTITY_INACTIVE: return INACTIVE_STRING;
            case ENTITY_ACTIVE: return ACTIVE_STRING;
            case ENTITY_STOPPING: return STOPPING_STRING;
            default: return "ResourceAdaptorEntityState in Unknown and Invalid State";
        }
    }

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

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

    /**
     * The internal state representation of the enumerated type.
     */
    private final int state;
}


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

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

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import javax.slee.management.DeploymentException;

import org.apache.log4j.Logger;
import org.mobicents.slee.container.component.ComponentManagementImpl;
import org.mobicents.slee.container.component.ServiceComponentImpl;
import org.mobicents.slee.container.component.deployment.jaxb.descriptors.ServiceDescriptorFactoryImpl;
import org.mobicents.slee.container.component.deployment.jaxb.descriptors.ServiceDescriptorImpl;

/**
 * Service Component builder
 * @author martins
 *
 */
public class DeployableUnitServiceComponentBuilder {

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

	private final ComponentManagementImpl componentManagement;

	/**
	 *
	 */
	public DeployableUnitServiceComponentBuilder(ComponentManagementImpl componentManagement) {
		this.componentManagement = componentManagement;
	}

	/**
	 * Builds a service component contained in the specified du jar file, with the specified and adds it to the specified deployable unit.
	 *
	 * @param serviceDescriptorFileName
	 * @param deployableUnitJar
	 * @param deployableUnit
	 * @param documentBuilder
	 * @throws DeploymentException
	 */
	public List<ServiceComponentImpl> buildComponents(String serviceDescriptorFileName, JarFile deployableUnitJar) throws DeploymentException {

		// make component jar entry
		JarEntry componentDescriptor = deployableUnitJar.getJarEntry(serviceDescriptorFileName);
		InputStream componentDescriptorInputStream = null;
		List<ServiceComponentImpl> result = new ArrayList<ServiceComponentImpl>();
    	try {
    		componentDescriptorInputStream = deployableUnitJar.getInputStream(componentDescriptor);
    		ServiceDescriptorFactoryImpl descriptorFactory = componentManagement.getComponentDescriptorFactory().getServiceDescriptorFactory();
    		for (ServiceDescriptorImpl descriptor : descriptorFactory.parse(componentDescriptorInputStream)) {
    			result.add(new ServiceComponentImpl(descriptor));
    		}
    	} catch (IOException e) {
    		throw new DeploymentException("failed to parse service descriptor from "+componentDescriptor.getName(),e);
    	}
    	finally {
    		if (componentDescriptorInputStream != null) {
    			try {
    				componentDescriptorInputStream.close();
    			} catch (IOException e) {
    				logger.error("failed to close inputstream of descriptor for jar "+componentDescriptor.getName());
    			}
    		}
    	}
    	return result;
    }

}


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

/***************************************************
 *                                                 *
 *  Restcomm: The Open Source JSLEE Platform      *
 *                                                 *
 *  Distributable under LGPL license.              *
 *  See terms of license at gnu.org.               *
 *                                                 *
 ***************************************************/
/*
 * ConcreteClassGeneratorUtils.java
 *
 * Created on Aug 19, 2004
 *
 */
package org.mobicents.slee.container.deployment;

import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

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

import javax.slee.SLEEException;

import org.apache.log4j.Logger;
import org.mobicents.slee.container.SleeContainerUtils;

/**
 * Utility class to generate concrete classes
 *
 * @author DERUELLE Jean jean.deruelle@gmail.com
 * @author Michele La Porta
 */
public class ConcreteClassGeneratorUtils {
	public static Logger logger = null;

	public static final String SBB_CONCRETE_CLASS_NAME_PREFIX = "";

	public static final String SBB_CONCRETE_CLASS_NAME_SUFFIX = "Impl";

	public static final String CONCRETE_ACTIVITY_INTERFACE_CLASS_NAME_PREFIX = "";

	public static final String CONCRETE_ACTIVITY_INTERFACE_CLASS_NAME_SUFFIX = "Impl";

	public static final String SBB_LOCAL_OBJECT_CLASS_NAME_PREFIX = "";

	public static final String SBB_LOCAL_OBJECT_CLASS_NAME_SUFFIX = "Impl";

	public static final String PROFILE_CONCRETE_CLASS_NAME_PREFIX = "";

	public static final String PROFILE_CONCRETE_CLASS_NAME_SUFFIX = "Impl";

	public static final String PROFILE_MBEAN_CONCRETE_CLASS_NAME_PREFIX = "";

	public static final String PROFILE_MBEAN_CONCRETE_CLASS_NAME_SUFFIX = "MBeanImpl";

	public static final String PROFILE_TRANSIENT_CLASS_NAME_PREFIX = "";

	public static final String PROFILE_TRANSIENT_CLASS_NAME_SUFFIX = "TransientState";

	public static final String SBB_USAGE_PARAMETERS_INTERFACE_PREFIX = "";

	public static final String SBB_USAGE_PARAMETERS_INTERFACE_SUFFIX = "Impl";

	public static final String PROFILE_LOCAL_CLASS_NAME_PREFIX = "";

	public static final String PROFILE_LOCAL_CLASS_NAME_SUFFIX = "LocalImpl";

	public static final String PROFILE_TABLE_CLASS_NAME_PREFIX = "";

	public static final String PROFILE_TABLE_CLASS_NAME_SUFFIX = "TableImpl";

	// The root class pool

	static {
		logger = Logger.getLogger(ConcreteClassGeneratorUtils.class);

	}

    /**
	 * Recursively walk a directory tree and return a List of all jars Files found;
	 * the List is sorted using File.compareTo.
	 *
	 * @param aStartingDir
	 *            is a valid directory, which can be read.
	 */
	static public List getJarsFileListing(File aStartingDir)
			throws FileNotFoundException {
		validateDirectory(aStartingDir);
		List result = new ArrayList();

		File[] filesAndDirs = aStartingDir.listFiles(new FileFilter() {

			public boolean accept(File pathname) {
				if(pathname.getName().endsWith(".jar"))
					return true;
				return false;
			}

		});
		List filesDirs = Arrays.asList(filesAndDirs);
		Iterator filesIter = filesDirs.iterator();
		File file = null;
		while (filesIter.hasNext()) {
			file = (File) filesIter.next();
			result.add(file); // always add, even if directory
			if (!file.isFile()) {
				// must be a directory
				// recursive call!
				List deeperList = getJarsFileListing(file);
				result.addAll(deeperList);
			}

		}
		Collections.sort(result);
		return result;
	}

	  /**
	  * Directory is valid if it exists, does not represent a file, and can be read.
	  */
	  static private void validateDirectory(File aDirectory)
			throws FileNotFoundException {
		if (aDirectory == null) {
			throw new IllegalArgumentException("Directory should not be null.");
		}
		if (!aDirectory.exists()) {
			throw new FileNotFoundException("Directory does not exist: "
					+ aDirectory);
		}
		if (!aDirectory.isDirectory()) {
			throw new IllegalArgumentException("Is not a directory: "
					+ aDirectory);
		}
		if (!aDirectory.canRead()) {
			throw new IllegalArgumentException("Directory cannot be read: "
					+ aDirectory);
		}
	}

	/**
	 *
	 * Create a concrete sbb class name based on a given sbb abstract class name
	 *
	 * @param sbbAbstractClassName the sbb abstract name which will be the base of the concrete class
	 */
	public static String getSbbConcreteClassName(String sbbAbstractClassName)
	{
		return
			ConcreteClassGeneratorUtils.SBB_CONCRETE_CLASS_NAME_PREFIX
			+ sbbAbstractClassName
			+ ConcreteClassGeneratorUtils.SBB_CONCRETE_CLASS_NAME_SUFFIX;
	}

	/**
	 * Create the links with possible interfaces
	 *
	 * @param concreteClass
	 *            the concrete class to which to add the interface links
	 * @param interfaces
	 *            the interfaces the concrete class has to implement
	 */
	public static void createInterfaceLinks(CtClass concreteClass,
			CtClass[] interfaces) {
		if (interfaces != null)
			concreteClass.setInterfaces(interfaces);
		else
			return;
		for (int i = 0; i < interfaces.length; i++) {
			logger.trace(concreteClass.getName() + " Implements link with "
					+ interfaces[i].getName() + " interface created");
		}
	}

	/**
	 * Create the inheritance link with the sbb absract class provided by the
	 * sbb developer
	 *
	 * @param concreteClass
	 *            the concrete class to which to add the inheritance link
	 * @param superClass
	 *            the superClass to set
	 */
	public static void createInheritanceLink(CtClass concreteClass,
			CtClass superClass) {
		if (superClass == null)
			return;
		try {
			concreteClass.setSuperclass(superClass);
			logger.trace(concreteClass.getName() + " Inheritance link with "
					+ superClass.getName() + " class created");
		} catch (CannotCompileException cce) {
			cce.printStackTrace();
		}
	}

	/**
	 * Add a concrete method invoking the interceptor interceptorName
	 * with the same parameters,name,return type as the method method
	 *
	 * @param concreteClass
	 *            the concrete where to add the interceptor method
	 * @param method
	 *            method from which is generating the new proxy method
	 * @param interceptorName
	 *            the interceptor name implementing the interface
	 *            InvocationHandler. This name must be the name of an existing
	 *            field of the concrete class
	 * @param callSuperMethod
	 *            if true the concrete implementation of the method will call
	 *            super()
	 */
	public static void addInterceptedMethod(CtClass concreteClass,
			CtMethod method, String interceptorName, boolean callSuperMethod) {
		if (method == null) throw new InvalidParameterException("Intercepted method should not be null");
		if (interceptorName == null) throw new InvalidParameterException("Interceptor class name should not be null");

		String methodToAdd = "public ";
		//Add the return type
		boolean hasReturn = false;
		CtClass returnType = null;
		try {
			returnType = method.getReturnType();
			methodToAdd = methodToAdd.concat(returnType.getName() + " ");
			hasReturn = true;
		} catch (NotFoundException nfe) {
			//nfe.printStackTrace();
		    logger.trace("No return type -- assuming return type is void " );
			methodToAdd = methodToAdd + "void ";
		}
		//Add the method name
		methodToAdd = methodToAdd.concat(method.getName() + "(");
		//Add the parameters
		CtClass[] parameterTypes = null;
		;
		String parametersInit = "Object[] args=null;";
		String argsInit = "Class[] classes=null;";
		try {
			parameterTypes = method.getParameterTypes();
			parametersInit = parametersInit + "args=new Object["
					+ parameterTypes.length + "];";
			argsInit = argsInit + "classes=new Class[" + parameterTypes.length
					+ "];";
			for (int argNumber = 0; argNumber < parameterTypes.length; argNumber++) {
				methodToAdd = methodToAdd.concat(parameterTypes[argNumber]
						.getName()
						+ " arg_" + argNumber);
				//handle the primitive types
				if (!parameterTypes[argNumber].isPrimitive())
					parametersInit = parametersInit + " args[" + argNumber
							+ "]=arg_" + argNumber + ";";
				else
					parametersInit = parametersInit
							+ " args["
							+ argNumber
							+ "]="
							+ ClassUtils
									.getObjectFromPrimitiveType(
											parameterTypes[argNumber].getName(),
											"arg_" + argNumber) + ";";
				String typeClass = parameterTypes[argNumber].getName();
				//handle the primitive types
				if (!parameterTypes[argNumber].isPrimitive()) {
					if (parameterTypes[argNumber].isArray()) {
						String arrayClassRepresentation = toArray(parameterTypes[argNumber]);
						if (arrayClassRepresentation != null)
							argsInit = argsInit + "classes[" + argNumber + "]="
									+ SleeContainerUtils.class.getName() + ".getCurrentThreadClassLoader().loadClass(\""
									+ arrayClassRepresentation + "\");";
					} else
						argsInit = argsInit + "classes[" + argNumber
								+ "]="+SleeContainerUtils.class.getName() + ".getCurrentThreadClassLoader().loadClass(\"" + typeClass + "\");";
				} else
					argsInit = argsInit + "classes[" + argNumber + "]="
							+ ClassUtils.getClassFromPrimitiveType(typeClass) + ".TYPE;";
				if (argNumber + 1 < parameterTypes.length)
					methodToAdd = methodToAdd + ",";
			}

			methodToAdd += ") ";

			// Add method exceptions
			if (method.getExceptionTypes().length > 0)
			{
			    CtClass[] exceptions = method.getExceptionTypes();
				methodToAdd += " throws ";
				for (int i = 0; i < exceptions.length-1; i++) {
				    String exName = exceptions[i].getName();
				    methodToAdd += exName + ", ";
				}
				methodToAdd += exceptions[exceptions.length-1].getName();
			}

		} catch (NotFoundException nfe) {
			nfe.printStackTrace();
			throw new SLEEException("Failed creating concrete Profile MBean implementation class", nfe);
		}

		// Start adding method body
		methodToAdd +=  " { ";
		methodToAdd += "" + parametersInit;
		methodToAdd += "" + argsInit;
		methodToAdd += "Class clazz=this.getClass();";
		methodToAdd += "Object result=null;";
		methodToAdd += "try{";
		//call the super method
		if (callSuperMethod) {
		    if(method.getName().equals("profileStore")){
				methodToAdd = methodToAdd + "super." + method.getName() + "(";
				if (parameterTypes != null && parameterTypes.length > 0) {
					for (int argNumber = 0; argNumber < parameterTypes.length; argNumber++) {
						methodToAdd = methodToAdd + "arg_" + argNumber;
						if (argNumber + 1 < parameterTypes.length)
							methodToAdd = methodToAdd + ",";
					}
				}
				methodToAdd = methodToAdd + ");";
		    }
		}
		methodToAdd = methodToAdd
				+ "java.lang.reflect.Method method=clazz.getDeclaredMethod(\""
				+ method.getName() + "\",classes" + ");";
		methodToAdd = methodToAdd + "result=" + interceptorName
				+ ".invoke(this,method,args); ";
		methodToAdd = methodToAdd
				+ "}catch(RuntimeException t){t.printStackTrace(); throw (t); "
				+ " } catch (Exception ex1) { ex1.printStackTrace(); throw (ex1); }";
		//call the super method
		if (callSuperMethod) {
		    if(!method.getName().equals("profileStore")){
				methodToAdd = methodToAdd + "super." + method.getName() + "(";
				if (parameterTypes != null && parameterTypes.length > 0) {
					for (int argNumber = 0; argNumber < parameterTypes.length; argNumber++) {
						methodToAdd = methodToAdd + "arg_" + argNumber;
						if (argNumber + 1 < parameterTypes.length)
							methodToAdd += ",";
					}
				}
				methodToAdd += ");";
		    }
		}
		//handle the primitive types
		if (hasReturn) {
			if (!returnType.getName().equalsIgnoreCase("void")) {
				if (!returnType.isPrimitive())
					methodToAdd = methodToAdd + "return ("
							+ returnType.getName() + ")result;";
				else
					methodToAdd = methodToAdd
							+ "return "
							+ ClassUtils
									.getPrimitiveTypeFromObject(returnType
											.getName(), "result") + ";";
			}

		}
		methodToAdd += "}";
		//Add the implementation code
		logger.trace("Method " + methodToAdd + " added");
		CtMethod methodTest;
		try {
			methodTest = CtNewMethod.make(methodToAdd, concreteClass);
			concreteClass.addMethod(methodTest);
		} catch (CannotCompileException cce) {
			throw new SLEEException("Cannot compile method " + method.getName(), cce);
		}
	}

	/**
	 * Transform an array class to its string representation

	 * example: String[] -> [Ljava.lang.String;
	 *
	 * @param typeClass
	 *            the array class to transform
	 * @return the String representation of the class
	 */
	public static String toArray(CtClass typeClass) {
		StringTokenizer st = new StringTokenizer(typeClass.getName(), "[");
		String name = null;
		CtClass arrayClass;
		try {
			arrayClass = typeClass.getComponentType();
			if (!arrayClass.isPrimitive())
				name = "L" + arrayClass.getName().replace('/', '.') + ";";
			else
				name = toJvmRepresentation(arrayClass.getName());
			st.nextToken();
			while (st.hasMoreTokens()) {
				st.nextToken();
				name = "[" + name;
			}
		} catch (NotFoundException e) {
			e.printStackTrace();
		}
		return name;
	}

	/**
	 * Get the jvm representation of the primitives types

	 * Exemple: int -> I, boolean -> Z and so on...
	 *
	 *
	 * @param primitiveTypeName
	 *            the primitive type name whose the jvm representation is wanted
	 * @return the jvm representation of the primitive type
	 */
	public static String toJvmRepresentation(String primitiveTypeName) {
		if (primitiveTypeName.equals("int"))
			return "I";
		if (primitiveTypeName.equals("boolean"))
			return "Z";
		if (primitiveTypeName.equals("byte"))
			return "B";
		if (primitiveTypeName.equals("char"))
			return "C";
		if (primitiveTypeName.equals("double"))
			return "D";
		if (primitiveTypeName.equals("float"))
			return "F";
		if (primitiveTypeName.equals("long"))
			return "J";
		if (primitiveTypeName.equals("short"))
			return "S";
		if (primitiveTypeName.equals("void"))
			return "V";
		return primitiveTypeName;
	}

	/**
	 * Copy declared methods from one class to another
	 *
	 * @param source
	 *            the class from which the methods are copied
	 * @param destination
	 *            the class to which the methods are copied
	 * @param exceptions
	 *            optionnal, defines the set of exceptions the methods can throw
	 */
	public static void copyMethods(CtClass source, CtClass destination,
			CtClass[] exceptions) {
		copyMethods(source.getDeclaredMethods(), destination, exceptions);
	}

	/**
	 * Copy all methods from one class to another
	 * FIXME emmartins: merge with other method when 1.1 dev cycle ends
	 * @param source
	 *            the class from which the methods are copied
	 * @param destination
	 *            the class to which the methods are copied
	 * @param exceptions
	 *            optionnal, defines the set of exceptions the methods can throw
	 */
	public static void copyAllMethods(CtClass source, CtClass destination,
			CtClass[] exceptions) {
		copyMethods(source.getDeclaredMethods(), destination, exceptions);
	}

	/**
	 * Copy methods to a class
	 *
	 * @param methods
	 *            the methods to copy
	 * @param destination
	 *            the class to which the methods are copied
	 * @param exceptions
	 *            optional, defines the set of exceptions the methods can throw
	 */
	public static void copyMethods(CtMethod[] methods, CtClass destination,
			CtClass[] exceptions) {
		CtMethod methodCopy = null;
		for (CtMethod method : methods) {
			try {
				methodCopy = new CtMethod(method, destination, null);
				if (exceptions != null) {
					try {
						methodCopy.setExceptionTypes(exceptions);
					} catch (NotFoundException e) {
						throw new SLEEException(e.getMessage(),e);
					}
				}
				destination.addMethod(methodCopy);
			} catch (CannotCompileException 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.container.service;

import java.io.Serializable;

import javax.slee.FactoryException;
import javax.slee.ServiceID;
import javax.slee.TransactionRequiredLocalException;
import javax.slee.serviceactivity.ServiceActivity;

import org.mobicents.slee.container.SleeContainer;
import org.mobicents.slee.container.SleeThreadLocals;
import org.mobicents.slee.container.management.ServiceManagementImpl;
import org.mobicents.slee.container.transaction.SleeTransactionManager;

/**
 * Implementation of the service activity factory.
 *
 *@author M. Ranganathan
 */
public class ServiceActivityFactoryImpl implements ServiceActivityFactory,
		Serializable {

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

	public static final String JNDI_NAME = "factory";

	private final ServiceManagementImpl serviceManagement;

	/**
	 * @param sleeContainer
	 */
	public ServiceActivityFactoryImpl(ServiceManagementImpl serviceManagement) {
		this.serviceManagement = serviceManagement;
	}

	/* (non-Javadoc)
	 * @see javax.slee.serviceactivity.ServiceActivityFactory#getActivity()
	 */
	public ServiceActivity getActivity()
			throws TransactionRequiredLocalException, FactoryException {

		final SleeContainer sleeContainer = serviceManagement.getSleeContainer();
		final SleeTransactionManager stm = sleeContainer.getTransactionManager();
		stm.mandateTransaction();

		ServiceID serviceID = SleeThreadLocals.getInvokingService();

		if (serviceID == null) {
			throw new FactoryException("unable to find out the invoking service id");
		}
		return new ServiceActivityImpl(serviceID);
	}

}


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

package org.mobicents.slee.container.deployment.jboss;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import javax.slee.ComponentID;
import javax.slee.ServiceID;

import org.jboss.logging.Logger;
import org.mobicents.slee.container.SleeContainer;
import org.mobicents.slee.container.component.ComponentDescriptorFactory;
import org.mobicents.slee.container.component.event.EventTypeDescriptor;
import org.mobicents.slee.container.component.event.EventTypeDescriptorFactory;
import org.mobicents.slee.container.component.library.LibraryDescriptor;
import org.mobicents.slee.container.component.library.LibraryDescriptorFactory;
import org.mobicents.slee.container.component.profile.ProfileSpecificationDescriptor;
import org.mobicents.slee.container.component.profile.ProfileSpecificationDescriptorFactory;
import org.mobicents.slee.container.component.ra.ResourceAdaptorDescriptor;
import org.mobicents.slee.container.component.ra.ResourceAdaptorDescriptorFactory;
import org.mobicents.slee.container.component.ratype.ResourceAdaptorTypeDescriptor;
import org.mobicents.slee.container.component.ratype.ResourceAdaptorTypeDescriptorFactory;
import org.mobicents.slee.container.component.sbb.ResourceAdaptorEntityBindingDescriptor;
import org.mobicents.slee.container.component.sbb.ResourceAdaptorTypeBindingDescriptor;
import org.mobicents.slee.container.component.sbb.SbbDescriptor;
import org.mobicents.slee.container.component.sbb.SbbDescriptorFactory;
import org.mobicents.slee.container.component.service.ServiceDescriptor;
import org.mobicents.slee.container.component.service.ServiceDescriptorFactory;
import org.mobicents.slee.container.deployment.jboss.action.ActivateServiceAction;
import org.mobicents.slee.container.deployment.jboss.action.DeactivateServiceAction;
import org.mobicents.slee.container.deployment.jboss.action.ManagementAction;
import org.mobicents.slee.container.management.jmx.editors.ComponentIDPropertyEditor;

/**
 * This class represents a SLEE Deployable Component such as a Profile
 * Specification, Event Type Definition, RA Type, Resource Adaptor, SBB or
 * Service. It also contains the dependencies and the install/uninstall actions
 * needed for that component.
 *
 * @author Alexandre Mendonça
 * @version 1.0
 */
public class DeployableComponent {
	// The logger.
	private static Logger logger = Logger.getLogger(DeployableComponent.class);

	public final static int PROFILESPEC_COMPONENT = 1;
	public final static int EVENTTYPE_COMPONENT = 2;
	public final static int RATYPE_COMPONENT = 3;
	public final static int RA_COMPONENT = 4;
	public final static int SBB_COMPONENT = 5;
	public final static int SERVICE_COMPONENT = 6;
	public final static int LIBRARY_COMPONENT = 7;

	// The DeploymentInfo short name
	private String diShortName;

	// The DeploymentInfo URL object
	private URL diURL;

	// The ID of the component.
	private ComponentID componentID;

	// The dependencies for this Component.
	private Collection<String> dependencies = new ArrayList<String>();

	// The actions needed to perform installation for this component.
	private Collection<ManagementAction> installActions = new ArrayList<ManagementAction>();

	// The actions needed to perform installation for this component.
	private Collection<ManagementAction> uninstallActions = new ArrayList<ManagementAction>();

	// The key identifying the component (type[name#vendor#version]).
	private String componentKey;

	// An indicator for the component type.
	private int componentType = -1;

	private DeployableUnitWrapper duWrapper;

	// The components inside this component
	private Collection<DeployableComponent> subComponents = new ArrayList<DeployableComponent>();

	private final SleeContainerDeployerImpl sleeContainerDeployer;

	/**
	 * Private constructor for the sub-components.
	 *
	 * @param dc
	 *            the base DeployableComponent
	 * @throws Exception
	 */
	private DeployableComponent(DeployableComponent dc,
			SleeContainerDeployerImpl sleeContainerDeployer) throws Exception {

		this.sleeContainerDeployer = sleeContainerDeployer;
		this.diShortName = dc.diShortName;
		this.diURL = dc.diURL;

		// We want no sub-sub-components...
		this.subComponents = null;
	}

	public DeployableComponent(DeployableUnitWrapper duWrapper, URL url,
			String fileName, SleeContainerDeployerImpl sleeContainerDeployer)
			throws Exception {
		this.sleeContainerDeployer = sleeContainerDeployer;
		this.duWrapper = duWrapper;
		this.diShortName = fileName;
		this.diURL = url;

		// Parse the component descriptor to obtain dependencies.
		this.subComponents = parseDescriptor();
	}

	/**
	 * Getter for this component dependencies.
	 *
	 * @return a Collection<String> with dependencies IDs.
	 */
	public Collection<String> getDependencies() {
		return this.dependencies;
	}

	/**
	 * Method for checking if the component is deployable, ie, meets the
	 * pre-reqs.
	 *
	 * @param deployedComponents
	 *            a Collection<String> with the IDs of the already deployed
	 *            components.
	 * @return true if it can be deployed.
	 */
	public boolean isDeployable(Collection<String> deployedComponents) {
		return deployedComponents.containsAll(dependencies);
	}

	/**
	 * Getter for the Component Key String.
	 *
	 * @return a String with the component key (type[name#vendor#version]).
	 */
	public String getComponentKey() {
		return this.componentKey;
	}

	/**
	 * Parser for the deployment descriptor. Minimal version obtained from
	 * Container.
	 *
	 * @return a String containing the Component ID.
	 * @throws IOException
	 */
	private Collection<DeployableComponent> parseDescriptor()
			throws IOException {
		if (logger.isTraceEnabled()) {
			logger.trace("Parsing Descriptor for " + this.diURL.toString());
		}

		Collection<DeployableComponent> deployableComponents = new ArrayList<DeployableComponent>();

		SleeContainer sleeContainer = SleeContainer.lookupFromJndi();
		ComponentDescriptorFactory componentDescriptorFactory = sleeContainer
				.getComponentManagement().getComponentDescriptorFactory();

		// Special case for the services...
		if (this.diShortName.endsWith(".xml")) {
			if (logger.isTraceEnabled()) {
				logger.trace("Parsing Service Descriptor.");
			}

			InputStream is = null;

			try {
				is = diURL.openStream();

				ServiceDescriptorFactory sdf = componentDescriptorFactory
						.getServiceDescriptorFactory();
				List<? extends ServiceDescriptor> serviceDescriptors = sdf
						.parse(is);

				for (ServiceDescriptor sd : serviceDescriptors) {
					DeployableComponent dc = new DeployableComponent(this,sleeContainerDeployer);

					dc.componentType = SERVICE_COMPONENT;

					dc.componentID = sd.getServiceID();

					dc.componentKey = getComponentIdAsString(dc.componentID);

					if (logger.isTraceEnabled()) {
						logger.trace("Component ID: " + dc.componentKey);
						logger.trace("------------------------------ Dependencies ------------------------------");
					}

					// Get the set of this sbb dependencies
					Set<ComponentID> serviceDependencies = sd
							.getDependenciesSet();

					// Iterate through dependencies set
					for (ComponentID dependencyId : serviceDependencies) {
						// Add the dependency
						dc.dependencies
								.add(getComponentIdAsString(dependencyId));

						if (logger.isTraceEnabled()) {
							logger.trace(getComponentIdAsString(dependencyId));
						}
					}

					if (logger.isTraceEnabled()) {
						logger.trace("--------------------------- End of Dependencies --------------------------");
					}

					dc.installActions.add(new ActivateServiceAction(
							(ServiceID) dc.componentID, sleeContainerDeployer.getSleeContainer().getServiceManagement()));

					dc.uninstallActions.add(new DeactivateServiceAction(
							(ServiceID) dc.componentID, sleeContainerDeployer.getSleeContainer().getServiceManagement()));

					deployableComponents.add(dc);
				}

				return deployableComponents;
			} catch (Exception e) {
				logger.error("", e);
				return null;
			} finally {
				// Clean up!
				if (is != null) {
					try {
						is.close();
					} finally {
						is = null;
					}
				}
			}
		}

		try {
			URL descriptorXML = null;

			// Determine whether the type of this instance is an sbb, event, RA
			// type, etc.
			if ((descriptorXML = duWrapper.getEntry("META-INF/sbb-jar.xml")) != null) {
				if (logger.isTraceEnabled()) {
					logger.trace("Parsing SBB Descriptor.");
				}

				InputStream is = null;

				try {
					is = descriptorXML.openStream();

					// Parse the descriptor using the factory
					SbbDescriptorFactory sbbdf = componentDescriptorFactory
							.getSbbDescriptorFactory();
					List<? extends SbbDescriptor> sbbDescriptors = sbbdf
							.parse(is);

					if (sbbDescriptors.isEmpty()) {
						logger.warn("The "
								+ duWrapper.getFileName()
								+ " deployment descriptor contains no sbb definitions");
						return null;
					}

					for (SbbDescriptor sbbDescriptor : sbbDescriptors) {
						DeployableComponent dc = new DeployableComponent(this,sleeContainerDeployer);

						dc.componentType = SBB_COMPONENT;

						// Get the Component ID
						dc.componentID = sbbDescriptor.getSbbID();

						// Get the Component Key
						dc.componentKey = getComponentIdAsString(dc.componentID);

						if (logger.isTraceEnabled()) {
							logger.trace("Component ID: " + dc.componentKey);
							logger.trace("------------------------------ Dependencies ------------------------------");
						}

						// Get the set of this sbb dependencies
						Set<ComponentID> sbbDependencies = sbbDescriptor
								.getDependenciesSet();

						// Iterate through dependencies set
						for (ComponentID dependencyId : sbbDependencies) {
							// Add the dependency
							dc.dependencies
									.add(getComponentIdAsString(dependencyId));

							if (logger.isTraceEnabled()) {
								logger.trace(getComponentIdAsString(dependencyId));
							}
						}

						// FIXME: This is special case for Links. Maybe it
						// should be treated in SbbDescriptorImpl?
						for (ResourceAdaptorTypeBindingDescriptor raTypeBinding : sbbDescriptor
								.getResourceAdaptorTypeBindings()) {
							for (ResourceAdaptorEntityBindingDescriptor raEntityBinding : raTypeBinding
									.getResourceAdaptorEntityBinding()) {
								String raLink = raEntityBinding
										.getResourceAdaptorEntityLink();

								// Add the dependency
								dc.dependencies.add(raLink);

								if (logger.isTraceEnabled()) {
									logger.trace(raLink);
								}
							}
						}

						if (logger.isTraceEnabled()) {
							logger.trace("--------------------------- End of Dependencies --------------------------");
						}

						deployableComponents.add(dc);
					}
				} catch (Exception e) {
					logger.error("", e);
				} finally {
					// Clean up!
					if (is != null) {
						try {
							is.close();
						} finally {
							is = null;
						}
					}
				}
			} else if ((descriptorXML = duWrapper
					.getEntry("META-INF/profile-spec-jar.xml")) != null) {
				if (logger.isTraceEnabled()) {
					logger.trace("Parsing Profile Specification Descriptor.");
				}

				InputStream is = null;

				try {
					// Get the InputStream
					is = descriptorXML.openStream();

					// Parse the descriptor using the factory
					ProfileSpecificationDescriptorFactory psdf = componentDescriptorFactory
							.getProfileSpecificationDescriptorFactory();
					List<? extends ProfileSpecificationDescriptor> psDescriptors = psdf
							.parse(is);

					// Get a list of the profile specifications in the
					// deployable unit.
					if (psDescriptors.isEmpty()) {
						logger.warn("The "
								+ duWrapper.getFileName()
								+ " deployment descriptor contains no profile-spec definitions");
						return null;
					}

					// Iterate through the profile spec nodes
					for (ProfileSpecificationDescriptor psDescriptor : psDescriptors) {
						DeployableComponent dc = new DeployableComponent(this,sleeContainerDeployer);

						// Set Component Type
						dc.componentType = PROFILESPEC_COMPONENT;

						// Get the Component ID
						dc.componentID = psDescriptor
								.getProfileSpecificationID();

						// Get the Component Key
						dc.componentKey = getComponentIdAsString(dc.componentID);

						if (logger.isTraceEnabled()) {
							logger.trace("Component ID: " + dc.componentKey);
							logger.trace("------------------------------ Dependencies ------------------------------");
						}

						// Get the set of this sbb dependencies
						Set<ComponentID> psDependencies = psDescriptor
								.getDependenciesSet();

						// Iterate through dependencies set
						for (ComponentID dependencyId : psDependencies) {
							// Add the dependency
							dc.dependencies
									.add(getComponentIdAsString(dependencyId));

							if (logger.isTraceEnabled()) {
								logger.trace(getComponentIdAsString(dependencyId));
							}
						}

						if (logger.isTraceEnabled()) {
							logger.trace("--------------------------- End of Dependencies --------------------------");
						}

						deployableComponents.add(dc);
					}
				} catch (Exception e) {
					logger.error("", e);
				} finally {
					// Clean up!
					if (is != null) {
						try {
							is.close();
						} finally {
							is = null;
						}
					}
				}
			} else if ((descriptorXML = duWrapper
					.getEntry("META-INF/event-jar.xml")) != null) {
				if (logger.isTraceEnabled()) {
					logger.trace("Parsing Event Definition Descriptor.");
				}

				InputStream is = null;

				try {
					// Get the InputStream
					is = descriptorXML.openStream();

					// Parse the descriptor using the factory
					EventTypeDescriptorFactory etdf = componentDescriptorFactory
							.getEventTypeDescriptorFactory();
					List<? extends EventTypeDescriptor> etDescriptors = etdf
							.parse(is);

					if (etDescriptors == null || etDescriptors.isEmpty()) {
						logger.warn("The "
								+ duWrapper.getFileName()
								+ " deployment descriptor contains no event-type definitions");
						return null;
					}

					for (EventTypeDescriptor etDescriptor : etDescriptors) {
						DeployableComponent dc = new DeployableComponent(this,sleeContainerDeployer);

						// Set Component Type
						dc.componentType = EVENTTYPE_COMPONENT;

						// Get the Component ID
						dc.componentID = etDescriptor.getEventTypeID();

						// Get the Component Key
						dc.componentKey = getComponentIdAsString(dc.componentID);

						if (logger.isTraceEnabled()) {
							logger.trace("Component ID: " + dc.componentKey);
							logger.trace("------------------------------ Dependencies ------------------------------");
						}

						// Get the set of this sbb dependencies
						Set<ComponentID> etDependencies = etDescriptor
								.getDependenciesSet();

						// Iterate through dependencies set
						for (ComponentID dependencyId : etDependencies) {
							// Add the dependency
							dc.dependencies
									.add(getComponentIdAsString(dependencyId));

							if (logger.isTraceEnabled()) {
								logger.trace(getComponentIdAsString(dependencyId));
							}
						}

						if (logger.isTraceEnabled()) {
							logger.trace("--------------------------- End of Dependencies --------------------------");
						}

						deployableComponents.add(dc);
					}

				} catch (Exception e) {
					logger.error("", e);
				} finally {
					// Clean up!
					if (is != null) {
						try {
							is.close();
						} finally {
							is = null;
						}
					}
				}
			} else if ((descriptorXML = duWrapper
					.getEntry("META-INF/resource-adaptor-type-jar.xml")) != null) {
				if (logger.isTraceEnabled()) {
					logger.trace("Parsing Resource Adaptor Type Descriptor.");
				}

				InputStream is = null;

				try {
					// Get the InputStream
					is = descriptorXML.openStream();

					// Parse the descriptor using the factory
					ResourceAdaptorTypeDescriptorFactory ratdf = componentDescriptorFactory
							.getResourceAdaptorTypeDescriptorFactory();
					List<? extends ResourceAdaptorTypeDescriptor> ratDescriptors = ratdf
							.parse(is);

					if (ratDescriptors == null || ratDescriptors.isEmpty()) {
						logger.warn("The "
								+ duWrapper.getFileName()
								+ " deployment descriptor contains no resource-adaptor-type definitions");
						return null;
					}

					// Go through all the Resource Adaptor Type Elements
					for (ResourceAdaptorTypeDescriptor ratDescriptor : ratDescriptors) {
						DeployableComponent dc = new DeployableComponent(this,sleeContainerDeployer);

						// Set Component Type
						dc.componentType = RATYPE_COMPONENT;

						// Get the Component ID
						dc.componentID = ratDescriptor
								.getResourceAdaptorTypeID();

						// Get the Component Key
						dc.componentKey = getComponentIdAsString(dc.componentID);

						if (logger.isTraceEnabled()) {
							logger.trace("Component ID: " + dc.componentKey);
							logger.trace("------------------------------ Dependencies ------------------------------");
						}

						// Get the set of this sbb dependencies
						Set<ComponentID> ratDependencies = ratDescriptor
								.getDependenciesSet();

						// Iterate through dependencies set
						for (ComponentID dependencyId : ratDependencies) {
							// Add the dependency
							dc.dependencies
									.add(getComponentIdAsString(dependencyId));

							if (logger.isTraceEnabled()) {
								logger.trace(getComponentIdAsString(dependencyId));
							}
						}

						if (logger.isTraceEnabled()) {
							logger.trace("--------------------------- End of Dependencies --------------------------");
						}

						deployableComponents.add(dc);
					}
				} catch (Exception e) {
					logger.error("", e);
				} finally {
					// Clean up!
					if (is != null) {
						try {
							is.close();
						} finally {
							is = null;
						}
					}
				}
			} else if ((descriptorXML = duWrapper
					.getEntry("META-INF/resource-adaptor-jar.xml")) != null) {
				if (logger.isTraceEnabled()) {
					logger.trace("Parsing Resource Adaptor Descriptor.");
				}

				InputStream is = null;

				try {
					// Get the InputStream
					is = descriptorXML.openStream();

					// Parse the descriptor using the factory
					ResourceAdaptorDescriptorFactory radf = componentDescriptorFactory
							.getResourceAdaptorDescriptorFactory();
					List<? extends ResourceAdaptorDescriptor> raDescriptors = radf
							.parse(is);

					DeployConfigParser sleeDeployConfigParser = sleeContainerDeployer.getSLEEDeployConfigParser();

					// Go through all the Resource Adaptor Elements
					for (ResourceAdaptorDescriptor raDescriptor : raDescriptors) {
						DeployableComponent dc = new DeployableComponent(this,sleeContainerDeployer);

						// Set Component Type
						dc.componentType = RA_COMPONENT;

						// Set the Component ID
						dc.componentID = raDescriptor.getResourceAdaptorID();

						// Set the Component Key
						dc.componentKey = getComponentIdAsString(dc.componentID);

						if (logger.isTraceEnabled()) {
							logger.trace("Component ID: " + dc.componentKey);
							logger.trace("------------------------------ Dependencies ------------------------------");
						}

						// Get the set of this sbb dependencies
						Set<ComponentID> raDependencies = raDescriptor
								.getDependenciesSet();

						// Iterate through dependencies set
						for (ComponentID dependencyId : raDependencies) {
							// Add the dependency
							dc.dependencies
									.add(getComponentIdAsString(dependencyId));

							if (logger.isTraceEnabled()) {
								logger.trace(getComponentIdAsString(dependencyId));
							}
						}

						if (logger.isTraceEnabled()) {
							logger.trace("--------------------------- End of Dependencies --------------------------");
						}

						// get management actions for this ra, in SLEE's deploy config
						if (sleeDeployConfigParser != null) {
							Collection<ManagementAction> managementActions = sleeDeployConfigParser.getPostInstallActions().get(dc.getComponentKey());
							if (managementActions != null) {
								dc.installActions.addAll(managementActions);
							}
							managementActions = sleeDeployConfigParser.getPreUninstallActions().get(dc.getComponentKey());
							if (managementActions != null) {
								dc.uninstallActions.addAll(managementActions);
							}
						}

						deployableComponents.add(dc);
					}
				} catch (Exception e) {
					logger.error("", e);
				} finally {
					// Clean up!
					if (is != null) {
						try {
							is.close();
						} finally {
							is = null;
						}
					}
				}
			} else if ((descriptorXML = duWrapper
					.getEntry("META-INF/library-jar.xml")) != null) {
				if (logger.isTraceEnabled()) {
					logger.trace("Parsing Library Descriptor.");
				}

				InputStream is = null;

				try {
					// Get the InputStream
					is = descriptorXML.openStream();

					// Parse the descriptor using the factory
					LibraryDescriptorFactory ldf = componentDescriptorFactory
							.getLibraryDescriptorFactory();
					List<? extends LibraryDescriptor> libraryDescriptors = ldf
							.parse(is);

					// Go through all the Resource Adaptor Elements
					for (LibraryDescriptor libraryDescriptor : libraryDescriptors) {
						DeployableComponent dc = new DeployableComponent(this,sleeContainerDeployer);

						// Set Component Type
						dc.componentType = LIBRARY_COMPONENT;

						// Set the Component ID
						dc.componentID = libraryDescriptor.getLibraryID();

						// Set the Component Key
						dc.componentKey = getComponentIdAsString(dc.componentID);

						if (logger.isTraceEnabled()) {
							logger.trace("Component ID: " + dc.componentKey);
							logger.trace("------------------------------ Dependencies ------------------------------");
						}

						// Get the set of this sbb dependencies
						Set<ComponentID> libraryDependencies = libraryDescriptor
								.getDependenciesSet();

						// Iterate through dependencies set
						for (ComponentID dependencyId : libraryDependencies) {
							// Add the dependency
							dc.dependencies
									.add(getComponentIdAsString(dependencyId));

							if (logger.isTraceEnabled()) {
								logger.trace(getComponentIdAsString(dependencyId));
							}
						}

						if (logger.isTraceEnabled()) {
							logger.trace("--------------------------- End of Dependencies --------------------------");
						}

						deployableComponents.add(dc);
					}
				} catch (Exception e) {
					logger.error("", e);
				} finally {
					// Clean up!
					if (is != null) {
						try {
							is.close();
						} finally {
							is = null;
						}
					}
				}
			} else {
				logger.warn("\r\n--------------------------------------------------------------------------------\r\n"
						+ "No Component Descriptor found in '"
						+ duWrapper.getFileName()
						+ "'.\r\n"
						+ "--------------------------------------------------------------------------------");

				return new ArrayList<DeployableComponent>();
			}
		} finally {
		}

		return deployableComponents;
	}

	/**
	 * Getter for Install Actions.
	 *
	 * @return a Collection of Object[] with the actions needed to install this
	 *         component.
	 */
	public Collection<ManagementAction> getInstallActions() {
		return installActions;
	}

	/**
	 * Getter for Uninstall Actions.
	 *
	 * @return a Collection of Object[] with the actions needed to uninstall
	 *         this component.
	 */
	public Collection<ManagementAction> getUninstallActions() {
		return uninstallActions;
	}

	/**
	 * Getter for component type.
	 *
	 * @return an int identifying the component type.
	 */
	public int getComponentType() {
		return componentType;
	}

	/**
	 * Getter for component id.
	 *
	 * @return the ComponentID for the component.
	 */
	public ComponentID getComponentID() {
		return componentID;
	}

	/**
	 * Getter for the sub components.
	 *
	 * @return Collection of DeployableComponents
	 */
	public Collection<DeployableComponent> getSubComponents() {
		return this.subComponents;
	}

	private String getComponentIdAsString(ComponentID componentId) {
		ComponentIDPropertyEditor cidPropertyEditor = new ComponentIDPropertyEditor();
		cidPropertyEditor.setValue(componentId);

		return cidPropertyEditor.getAsText();
	}
}


package javax.slee;

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

/**
 * This class defines an enumerated type that encapsulates the values available for
 * address or numbering plans.  An address plan specifies the format and structure
 * of an associated address string.  A numbering plan typically consists of decimal
 * digits segmented into groups in order to identify specific elements used for
 * identification, routing, and charging capabilities.
 *

 * 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 AddressPlan implements Serializable {
    /**
     * An integer representation of {@link #NOT_PRESENT}.
     */
    public static final int ADDRESS_PLAN_NOT_PRESENT = -1;

    /**
     * An integer representation of {@link #UNDEFINED}.
     */
    public static final int ADDRESS_PLAN_UNDEFINED = 0;

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

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

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

    /**
     * An integer representation of {@link #E164}.
     */
    public static final int ADDRESS_PLAN_E164 = 4;

    /**
     * An integer representation of {@link #AESA}.
     */
    public static final int ADDRESS_PLAN_AESA = 5;

    /**
     * An integer representation of {@link #URI}.
     */
    public static final int ADDRESS_PLAN_URI = 6;

    /**
     * An integer representation of {@link #NSAP}.
     */
    public static final int ADDRESS_PLAN_NSAP = 7;

    /**
     * An integer representation of {@link #SMTP}.
     */
    public static final int ADDRESS_PLAN_SMTP = 8;

    /**
     * An integer representation of {@link #X400}.
     */
    public static final int ADDRESS_PLAN_X400 = 10;

    /**
     * An integer representation of {@link #SIP}.
     */
    public static final int ADDRESS_PLAN_SIP = 11;

    /**
     * An integer representation of {@link #E164_MOBILE}.
     */
    public static final int ADDRESS_PLAN_E164_MOBILE = 13;

    /**
     * An integer representation of {@link #H323}.
     */
    public static final int ADDRESS_PLAN_H323 = 14;

    /**
     * An integer representation of {@link #GT}.
     */
    public static final int ADDRESS_PLAN_GT = 15;

    /**
     * An integer representation of {@link #SSN}.
     */
    public static final int ADDRESS_PLAN_SSN = 16;

    /**
     * An integer representation of {@link #SLEE_PROFILE_TABLE}.
     */
    public static final int ADDRESS_PLAN_SLEE_PROFILE_TABLE = 20;

    /**
     * An integer representation of {@link #SLEE_PROFILE}.
     */
    public static final int ADDRESS_PLAN_SLEE_PROFILE = 21;

    /**
     * A string representation of {@link #NOT_PRESENT}.
     */
    public static final String NOT_PRESENT_STRING = "Not Present";

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

    /**
     * A string representation of {@link #IP}.
     */
    public static final String IP_STRING = "IP";

    /**
     * A string representation of {@link #MULTICAST}.
     */
    public static final String MULTICAST_STRING = "Multicast";

    /**
     * A string representation of {@link #UNICAST}.
     */
    public static final String UNICAST_STRING = "Unicast";

    /**
     * A string representation of {@link #E164}.
     */
    public static final String E164_STRING = "E.164";

    /**
     * A string representation of {@link #AESA}.
     */
    public static final String AESA_STRING = "AESA";

    /**
     * A string representation of {@link #URI}.
     */
    public static final String URI_STRING = "URI";

    /**
     * A string representation of {@link #NSAP}.
     */
    public static final String NSAP_STRING = "NSAP";

    /**
     * A string representation of {@link #SMTP}.
     */
    public static final String SMTP_STRING = "SMTP";

    /**
     * A string representation of {@link #E164_MOBILE}.
     */
    public static final String E164_MOBILE_STRING = "E.164 Mobile";

    /**
     * A string representation of {@link #X400}.
     */
    public static final String X400_STRING = "X400";

    /**
     * A string representation of {@link #SIP}.
     */
    public static final String SIP_STRING = "SIP";

    /**
     * A string representation of {@link #H323}.
     */
    public static final String H323_STRING = "H323";

    /**
     * A string representation of {@link #GT}.
     */
    public static final String GT_STRING = "GT";

    /**
     * A string representation of {@link #SSN}.
     */
    public static final String SSN_STRING = "SSN";

    /**
     * A string representation of {@link #SLEE_PROFILE_TABLE}.
     */
    public static final String SLEE_PROFILE_TABLE_STRING = "SLEE ProfileTable";

    /**
     * A string representation of {@link #SLEE_PROFILE}.
     */
    public static final String SLEE_PROFILE_STRING = "SLEE Profile";

    /**
     * The NOT_PRESENT value indicates that the address is not present.
     */
    public static final AddressPlan NOT_PRESENT = new AddressPlan(ADDRESS_PLAN_NOT_PRESENT);

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

    /**
     * The IP value indicates that the address is an IP address
     * in dotted notation.
     */
    public static final AddressPlan IP = new AddressPlan(ADDRESS_PLAN_IP);

    /**
     * The MULTICAST value indicates that the address is an IP address in
     * dotted notation that is either an IPv4 class D address or an equivalent IPv6
     * address.
     */
    public static final AddressPlan MULTICAST = new AddressPlan(ADDRESS_PLAN_MULTICAST);

    /**
     * The UNICAST value indicates that the address is an IP address
     * in dotted notation that is not a multicast or broadcast address.
     */
    public static final AddressPlan UNICAST = new AddressPlan(ADDRESS_PLAN_UNICAST);

    /**
     * The E164 value indicates that the address is an international
     * number without the international access code, but including the country
     * code and area code (without the leading zero).
     */
    public static final AddressPlan E164 = new AddressPlan(ADDRESS_PLAN_E164);

    /**
     * The AESA value indicates that the address is an ATM End
     * System Address in binary format (40 bytes).
     */
    public static final AddressPlan AESA = new AddressPlan(ADDRESS_PLAN_AESA);

    /**
     * The URI value indicates that the address is a uniform resource
     * locator as defined in IETF RFC 2396.
     */
    public static final AddressPlan URI = new AddressPlan(ADDRESS_PLAN_URI);

    /**
     * The NSAP value indicates that the address is a binary
     * representation of a Network Service Access Point.
     */
    public static final AddressPlan NSAP = new AddressPlan(ADDRESS_PLAN_NSAP);

    /**
     * The SMTP value indicates that the address is an email address
     * as defined in IETF RFC 822.
     */
    public static final AddressPlan SMTP = new AddressPlan(ADDRESS_PLAN_SMTP);

    /**
     * The E164_MOBILE value indicates that the address is an E.164
     * mobile number.
     */
    public static final AddressPlan E164_MOBILE = new AddressPlan(ADDRESS_PLAN_E164_MOBILE);

    /**
     * The X400 value indicates that the address is an X400 address
     * structured as a set of attribute value pairs separated by semicolons.
     */
    public static final AddressPlan X400 = new AddressPlan(ADDRESS_PLAN_X400);

    /**
     * The SIP value indicates that the address is a Session Initiation
     * Protocol address as specified in IETF RFC 2543.
     */
    public static final AddressPlan SIP = new AddressPlan(ADDRESS_PLAN_SIP);

    /**
     * The H323 value indicates that the address is an H.323 address.
     * An H.323 address may be identified by a list of addresses of different
     * types, including URLs.
     */
    public static final AddressPlan H323 = new AddressPlan(ADDRESS_PLAN_H323);

    /**
     * The GT value indicates that the address is a Global Title.
     */
    public static final AddressPlan GT = new AddressPlan(ADDRESS_PLAN_GT);

    /**
     * The SSN value indicates that the address is a Sub System Number.
     */
    public static final AddressPlan SSN = new AddressPlan(ADDRESS_PLAN_SSN);

    /**
     * The SLEE_PROFILE_TABLE value indicates that the address is the
     * name of SLEE profile table.
     */
    public static final AddressPlan SLEE_PROFILE_TABLE = new AddressPlan(ADDRESS_PLAN_SLEE_PROFILE_TABLE);

    /**
     * The SLEE_PROFILE value indicates that the address is the encoded
     * table name and profile name of a SLEE profile.
     */
    public static final AddressPlan SLEE_PROFILE = new AddressPlan(ADDRESS_PLAN_SLEE_PROFILE);

    /**
     * Get an AddressPlan object from an integer value.
     * @param plan the address plan as an integer.
     * @return an AddressPlan object corresponding to plan.
     * @throws IllegalArgumentException if plan is not a valid
     *        address plan value.
     */
    public static AddressPlan fromInt(int plan) throws IllegalArgumentException {
        switch (plan) {
            case ADDRESS_PLAN_NOT_PRESENT: return NOT_PRESENT;
            case ADDRESS_PLAN_UNDEFINED: return UNDEFINED;
            case ADDRESS_PLAN_IP: return IP;
            case ADDRESS_PLAN_MULTICAST: return MULTICAST;
            case ADDRESS_PLAN_UNICAST: return UNICAST;
            case ADDRESS_PLAN_E164: return E164;
            case ADDRESS_PLAN_AESA: return AESA;
            case ADDRESS_PLAN_URI: return URI;
            case ADDRESS_PLAN_NSAP: return NSAP;
            case ADDRESS_PLAN_SMTP: return SMTP;
            case ADDRESS_PLAN_X400: return X400;
            case ADDRESS_PLAN_SIP: return SIP;
            case ADDRESS_PLAN_E164_MOBILE: return E164_MOBILE;
            case ADDRESS_PLAN_H323: return H323;
            case ADDRESS_PLAN_GT: return GT;
            case ADDRESS_PLAN_SSN: return SSN;
            case ADDRESS_PLAN_SLEE_PROFILE_TABLE: return SLEE_PROFILE_TABLE;
            case ADDRESS_PLAN_SLEE_PROFILE: return SLEE_PROFILE;
            default: throw new IllegalArgumentException("Invalid address plan: " + plan);
        }
    }

    /**
     * Get an AddressPlan object from a string value.
     * @param plan the address plan as a string, for example as returned by the {@link #toString()}
     *        method (case insensitive).
     * @return an AddressPlan object corresponding to plan.
     * @throws NullPointerException if plan is null.
     * @throws IllegalArgumentException if plan is not a valid
     *        address plan value.
     * @since SLEE 1.1
     */
    public static AddressPlan fromString(String plan) throws NullPointerException, IllegalArgumentException {
        if (plan == null) throw new NullPointerException("plan is null");
        if (plan.equalsIgnoreCase(NOT_PRESENT_STRING)) return NOT_PRESENT;
        if (plan.equalsIgnoreCase(UNDEFINED_STRING)) return UNDEFINED;
        if (plan.equalsIgnoreCase(IP_STRING)) return IP;
        if (plan.equalsIgnoreCase(MULTICAST_STRING)) return MULTICAST;
        if (plan.equalsIgnoreCase(UNICAST_STRING)) return UNICAST;
        if (plan.equalsIgnoreCase(E164_STRING)) return E164;
        if (plan.equalsIgnoreCase(AESA_STRING)) return AESA;
        if (plan.equalsIgnoreCase(URI_STRING)) return URI;
        if (plan.equalsIgnoreCase(NSAP_STRING)) return NSAP;
        if (plan.equalsIgnoreCase(SMTP_STRING)) return SMTP;
        if (plan.equalsIgnoreCase(X400_STRING)) return X400;
        if (plan.equalsIgnoreCase(SIP_STRING)) return SIP;
        if (plan.equalsIgnoreCase(E164_MOBILE_STRING)) return E164_MOBILE;
        if (plan.equalsIgnoreCase(H323_STRING)) return H323;
        if (plan.equalsIgnoreCase(GT_STRING)) return GT;
        if (plan.equalsIgnoreCase(SSN_STRING)) return SSN;
        if (plan.equalsIgnoreCase(SLEE_PROFILE_TABLE_STRING)) return SLEE_PROFILE_TABLE;
        if (plan.equalsIgnoreCase(SLEE_PROFILE_STRING)) return SLEE_PROFILE;
        throw new IllegalArgumentException("Invalid address plan: " + plan);
    }

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

    /**
     * Determine if this AddressPlan object represents the NOT_PRESENT address
     * plan value.
     *

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

     *     if (plan.isNotPresent()) ...
     *

     * is interchangeable with the code:
     *

     *    if (plan == AddressPlan.NOT_PRESENT) ...
     *

     * @return true if this object represents the NOT_PRESENT address plan
     *       value, false otherwise.
     */
    public boolean isNotPresent() {
        return plan == ADDRESS_PLAN_NOT_PRESENT;
    }

    /**
     * Determine if this AddressPlan object represents the UNDEFINED address
     * plan value.
     *

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

     *     if (plan.isUndefined()) ...
     *

     * is interchangeable with the code:
     *

     *    if (plan == AddressPlan.UNDEFINED) ...
     *

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

    /**
     * Determine if this AddressPlan object represents the IP address
     * plan value.
     *

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

     *     if (plan.isIP()) ...
     *

     * is interchangeable with the code:
     *

     *    if (plan == AddressPlan.IP) ...
     *

     * @return true if this object represents the IP address plan
     *       value, false otherwise.
     */
    public boolean isIP() {
        return plan == ADDRESS_PLAN_IP;
    }

    /**
     * Determine if this AddressPlan object represents the MULTICAST address
     * plan value.
     *

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

     *     if (plan.isMulticast()) ...
     *

     * is interchangeable with the code:
     *

     *    if (plan == AddressPlan.MULTICAST) ...
     *

     * @return true if this object represents the MULTICAST address plan
     *       value, false otherwise.
     */
    public boolean isMulticast() {
        return plan == ADDRESS_PLAN_MULTICAST;
    }

    /**
     * Determine if this AddressPlan object represents the UNICAST address
     * plan value.
     *

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

     *     if (plan.isUnicast()) ...
     *

     * is interchangeable with the code:
     *

     *    if (plan == AddressPlan.UNICAST) ...
     *

     * @return true if this object represents the UNICAST address plan
     *       value, false otherwise.
     */
    public boolean isUnicast() {
        return plan == ADDRESS_PLAN_UNICAST;
    }

    /**
     * Determine if this AddressPlan object represents the E164 address
     * plan value.
     *

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

     *     if (plan.isE164()) ...
     *

     * is interchangeable with the code:
     *

     *    if (plan == AddressPlan.E164) ...
     *

     * @return true if this object represents the E164 address plan
     *       value, false otherwise.
     */
    public boolean isE164() {
        return plan == ADDRESS_PLAN_E164;
    }

    /**
     * Determine if this AddressPlan object represents the AESA address
     * plan value.
     *

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

     *     if (plan.isAESA()) ...
     *

     * is interchangeable with the code:
     *

     *    if (plan == AddressPlan.AESA) ...
     *

     * @return true if this object represents the AESA address plan
     *       value, false otherwise.
     */
    public boolean isAESA() {
        return plan == ADDRESS_PLAN_AESA;
    }

    /**
     * Determine if this AddressPlan object represents the URI address
     * plan value.
     *

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

     *     if (plan.isURI()) ...
     *

     * is interchangeable with the code:
     *

     *    if (plan == AddressPlan.URI) ...
     *

     * @return true if this object represents the URI address plan
     *       value, false otherwise.
     */
    public boolean isURI() {
        return plan == ADDRESS_PLAN_URI;
    }

    /**
     * Determine if this AddressPlan object represents the NSAP address
     * plan value.
     *

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

     *     if (plan.isNSAP()) ...
     *

     * is interchangeable with the code:
     *

     *    if (plan == AddressPlan.NSAP) ...
     *

     * @return true if this object represents the NSAP address plan
     *       value, false otherwise.
     */
    public boolean isNSAP() {
        return plan == ADDRESS_PLAN_NSAP;
    }

    /**
     * Determine if this AddressPlan object represents the SMTP address
     * plan value.
     *

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

     *     if (plan.isSMTP()) ...
     *

     * is interchangeable with the code:
     *

     *    if (plan == AddressPlan.SMTP) ...
     *

     * @return true if this object represents the SMTP address plan
     *       value, false otherwise.
     */
    public boolean isSMTP() {
        return plan == ADDRESS_PLAN_SMTP;
    }

    /**
     * Determine if this AddressPlan object represents the X400 address
     * plan value.
     *

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

     *     if (plan.isX400()) ...
     *

     * is interchangeable with the code:
     *

     *    if (plan == AddressPlan.X400) ...
     *

     * @return true if this object represents the X400 address plan
     *       value, false otherwise.
     */
    public boolean isX400() {
        return plan == ADDRESS_PLAN_X400;
    }

    /**
     * Determine if this AddressPlan object represents the SIP address
     * plan value.
     *

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

     *     if (plan.isSIP()) ...
     *

     * is interchangeable with the code:
     *

     *    if (plan == AddressPlan.SIP) ...
     *

     * @return true if this object represents the SIP address plan
     *       value, false otherwise.
     */
    public boolean isSIP() {
        return plan == ADDRESS_PLAN_SIP;
    }

    /**
     * Determine if this AddressPlan object represents the E164_MOBILE address
     * plan value.
     *

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

     *     if (plan.isE164Mobile()) ...
     *

     * is interchangeable with the code:
     *

     *    if (plan == AddressPlan.E164_MOBILE) ...
     *

     * @return true if this object represents the E164_MOBILE address plan
     *       value, false otherwise.
     */
    public boolean isE164Mobile() {
        return plan == ADDRESS_PLAN_E164_MOBILE;
    }

    /**
     * Determine if this AddressPlan object represents the H323 address
     * plan value.
     *

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

     *     if (plan.isH323()) ...
     *

     * is interchangeable with the code:
     *

     *    if (plan == AddressPlan.H323) ...
     *

     * @return true if this object represents the H323 address plan
     *       value, false otherwise.
     */
    public boolean isH323() {
        return plan == ADDRESS_PLAN_H323;
    }

    /**
     * Determine if this AddressPlan object represents the GT address
     * plan value.
     *

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

     *     if (plan.isGT()) ...
     *

     * is interchangeable with the code:
     *

     *    if (plan == AddressPlan.GT) ...
     *

     * @return true if this object represents the GT address plan
     *       value, false otherwise.
     */
    public boolean isGT() {
        return plan == ADDRESS_PLAN_GT;
    }

    /**
     * Determine if this AddressPlan object represents the SSN address
     * plan value.
     *

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

     *     if (plan.isSSN()) ...
     *

     * is interchangeable with the code:
     *

     *    if (plan == AddressPlan.SSN) ...
     *

     * @return true if this object represents the SSN address plan
     *       value, false otherwise.
     */
    public boolean isSSN() {
        return plan == ADDRESS_PLAN_SSN;
    }

    /**
     * Determine if this AddressPlan object represents the SLEE_PROFILE_TABLE address
     * plan value.
     *

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

     *     if (plan.isSleeProfileTable()) ...
     *

     * is interchangeable with the code:
     *

     *    if (plan == AddressPlan.SLEE_PROFILE_TABLE) ...
     *

     * @return true if this object represents the SLEE_PROFILE_TABLE address plan
     *       value, false otherwise.
     */
    public boolean isSleeProfileTable() {
        return plan == ADDRESS_PLAN_SLEE_PROFILE_TABLE;
    }

    /**
     * Determine if this AddressPlan object represents the SLEE_PROFILE address
     * plan value.
     *

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

     *     if (plan.isSleeProfile()) ...
     *

     * is interchangeable with the code:
     *

     *    if (plan == AddressPlan.SLEE_PROFILE) ...
     *

     * @return true if this object represents the SLEE_PROFILE address plan
     *       value, false otherwise.
     */
    public boolean isSleeProfile() {
        return plan == ADDRESS_PLAN_SLEE_PROFILE;
    }

    /**
     * Compare this address plan 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 plan value as this,
     *        false otherwise.
     */
    public boolean equals(Object obj) {
        if (obj == this) return true;

        return (obj instanceof AddressPlan) && ((AddressPlan)obj).plan == plan;
    }

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

    /**
     * Get the string representation of the address plan object.
     * @return the string representation of the address plan object.
     */
    public String toString() {
        switch (plan) {
            case ADDRESS_PLAN_NOT_PRESENT: return NOT_PRESENT_STRING;
            case ADDRESS_PLAN_UNDEFINED: return UNDEFINED_STRING;
            case ADDRESS_PLAN_IP: return IP_STRING;
            case ADDRESS_PLAN_MULTICAST: return MULTICAST_STRING;
            case ADDRESS_PLAN_UNICAST: return UNICAST_STRING;
            case ADDRESS_PLAN_E164: return E164_STRING;
            case ADDRESS_PLAN_AESA: return AESA_STRING;
            case ADDRESS_PLAN_URI: return URI_STRING;
            case ADDRESS_PLAN_NSAP: return NSAP_STRING;
            case ADDRESS_PLAN_SMTP: return SMTP_STRING;
            case ADDRESS_PLAN_X400: return X400_STRING;
            case ADDRESS_PLAN_SIP: return SIP_STRING;
            case ADDRESS_PLAN_E164_MOBILE: return E164_MOBILE_STRING;
            case ADDRESS_PLAN_H323: return H323_STRING;
            case ADDRESS_PLAN_GT: return GT_STRING;
            case ADDRESS_PLAN_SSN: return SSN_STRING;
            case ADDRESS_PLAN_SLEE_PROFILE_TABLE: return SLEE_PROFILE_TABLE_STRING;
            case ADDRESS_PLAN_SLEE_PROFILE: return SLEE_PROFILE_STRING;
            default: return "AddressPlan in Unknown and Invalid State";
        }
    }

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

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

    private final int plan;
}