FileDocCategorySizeDatePackage
ConfigFactory.javaAPI DocGlassfish v2 API26543Fri May 04 22:23:18 BST 2007com.sun.enterprise.management.config

ConfigFactory.java

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 * 
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License. You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [year]
 * [name of copyright owner]"
 * 
 * Contributor(s):
 * 
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
 
/*
 * $Header: /cvs/glassfish/admin/mbeanapi-impl/src/java/com/sun/enterprise/management/config/ConfigFactory.java,v 1.18 2007/05/05 05:23:17 tcfujii Exp $
 * $Revision: 1.18 $
 * $Date: 2007/05/05 05:23:17 $
 */
package com.sun.enterprise.management.config;

import java.util.Map;
import java.util.Set;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Properties;
import java.util.Collections;
import java.util.logging.Logger;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import java.lang.reflect.Method;

import javax.management.ObjectName;
import javax.management.MBeanServer;
import javax.management.AttributeList;
import javax.management.Attribute;
import javax.management.InstanceNotFoundException;

import com.sun.appserv.management.base.AMX;
import com.sun.appserv.management.base.Util;
import com.sun.appserv.management.base.Container;
import com.sun.appserv.management.base.QueryMgr;

import com.sun.appserv.management.DomainRoot;

import com.sun.appserv.management.util.misc.MapUtil;
import com.sun.appserv.management.util.misc.StringUtil;
import com.sun.appserv.management.util.misc.CollectionUtil;
import com.sun.appserv.management.util.stringifier.SmartStringifier;
import com.sun.appserv.management.util.misc.Output;

import com.sun.appserv.management.util.jmx.MBeanRegistrationListener;
import com.sun.appserv.management.util.jmx.JMXUtil;

import com.sun.appserv.management.config.DomainConfig;
import com.sun.appserv.management.config.PropertiesAccess;
import com.sun.appserv.management.config.CommonConfigKeys;

import com.sun.enterprise.management.support.ParamNameMapper;
import com.sun.enterprise.management.support.LoaderMBean;
import com.sun.enterprise.management.support.OldConfigTypes;
import com.sun.enterprise.management.support.OldTypeToJ2EETypeMapper;
import com.sun.enterprise.management.support.oldconfig.OldConfigProxies;
import com.sun.enterprise.management.support.oldconfig.OldResourcesMBean;


import com.sun.appserv.management.base.AMXDebug;

/**
	Factory for creating and removing configs.
 */
public class ConfigFactory
{
	private final ConfigFactoryCallback		mCallbacks;
	private ParamNameMapper	mParamNameMapper = null;
    private final Output    mDebug;
    
	/**
		Whenever a name is required during creation of a new config item,
		this key is what is used within the Map. Usually, however, the name
		is passed as the first argument in createXXX().
	 */
    protected final static String CONFIG_NAME_KEY = "Name";
    
		public 
	ConfigFactory( final ConfigFactoryCallback	callbacks) 
	{
		mCallbacks	= callbacks;
		
		mDebug  = AMXDebug.getInstance().getOutput( getClass().getName() );
	}
	
	    protected final MBeanServer
	 getMBeanServer()
	 {
	    return getCallbacks().getMBeanServer();
	 }
	
	 	protected final void
	debug(final Object o)
	{
        mDebug.println( o );
	}
	
	
		protected final ConfigFactoryCallback
	getCallbacks()
	{
		return( mCallbacks );
	}
	
	
		protected static void
	putNonNull(
		final Map<String,String>		m,
		final String	key,
		final Object	value)
	{
		if ( value != null )
		{
			m.put( key, "" + value );
		}
	}
	
		protected final String
	getConfigName()
	{
		return( getCallbacks().getConfigName() );
	}
	
	    protected final String
    getContainerName()
    {
        final String name   = getFactoryContainer().getName();
        if ( name == null )
        {
            throw new IllegalArgumentException();
        }
        return name;
    }
    
		protected final Logger
	getLogger()
	{
		return( getCallbacks().getLogger() );
	}

		protected final DomainRoot
	getDomainRoot()
	{
		return( getCallbacks().getDomainRoot() );
	}
	
		protected final QueryMgr
	getQueryMgr()
	{
		return( getDomainRoot().getQueryMgr() );
	}
	
		protected final DomainConfig
	getDomainConfig()
	{
		return( getDomainRoot().getDomainConfig() );
	}
	
		protected final Container
	getFactoryContainer()
	{
		return( getCallbacks().getFactoryContainer() );
	}
	
		protected final OldConfigProxies
	getOldConfigProxies()
	{
		return( getCallbacks().getOldConfigProxies() );
	}
	
	    protected final void
	remove(  )
	{
	    throw new RuntimeException( "form 'remove()' no longer supported" );
	}
	
        protected WaitForUnregistrationListener
    newWaitForUnregistrationListener( final ObjectName objectName )
    {
        WaitForUnregistrationListener   listener = null;
        try
        {
            final String name =
                "WaitForUnregistrationListener for " + JMXUtil.toString(objectName);
            
            listener    = new WaitForUnregistrationListener( name, objectName );
            listener.startListening();
            return listener;
        }
        catch( Exception e )
        {
            throw new RuntimeException( e );
        }
    }
    
    protected final class WaitForUnregistrationListener extends MBeanRegistrationListener
    {
        private final ObjectName        mTarget;
        private final long              mStart;
        private volatile long           mElapsed;
        private final CountDownLatch    mLatch;
        private final boolean           mWasUnregistered = false;

        private WaitForUnregistrationListener(
            final String name,
            final ObjectName objectName )
            throws InstanceNotFoundException, java.io.IOException
        {
            super( name, getMBeanServer(), null );
            mTarget     = objectName;
            mLatch      = new CountDownLatch(1);
            mStart      = System.currentTimeMillis();
            mElapsed    = -1;
        }
        
        public ObjectName   getTarget()     { return mTarget; }
        public long         getElapsed()    { return mElapsed; }
        protected void mbeanRegistered( final ObjectName objectName ) {}
        
            protected void
        mbeanUnregistered( final ObjectName objectName )
        {
            if ( mTarget.equals( objectName ) )
            {
                mElapsed    = System.currentTimeMillis() - mStart;
                mLatch.countDown();
                cleanup();
            }
        }
        
            private boolean
        await( final long timeoutMillis )
        {
            try
            {
                mLatch.await( timeoutMillis, TimeUnit.MILLISECONDS );
            }
            catch ( final InterruptedException e )
            {
            }
            
            final boolean   gotRegistration = mElapsed >= 0;
            if ( ! gotRegistration )
            {
                mElapsed    = timeoutMillis;
            }
            
            return gotRegistration;
        }
    
            public void
         waitForUnregistration( )
         {
            final long MAX_WAIT_MILLIS  = 15 * 1000;    // 15 seconds, very generous
            
            final boolean success = await( MAX_WAIT_MILLIS );
            
            if ( ! success )
            {
                throw new RuntimeException( "MBean " + JMXUtil.toString( getTarget() ) +
                " failed to unregister in " + getElapsed() + " ms, " + 
                    "isRegistered=" + getMBeanServer().isRegistered( getTarget() ) );
            }
            
            if ( getElapsed() > 1000 )
            {
               getLogger().info( "ConfigFactory.waitForUnregistration: MBean " +
                    JMXUtil.toString( getTarget() ) + " unregistered in " + getElapsed() + " ms" );
            }
         }
     }
     
	/** 
	    Remove the config represented by the AMX MBean with the
	    specified ObjectName.
	 */
		public final void
	remove( final ObjectName objectName )
	{
		if ( objectName == null )
		{
			throw new RuntimeException( new InstanceNotFoundException() );
		}
		
		final WaitForUnregistrationListener l  =
		    newWaitForUnregistrationListener( objectName );
		
		internalRemove( objectName );
		
		// do not return to caller until the MBean actually is unregistered!
		l.waitForUnregistration();
		
		getCallbacks().sendConfigRemovedNotification( objectName );
	}
	
		protected void
	removeByName( final String	name )
	{
		throw new UnsupportedOperationException( "removeByNameInternal" );
	}
	
		protected void
	internalRemove( final ObjectName	objectName )
	{
		removeByName( Util.getName( objectName ) );
	}
	
	/**
		Get the names of parameters that don't map via the default algorithms.
	 */
		protected Map<String,String>
	getParamNameOverrides()
	{
		// none, by default
		return( Collections.emptyMap() );
	}


		protected synchronized ParamNameMapper
	getParamNameMapper()
	{
		if ( mParamNameMapper == null )
		{
			mParamNameMapper	=
				new ParamNameMapper( getParamNameOverrides() );
		}
		
		return( mParamNameMapper );
	}
	
		protected boolean
	getBooleanOption( final Map<String,String> m, final String key )
	{
		boolean	value	= false;
		final Object	obj	= (m == null) ? null : m.get( key );
		if ( obj != null )
		{
			if ( obj instanceof Boolean )
			{
				value	= ((Boolean)obj).booleanValue();
			}
			else if ( obj instanceof String )
			{
				value	= Boolean.valueOf( (String)obj ).booleanValue();
			}
			else
			{
				throw new IllegalArgumentException( "Illegal value for Boolean " + key );
			}
			
		}
		return( value );
	}
	
		protected boolean
	requireValidReferences( final Map<String,String> options )
	{
		return ! getBooleanOption( options, CommonConfigKeys.IGNORE_MISSING_REFERENCES_KEY );
	}
	
	
	private final static Class[]	ATTRS_ONLY_SIG	=
		new Class[] { AttributeList.class };
	private final static Class[]	ATTRS_AND_PROPS_SIG	=
		new Class[] { AttributeList.class, Properties.class };
		
	
		protected final Method
	findAnyMethod( String methodName, final Class[] sig )
	{
		Method	m	= null;
		try
		{
			m	= this.getClass().getDeclaredMethod( methodName, sig );
		}
		catch( NoSuchMethodException e )
		{
			// ok, doesn't exist
		}
		
		return( m );
	}

		protected final ObjectName
	createChild( final Map<String,String>		params )
	{
		return( createNamedChild( null, params ) );
	}
	
	/**
		Create an "old" child MBean of the specified name using the specified parameters,
		and then create a corresponding AMX MBean.
		The parameters need not include the name; it will be added.
		<p>
		The parameters are first translated to an AttributeList and Properties. See
		translateParams() for details.
		
		@return the ObjectName of the new AMX MBean
		
	 */
		protected final ObjectName
	createNamedChild(
		final String	name,
		final Map<String,String>		params )
	{
		debug( "createNamedChild: " + name + ":\n{\n" + stringify( params ) + "\n}");
		
		final AttributeList		attrs	= new AttributeList();
		final Properties		props	= new Properties();
		
		translateParams( params, attrs, props );
		
		debug( "createNamedChild: translated attrs:\n{\n" + stringify( attrs ) + "\n}");
		if ( props.keySet().size() != 0 )
		{
		    debug( "createNamedChild: translated props:\n" + stringify( props ) );
		}
		
		ObjectName	oldObjectName		= null;
		boolean		propertiesHandled	= false;

		if ( findAnyMethod( "createOldChildConfig", ATTRS_AND_PROPS_SIG ) != null )
		{
		    debug( "createNamedChild: calling createOldChildConfig using attrs\n" +
		        stringify( attrs ) + "\nand props \n" + stringify( props ) );
		        
			oldObjectName	= createOldChildConfig( attrs, props );
			propertiesHandled = true;
		}
		else if ( findAnyMethod( "createOldChildConfig", ATTRS_ONLY_SIG ) != null )
		{
		    debug( "createNamedChild: calling createOldChildConfig using attrs\n" +
		        stringify( attrs ));
		        
			oldObjectName	= createOldChildConfig( attrs );
		}
		else
		{
			throw new UnsupportedOperationException( "createOldChildConfig" );
		}
		
		return finish( oldObjectName, propertiesHandled ? null : props );
	}
	   
	   
	     protected final ObjectName
	 finish(
	    final ObjectName oldObjectName,
	    final Properties props)
	 {
		assert( oldObjectName != null );
		debug( "createNamedChild: created: " + StringUtil.quote( oldObjectName.toString() ) );
		
		if ( ! getMBeanServer().isRegistered( oldObjectName ) )
		{
			throw new RuntimeException( new InstanceNotFoundException( oldObjectName.toString() ) );
		}
		
		// need the new AMX name to set properties
		final ObjectName	amxName	= getCallbacks().getLoader().sync( oldObjectName );
		debug( "createNamedChild: amx object name: " + StringUtil.quote( amxName.toString() ) );

		if ( props != null && props.size() > 0)
		{
		    debug( "Setting properties: " + stringify( props ) );
			setAllProperties( amxName, props );
		}

        // ensure that all sub-elements are also present
        getCallbacks().getLoader().waitAll();
        
		getCallbacks().sendConfigCreatedNotification( amxName );
		return( amxName );
	 }
	
	
	protected static final Set<String> NO_OPTIONAL_KEYS	= Collections.emptySet();
	/**
		  By default, assume there are no optional keys.
	 */
	    protected Set<String>
	getLegalOptionalCreateKeys()
	{
		return( NO_OPTIONAL_KEYS );
	}
	
		protected void
	checkLegalOptions( final Map<String,String> options )
	{
		if ( options != null )
		{
			final Set<String>	legalKeys	= getLegalOptionalCreateKeys();
			if ( legalKeys != null )
			{
			    debug( "Legal optional keys: " + stringify( legalKeys ) );
			}
			if ( legalKeys != null )
			{
				// remove all legal Attribute keys
				final Map<String,String> remaining	= new HashMap<String,String>( options );
				remaining.keySet().removeAll( legalKeys );
				
				final HashMap<String,String>	illegal	= new HashMap<String,String>();
				
				// find all non-properties; these are illegal
				final Iterator	iter	= remaining.keySet().iterator();
				while ( iter.hasNext() )
				{
					final String	key	= (String)iter.next();
					if ( ! key.startsWith( PropertiesAccess.PROPERTY_PREFIX ) )
					{
						illegal.put( key, remaining.get( key ) );
					}
				}

				if ( illegal.size() != 0 )
				{
				    final String msg    = "Illegal optional keys: " +
						MapUtil.toString( illegal, ",");
				
				    debug( msg );
					throw new IllegalArgumentException( msg );
				}
			}
		}
		else
		{
			// no options, so they're legal!
		}
	}

	/**
		Initialize a Map of parameters consisting of attributes and properties.
		First the optional parameters are inserted.
		Then the name/value pairs in the Object[] are added, possibly overwriting any
		values that were redundantly specified in the optional map.
		
		@param name
		@param required name/value pairings; even ones are keys, odd ones are values
		@param optional	additional name/value pairings
	 */
		protected final Map<String,String>
	initParams(
		final String	name,
		final String[]	required,
		final Map<String,String>		optional )
	{
		checkLegalOptions( optional );
		
		final Map<String,String>	m	= initParams( required, optional );

		if ( name == null || name.length() == 0 )
		{
			throw new IllegalArgumentException( "Illegal to have null or empty name" );
		}
		
		m.put( CONFIG_NAME_KEY, name );
		return( m );
	}
	
	/**
		Validate parameters.  The params Map contains all parameters, including
		Attributes and properties as 
		
		@param params
	 */
		protected final void
	validateParams( final Map<String,?> params )
	{
		for( final String name : params.keySet() )
		{
			final Object	value	= params.get( name );
			
			validateParam( name, value );
		}
	}
	
	/**
		Validate a parameter to a create() or createAbc() method.
		Subclasses should verify that the parameter name is legal,
		and optionally validate its value as well.
		
		@param name
		@param value
	 */
		protected final void
	validateParam(
		final String	name,
		final Object	value )
	{
		if ( name == null || name.length() == 0 )
		{
			throw new IllegalArgumentException( "parameter name must be non-null and non-empty" );
		}
		
		if ( name.startsWith( PropertiesAccess.PROPERTY_PREFIX ) )
		{
			if ( ! (value instanceof String) )
			{
				throw new IllegalArgumentException( "Property value must be string: " +
					name + ", class =" + value.getClass().getName() );
			}
		}
	}
	
	
	/**
		Initalize parameters, no name supplied.
	 */
		protected final Map<String,String>
	initParams(
		final String[]	required,
		final Map<String,String> optionalIn )
	{
	    // guarantee that all arguments are Strings;
	    // clients can be using old version of the interfaces and/or non-generic
	    // versions of Map
	    final Map<String,String> optional = MapUtil.toStringStringMap( optionalIn );
	    
		final Map<String,String>	m	= new HashMap<String,String>();
		
		if ( optional != null )
		{
			m.putAll( optional );
			m.remove( CommonConfigKeys.IGNORE_MISSING_REFERENCES_KEY );
		}
		if ( required != null )
		{
			m.putAll( MapUtil.newMap( required ) );
		}
		
		validateParams( m );
		
		return( m );
	}
	
	/**
		Initalize parameters, no name supplied.
	 */
		protected final Map<String,String>
	initParams( final Map<String,String>		optional )
	{
		return( initParams( (String[])null, optional ) );
	}
	
	
	/**
		Translate the Map of parameters to Attributes and Properties.  AttibuteNames
		are mapped to the underlying names.  Property names are not mapped, but the
		PROPERTY_PREFIX is stripped.
		
		@param paramsToTranslate
		@param attrsOut
		@param propsOut
	 */
		protected final void
	translateParams(
		final Map<String,String>			paramsToTranslate,
		final AttributeList	attrsOut,
		final Properties	propsOut )
	{
		final ParamNameMapper	mapper	= getParamNameMapper();
		
		final Iterator	iter	= paramsToTranslate.keySet().iterator();
		final String	propertyPrefix	= PropertiesAccess.PROPERTY_PREFIX;
		while( iter.hasNext() )
		{
			final String	key	= (String)iter.next();
			final Object	value	= paramsToTranslate.get( key );
			
			if ( key.startsWith( propertyPrefix ) )
			{
				final String	name	=
					key.substring( propertyPrefix.length(), key.length() );
					
				propsOut.put( name, value );
			}
			else
			{
				final String	translatedName	= mapper.mangleAttributeName( key );
				
				final Attribute	attr	= new Attribute( translatedName, value );
				
				attrsOut.add( attr );
			}
		}
	}

	/**
		Given a set of translated Attributes, create the appropriate type of child
		and return its "old" config ObjectName
		
		@param	translatedAttrs	
		@return ObjectName of newly-created child
	 */
		protected ObjectName
	createOldChildConfig(
		final AttributeList translatedAttrs )
	{
		throw new UnsupportedOperationException( "createOldChildConfig( AttributeList )" );
	}
	
	/**
		Given a set of translated Attributes, create the appropriate type of child
		and return its "old" config ObjectName
		
		@param	translatedAttrs	
		@param	props	Properties to also use	
		@return ObjectName of newly-created child
	 */
		protected ObjectName
	createOldChildConfig(
		final AttributeList translatedAttrs,
		final Properties	props )
	{
		throw new UnsupportedOperationException( "createOldChildConfig( AttributeList, Properties)" );
	}
	
		protected final void
	trace( Object o )
	{
	    debug( o );
	}
	
		protected String
	stringify( Object o )
	{
		return( SmartStringifier.toString( o ) );
	}
	
	/**
		Given a set of translated Attributes, create the appropriate type of child
		and return its "old" config ObjectName

		@param	oldChildType
		@param	translatedAttrs	
		@return ObjectName of newly-created child
	 */
		protected ObjectName
	createOldChildByType( 
		final String		oldChildType, 
		final AttributeList translatedAttrs )
	{
		throw new UnsupportedOperationException( "createOldChildByType( String, AttributeList )" );
	}
	
	/**
		Given a set of translated Attributes, create the appropriate type of child
		and return its "old" config ObjectName

		@param	oldChildType
		@param	translatedAttrs	
		@param	props	Properties to also use	
		@return ObjectName of newly-created child
	 */
		protected ObjectName
	createOldChildByType(
		final String		oldChildType, 
		final AttributeList translatedAttrs,
		final Properties	props )
	{
		throw new UnsupportedOperationException( "createOldChildByType( String, AttributeList, Properties )" );
	}
	
		private static final Class[] TYPE_AND_ATTRS_AND_PROPS_SIG = 
		new Class[] { String.class, AttributeList.class, Properties.class };

	private static final Class[] TYPE_AND_ATTRS_SIG = 
		new Class[] { String.class, AttributeList.class };

	
		protected final ObjectName
	createChildByType(
		final String childJ2EEType,
		final Map<String,String> params )
	{
		//assert getChildInfos().contains (childJ2EEType) : 
			//childJ2EEType + " is not a valid child of " + getSelfJ2EEType ();

		final String oldType = getOldTypeToJ2EETypeMapper().j2eeTypeToOldType( childJ2EEType );

		assert oldType != null;

		final Properties	props	= new Properties();
		final AttributeList	attrs	= new AttributeList();

		translateParams( params, attrs, props );

		ObjectName	oldObjectName		= null;
		boolean		propertiesHandled	= false;

		if ( findAnyMethod( "createOldChildByType", TYPE_AND_ATTRS_AND_PROPS_SIG ) != null )
		{
			oldObjectName	= createOldChildByType( oldType, attrs, props );
			propertiesHandled = true;
		}
		else if ( findAnyMethod( "createOldChildByType", TYPE_AND_ATTRS_SIG ) != null )
		{
			oldObjectName	= createOldChildByType( oldType, attrs );
		}
		else if ( findAnyMethod( "createOldChildByType", ATTRS_ONLY_SIG ) != null )
		{
			oldObjectName	= createOldChildConfig( attrs );
		}
		else
		{
			throw new UnsupportedOperationException( "createOldChildByType" );
		}
		
		assert( oldObjectName != null );
		debug( "createChildByType: oldObjectName: " + StringUtil.quote( oldObjectName.toString() ) );

		// need the new AMX name to set properties
		final ObjectName	amxName	= getCallbacks().getLoader().sync( oldObjectName );
		debug( "createChildByType: amx object name: " + StringUtil.quote( amxName.toString() ) );

		if ( props.size() > 0 && !propertiesHandled )
		{
			setAllProperties( amxName, props );
		}

		getCallbacks().sendConfigCreatedNotification( amxName );
		return( amxName );
	}

	


		protected final void
	setAllProperties(
		final ObjectName	amxObjectName,
		final Properties	props )
	{
		final PropertiesAccess	proxy	= PropertiesAccess.class.cast(
		    getCallbacks().getProxyFactory().getProxy( amxObjectName, AMX.class) );
		
		setAllProperties( proxy, props );
	}
	
	/**
		For each property in props , call setPropertyValue()
	 */
		protected final void
	setAllProperties(
		final PropertiesAccess	target,
		final Properties		props )
	{
		final Iterator	iter	= props.keySet().iterator();
		
		while ( iter.hasNext() )
		{
			final String	key	= (String)iter.next();
			
			target.setPropertyValue( key, (String)props.get( key ) );
		}
	}


		protected OldTypeToJ2EETypeMapper 
	getOldTypeToJ2EETypeMapper()
	{
		return OldConfigTypes.getInstance();
	}
	
	

        
		protected ObjectName
	syncNewAMXMBeanWithOld(ObjectName oldObjectName)
	{
		final ObjectName amxName = getCallbacks().getLoader().sync( oldObjectName );
		
		getCallbacks().sendConfigCreatedNotification( amxName );
		return amxName;
	}
	
	
	
		final OldResourcesMBean
	getOldResourcesMBean()
	{
		return( getOldConfigProxies().getOldResourcesMBean( ) );
	}
	
		protected static String
	quote( Object o )
	{
		return( StringUtil.quote( o.toString() ) );
	}
	
	
	
		protected void
	checkNonEmptyString( final String s, final String name )
	{
		if (  s == null ||  s.length() == 0 )
		{
			throw new IllegalArgumentException( "Parameter may not be null or empty: " +
				quote( name ) );
		}
	}
		
	    protected final Object
	getValue( final Map<String,String> m, final String key )
	{
	    return (m == null) ? null : m.get( key );
	}
	
	    protected final String
	getString( final Map<String,String> m, final String key )
	{
	    return (String)getValue( m, key );
	}
	
	    protected final Boolean
	getBoolean(
	    final Map<String,String> m,
	    final String             key,
	    final Boolean            defaultValue )
	{
	    final Object    value   = getValue( m, key );
	    
	    return (value == null) ? defaultValue : Boolean.valueOf( "" + value );
	}
	
	
		protected boolean
	sleepMillis( final long millis )
	{
		boolean	interrupted	= false;
		
		try
		{
			Thread.sleep( millis );
		}
		catch( InterruptedException e )
		{
			Thread.interrupted();
			interrupted	= true;
		}
		
		return interrupted;
	}
	
	    protected AMX
	requireItem(
	    final String j2eeType,
	    final String name )
	{
	    final AMX item  = getFactoryContainer().getContainee( j2eeType, name );
	    if ( item == null )
	    {
	        throw new IllegalArgumentException( j2eeType + "=" + name );
	    }
	    return item;
	}
}