Skip to Content.
Sympa Menu

notify-dpml - r1513 - in trunk/main: depot/core/src/main/net/dpml/depot depot/tools/builder/src/main/net/dpml/tools/tasks metro/component/src/main/net/dpml/component metro/model/src/main/net/dpml/metro metro/model/src/main/net/dpml/metro/data metro/model/src/main/net/dpml/metro/info metro/model/src/test/net/dpml/metro/info/test metro/runtime/src/main/net/dpml/metro/builder metro/runtime/src/main/net/dpml/metro/runtime metro/state/api/src/main/net/dpml/state metro/state/impl metro/state/impl/src/main/net/dpml/state/impl metro/state/impl/src/test/net/dpml/state/test metro/test metro/test/etc/data metro/test/src/main/net/dpml/test metro/test/src/test/net/dpml/test/runtime transit/core/src/main/net/dpml/lang transit/core/src/main/net/dpml/transit transit/core/src/main/net/dpml/transit/monitor transit/core/src/main/net/dpml/util transit/tools/src/main/net/dpml/transit/tools

notify-dpml AT lists.ibiblio.org

Subject: DPML Notify

List archive

Chronological Thread  
  • From: mcconnell at BerliOS <mcconnell AT mail.berlios.de>
  • To: notify-dpml AT lists.ibiblio.org
  • Subject: r1513 - in trunk/main: depot/core/src/main/net/dpml/depot depot/tools/builder/src/main/net/dpml/tools/tasks metro/component/src/main/net/dpml/component metro/model/src/main/net/dpml/metro metro/model/src/main/net/dpml/metro/data metro/model/src/main/net/dpml/metro/info metro/model/src/test/net/dpml/metro/info/test metro/runtime/src/main/net/dpml/metro/builder metro/runtime/src/main/net/dpml/metro/runtime metro/state/api/src/main/net/dpml/state metro/state/impl metro/state/impl/src/main/net/dpml/state/impl metro/state/impl/src/test/net/dpml/state/test metro/test metro/test/etc/data metro/test/src/main/net/dpml/test metro/test/src/test/net/dpml/test/runtime transit/core/src/main/net/dpml/lang transit/core/src/main/net/dpml/transit transit/core/src/main/net/dpml/transit/monitor transit/core/src/main/net/dpml/util transit/tools/src/main/net/dpml/transit/tools
  • Date: Mon, 19 Jun 2006 05:27:40 +0200

Author: mcconnell
Date: 2006-06-19 05:26:47 +0200 (Mon, 19 Jun 2006)
New Revision: 1513

Added:

trunk/main/metro/component/src/main/net/dpml/component/ProviderListener.java
trunk/main/metro/component/src/main/net/dpml/component/Status.java
trunk/main/metro/component/src/main/net/dpml/component/StatusEvent.java
trunk/main/transit/core/src/main/net/dpml/util/EventHandler.java
trunk/main/transit/core/src/main/net/dpml/util/EventQueue.java
trunk/main/transit/core/src/main/net/dpml/util/UnicastEventSource.java
Removed:

trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/InstanceInvocationHandler.java

trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultStateListener.java
trunk/main/metro/test/src/main/net/dpml/test/ObserverComponent.java
trunk/main/metro/test/src/test/net/dpml/test/runtime/ObserverTestCase.java
Modified:
trunk/main/depot/core/src/main/net/dpml/depot/Main.java

trunk/main/depot/tools/builder/src/main/net/dpml/tools/tasks/JUnitTestTask.java
trunk/main/metro/component/src/main/net/dpml/component/Component.java
trunk/main/metro/component/src/main/net/dpml/component/Composition.java
trunk/main/metro/component/src/main/net/dpml/component/InitialContext.java

trunk/main/metro/component/src/main/net/dpml/component/LocalEventProducer.java
trunk/main/metro/component/src/main/net/dpml/component/Provider.java
trunk/main/metro/model/src/main/net/dpml/metro/ComponentHandler.java
trunk/main/metro/model/src/main/net/dpml/metro/ComponentModel.java
trunk/main/metro/model/src/main/net/dpml/metro/ComponentModelManager.java
trunk/main/metro/model/src/main/net/dpml/metro/ContextModel.java
trunk/main/metro/model/src/main/net/dpml/metro/PartsManager.java

trunk/main/metro/model/src/main/net/dpml/metro/data/DeploymentDirective.java
trunk/main/metro/model/src/main/net/dpml/metro/info/CategoryDescriptor.java
trunk/main/metro/model/src/main/net/dpml/metro/info/CollectionPolicy.java
trunk/main/metro/model/src/main/net/dpml/metro/info/Composite.java
trunk/main/metro/model/src/main/net/dpml/metro/info/ContextDescriptor.java
trunk/main/metro/model/src/main/net/dpml/metro/info/Descriptor.java
trunk/main/metro/model/src/main/net/dpml/metro/info/InfoDescriptor.java
trunk/main/metro/model/src/main/net/dpml/metro/info/LifestylePolicy.java
trunk/main/metro/model/src/main/net/dpml/metro/info/Priority.java
trunk/main/metro/model/src/main/net/dpml/metro/info/ThreadSafePolicy.java
trunk/main/metro/model/src/main/net/dpml/metro/info/Type.java

trunk/main/metro/model/src/test/net/dpml/metro/info/test/InfoDescriptorTestCase.java

trunk/main/metro/runtime/src/main/net/dpml/metro/builder/ComponentDecoder.java

trunk/main/metro/runtime/src/main/net/dpml/metro/builder/ComponentTypeDecoder.java

trunk/main/metro/runtime/src/main/net/dpml/metro/builder/ComponentTypeEncoder.java

trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/ComponentController.java

trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/CompositionClassLoader.java

trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/CompositionController.java

trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/ContextInvocationHandler.java

trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultComponentHandler.java

trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultComponentModel.java

trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultComposition.java

trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultContextModel.java

trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultPartsManager.java

trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultProvider.java

trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/PartsInvocationHandler.java

trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/StandardLogger.java

trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/UnicastEventSource.java
trunk/main/metro/state/api/src/main/net/dpml/state/StateMachine.java
trunk/main/metro/state/impl/build.xml

trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultStateMachine.java

trunk/main/metro/state/impl/src/test/net/dpml/state/test/DefaultStateMachineTestCase.java
trunk/main/metro/test/build.xml
trunk/main/metro/test/etc/data/logging.properties

trunk/main/metro/test/src/test/net/dpml/test/runtime/ComponentModelTestCase.java
trunk/main/metro/test/src/test/net/dpml/test/runtime/ProviderTestCase.java

trunk/main/metro/test/src/test/net/dpml/test/runtime/WeakCollectionPolicyTestCase.java
trunk/main/transit/core/src/main/net/dpml/lang/Part.java
trunk/main/transit/core/src/main/net/dpml/lang/PartDecoder.java
trunk/main/transit/core/src/main/net/dpml/transit/DefaultCacheModel.java
trunk/main/transit/core/src/main/net/dpml/transit/DefaultCodeBaseModel.java
trunk/main/transit/core/src/main/net/dpml/transit/DefaultHostModel.java
trunk/main/transit/core/src/main/net/dpml/transit/DefaultLayoutModel.java

trunk/main/transit/core/src/main/net/dpml/transit/DefaultLayoutRegistryModel.java
trunk/main/transit/core/src/main/net/dpml/transit/DefaultModel.java
trunk/main/transit/core/src/main/net/dpml/transit/DefaultProxyModel.java
trunk/main/transit/core/src/main/net/dpml/transit/DefaultTransitModel.java

trunk/main/transit/core/src/main/net/dpml/transit/SecuredTransitContext.java
trunk/main/transit/core/src/main/net/dpml/transit/StandardLayoutModel.java
trunk/main/transit/core/src/main/net/dpml/transit/Transit.java

trunk/main/transit/core/src/main/net/dpml/transit/monitor/LoggingAdapter.java
trunk/main/transit/tools/src/main/net/dpml/transit/tools/PluginTask.java
Log:
move part management from the component model down into the provider

Modified: trunk/main/depot/core/src/main/net/dpml/depot/Main.java
===================================================================
--- trunk/main/depot/core/src/main/net/dpml/depot/Main.java 2006-06-08
08:10:50 UTC (rev 1512)
+++ trunk/main/depot/core/src/main/net/dpml/depot/Main.java 2006-06-19
03:26:47 UTC (rev 1513)
@@ -232,7 +232,7 @@
Transit transit = Transit.getInstance( model );
setupMonitors( transit, (Adapter) logger );

- Part part = Part.load( uri );
+ Part part = Part.load( uri, true );
m_plugin =
part.instantiate(
new Object[]

Modified:
trunk/main/depot/tools/builder/src/main/net/dpml/tools/tasks/JUnitTestTask.java
===================================================================
---
trunk/main/depot/tools/builder/src/main/net/dpml/tools/tasks/JUnitTestTask.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/depot/tools/builder/src/main/net/dpml/tools/tasks/JUnitTestTask.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -40,6 +40,7 @@
import org.apache.tools.ant.types.Environment;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.Commandline;

/**
* JUnit test execution.
@@ -124,6 +125,11 @@
*/
public static final String TEST_EXCLUDES_VALUE = "**/Abstract*.java,
**/AllTest*.java";

+ /**
+ * the key for the exclude pattern for test cases
+ */
+ public static final String VERBOSE_KEY = "project.test.verbose";
+
private File m_source;
private String m_classPathRef;
private Path m_classPath;
@@ -266,6 +272,13 @@
getBooleanProperty(
HALT_ON_FAILURE_KEY, HALT_ON_FAILURE_VALUE ) );

+ String verbose = getContext().getProperty( "project.test.verbose" );
+ if( null != verbose )
+ {
+ Commandline.Argument arg = junit.createJvmarg();
+ arg.setValue( "-verbose:" + verbose );
+ }
+
final File reports = getContext().getTargetReportsTestDirectory();
mkDir( reports );


Modified:
trunk/main/metro/component/src/main/net/dpml/component/Component.java
===================================================================
--- trunk/main/metro/component/src/main/net/dpml/component/Component.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/metro/component/src/main/net/dpml/component/Component.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -33,14 +33,14 @@
public interface Component extends Remote, Commissionable
{
/**
- * Return a handler capable of supporting the requested service.
- * @param service the service descriptor
- * @return a component matching the requested service
- * @exception ServiceNotFoundException if no component could found
- * @exception RemoteException if a remote I/O occurs
+ * Return a provider of an instance of the component.
+ * @return the instance provider
+ * @exception InvocationTargetException if a target invocation error
occurs
+ * @exception ControlException if a controller related error occurs
+ * @exception RemoteException if a remote exception occurs
*/
- Component lookup( Service service ) throws ServiceNotFoundException,
RemoteException;
-
+ Provider getProvider() throws ControlException,
InvocationTargetException, RemoteException;
+
/**
* Return true if this handler is a candidate for the supplied service
definition.
* @param service the service descriptor
@@ -77,16 +77,5 @@
*/
int size() throws RemoteException;

- /**
- * Return a reference to a instance of the component handled by the
handler.
- * @return the instance holder
- * @exception InvocationTargetException if the component instantiation
process
- * is on demand and an target invocation error occurs
- * @exception ControlException if the component could not be established
due to a controller
- * related error
- * @exception RemoteException if a remote exception occurs
- */
- Provider getProvider() throws ControlException,
InvocationTargetException, RemoteException;
-
}


Modified:
trunk/main/metro/component/src/main/net/dpml/component/Composition.java
===================================================================
--- trunk/main/metro/component/src/main/net/dpml/component/Composition.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/metro/component/src/main/net/dpml/component/Composition.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -20,6 +20,7 @@

import java.io.IOException;
import java.net.URI;
+import java.lang.ref.WeakReference;

import net.dpml.lang.Classpath;
import net.dpml.lang.Info;
@@ -38,7 +39,7 @@
private final Directive m_directive;
private final Controller m_controller;

- private Model m_model;
+ private transient WeakReference m_model;

/**
* Creation of a new abstract composition instance.
@@ -110,22 +111,28 @@
*/
public Model getModel()
{
- if( null == m_model )
+ if( null != m_model )
{
- try
+ Model model = (Model) m_model.get();
+ if( null != model )
{
- m_model = m_controller.createModel( this );
+ return model;
}
- catch( Throwable e )
- {
- URI uri = m_controller.getURI();
- final String error =
- "Unexpected error while attempting to create a component
model."
- + "\nDirective: " + m_directive;
- throw new ControlRuntimeException( uri, error, e );
- }
}
- return m_model;
+ try
+ {
+ Model model = m_controller.createModel( this );
+ m_model = new WeakReference( model );
+ return model;
+ }
+ catch( Throwable e )
+ {
+ URI uri = m_controller.getURI();
+ final String error =
+ "Unexpected error while attempting to create a component
model."
+ + "\nDirective: " + m_directive;
+ throw new ControlRuntimeException( uri, error, e );
+ }
}

/**

Modified:
trunk/main/metro/component/src/main/net/dpml/component/InitialContext.java
===================================================================
---
trunk/main/metro/component/src/main/net/dpml/component/InitialContext.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/component/src/main/net/dpml/component/InitialContext.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,4 +1,5 @@
/*
+/*
* Copyright (c) 2005 Stephen J. McConnell
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -254,11 +255,9 @@
*/
public void dispose()
{
- getInternalLogger().debug( "initiating context disposal" );
ControllerDisposalEvent event = new ControllerDisposalEvent( this );
enqueueEvent( event, false );
super.dispose();
- getInternalLogger().debug( "disposed" );
}


//----------------------------------------------------------------------------

Modified:
trunk/main/metro/component/src/main/net/dpml/component/LocalEventProducer.java
===================================================================
---
trunk/main/metro/component/src/main/net/dpml/component/LocalEventProducer.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/component/src/main/net/dpml/component/LocalEventProducer.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -127,7 +127,6 @@
}
synchronized( m_lock )
{
- m_logger.debug( "adding context listener" );
m_listeners.put( listener, null );
}
startEventDispatchThread( m_logger );
@@ -145,7 +144,6 @@
}
synchronized( m_lock )
{
- m_logger.debug( "removing context listener" );
m_listeners.remove( listener );
}
}

Modified: trunk/main/metro/component/src/main/net/dpml/component/Provider.java
===================================================================
--- trunk/main/metro/component/src/main/net/dpml/component/Provider.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/metro/component/src/main/net/dpml/component/Provider.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -27,6 +27,8 @@
import net.dpml.state.UnknownOperationException;
import net.dpml.state.UnknownTransitionException;

+import net.dpml.job.Commissionable;
+
/**
* Provider holder.
*
@@ -36,6 +38,28 @@
public interface Provider extends Remote
{
/**
+ * Return a parent provider.
+ * @return the parent provider or null if this is a root provider
+ * @exception RemoteException if a remote I/O occurs
+ */
+ Provider getParent() throws RemoteException;
+
+ /**
+ * Return the current status of the provider.
+ * @return the provider status
+ */
+ Status getStatus() throws RemoteException;
+
+ /**
+ * Return a provider capable of supporting the requested service.
+ * @param service the service descriptor
+ * @return a component matching the requested service
+ * @exception ServiceNotFoundException if no component could found
+ * @exception RemoteException if a remote I/O occurs
+ */
+ Provider lookup( Service service ) throws ServiceNotFoundException,
RemoteException;
+
+ /**
* Returns the current state of the control.
* @return the current runtime state
* @exception RemoteException if a remote I/O error occurs
@@ -102,4 +126,5 @@
Object invoke( String method, Object[] args )
throws UnknownOperationException, InvocationTargetException,
IllegalStateException, RemoteException;
+
}

Added:
trunk/main/metro/component/src/main/net/dpml/component/ProviderListener.java
===================================================================
---
trunk/main/metro/component/src/main/net/dpml/component/ProviderListener.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/component/src/main/net/dpml/component/ProviderListener.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2005 Stephen J. McConnell
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.component;
+
+import java.util.EventListener;
+
+import net.dpml.state.StateListener;
+
+/**
+ * An interface implementation by controller concerned with or responsible
+ * for handling changes in a local runtime directory context.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface ProviderListener extends StateListener
+{
+ /**
+ * Notify the listener of a change to the provider status.
+ *
+ * @param event the status change event
+ */
+ void statusChanged( StatusEvent event );
+
+}

Added: trunk/main/metro/component/src/main/net/dpml/component/Status.java
===================================================================
--- trunk/main/metro/component/src/main/net/dpml/component/Status.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/metro/component/src/main/net/dpml/component/Status.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.component;
+
+import net.dpml.lang.Enum;
+
+/**
+ * Provider deployment status enumeration.
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public final class Status extends Enum
+{
+ //-------------------------------------------------------------------
+ // static
+ //-------------------------------------------------------------------
+
+ /**
+ * Serial version identifier.
+ */
+ static final long serialVersionUID = 1L;
+
+ /**
+ * The provider has been instantiated but remains uncommissioned.
+ */
+ public static final Status INSTANTIATED = new Status( "instantiated" );
+
+ /**
+ * The provider is in the process of commissioning its internal structure
+ * following which the provider will attempt to establish a instance value
+ * and transition to AVAILABLE.
+ */
+ public static final Status COMMISSIONING = new Status( "commissioning" );
+
+ /**
+ * The provider has successfully established the target instance.
+ */
+ public static final Status AVAILABLE = new Status( "available" );
+
+ /**
+ * The provider is in the process of decommissioning it's internal parts.
+ */
+ public static final Status DECOMMISSIONING = new Status(
"decommissioning" );
+
+ /**
+ * The provider is not longer available.
+ */
+ public static final Status DISPOSED = new Status( "disposed" );
+
+ /**
+ * Array of static status enumeration values.
+ */
+ private static final Status[] ENUM_VALUES =
+ new Status[]{INSTANTIATED, COMMISSIONING, AVAILABLE, DECOMMISSIONING,
DISPOSED};
+
+ /**
+ * Returns an array of activation enum values.
+ * @return the activation policies array
+ */
+ public static Status[] values()
+ {
+ return ENUM_VALUES;
+ }
+
+ /**
+ * Internal constructor.
+ * @param label the enumeration label.
+ */
+ private Status( String label )
+ {
+ super( label );
+ }
+
+ /**
+ * Parse the supplied name.
+ * @param value the value to parse
+ * @return the collection policy
+ */
+ public static Status parse( String value )
+ {
+ if( INSTANTIATED.getName().equalsIgnoreCase( value ) )
+ {
+ return INSTANTIATED;
+ }
+ else if( COMMISSIONING.getName().equalsIgnoreCase( value ) )
+ {
+ return COMMISSIONING;
+ }
+ else if( AVAILABLE.getName().equalsIgnoreCase( value ) )
+ {
+ return AVAILABLE;
+ }
+ else if( DECOMMISSIONING.getName().equalsIgnoreCase( value ) )
+ {
+ return DECOMMISSIONING;
+ }
+ else if( DISPOSED.getName().equalsIgnoreCase( value ) )
+ {
+ return DISPOSED;
+ }
+ else
+ {
+ final String error =
+ "Unrecognized status argument [" + value + "]";
+ throw new IllegalArgumentException( error );
+ }
+ }
+}

Added: trunk/main/metro/component/src/main/net/dpml/component/StatusEvent.java
===================================================================
--- trunk/main/metro/component/src/main/net/dpml/component/StatusEvent.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/metro/component/src/main/net/dpml/component/StatusEvent.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.component;
+
+import java.util.EventObject;
+
+/**
+ * Event triggered as a result of change to the value of a context entry.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class StatusEvent extends EventObject
+{
+ /**
+ * Serial version identifier.
+ */
+ static final long serialVersionUID = 1L;
+
+ private final Status m_new;
+ private final Status m_old;
+
+ /**
+ * Construct a new <code>StatusEvent</code>.
+ *
+ * @param source the source provider
+ * @param oldStatus the initial provider status
+ * @param newStatus the new provider status
+ */
+ public StatusEvent( final Provider source, Status oldStatus, Status
newStatus )
+ {
+ super( source );
+
+ m_new = newStatus;
+ m_old = oldStatus;
+ }
+
+ /**
+ * Return the prior status value.
+ * @return the provider status prior to the status change
+ */
+ public Status getOldStatus()
+ {
+ return m_old;
+ }
+
+ /**
+ * Return the status value.
+ * @return the provider status
+ */
+ public Status getNewStatus()
+ {
+ return m_new;
+ }
+
+ /**
+ * Return the component model that initiating the event.
+ * @return the source model
+ */
+ public Provider getProvider()
+ {
+ return (Provider) super.getSource();
+ }
+}
+

Modified: trunk/main/metro/model/src/main/net/dpml/metro/ComponentHandler.java
===================================================================
--- trunk/main/metro/model/src/main/net/dpml/metro/ComponentHandler.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/metro/model/src/main/net/dpml/metro/ComponentHandler.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,5 +1,5 @@
/*
- * Copyright 2005 Stephen J. McConnell.
+ * Copyright 2005-2006 Stephen J. McConnell.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -49,11 +49,5 @@
*/
ComponentModelManager getComponentManager() throws RemoteException;

- /**
- * Return the internal parts manager.
- * @return the parts manager
- * @exception RemoteException if a remote I/O error occurs
- */
- PartsManager getPartsManager() throws RemoteException;
}


Modified: trunk/main/metro/model/src/main/net/dpml/metro/ComponentModel.java
===================================================================
--- trunk/main/metro/model/src/main/net/dpml/metro/ComponentModel.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/metro/model/src/main/net/dpml/metro/ComponentModel.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,5 +1,5 @@
/*
- * Copyright 2005 Stephen J. McConnell.
+ * Copyright 2005-2006 Stephen J. McConnell.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -70,6 +70,14 @@
Classpath getClasspath() throws RemoteException;

/**
+ * Return the component thread-safe status.
+ *
+ * @return the threadsafe status
+ * @exception RemoteException if a remote exception occurs
+ */
+ boolean isThreadSafe() throws RemoteException;
+
+ /**
* Return the component lifestyle policy.
*
* @return the lifestyle policy value

Modified:
trunk/main/metro/model/src/main/net/dpml/metro/ComponentModelManager.java
===================================================================
--- trunk/main/metro/model/src/main/net/dpml/metro/ComponentModelManager.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/metro/model/src/main/net/dpml/metro/ComponentModelManager.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,5 +1,5 @@
/*
- * Copyright 2005 Stephen J. McConnell.
+ * Copyright 2005-2006 Stephen J. McConnell.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -63,6 +63,6 @@
* @param policy the collection policy value
* @exception RemoteException if a remote I/O error occurs
*/
- void setCollectionPolicy( CollectionPolicy policy ) throws
RemoteException;
+ //void setCollectionPolicy( CollectionPolicy policy ) throws
RemoteException;
}


Modified: trunk/main/metro/model/src/main/net/dpml/metro/ContextModel.java
===================================================================
--- trunk/main/metro/model/src/main/net/dpml/metro/ContextModel.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/metro/model/src/main/net/dpml/metro/ContextModel.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,5 +1,5 @@
/*
- * Copyright 2005 Stephen J. McConnell.
+ * Copyright 2005-2006 Stephen J. McConnell.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

Modified: trunk/main/metro/model/src/main/net/dpml/metro/PartsManager.java
===================================================================
--- trunk/main/metro/model/src/main/net/dpml/metro/PartsManager.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/metro/model/src/main/net/dpml/metro/PartsManager.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,5 +1,5 @@
/*
- * Copyright 2005 Stephen J. McConnell.
+ * Copyright 2005-2006 Stephen J. McConnell.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,6 +46,12 @@
ComponentHandler getComponentHandler( String key ) throws
UnknownKeyException;

/**
+ * Return an array of all component handlers.
+ * @return the local component handler array
+ */
+ ComponentHandler[] getComponentHandlers();
+
+ /**
* Return an array of component handlers assignable to the supplied
service.
* @param service the service class to match against
* @return the local component handler array

Modified:
trunk/main/metro/model/src/main/net/dpml/metro/data/DeploymentDirective.java
===================================================================
---
trunk/main/metro/model/src/main/net/dpml/metro/data/DeploymentDirective.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/model/src/main/net/dpml/metro/data/DeploymentDirective.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,5 +1,5 @@
/*
- * Copyright 2004 Stephen J. McConnell.
+ * Copyright 2004-2006 Stephen J. McConnell.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -114,7 +114,7 @@
}
else
{
- m_name = null;
+ throw new NullPointerException( "name" );
}
}


Modified:
trunk/main/metro/model/src/main/net/dpml/metro/info/CategoryDescriptor.java
===================================================================
---
trunk/main/metro/model/src/main/net/dpml/metro/info/CategoryDescriptor.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/model/src/main/net/dpml/metro/info/CategoryDescriptor.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,6 +1,5 @@
/*
* Copyright 2004 Stephen J. McConnell.
- * Copyright 1999-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

Modified:
trunk/main/metro/model/src/main/net/dpml/metro/info/CollectionPolicy.java
===================================================================
--- trunk/main/metro/model/src/main/net/dpml/metro/info/CollectionPolicy.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/metro/model/src/main/net/dpml/metro/info/CollectionPolicy.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,6 +1,5 @@
/*
* Copyright 2004 Stephen J. McConnell.
- * Copyright 1999-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

Modified: trunk/main/metro/model/src/main/net/dpml/metro/info/Composite.java
===================================================================
--- trunk/main/metro/model/src/main/net/dpml/metro/info/Composite.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/metro/model/src/main/net/dpml/metro/info/Composite.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,6 +1,5 @@
/*
* Copyright 2004 Stephen J. McConnell.
- * Copyright 1999-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

Modified:
trunk/main/metro/model/src/main/net/dpml/metro/info/ContextDescriptor.java
===================================================================
---
trunk/main/metro/model/src/main/net/dpml/metro/info/ContextDescriptor.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/model/src/main/net/dpml/metro/info/ContextDescriptor.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,6 +1,5 @@
/*
* Copyright 2004 Stephen J. McConnell.
- * Copyright 1999-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

Modified: trunk/main/metro/model/src/main/net/dpml/metro/info/Descriptor.java
===================================================================
--- trunk/main/metro/model/src/main/net/dpml/metro/info/Descriptor.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/metro/model/src/main/net/dpml/metro/info/Descriptor.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,6 +1,5 @@
/*
* Copyright 2004 Stephen J. McConnell.
- * Copyright 1999-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

Modified:
trunk/main/metro/model/src/main/net/dpml/metro/info/InfoDescriptor.java
===================================================================
--- trunk/main/metro/model/src/main/net/dpml/metro/info/InfoDescriptor.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/metro/model/src/main/net/dpml/metro/info/InfoDescriptor.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,6 +1,5 @@
/*
* Copyright 2004 Stephen J. McConnell.
- * Copyright 1999-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -167,14 +166,7 @@

if( lifestyle == null )
{
- if( threadsafe == ThreadSafePolicy.TRUE )
- {
- m_lifestyle = LifestylePolicy.SINGLETON;
- }
- else
- {
- m_lifestyle = LifestylePolicy.THREAD;
- }
+ m_lifestyle = LifestylePolicy.SYSTEM;
}
else
{
@@ -300,6 +292,16 @@
}

/**
+ * Ruturn the thread-safe status.
+ *
+ * @return the thread-safe status
+ */
+ public boolean isThreadSafe()
+ {
+ return m_threadsafe.equals( ThreadSafePolicy.TRUE );
+ }
+
+ /**
* Ruturn the thread-safe policy value.
*
* @return the thread-safe policy value

Modified:
trunk/main/metro/model/src/main/net/dpml/metro/info/LifestylePolicy.java
===================================================================
--- trunk/main/metro/model/src/main/net/dpml/metro/info/LifestylePolicy.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/metro/model/src/main/net/dpml/metro/info/LifestylePolicy.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,6 +1,5 @@
/*
* Copyright 2004-2006 Stephen J. McConnell.
- * Copyright 1999-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,10 +46,15 @@
public static final LifestylePolicy SINGLETON = new LifestylePolicy(
"singleton" );

/**
+ * Singleton lifestyle policy.
+ */
+ public static final LifestylePolicy SYSTEM = new LifestylePolicy(
"system" );
+
+ /**
* Array of static activation policy enumeration values.
*/
private static final LifestylePolicy[] ENUM_VALUES =
- new LifestylePolicy[]{TRANSIENT, THREAD, SINGLETON};
+ new LifestylePolicy[]{TRANSIENT, THREAD, SINGLETON, SYSTEM};

/**
* Returns an array of activation enum values.
@@ -100,6 +104,10 @@
{
return SINGLETON;
}
+ else if( value.equalsIgnoreCase( "system" ) )
+ {
+ return SYSTEM;
+ }
else
{
final String error =

Modified: trunk/main/metro/model/src/main/net/dpml/metro/info/Priority.java
===================================================================
--- trunk/main/metro/model/src/main/net/dpml/metro/info/Priority.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/metro/model/src/main/net/dpml/metro/info/Priority.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,6 +1,5 @@
/*
* Copyright 2004 Stephen J. McConnell.
- * Copyright 1999-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

Modified:
trunk/main/metro/model/src/main/net/dpml/metro/info/ThreadSafePolicy.java
===================================================================
--- trunk/main/metro/model/src/main/net/dpml/metro/info/ThreadSafePolicy.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/metro/model/src/main/net/dpml/metro/info/ThreadSafePolicy.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,6 +1,5 @@
/*
* Copyright 2004 Stephen J. McConnell.
- * Copyright 1999-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

Modified: trunk/main/metro/model/src/main/net/dpml/metro/info/Type.java
===================================================================
--- trunk/main/metro/model/src/main/net/dpml/metro/info/Type.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/metro/model/src/main/net/dpml/metro/info/Type.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,6 +1,5 @@
/*
- * Copyright 2004 Stephen J. McConnell.
- * Copyright 1999-2004 The Apache Software Foundation
+ * Copyright 2004-2006 Stephen J. McConnell.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

Modified:
trunk/main/metro/model/src/test/net/dpml/metro/info/test/InfoDescriptorTestCase.java
===================================================================
---
trunk/main/metro/model/src/test/net/dpml/metro/info/test/InfoDescriptorTestCase.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/model/src/test/net/dpml/metro/info/test/InfoDescriptorTestCase.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -85,30 +85,6 @@
}

/**
- * Test the threadsafe default lifestyle policy.
- */
- public void testThreadSafeLifestyle()
- {
- InfoDescriptor info = new InfoDescriptor(
- m_name, m_classname, m_version, null, m_collection,
- ThreadSafePolicy.TRUE, getProperties() );
- LifestylePolicy lifestyle = info.getLifestylePolicy();
- assertEquals( "default-threadsafe-lifestyle",
LifestylePolicy.SINGLETON, lifestyle );
- }
-
- /**
- * Test the non-threadsafe default lifestyle policy.
- */
- public void testNonThreadSafeLifestyle()
- {
- InfoDescriptor info = new InfoDescriptor(
- m_name, m_classname, m_version, null, m_collection,
- ThreadSafePolicy.FALSE, getProperties() );
- LifestylePolicy lifestyle = info.getLifestylePolicy();
- assertEquals( "default-non-threadsafe-lifestyle",
LifestylePolicy.THREAD, lifestyle );
- }
-
- /**
* Test the thread safe policy.
*/
public void testThreadsafeCapable()

Modified:
trunk/main/metro/runtime/src/main/net/dpml/metro/builder/ComponentDecoder.java
===================================================================
---
trunk/main/metro/runtime/src/main/net/dpml/metro/builder/ComponentDecoder.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/runtime/src/main/net/dpml/metro/builder/ComponentDecoder.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -107,7 +107,7 @@
private ComponentDirective createComponentDirective( Element element )
throws DecodingException
{
String classname = buildComponentClassname( element );
- String name = buildComponentName( element );
+ String name = buildComponentName( element, classname );
ActivationPolicy activation = buildActivationPolicy( element );
CollectionPolicy collection = buildCollectionPolicy( element );
LifestylePolicy lifestyle = buildLifestylePolicy( element );
@@ -162,9 +162,25 @@
return CollectionPolicy.parse( policy );
}

- private String buildComponentName( Element element )
+ private String buildComponentName( Element element, String classname )
{
- return ElementHelper.getAttribute( element, "name" );
+ String name = ElementHelper.getAttribute( element, "name" );
+ if( null != name )
+ {
+ return name;
+ }
+ else
+ {
+ name = ElementHelper.getAttribute( element, "key" );
+ if( null != name )
+ {
+ return name;
+ }
+ else
+ {
+ return toName( classname );
+ }
+ }
}

private CategoriesDirective getNestedCategoriesDirective( Element root )
@@ -346,4 +362,24 @@
ComponentDirective directive = createComponentDirective( element );
return new PartReference( key, directive );
}
+
+ /**
+ * Internal utility to get the name of the class without the package
name. Used
+ * when constructing a default component name.
+ * @param classname the fully qualified classname
+ * @return the short class name without the package name
+ */
+ private String toName( String classname )
+ {
+ int i = classname.lastIndexOf( "." );
+ if( i == -1 )
+ {
+ return classname.toLowerCase();
+ }
+ else
+ {
+ return classname.substring( i + 1, classname.length()
).toLowerCase();
+ }
+ }
+
}

Modified:
trunk/main/metro/runtime/src/main/net/dpml/metro/builder/ComponentTypeDecoder.java
===================================================================
---
trunk/main/metro/runtime/src/main/net/dpml/metro/builder/ComponentTypeDecoder.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/runtime/src/main/net/dpml/metro/builder/ComponentTypeDecoder.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,5 +1,5 @@
/*
- * Copyright 2004 Stephen J. McConnell.
+ * Copyright 2006 Stephen J. McConnell.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

Modified:
trunk/main/metro/runtime/src/main/net/dpml/metro/builder/ComponentTypeEncoder.java
===================================================================
---
trunk/main/metro/runtime/src/main/net/dpml/metro/builder/ComponentTypeEncoder.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/runtime/src/main/net/dpml/metro/builder/ComponentTypeEncoder.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,5 +1,5 @@
/*
- * Copyright 2004 Stephen J. McConnell.
+ * Copyright 2006 Stephen J. McConnell.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

Modified:
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/ComponentController.java
===================================================================
---
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/ComponentController.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/ComponentController.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,5 +1,5 @@
/*
- * Copyright 2005 Stephen J. McConnell.
+ * Copyright 2005-2006 Stephen J. McConnell.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,6 +32,7 @@
import net.dpml.component.Component;
import net.dpml.component.Model;
import net.dpml.component.ServiceNotFoundException;
+import net.dpml.component.Provider;

import net.dpml.lang.StandardClassLoader;
import net.dpml.lang.Version;
@@ -51,6 +52,7 @@

import net.dpml.util.Logger;
import net.dpml.util.DefaultLogger;
+import net.dpml.util.EventQueue;

/**
* The ComponentController class is a controller of a component instance.
@@ -107,15 +109,21 @@
* Creation of a new component model using a supplied composition
datatstructure
* from which the classloader and deplyment strategy can be resolved.
* @param composition a composition datastructure
- * @exception ControlException if an error occuts during model creation
+ * @exception ControlException if an error occurs during model creation
*/
public ComponentModel createComponentModel( DefaultComposition
composition ) throws ControlException
{
- String partition = m_controller.getPartition() +
Model.PARTITION_SEPARATOR;
try
{
- Logger logger = new DefaultLogger( partition );
- return new DefaultComponentModel( logger, this, composition,
partition );
+ String partition = m_controller.getPartition() +
Model.PARTITION_SEPARATOR;
+ ClassLoader classloader = composition.getClassLoader();
+ Classpath classpath = composition.getClasspath();
+ ComponentDirective directive =
composition.getComponentDirective();
+ String name = directive.getName();
+ String path = partition + name;
+ Logger logger = new DefaultLogger( path );
+ EventQueue queue = m_controller.getEventQueue();
+ return new DefaultComponentModel( queue, logger, classloader,
classpath, this, directive, partition );
}
catch( RemoteException e )
{
@@ -150,7 +158,9 @@
try
{
Logger logger = new DefaultLogger( partition );
- return new DefaultComponentModel( logger, anchor, this,
classpath, directive, partition );
+ ClassLoader classloader = getClassLoader( anchor, classpath );
+ EventQueue queue = m_controller.getEventQueue();
+ return new DefaultComponentModel( queue, logger, classloader,
classpath, this, directive, partition );
}
catch( RemoteException e )
{
@@ -188,7 +198,7 @@
* @return the runtime handler
*/
DefaultComponentHandler createDefaultComponentHandler(
- Component parent, ClassLoader anchor, ComponentModel context, boolean
flag )
+ Provider parent, ClassLoader anchor, ComponentModel context, boolean
flag )
throws ControlException
{
try
@@ -198,7 +208,8 @@
Logger logger = new DefaultLogger( path );
Classpath classpath = context.getClasspath();
ClassLoader classloader = resolveClassLoader( anchor, context );
- return new DefaultComponentHandler( parent, classloader, logger,
this, context, flag );
+ EventQueue queue = m_controller.getEventQueue();
+ return new DefaultComponentHandler( queue, parent, classloader,
logger, this, context, flag );
}
catch( RemoteException e )
{
@@ -249,8 +260,8 @@
// types:
// 1. net.dpml.logging.Logger;
// 2. java.util.logging.Logger;
- // 4. #Context
- // 5. #Parts
+ // 3. #Context
+ // 4. #Parts
//

for( int i=0; i<classes.length; i++ )
@@ -277,7 +288,7 @@
}
else if( parts.isAssignableFrom( c ) )
{
- args[i] = createPartsInvocationHandler( handler, parts );
+ args[i] = createPartsInvocationHandler( provider, parts );
}
else
{
@@ -473,13 +484,12 @@
}
}

- private Object createPartsInvocationHandler( DefaultComponentHandler
handler, Class clazz )
+ private Object createPartsInvocationHandler( DefaultProvider provider,
Class clazz )
throws ControlException
{
- PartsManager manager = handler.getPartsManager();
try
{
- InvocationHandler invocationHandler = new
PartsInvocationHandler( manager );
+ InvocationHandler invocationHandler = new
PartsInvocationHandler( provider );
ClassLoader classloader = clazz.getClassLoader();
return Proxy.newProxyInstance( classloader, new Class[]{clazz},
invocationHandler );
}
@@ -540,7 +550,7 @@
return map.get( key );
}

- // resolve using defaults
+ // resolve using entry directive

EntryDescriptor descriptor =
handler.getType().getContextDescriptor().getEntryDescriptor( key );
Directive directive = context.getEntryDirective( key );
@@ -671,20 +681,13 @@
private Object executeLookup( DefaultProvider provider, DefaultService
service )
throws Exception
{
- // Provider parent = provider.getParentProvider();
-
- DefaultComponentHandler handler =
provider.getDefaultComponentHandler();
- Component parent = handler.getParentHandler();
-
+ Provider parent = provider.getParent();
if( null != parent )
{
try
{
- //Provider p = parent.lookup( service );
- //return p.getValue( false );
-
- Component component = parent.lookup( service );
- return component.getProvider().getValue( false );
+ Provider p = parent.lookup( service );
+ return p.getValue( false );
}
catch( RemoteException e )
{

Modified:
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/CompositionClassLoader.java
===================================================================
---
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/CompositionClassLoader.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/CompositionClassLoader.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005 Stephen J. McConnell
+ * Copyright (c) 2005-2006 Stephen J. McConnell
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

Modified:
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/CompositionController.java
===================================================================
---
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/CompositionController.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/CompositionController.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -49,6 +49,7 @@

import net.dpml.util.Logger;
import net.dpml.util.DefaultLogger;
+import net.dpml.util.EventQueue;

import org.w3c.dom.Element;

@@ -79,9 +80,9 @@
private final Logger m_logger;
private final ControllerContext m_context;
private final ComponentController m_controller;
- private final HashMap m_handlers = new HashMap(); // foreign controllers
private final InternalControllerContextListener m_listener;
private final String m_partition;
+ private final EventQueue m_events;

//--------------------------------------------------------------------
// mutable state
@@ -106,15 +107,46 @@
m_context = context;
m_partition = context.getPartition();
Logger root = new DefaultLogger( m_partition );
- m_logger = root.getChildLogger( "control" );
- m_listener = new InternalControllerContextListener( this );
+ m_logger = root.getChildLogger( "dpml.metro" );
+ m_listener = new InternalControllerContextListener();
m_context.addControllerContextListener( m_listener );
- m_logger.debug( "controller: " + CONTROLLER_URI );
m_controller = new ComponentController( m_logger, this );
+ m_events = new EventQueue( m_logger );

- startEventDispatchThread();
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace(
+ "loaded controller ["
+ + getClass().getName()
+ + "#"
+ + System.identityHashCode( this )
+ + "]" );
+ }
}

+ EventQueue getEventQueue()
+ {
+ return m_events;
+ }
+
+ /**
+ * Controller finalization.
+ * @exception Throwable if a finalization error occurs
+ */
+ protected void finalize() throws Throwable
+ {
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace(
+ "finalizing controller ["
+ + getClass().getName()
+ + "#"
+ + System.identityHashCode( this )
+ + "]" );
+ }
+ dispose();
+ }
+
//--------------------------------------------------------------------
// Builder
//--------------------------------------------------------------------
@@ -129,6 +161,12 @@
*/
public Part build( Info info, Classpath classpath, Element strategy )
throws IOException
{
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace(
+ "building strategy"
+ + "\n URI: " + info.getURI() );
+ }
ClassLoader context = Thread.currentThread().getContextClassLoader();
try
{
@@ -202,7 +240,8 @@
StringBuffer buffer = new StringBuffer();
buffer.append( "created " );
buffer.append( category.toString() );
- buffer.append( " classloader: " + id );
+ buffer.append( " classloader" );
+ buffer.append( "\n ID: " + id );
if( classloader instanceof URLClassLoader )
{
URLClassLoader loader = (URLClassLoader) classloader;
@@ -240,7 +279,13 @@
*/
public Model createModel( URI uri ) throws ControlException, IOException
{
- Part part = Part.load( uri );
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace(
+ "creating new model from URI"
+ + "\n URI: " + uri );
+ }
+ Part part = Part.load( uri, false );
if( part instanceof Composition )
{
Composition composition = (Composition) part;
@@ -266,6 +311,12 @@
*/
public Model createModel( Composition composition ) throws
ControlException, IOException
{
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace(
+ "creating new model from part"
+ + "\n URI: " + composition.getInfo().getURI() );
+ }
if( composition instanceof DefaultComposition )
{
DefaultComposition data = (DefaultComposition) composition;
@@ -289,7 +340,13 @@
*/
public Component createComponent( URI uri ) throws Exception
{
- Part part = Part.load( uri );
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace(
+ "creating new component from URI"
+ + "\nURI: " + uri );
+ }
+ Part part = Part.load( uri, false );
if( part instanceof DefaultComposition )
{
DefaultComposition composition = (DefaultComposition) part;
@@ -326,6 +383,17 @@
*/
private Component createComponent( Model model, boolean flag ) throws
Exception
{
+ if( getLogger().isTraceEnabled() )
+ {
+ if( flag )
+ {
+ getLogger().trace( "creating new locally controlled
component" );
+ }
+ else
+ {
+ getLogger().trace( "creating new managed component" );
+ }
+ }
if( model instanceof ComponentModel )
{
ClassLoader anchor = Logger.class.getClassLoader();
@@ -376,9 +444,14 @@

void dispose()
{
- getLogger().debug( "initating controller disposal" );
- m_context.removeControllerContextListener( m_listener );
- m_dispatch.dispose();
+ if( !m_disposed )
+ {
+ getLogger().debug( "initating shutdown" );
+ m_context.removeControllerContextListener( m_listener );
+ m_events.terminateDispatchThread();
+ m_disposed = true;
+ getLogger().debug( "shutdown complete" );
+ }
}

private static URI createStaticURI( String path )
@@ -405,156 +478,12 @@
}
}

- /**
- * Queue of pending notification events. When an event for which
- * there are one or more listeners occurs, it is placed on this queue
- * and the queue is notified. A background thread waits on this queue
- * and delivers the events. This decouples event delivery from
- * the application concern, greatly simplifying locking and reducing
- * opportunity for deadlock.
- */
- private static final List EVENT_QUEUE = new LinkedList();
-
/**
- * Enqueue an event for delivery to registered
- * listeners unless there are no registered
- * listeners.
- * @param event the event to enqueue
- */
- static void enqueueEvent( EventObject event )
- {
- synchronized( EVENT_QUEUE )
- {
- EVENT_QUEUE.add( event );
- EVENT_QUEUE.notify();
- }
- }
-
- /**
- * A single background thread ("the event notification thread") monitors
- * the event queue and delivers events that are placed on the queue.
- */
- private static class EventDispatchThread extends Thread
- {
- private final Logger m_logger;
-
- private boolean m_continue = true;
-
- EventDispatchThread( Logger logger )
- {
- m_logger = logger;
- m_logger.debug( "starting event dispatch thread" );
- }
-
- void dispose()
- {
- synchronized( EVENT_QUEUE )
- {
- m_logger.debug( "stopping event dispatch thread" );
- m_continue = false;
- EVENT_QUEUE.notify();
- }
- }
-
- public void run()
- {
- while( m_continue )
- {
- // Wait on EVENT_QUEUE till an event is present
- EventObject event = null;
- synchronized( EVENT_QUEUE )
- {
- try
- {
- while( EVENT_QUEUE.isEmpty() )
- {
- EVENT_QUEUE.wait();
- }
- Object object = EVENT_QUEUE.remove( 0 );
- try
- {
- event = (EventObject) object;
- }
- catch( ClassCastException cce )
- {
- final String error =
- "Unexpected class cast exception while
processing an event."
- + "\nEvent: " + object;
- throw new IllegalStateException( error );
- }
- }
- catch( InterruptedException e )
- {
- return;
- }
- }
-
- Object source = event.getSource();
- if( source instanceof UnicastEventSource )
- {
- UnicastEventSource producer = (UnicastEventSource)
source;
- try
- {
- producer.processEvent( event );
- }
- catch( Throwable e )
- {
- final String error =
- "Unexpected error while processing event."
- + "\nEvent: " + event
- + "\nSource: " + source;
- m_logger.warn( error, e );
- }
- }
- else
- {
- final String error =
- "Event source ["
- + source.getClass().getName()
- + "] is not an instance of " +
UnicastEventSource.class.getName();
- throw new IllegalStateException( error );
- }
- }
-
- m_logger.info( "Controller event queue terminating." );
- }
- }
-
- private EventDispatchThread m_dispatch = null;
-
- /**
- * This method starts the event dispatch thread the first time it
- * is called. The event dispatch thread will be started only
- * if someone registers a listener.
- */
- private synchronized void startEventDispatchThread()
- {
- if( m_dispatch == null )
- {
- Logger logger = getLogger().getChildLogger( "event" );
- m_dispatch = new EventDispatchThread( logger );
- m_dispatch.setDaemon( true );
- m_dispatch.start();
- }
- }
-
- /**
* Controller context listener.
*/
private class InternalControllerContextListener implements
ControllerContextListener
{
- private final CompositionController m_controller;
-
/**
- * Creation of a new controller context listener.
- * @param controller the controller to which change event actions are
applied
- */
- InternalControllerContextListener( final CompositionController
controller )
- {
- m_controller = controller;
- }
-
- /**
* Notify the listener that the working directory has changed.
*
* @param event the change event
@@ -578,7 +507,7 @@
*/
public void controllerDisposal( ControllerContextEvent event )
{
- m_controller.dispose();
+ dispose();
}
}
}

Modified:
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/ContextInvocationHandler.java
===================================================================
---
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/ContextInvocationHandler.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/ContextInvocationHandler.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,5 +1,5 @@
/*
- * Copyright 2004 Stephen J. McConnell.
+ * Copyright 2004-2006 Stephen J. McConnell.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -45,12 +45,7 @@
* The component.
*/
private final DefaultProvider m_provider;
-
- /**
- * The component.
- */
- private final DefaultComponentHandler m_handler;
-
+
//-------------------------------------------------------------------
// constructor
//-------------------------------------------------------------------
@@ -63,7 +58,6 @@
ContextInvocationHandler( DefaultProvider provider )
{
m_provider = provider;
- m_handler = provider.getDefaultComponentHandler();
}

//-------------------------------------------------------------------
@@ -72,7 +66,7 @@

private DefaultComponentHandler getDefaultComponentHandler()
{
- return m_handler;
+ return m_provider.getDefaultComponentHandler();
}

/**
@@ -94,17 +88,16 @@
}
else if( ComponentContext.class == source )
{
- return method.invoke( m_handler, args );
+ DefaultComponentHandler handler = getDefaultComponentHandler();
+ return method.invoke( handler, args );
}
else
{
- DefaultComponentHandler handler = getDefaultComponentHandler();
String name = method.getName();
if( name.startsWith( "get" ) )
{
String key = EntryDescriptor.getEntryKey( method );
Object value = getContextValue( key );
- //Object value = handler.getContextValue( key );
if( null != value )
{
return value;
@@ -120,6 +113,11 @@
throw new IllegalStateException( error );
}
}
+ else
+ {
+ throw new NoSuchMethodException( name );
+ }
+ /*
if( ( null != args ) && ( args.length == 1 ) )
{
if( "addPropertyChangeListener".equals( name ) )
@@ -135,12 +133,14 @@
return null;
}
}
- throw new NoSuchMethodException( name );
+ */
}
}

Object getContextValue( String key ) throws ControlException
{
- return m_handler.getComponentController().getContextValue(
m_provider, key );
+ DefaultComponentHandler handler = getDefaultComponentHandler();
+ return handler.getComponentController().getContextValue( m_provider,
key );
}
+
}

Modified:
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultComponentHandler.java
===================================================================
---
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultComponentHandler.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultComponentHandler.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,5 +1,5 @@
/*
- * Copyright 2005 Stephen J. McConnell.
+ * Copyright 2005-2006 Stephen J. McConnell.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -60,6 +60,7 @@
import net.dpml.state.State;

import net.dpml.util.Logger;
+import net.dpml.util.EventQueue;


/**
@@ -113,7 +114,7 @@
// immutable state

//--------------------------------------------------------------------------

- private final Logger m_logger;
+ private final Provider m_parent;
private final ComponentController m_controller;
private final ComponentModel m_model;
private final State m_graph;
@@ -124,12 +125,10 @@
private final String m_path;
private final URI m_uri;
private final Holder m_holder;
- private final Component m_parent;
private final PropertyChangeSupport m_support;
private final Map m_cache = new Hashtable(); // context overloading
entry/value cache
private final Map m_map = new Hashtable(); // symbolic value map
- private final DefaultPartsManager m_parts;
- private final boolean m_flag;
+ private final boolean m_flag; // locally managed


//--------------------------------------------------------------------------
// mutable state
@@ -142,24 +141,30 @@

//--------------------------------------------------------------------------

DefaultComponentHandler(
- final Component parent, final ClassLoader classloader, final Logger
logger,
+ final EventQueue queue,
+ final Provider parent, final ClassLoader classloader, final Logger
logger,
final ComponentController control, final ComponentModel model, boolean
flag )
throws RemoteException, ControlException
{
- super( logger );
+ super( queue, logger );

m_parent = parent;
+
m_classloader = classloader;
- m_logger = logger;
m_controller = control;
m_model = model;
m_path = model.getContextPath();
m_flag = flag;

+ String classname = model.getImplementationClassName();
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "creating new component handler [" + m_path +
"] for class [" + classname + "]" );
+ }
+
m_support = new PropertyChangeSupport( this );
model.addModelListener( this );

- String classname = model.getImplementationClassName();
try
{
m_class = control.loadComponentClass( classloader, classname );
@@ -218,11 +223,12 @@
m_map.put( "work", work.toString() );
m_map.put( "temp", temp.toString() );
m_map.put( "uri", m_uri.toASCIIString() );
-
+
LifestylePolicy lifestyle = model.getLifestylePolicy();
if( lifestyle.equals( LifestylePolicy.SINGLETON ) )
{
- m_holder = new SingletonHolder();
+ CollectionPolicy collection = model.getCollectionPolicy();
+ m_holder = new SingletonHolder( collection );
}
else if( lifestyle.equals( LifestylePolicy.TRANSIENT ) )
{
@@ -234,29 +240,37 @@
}
else
{
- final String error =
- "Unsuppported lifestyle policy: " + lifestyle;
- throw new UnsupportedOperationException( error );
+ if( m_type.getInfo().isThreadSafe() )
+ {
+ CollectionPolicy collection = model.getCollectionPolicy();
+ m_holder = new SingletonHolder( collection );
+ }
+ else
+ {
+ m_holder = new ThreadHolder();
+ }
}

- // At this point the component handler is fully established with
respect to
- // its own logic as a simple component. Before completing
initialization we
- // need to establish all of the component parts that are children of
this
- // component.
-
- m_parts = new DefaultPartsManager( control, this, logger );
-
if( getLogger().isDebugEnabled() )
{
- String style = lifestyle.toString().toLowerCase();
+ String lifestyleName = m_holder.getName();
getLogger().debug(
"established "
- + style
- + " handler for ["
- + m_class.getName()
+ + lifestyleName
+ + " lifestyle handler for ["
+ + classname
+ "]" );
}
}
+
+ /**
+ * Return the logging channel assigned to the event source.
+ * @return the logging channel
+ */
+ Logger getLogger()
+ {
+ return super.getLogger();
+ }


//--------------------------------------------------------------------------
// ComponentContext
@@ -344,10 +358,6 @@
return m_cache;
}

-
//--------------------------------------------------------------------------
- // Component
-
//--------------------------------------------------------------------------
-
/**
* Return a mutible context map.
*
@@ -357,50 +367,12 @@
{
return m_map;
}
+
+
//--------------------------------------------------------------------------
+ // Component
+
//--------------------------------------------------------------------------

/**
- * Return a handler capable of supporting the requested service.
- * @param service the service definition
- * @return a component matching the serivce definiton
- * @exception ServiceNotFoundException if no component found
- * @exception RemoteException if a remote exception occurs
- */
- public Component lookup( Service service ) throws
ServiceNotFoundException, RemoteException
- {
- if( getLogger().isDebugEnabled() )
- {
- getLogger().debug(
- "mediating lookup for ["
- + service.getServiceClass().getName()
- + "]." );
- }
-
- // check if a child component can handle the request
-
- Component[] components = m_parts.getComponents();
- for( int i=0; i<components.length; i++ )
- {
- Component component = components[i];
- if( component.isaCandidate( service ) )
- {
- return component;
- }
- }
-
- // delegate to the parent
-
- if( m_parent != null )
- {
- return m_parent.lookup( service );
- }
- else
- {
- String classname = service.getServiceClass().getName();
- throw new ServiceNotFoundException(
CompositionController.CONTROLLER_URI, classname );
- }
- }
-
- /**
* Return the number of instances currently under management. If the
component
* is a singleton the value returned will be between zero and 1
(depending on the
* activated status of the handler. If the component is transient, the
instance
@@ -423,6 +395,27 @@
}

/**
+ * Get the activation policy. If the activation policy is STARTUP, an
implementation
+ * a handler shall immidiately activation a runtime instance. If the
policy is on DEMAND
+ * an implementation shall defer activiation until an explicit request is
received. If
+ * the policy if SYSTEM activation may occur at the discretion of an
implementation.
+ *
+ * @return the activation policy
+ * @exception RemoteException if a remote exception occurs
+ * @see ActivationPolicy#SYSTEM
+ * @see ActivationPolicy#STARTUP
+ * @see ActivationPolicy#DEMAND
+ */
+ public ActivationPolicy getActivationPolicy() throws RemoteException
+ {
+ return m_model.getActivationPolicy();
+ }
+
+
//--------------------------------------------------------------------------
+ // Commissionable
+
//--------------------------------------------------------------------------
+
+ /**
* Activate the component handler. If the component declares an activate
on
* startup policy then a new instance will be created and activated.
*
@@ -435,6 +428,11 @@
{
return;
}
+
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "commissioning" );
+ }

// setup and subsidiary logging channels declared by the component
type

@@ -479,22 +477,13 @@
throw new ControllerException( error, e );
}

- // ISSUE: the current implementation is commissioning parts at the
level
- // of the component when in fact we should be commissioning (and
demommissioning
- // parts at the level of the provider (because a component
implementation can
- // modify the state of a given provider which means different
providers from the
- // same component may have different state.
-
try
{
if( m_model.getActivationPolicy().equals(
ActivationPolicy.STARTUP ) )
{
getLogger().debug( "activating" );
- Provider provider = m_holder.getProvider();
- // provider.commission() ??? see above note
+ m_holder.getProvider();
}
-
- m_parts.commission(); // see above note
m_active = true;
}
catch( RemoteException e )
@@ -533,23 +522,6 @@
}

/**
- * Get the activation policy. If the activation policy is STARTUP, an
implementation
- * a handler shall immidiately activation a runtime instance. If the
policy is on DEMAND
- * an implementation shall defer activiation until an explicit request is
received. If
- * the policy if SYSTEM activation may occur at the discretion of an
implementation.
- *
- * @return the activation policy
- * @exception RemoteException if a remote exception occurs
- * @see ActivationPolicy#SYSTEM
- * @see ActivationPolicy#STARTUP
- * @see ActivationPolicy#DEMAND
- */
- public ActivationPolicy getActivationPolicy() throws RemoteException
- {
- return m_model.getActivationPolicy();
- }
-
- /**
* Deactivate the component.
*/
public synchronized void decommission()
@@ -559,35 +531,21 @@
return;
}

- getLogger().debug( "decommissioning" );
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "decommissioning" );
+ }

//
- // dispose of all of the instances managed by this component
- //
-
- m_holder.dispose();
-
- //
// deactivate all of the subsidiary components
//

- m_parts.decommission();
-
+ m_holder.decommission();
m_active = false;
-
getLogger().debug( "decommissioned" );
}

/**
- * Return the array of services provider by the handler.
- * @return the service array
- */
- public Service[] getServices()
- {
- return m_services;
- }
-
- /**
* Return true if this handler is a candidate for the supplied service
definition.
* @param service the service definition
* @return true if this is a candidate
@@ -620,7 +578,7 @@
* Process the supplied event.
* @param event the event object
*/
- protected void processEvent( EventObject event )
+ public void processEvent( EventObject event )
{
// TODO
}
@@ -629,18 +587,18 @@
// DefaultComponentHandler

//--------------------------------------------------------------------------

- ComponentController getComponentController()
+ /**
+ * Return the array of services provider by the handler.
+ * @return the service array
+ */
+ public Service[] getServices()
{
- return m_controller;
+ return m_services;
}

- /**
- * Return the internal parts manager.
- * @return the part manager
- */
- public PartsManager getPartsManager()
+ ComponentController getComponentController()
{
- return m_parts;
+ return m_controller;
}

/**
@@ -652,6 +610,10 @@
*/
void addPropertyChangeListener( PropertyChangeListener listener )
{
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "adding property change listener: [" +
listener + "]" );
+ }
m_support.addPropertyChangeListener( listener );
}

@@ -661,6 +623,10 @@
*/
void removePropertyChangeListener( PropertyChangeListener listener )
{
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "removing property change listener: [" +
listener + "]" );
+ }
m_support.removePropertyChangeListener( listener );
}

@@ -671,9 +637,22 @@
{
synchronized( getLock() )
{
- getLogger().debug( "disposal" );
+ if( getLogger().isDebugEnabled() )
+ {
+ getLogger().debug( "initiating disposal" );
+ }
decommission();
- //m_holder.dispose();
+ try
+ {
+ m_model.removeModelListener( this );
+ }
+ catch( RemoteException e )
+ {
+ if( getLogger().isWarnEnabled() )
+ {
+ getLogger().warn( "ignoring model listener removal
remote error", e );
+ }
+ }
if( m_flag )
{
if( m_model instanceof Disposable )
@@ -683,39 +662,13 @@
}
}
super.dispose();
+ if( getLogger().isDebugEnabled() )
+ {
+ getLogger().debug( "disposal complete" );
+ }
}
}

- /**
- * Return a subsidiary component.
- * @param key the subsidiary component key
- * @return the subsidiary component
- * @exception UnknownKeyException if the key does not match
- * any of the internal components managed by this component
- */
- Component getPartHandler( String key ) throws UnknownKeyException
- {
- ComponentHandler handler = m_parts.getComponentHandler( key );
- if( handler instanceof Component )
- {
- return (Component) handler;
- }
- else
- {
- final String error =
- "Internal error. Component handler ["
- + handler
- + "] is not an instance of "
- + Component.class.getName();
- throw new ControllerRuntimeException( error );
- }
- }
-
- //Object getContextValue( String key ) throws ControlException
- //{
- // return m_controller.getContextValue( this, key );
- //}
-
State getStateGraph()
{
return m_graph;
@@ -730,8 +683,8 @@
{
return m_classloader;
}
-
- Component getParentHandler()
+
+ Provider getParentProvider()
{
return m_parent;
}
@@ -750,11 +703,6 @@
return m_path;
}

- Object createNewObject( DefaultProvider provider ) throws
ControlException, InvocationTargetException
- {
- return m_controller.createInstance( provider );
- }
-
Class[] getServiceClassArray()
{
Class[] classes = new Class[ m_services.length ];
@@ -784,6 +732,14 @@
return "component:" + getClass().getName();
}
}
+
+ protected void finalize() throws Throwable
+ {
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "finalizing component handler" );
+ }
+ }


//--------------------------------------------------------------------------
// utilities
@@ -798,14 +754,19 @@
private DefaultProvider createDefaultProvider()
throws InvocationTargetException, ControlException
{
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "creating new provider" );
+ }
try
{
- return new DefaultProvider( this, getLogger() );
+ EventQueue queue = getEventQueue();
+ return new DefaultProvider( queue, this, getLogger() );
}
catch( RemoteException e )
{
final String error =
- "Unable to create instance holder due to a remote exception.";
+ "Unable to create provider due to a remote exception.";
throw new ControllerException( error, e );
}
}
@@ -836,7 +797,7 @@
/**
* Dispose of the holder and all managed instances.
*/
- void dispose()
+ void decommission()
{
if( isDisposed() )
{
@@ -855,6 +816,12 @@
{
return m_disposed;
}
+
+ /**
+ * Return the holder lifestyle policy name.
+ * @return the policy value as a string
+ */
+ abstract String getName();
}

/**
@@ -865,13 +832,43 @@
*/
private class SingletonHolder extends Holder
{
+ private final CollectionPolicy m_collection;
private Reference m_reference;

/**
* Creation of a new singleton holder.
*/
- SingletonHolder()
+ SingletonHolder( CollectionPolicy policy )
{
+ if( policy.equals( CollectionPolicy.SYSTEM ) )
+ {
+ if( null == m_parent )
+ {
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "assigning hard (system)
collection policy" );
+ }
+ m_collection = CollectionPolicy.HARD;
+ }
+ else
+ {
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "assigning soft (system)
collection policy" );
+ }
+ m_collection = CollectionPolicy.SOFT;
+ }
+ }
+ else
+ {
+ if( getLogger().isDebugEnabled() )
+ {
+ String name = policy.getName();
+ getLogger().debug( "assigning " + name + " collection
policy" );
+ }
+ m_collection = policy;
+ }
+
m_reference = createReference( null );
}

@@ -890,7 +887,7 @@
}
}

- void dispose()
+ void decommission()
{
if( !isDisposed() )
{
@@ -900,7 +897,7 @@
provider.dispose();
}
m_reference.clear();
- super.dispose();
+ super.decommission();
}
}

@@ -915,6 +912,38 @@
return 0;
}
}
+
+ String getName()
+ {
+ return "singleton";
+ }
+
+ /**
+ * Constructs a reference that reflects the component cololection
policy.
+ * @param object the initial reference value
+ * @return the reference
+ */
+ private Reference createReference( Object object )
+ {
+ if( m_collection.equals( CollectionPolicy.SOFT ) )
+ {
+ return new SoftReference( object );
+ }
+ else if( m_collection.equals( CollectionPolicy.WEAK ) )
+ {
+ return new WeakReference( object );
+ }
+ else if( m_collection.equals( CollectionPolicy.HARD ) )
+ {
+ return new HardReference( object );
+ }
+ else
+ {
+ final String error =
+ "Supplied collection policy is abstract: " + m_collection;
+ throw new IllegalArgumentException( error );
+ }
+ }
}

/**
@@ -924,38 +953,43 @@
*/
private class TransientHolder extends Holder
{
- private WeakHashMap m_instances = new WeakHashMap(); // transients
+ private final WeakHashMap m_providers = new WeakHashMap(); //
transients

DefaultProvider getProvider() throws ControlException,
InvocationTargetException
{
- DefaultProvider instance = createDefaultProvider();
- m_instances.put( instance, null );
- return instance;
+ DefaultProvider provider = createDefaultProvider();
+ m_providers.put( provider, null );
+ return provider;
}

- void dispose()
+ void decommission()
{
if( !isDisposed() )
{
- DefaultProvider[] instances = getAllProviders();
- for( int i=0; i<instances.length; i++ )
+ DefaultProvider[] providers = getAllProviders();
+ for( int i=0; i<providers.length; i++ )
{
- DefaultProvider instance = instances[i];
- m_instances.remove( instance );
- instance.dispose();
+ DefaultProvider provider = providers[i];
+ m_providers.remove( provider );
+ provider.dispose();
}
- super.dispose();
+ super.decommission();
}
}

int getProviderCount()
{
- return m_instances.size();
+ return m_providers.size();
}

+ String getName()
+ {
+ return "transient";
+ }
+
private DefaultProvider[] getAllProviders()
{
- return (DefaultProvider[]) m_instances.keySet().toArray( new
DefaultProvider[0] );
+ return (DefaultProvider[]) m_providers.keySet().toArray( new
DefaultProvider[0] );
}
}

@@ -966,19 +1000,19 @@
*/
private class ThreadHolder extends Holder
{
- private ThreadLocalHolder m_threadLocalHolder = new
ThreadLocalHolder();
+ private final ThreadLocalHolder m_threadLocalHolder = new
ThreadLocalHolder();

DefaultProvider getProvider() throws ControlException,
InvocationTargetException
{
return (DefaultProvider) m_threadLocalHolder.get();
}

- void dispose()
+ void decommission()
{
if( !isDisposed() )
{
- m_threadLocalHolder.dispose();
- super.dispose();
+ m_threadLocalHolder.decommission();
+ super.decommission();
}
}

@@ -986,6 +1020,11 @@
{
return m_threadLocalHolder.getProviderCount();
}
+
+ String getName()
+ {
+ return "per-thread";
+ }

private DefaultProvider[] getAllProviders()
{
@@ -998,108 +1037,54 @@
*/
private class ThreadLocalHolder extends ThreadLocal
{
- private WeakHashMap m_instances = new WeakHashMap(); // per thread
instances
+ private final WeakHashMap m_providers = new WeakHashMap(); // per
thread instances

protected Object initialValue()
{
try
{
- DefaultProvider instance = createDefaultProvider();
- m_instances.put( instance, null );
- return instance;
+ DefaultProvider provider = createDefaultProvider();
+ m_providers.put( provider, null );
+ return provider;
}
catch( Exception e )
{
final String error =
"Per-thread lifestyle policy handler encountered an error "
- + "while attempting to establish instance.";
+ + "while attempting to establish provider.";
throw new ControllerRuntimeException( error, e );
}
}

int getProviderCount()
{
- return m_instances.size();
+ return m_providers.size();
}

DefaultProvider[] getAllProviders()
{
- return (DefaultProvider[]) m_instances.keySet().toArray( new
DefaultProvider[0] );
+ return (DefaultProvider[]) m_providers.keySet().toArray( new
DefaultProvider[0] );
}

- void dispose()
+ void decommission()
{
- DefaultProvider[] instances = getAllProviders();
- for( int i=0; i<instances.length; i++ )
+ DefaultProvider[] providers = getAllProviders();
+ for( int i=0; i<providers.length; i++ )
{
- DefaultProvider instance = instances[i];
- instance.dispose();
- m_instances.remove( instance );
+ DefaultProvider provider = providers[i];
+ provider.dispose();
+ m_providers.remove( provider );
}
}
}

/**
- * Constructs a reference that reflects the component cololection policy.
- * @param object the initial reference value
- * @return the reference
- */
- private Reference createReference( Object object )
- {
- //
- // if this is a top-level component then set the collection policy
- // to hard otherwise we'll loose the instance because nothing is
- // referencing it directly
- //
-
- try
- {
- CollectionPolicy policy = m_model.getCollectionPolicy();
-
- //
- // if an explicit collection policy is defined then apply it now
- // otherwise use SOFT collection as the SYSTEM default
- //
-
- if( policy.equals( CollectionPolicy.SOFT ) )
- {
- return new SoftReference( object );
- }
- else if( policy.equals( CollectionPolicy.WEAK ) )
- {
- return new WeakReference( object );
- }
- else if( policy.equals( CollectionPolicy.HARD ) )
- {
- return new HardReference( object );
- }
- else // SYSTEM
- {
- if( null == m_parent )
- {
- return new HardReference( object );
- }
- else
- {
- return new SoftReference( object );
- }
- }
- }
- catch( RemoteException e )
- {
- final String error =
- "Reference object creating failure due to a remote exception.";
- throw new ControllerRuntimeException( error, e );
- }
- }
-
- /**
* A reference class that implements hard reference semantics.
*/
private static class HardReference extends SoftReference
{
- private Object m_referent;
-
+ private final Object m_referent; // hard reference
+
/**
* Creation of a new hard reference.
* @param referent the referenced object

Modified:
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultComponentModel.java
===================================================================
---
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultComponentModel.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultComponentModel.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -51,6 +51,7 @@
import net.dpml.metro.ContextModelManager;

import net.dpml.util.Logger;
+import net.dpml.util.EventQueue;

/**
* Default implementation of a mutable component model.
@@ -76,48 +77,26 @@
private final PartReference[] m_references;
private final Class m_class;
private final String m_classname;
+ private final LifestylePolicy m_lifestyle;
+ private final CollectionPolicy m_collection;

private ActivationPolicy m_activation;
- private LifestylePolicy m_lifestyle;
- private CollectionPolicy m_collection;

//
------------------------------------------------------------------------
// constructor
//
------------------------------------------------------------------------

public DefaultComponentModel(
- Logger logger, ComponentController controller, DefaultComposition
composition, String partition )
- throws ControlException, IOException, RemoteException
- {
- super( logger );
-
- m_classpath = composition.getClasspath();
- m_controller = controller;
- m_directive = composition.getComponentDirective();
- m_classloader = composition.getClassLoader();
- m_classname = m_directive.getClassname();
- m_class = m_controller.loadComponentClass( m_classloader,
m_classname );
- m_type = m_controller.loadType( m_class );
- m_path = setupPath( partition );
- m_activation = m_directive.getActivationPolicy();
- m_lifestyle = setupLifestyle();
- m_collection = m_directive.getCollectionPolicy();
- ContextDirective context = m_directive.getContextDirective();
- m_context = new DefaultContextModel( this, logger, m_classloader,
m_type, context );
- m_references = buildPartReferences();
- }
-
- public DefaultComponentModel(
- Logger logger, ClassLoader anchor, ComponentController controller,
Classpath classpath,
+ EventQueue queue, Logger logger, ClassLoader classloader, Classpath
classpath, ComponentController controller,
ComponentDirective directive, String partition )
throws ControlException, IOException, RemoteException
{
- super( logger );
+ super( queue, logger );

m_classpath = classpath;
m_controller = controller;
m_directive = directive;
- m_classloader = m_controller.getClassLoader( anchor, classpath );
+ m_classloader = classloader;
m_classname = directive.getClassname();
m_class = m_controller.loadComponentClass( m_classloader,
m_classname );
m_type = m_controller.loadType( m_class );
@@ -126,9 +105,23 @@
m_lifestyle = setupLifestyle();
m_collection = directive.getCollectionPolicy();
ContextDirective context = directive.getContextDirective();
- m_context = new DefaultContextModel( this, logger, m_classloader,
m_type, context );
+ m_context =
+ new DefaultContextModel(
+ queue,
+ this, logger, m_classloader, m_type, context );
m_references = buildPartReferences();
}
+
+ /**
+ * Return the component thread-safe status.
+ *
+ * @return the threadsafe status
+ * @exception RemoteException if a remote exception occurs
+ */
+ public boolean isThreadSafe() throws RemoteException
+ {
+ return m_type.getInfo().isThreadSafe();
+ }

/**
* Return the inital array of part references.
@@ -144,9 +137,9 @@
return m_classpath;
}

- protected void processEvent( EventObject event )
+ public void processEvent( EventObject event )
{
- EventListener[] listeners = super.listeners();
+ EventListener[] listeners = super.getEventListeners();
for( int i=0; i < listeners.length; i++ )
{
EventListener listener = listeners[i];
@@ -177,8 +170,12 @@
*/
public void addModelListener( ModelListener listener )
{
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "adding component model listener [" +
listener + "]" );
+ }
super.addListener( listener );
- m_context.addModelListener( listener );
+ //m_context.addModelListener( listener ); // ???? why not directly
on context model ??
}

/**
@@ -187,8 +184,12 @@
*/
public void removeModelListener( ModelListener listener )
{
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "removing component model listener [" +
listener + "]" );
+ }
super.removeListener( listener );
- m_context.removeListener( listener );
+ //m_context.removeListener( listener ); // ???? why not directly on
context model ??
}

//
------------------------------------------------------------------------
@@ -278,18 +279,6 @@
}

/**
- * Override the assigned collection policy.
- * @param policy the collection policy value
- */
- public void setCollectionPolicy( CollectionPolicy policy )
- {
- CollectionPolicy old = m_collection;
- m_collection = policy;
- ModelEvent event = new ModelEvent( this, "collection.policy", old,
policy );
- enqueueEvent( event );
- }
-
- /**
* Return the current context model.
*
* @return the context model

Modified:
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultComposition.java
===================================================================
---
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultComposition.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultComposition.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -42,7 +42,7 @@
public final class DefaultComposition extends Composition
{
private ComponentDirective m_directive;
-
+
/**
* Creation of a new composition diefinition.
* @param logger the assigned logging channel

Modified:
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultContextModel.java
===================================================================
---
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultContextModel.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultContextModel.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,5 +1,5 @@
/*
- * Copyright 2005 Stephen J. McConnell.
+ * Copyright 2005-2006 Stephen J. McConnell.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,6 +42,7 @@
import net.dpml.metro.info.Type;

import net.dpml.util.Logger;
+import net.dpml.util.EventQueue;

/**
* Default implementation of <tt>ContextModel</tt>.
@@ -83,11 +84,11 @@
* @exception RemoteException if a remote I/O error occurs
*/
DefaultContextModel(
- DefaultComponentModel parent, Logger logger, ClassLoader classloader,
+ EventQueue queue, DefaultComponentModel parent, Logger logger,
ClassLoader classloader,
Type type, ContextDirective directive )
throws ModelException, RemoteException
{
- super( logger );
+ super( queue, logger );

m_parent = parent;
m_directive = directive;
@@ -120,6 +121,10 @@
*/
public void addModelListener( ModelListener listener )
{
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "adding context model listener [" + listener
+ "]" );
+ }
super.addListener( listener );
}

@@ -129,6 +134,10 @@
*/
public void removeModelListener( ModelListener listener )
{
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "removing context model listener [" +
listener + "]" );
+ }
super.removeListener( listener );
}

@@ -136,9 +145,9 @@
* Process a context model event.
* @param event the event to process
*/
- protected void processEvent( EventObject event )
+ public void processEvent( EventObject event )
{
- EventListener[] listeners = super.listeners();
+ EventListener[] listeners = super.getEventListeners();
for( int i=0; i < listeners.length; i++ )
{
EventListener listener = listeners[i];
@@ -282,6 +291,11 @@
throw new UnknownKeyException( key );
}

+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "setting new context entry [" + key + "]" );
+ }
+
Object old = m_contextTable.get( key );
m_contextTable.put( key, directive );
ModelEvent event = new ModelEvent( m_parent, "context.entry:" + key,
old, directive );

Modified:
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultPartsManager.java
===================================================================
---
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultPartsManager.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultPartsManager.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,5 +1,5 @@
/*
- * Copyright 2004 Stephen J. McConnell.
+ * Copyright 2004-2006 Stephen J. McConnell.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,13 +30,8 @@
import net.dpml.component.Model;
import net.dpml.component.Service;
import net.dpml.component.Directive;
+import net.dpml.component.Disposable;

-import net.dpml.job.CommissionerEvent;
-import net.dpml.job.CommissionerController;
-import net.dpml.job.TimeoutException;
-import net.dpml.job.TimeoutError;
-import net.dpml.job.impl.DefaultCommissioner;
-
import net.dpml.lang.Classpath;
import net.dpml.lang.UnknownKeyException;
import net.dpml.lang.Version;
@@ -51,101 +46,112 @@
import net.dpml.util.Logger;

/**
- * Default implementation of the local Parts interface.
+ * Null implementation of the local Parts interface.
*
* @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
* @version @PROJECT-VERSION@
*/
-class DefaultPartsManager implements PartsManager
+class DefaultPartsManager implements PartsManager, Disposable
{
- //-------------------------------------------------------------------
- // state
- //-------------------------------------------------------------------
-
- /**
- * Internal handle to the component controller.
- */
- private final ComponentController m_control;
-
- /**
- * The component handler.
- */
- private final DefaultComponentHandler m_handler;
-
- /**
- * The logging channel.
- */
- private final Logger m_logger;
-
- /**
- * The internal map of component handlers.
- */
- private final Map m_handlers = new Hashtable();
-
- private boolean m_commissioned = false;
-
- private final Map m_parts;
-
+ private final DefaultProvider m_provider;
private final String[] m_keys;
+ private final ComponentHandler[] m_components;

- //-------------------------------------------------------------------
- // constructor
- //-------------------------------------------------------------------
-
- /**
- * Create a new parts manager.
- *
- * @param handler the component handler
- * @param logger the logging channel
- */
- DefaultPartsManager( ComponentController control,
DefaultComponentHandler handler, Logger logger )
- throws ControlException, RemoteException
+ private boolean m_commissioned;
+
+ DefaultPartsManager( DefaultProvider provider ) throws RemoteException
{
- m_control = control;
- m_handler = handler;
- m_logger = logger;
+ m_provider = provider;

+ DefaultComponentHandler handler =
provider.getDefaultComponentHandler();
ClassLoader classloader = handler.getClassLoader();
ComponentModel model = handler.getComponentModel();
+ String partition = model.getContextPath();
+ final String base = partition + Model.PARTITION_SEPARATOR;
PartReference[] references = model.getPartReferences();
+ m_keys = new String[ references.length ];
+ m_components = new ComponentHandler[ references.length ];

- m_keys = getKeys( references );
+ if( references.length > 0 )
+ {
+ if( provider.getLogger().isDebugEnabled() )
+ {
+ provider.getLogger().debug( "building internal parts" );
+ }
+ }

- String partition = model.getContextPath();
- final String base = partition + Model.PARTITION_SEPARATOR;
- m_parts = processParts( control, classloader, base, references );
- for( int i=0; i<references.length; i++ )
+ for( int i=0; i < references.length; i++ )
{
- PartReference reference = references[i];
- String key = reference.getKey();
- try
+ PartReference ref = references[i];
+ String key = ref.getKey();
+ m_keys[i] = key;
+ Directive part = ref.getDirective();
+ if( part instanceof ComponentDirective )
{
- ComponentModel manager = (ComponentModel) m_parts.get( key );
- Component component = control.createDefaultComponentHandler(
handler, classloader, manager, true );
- m_handlers.put( key, component );
+ try
+ {
+ Classpath classpath = new Classpath();
+ ComponentDirective directive = (ComponentDirective) part;
+ ComponentController controller =
handler.getComponentController();
+ ComponentModel manager =
+ controller.createComponentModel( classloader,
classpath, base, directive );
+ ComponentHandler component =
+ controller.createDefaultComponentHandler( m_provider,
classloader, manager, true );
+ m_components[i] = component;
+ }
+ catch( Exception e )
+ {
+ final String error =
+ "Internal error while attempting to create a
subsidiary part ["
+ + key
+ + "] in ["
+ + m_provider
+ + "]";
+ throw new ControllerRuntimeException( error, e );
+ }
}
- catch( Exception e )
+ else
{
final String error =
- "Internal error while attempting to create a subsidiary
part ["
- + key
- + "] in component ["
- + handler
- + "]";
- throw new ControllerRuntimeException( error, e );
+ "Foreign part ["
+ + part.getClass()
+ + "] not supported.";
+ throw new UnsupportedOperationException( error );
}
}
}

- private ComponentModel getComponentModel()
+ //-------------------------------------------------------------------
+ // Disposable
+ //-------------------------------------------------------------------
+
+ public void dispose()
{
- return m_handler.getComponentModel();
+ decommission();
+ String[] keys = getKeys();
+ for( int i=keys.length-1; i>-1; i-- )
+ {
+ try
+ {
+ String key = keys[i];
+ ComponentHandler handler = getComponentHandler( key );
+ if( handler instanceof Disposable )
+ {
+ Disposable disposable = (Disposable) handler;
+ disposable.dispose();
+ }
+ }
+ catch( UnknownKeyException e )
+ {
+ e.printStackTrace(); // will not happen
+ }
+ }
}
-
+
//-------------------------------------------------------------------
// PartsManager
//-------------------------------------------------------------------
-
+
/**
* Return the array of keys used to identify internal parts.
* @return the part key array
@@ -156,20 +162,22 @@
}

/**
+ * Return an array of all component handlers.
+ * @return the local component handler array
+ */
+ public ComponentHandler[] getComponentHandlers()
+ {
+ return m_components;
+ }
+
+ /**
* Return a component handler.
* @param key the internal component key
- * @return the local component handler
+ * @return the component handler
*/
public synchronized Component getComponent( String key ) throws
UnknownKeyException
{
- if( m_handlers.containsKey( key ) )
- {
- return (Component) m_handlers.get( key );
- }
- else
- {
- throw new UnknownKeyException( key );
- }
+ return getComponentHandler( key );
}

/**
@@ -181,73 +189,44 @@
{
Service service = new DefaultService( clazz, Version.parse( "-1" ) );
ArrayList list = new ArrayList();
- Component[] components = getComponents();
+ ComponentHandler[] components = getComponentHandlers();
for( int i=0; i<components.length; i++ )
{
- Component component = components[i];
- if( component instanceof ComponentHandler )
+ ComponentHandler component = components[i];
+ try
{
- ComponentHandler handler = (ComponentHandler) component;
- try
+ if( component.isaCandidate( service ) )
{
- if( handler.isaCandidate( service ) )
- {
- list.add( component );
- }
+ list.add( component );
}
- catch( RemoteException e )
- {
- final String error =
- "Unexpected remote exception raised during subsidiary
component evaluation."
- + "\nEnclosing Component: " + m_handler;
- throw new ControllerRuntimeException( error, e );
- }
}
+ catch( RemoteException e )
+ {
+ final String error =
+ "Unexpected remote exception raised during subsidiary
component evaluation."
+ + "\nProvider: " + m_provider;
+ throw new ControllerRuntimeException( error, e );
+ }
}
return (ComponentHandler[]) list.toArray( new ComponentHandler[0] );
}

/**
- * Return the component model for the supplied component.
- * @param component the component
- * @return the component model
- */
- public Model getComponentModel( Component component )
- {
- if( component instanceof DefaultComponentHandler )
- {
- DefaultComponentHandler handler = (DefaultComponentHandler)
component;
- return handler.getComponentModel();
- }
- else
- {
- final String error =
- "Component ["
- + component
- + "] is not castable to
net.dpml.metro.runtime.DefaultComponentHandler.";
- throw new IllegalArgumentException( error );
- }
- }
-
- /**
* Return a component handler.
* @param key the internal component key
* @return the local component handler
*/
public synchronized ComponentHandler getComponentHandler( String key )
throws UnknownKeyException
{
- if( null == key )
+ for( int i=0; i<m_keys.length; i++ )
{
- throw new NullPointerException( "key" );
+ String k = m_keys[i];
+ if( k.equals( key ) )
+ {
+ return m_components[i];
+ }
}
- if( m_handlers.containsKey( key ) )
- {
- return (ComponentHandler) m_handlers.get( key );
- }
- else
- {
- throw new UnknownKeyException( key );
- }
+ throw new UnknownKeyException( key );
}

/**
@@ -270,59 +249,38 @@
{
if( m_commissioned )
{
- final String error =
- "Illegal attempt to commission a part manager that is already
commissioned."
- + "Component: " + m_handler;
- throw new IllegalStateException( error );
+ return;
}
-
- String label = m_handler.toString();
- DefaultCommissioner queue =
- new DefaultCommissioner( label, true, new
InternalCommissionerController( true ) );
-
- ControlException exception = null;
ArrayList list = new ArrayList();
- Component[] components = getComponents();
+ ComponentHandler[] components = getComponentHandlers();
if( components.length > 0 )
{
- getLogger().debug( "commissioning internal parts" );
+ m_provider.getLogger().debug( "commissioning internal parts" );
for( int i=0; i<components.length; i++ )
{
- Component component = components[i];
+ ComponentHandler component = components[i];
try
{
if( component.getActivationPolicy().equals(
ActivationPolicy.STARTUP ) )
{
- list.add( component );
- queue.add( component, 0 );
+ component.commission();
}
}
catch( Throwable e )
{
final String error =
"Error during the commission of the internal parts of
a component."
- + "\nEnclosing Component: " + m_handler
- + "\nInternal Part: " + component;
- exception = new ControllerException( error, e );
- break;
+ + "\nProvider: " + m_provider
+ + "\nPart: " + component;
+ throw new ControllerException( error, e );
}
}
}
-
- if( null != exception )
- {
- Component[] selection = (Component[]) list.toArray( new
Component[0] );
- decommission( selection );
- throw exception;
- }
- else
- {
- m_commissioned = true;
- }
+ m_commissioned = true;
}

/**
- * Initiate deactivation of all internal parts.
+ * Initiate decommissioning of all internal parts.
*/
public synchronized void decommission()
{
@@ -330,248 +288,27 @@
{
return;
}
-
- Component[] components = getComponents();
- decommission( components );
- }
-
- /**
- * Initiate deactivation of all internal parts.
- */
- private void decommission( Component[] components )
- {
- String label = m_handler.toString();
- DefaultCommissioner queue =
- new DefaultCommissioner( label, false, new
InternalCommissionerController( false ) );
-
- try
+ ComponentHandler[] components = getComponentHandlers();
+ if( components.length > 0 )
{
- int n = components.length -1;
- for( int i=n; i>-1; i-- )
+ m_provider.getLogger().debug( "decommissioning internal parts in
[" + m_provider + "]" );
+ for( int i=0; i<components.length; i++ )
{
- Component component = components[i];
+ ComponentHandler component = components[i];
try
{
- queue.add( component, 0 );
+ component.decommission();
}
catch( Throwable e )
{
- final String message =
- "Ignoring exception raised during deactivation.";
- getLogger().warn( message, e );
+ final String error =
+ "Error during the decommission of the internal parts
of a component."
+ + "\nProvider: " + m_provider
+ + "\nPart: " + component;
+ m_provider.getLogger().warn( error, e );
}
}
}
- finally
- {
- m_commissioned = false;
- }
+ m_commissioned = false;
}
-
- Component[] getComponents()
- {
- return (Component[]) m_handlers.values().toArray( new Component[0] );
- }
-
- private Logger getLogger()
- {
- return m_logger;
- }
-
- private Map processParts(
- ComponentController controller, ClassLoader classloader, String base,
PartReference[] references )
- throws ControlException, RemoteException
- {
- Map map = new Hashtable();
- for( int i=0; i < references.length; i++ )
- {
- PartReference ref = references[i];
- String key = ref.getKey();
- Directive part = ref.getDirective();
- if( part instanceof ComponentDirective )
- {
- Classpath classpath = new Classpath();
- ComponentDirective component = (ComponentDirective) part;
- ComponentModel model =
- controller.createComponentModel( classloader, classpath,
base, component );
- map.put( key, model );
- }
- else
- {
- final String error =
- "Foreign part ["
- + part.getClass()
- + "] not supported.";
- throw new UnsupportedOperationException( error );
- }
- }
- return map;
- }
-
- /**
- * Test controller.
- */
- public class InternalCommissionerController implements
CommissionerController
- {
- private boolean m_fail;
-
- InternalCommissionerController( boolean fail )
- {
- m_fail = fail;
- }
-
- /**
- * Notification that a commissioning or decommissioning
- * process has commenced.
- * @param event the commissioner event
- */
- public void started( CommissionerEvent event )
- {
- String message =
- getAction( event )
- + "["
- + getName( event )
- + "]";
- getLogger().debug( message );
- }
-
- /**
- * Notification that a commissioning or decommissioning
- * process has completed.
- * @param event the commissioner event
- */
- public void completed( CommissionerEvent event )
- {
- String message =
- getAction( event )
- + "["
- + getName( event )
- + "] completed in "
- + event.getDuration()
- + " milliseconds";
- getLogger().debug( message );
- }
-
- /**
- * Notification that a commissioning or decommissioning
- * process has been interrupted.
- * @param event the commissioner event
- * @exception TimeoutException thrown ofter logging event
- */
- public void interrupted( CommissionerEvent event ) throws
TimeoutException
- {
- String message =
- getAction( event )
- + "of ["
- + getName( event )
- + "] interrupted after "
- + event.getDuration()
- + " milliseconds";
- getLogger().debug( message );
- if( m_fail )
- {
- throw new TimeoutException( event.getDuration() );
- }
- }
-
- /**
- * Notification that a commissioning or decommissioning
- * process has been terminated.
- * @param event the commissioner event
- * @exception TimeoutError thrown ofter logging event
- */
- public void terminated( CommissionerEvent event ) throws TimeoutError
- {
- String message =
- getAction( event )
- + "of ["
- + getName( event )
- + "] terminated after "
- + event.getDuration()
- + " milliseconds";
- getLogger().debug( message );
- if( m_fail )
- {
- throw new TimeoutError( event.getDuration() );
- }
- }
-
- /**
- * Notification that a commissioning or decommissioning
- * process failed.
- * @param event the commissioner event
- * @param cause the causal exception
- * @exception InvocationTargetException throw after logging event
- */
- public void failed( CommissionerEvent event, Throwable cause )
throws InvocationTargetException
- {
- if( m_fail )
- {
- if( cause instanceof InvocationTargetException )
- {
- throw (InvocationTargetException) cause;
- }
- else
- {
- throw new InvocationTargetException( cause );
- }
- }
- else
- {
- String message =
- getAction( event )
- + "of ["
- + event.getSource()
- + "] failed due ["
- + cause.getClass().getName()
- + "]";
- getLogger().error( message, cause );
- }
- }
-
- private String getAction( CommissionerEvent event )
- {
- if( event.isCommissioning() )
- {
- return "commissioning ";
- }
- else
- {
- return "decommissioning ";
- }
- }
-
- private String getName( CommissionerEvent event )
- {
- Object source = event.getSource();
- if( source instanceof DefaultComponentHandler )
- {
- try
- {
- DefaultComponentHandler handler =
(DefaultComponentHandler) source;
- return handler.getComponentModel().getName();
- }
- catch( Exception e )
- {
- return source.toString();
- }
- }
- else
- {
- return source.toString();
- }
- }
- }
-
- private String[] getKeys( PartReference[] references )
- {
- String[] keys = new String[ references.length ];
- for( int i=0; i < references.length; i++ )
- {
- PartReference ref = references[i];
- String key = ref.getKey();
- keys[i] = key;
- }
- return keys;
- }
}

Modified:
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultProvider.java
===================================================================
---
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultProvider.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultProvider.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,5 +1,5 @@
/*
- * Copyright 2004 Stephen J. McConnell.
+ * Copyright 2004-2006 Stephen J. McConnell.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,14 +22,23 @@
import java.beans.PropertyChangeEvent;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.rmi.RemoteException;
import java.util.EventObject;
import java.util.EventListener;

import net.dpml.component.Provider;
+import net.dpml.component.Component;
import net.dpml.component.ControlException;
+import net.dpml.component.Service;
+import net.dpml.component.ServiceNotFoundException;
+import net.dpml.component.Disposable;
+import net.dpml.component.Status;

+import net.dpml.metro.PartsManager;
+import net.dpml.metro.ComponentHandler;
+
import net.dpml.state.State;
import net.dpml.state.StateEvent;
import net.dpml.state.StateListener;
@@ -37,23 +46,24 @@
import net.dpml.state.UnknownOperationException;
import net.dpml.state.impl.DefaultStateMachine;

+import net.dpml.lang.UnknownKeyException;
+
import net.dpml.util.Logger;
+import net.dpml.util.EventQueue;

/**
- * The DefaultProvider class maintains the state of a client instance. On
creation
+ * The DefaultProvider class maintains the state of a single instance. On
creation
* of a new DefaultProvider the implementation constructs a proxy based on
the
- * service clesses declared within the component type, establishes the
instance, and
+ * service classes declared within the component type, establishes the
instance, and
* executes initialization based on the state graph associated with the
* object. If a request is made by the container for the disposal of an
instance of
* this class, the implementation will execute a formal termination sequence
on the
- * client instance using the state graph declarations. Finally, if the
client instance
- * implements the Disposable interface - the implementation will invoke the
dispose
- * operation on the client instance.
+ * instance using the state graph declarations.
*
* @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
* @version @PROJECT-VERSION@
*/
-class DefaultProvider extends UnicastEventSource implements Provider
+class DefaultProvider extends UnicastEventSource implements Provider,
InvocationHandler
{
//-------------------------------------------------------------------
// state
@@ -69,37 +79,34 @@
*/
private final DefaultStateMachine m_machine;

+ /**
+ * Internal parts of the component.
+ */
+ private final PartsManager m_parts;
+
+ /**
+ * The proxied instance.
+ */
+ private final Object m_proxy;
+
+ //private final StateEventPropergator m_propergator;
+
//-------------------------------------------------------------------
// mutable state
//-------------------------------------------------------------------

+ private Status m_status = Status.INSTANTIATED;
+
/**
* The raw instance.
*/
private Object m_value;

/**
- * The proxied instance.
- */
- private Object m_proxy;
-
- /**
* Tag used within logging messages.
*/
private String m_tag;

- /**
- * The available state.
- */
- private boolean m_activated = false;
-
- /**
- * The available state.
- */
- private boolean m_disposed = false;
-
- //private final DefaultPartsManager m_parts;
-
//-------------------------------------------------------------------
// constructor
//-------------------------------------------------------------------
@@ -110,35 +117,95 @@
* @param handler the component handler
* @param logger the logging channel
*/
- DefaultProvider( DefaultComponentHandler handler, Logger logger )
+ DefaultProvider( EventQueue queue, DefaultComponentHandler handler,
Logger logger )
throws RemoteException, ControlException, InvocationTargetException
{
- super( logger );
+ super( queue, logger );

if( null == handler )
{
throw new NullPointerException( "handler" );
}
- if( null == logger )
+
+ m_handler = handler;
+
+ if( getLogger().isTraceEnabled() )
{
- throw new NullPointerException( "logger" );
+ getLogger().trace( "provider instantiation" );
}

- m_handler = handler;
- State graph = handler.getStateGraph();
- m_machine = new DefaultStateMachine( graph );
- m_machine.addPropertyChangeListener( new StateEventPropergator( this
) );
+ State graph = m_handler.getStateGraph();
+ m_machine = new DefaultStateMachine( queue, logger, graph );
+ //m_propergator = new StateEventPropergator();
+ //m_machine.addPropertyChangeListener( m_propergator );
+ m_parts = new DefaultPartsManager( this );

- //m_parts = new DefaultPartsManager( control, handler, logger );
-
- initialize();
+ ClassLoader classloader = m_handler.getClassLoader();
+ Class[] services = m_handler.getServiceClassArray();
+ if( allClassesAreInterfaces( services ) )
+ {
+ m_proxy = Proxy.newProxyInstance( classloader, services, this );
+ }
+ else
+ {
+ m_proxy = null;
+ }
}
-
+
+ void initialize()
+ throws RemoteException, ControlException, InvocationTargetException
+ {
+ synchronized( m_status )
+ {
+ m_status = Status.COMMISSIONING;
+ try
+ {
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace(
+ "instantiating ["
+ + m_handler.getImplementationClass().getName()
+ + "]" );
+ }
+
+ m_parts.commission();
+ m_value = m_handler.getComponentController().createInstance(
this );
+ m_tag = createTag( m_value );
+ if( getLogger().isDebugEnabled() )
+ {
+ getLogger().debug( "instantiated " + m_tag );
+ }
+
+ m_machine.initialize( m_value );
+ m_status = Status.AVAILABLE;
+ if( getLogger().isDebugEnabled() )
+ {
+ getLogger().debug( "activated " + m_tag );
+ }
+ }
+ catch( Exception e )
+ {
+ final String error =
+ "An error occured while attempting to initialize provider
[" + this + "]";
+ throw new ControllerException( error, e );
+ }
+ }
+ }
+
//-------------------------------------------------------------------
// Provider
//-------------------------------------------------------------------

/**
+ * Return the current status of the provider.
+ * @return the provider status
+ */
+ public Status getStatus()
+ {
+ return m_status;
+ }
+
+ /**
* Returns the current state of the instance.
* @return the current runtime state
*/
@@ -153,7 +220,11 @@
*/
public synchronized void addStateListener( StateListener listener )
{
- super.addListener( listener );
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "adding state listener [" + listener + "] to
" + m_tag );
+ }
+ m_machine.addStateListener( listener );
}

/**
@@ -162,9 +233,13 @@
*/
public synchronized void removeStateListener( StateListener listener )
{
- super.removeListener( listener );
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "removing state listener [" + listener + "]
to " + m_tag );
+ }
+ m_machine.removeStateListener( listener );
}
-
+
/**
* Return the runtime value associated with this instance.
* @param isolate if TRUE the value returned is a proxy exposing the
@@ -173,28 +248,48 @@
*/
public Object getValue( boolean isolate )
{
- if( isDisposed() )
+ synchronized( m_status )
{
- throw new IllegalStateException( "disposed" );
- }
- if( !m_activated )
- {
- throw new IllegalStateException( "deactivated" );
- }
- if( isolate )
- {
- if( null != m_proxy )
+ if( Status.INSTANTIATED.equals( m_status ) )
{
+ try
+ {
+ initialize();
+ }
+ catch( Exception e )
+ {
+ final String error =
+ "Initialization failure.";
+ throw new ControllerRuntimeException( error, e );
+ }
+ }
+ checkAvailable();
+ if( isolate && ( null != m_proxy ) )
+ {
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "returning proxied service " + m_tag
);
+ }
return m_proxy;
}
else
{
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "returning service instance " + m_tag
);
+ }
return m_value;
}
}
- else
+ }
+
+ private void checkAvailable()
+ {
+ if( !Status.AVAILABLE.equals( m_status ) )
{
- return m_value;
+ final String error =
+ "Provider is not available (current status " +
m_status.getName() + ")";
+ throw new IllegalStateException( error );
}
}

@@ -208,7 +303,12 @@
public synchronized State apply( String key )
throws UnknownTransitionException, InvocationTargetException
{
- return m_machine.apply( key, m_value );
+ Object value = getValue( false );
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "applying state transition [" + key + "] to "
+ m_tag );
+ }
+ return m_machine.apply( key, value );
}

/**
@@ -223,7 +323,12 @@
public synchronized Object exec( String name, Object[] args )
throws UnknownOperationException, InvocationTargetException
{
- return m_machine.execute( name, m_value, args );
+ Object value = getValue( false );
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "applying operation [" + name + "] to " +
m_tag );
+ }
+ return m_machine.execute( name, value, args );
}

/**
@@ -238,19 +343,84 @@
public Object invoke( String method, Object[] args )
throws UnknownOperationException, InvocationTargetException,
IllegalStateException
{
- return m_machine.invoke( m_value, method, args );
+ Object value = getValue( false );
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "invoking method [" + method + "] to " +
m_tag );
+ }
+ return m_machine.invoke( value, method, args );
}

+
+ /**
+ * Return a handler capable of supporting the requested service.
+ * @param service the service definition
+ * @return a component matching the serivce definiton
+ * @exception ServiceNotFoundException if no component found
+ * @exception RemoteException if a remote exception occurs
+ */
+ public Provider lookup( Service service ) throws
ServiceNotFoundException, RemoteException
+ {
+ if( getLogger().isDebugEnabled() )
+ {
+ getLogger().debug(
+ "mediating lookup for ["
+ + service.getServiceClass().getName()
+ + "]" );
+ }
+
+ // check if a child component can handle the request
+
+ ComponentHandler[] components = m_parts.getComponentHandlers();
+ for( int i=0; i<components.length; i++ )
+ {
+ Component component = components[i];
+ if( component.isaCandidate( service ) )
+ {
+ try
+ {
+ return component.getProvider();
+ }
+ catch( Exception e )
+ {
+ final String error =
+ "Internal error while attempting to resolve provider."
+ + "\nEnclosing Provider: " + this
+ + "\nComponent: " + component;
+ throw new ControllerRuntimeException( error, e );
+ }
+ }
+ }
+
+ // delegate to the parent
+
+ Provider parent = getParent();
+ if( null != parent )
+ {
+ return parent.lookup( service );
+ }
+ else
+ {
+ String classname = service.getServiceClass().getName();
+ throw new ServiceNotFoundException(
CompositionController.CONTROLLER_URI, classname );
+ }
+ }
+
+ public Provider getParent()
+ {
+ return m_handler.getParentProvider();
+ }
+

//--------------------------------------------------------------------------
// EventProducer

//--------------------------------------------------------------------------

- protected void processEvent( EventObject event )
+ public void processEvent( EventObject event )
{
if( event instanceof StateEvent )
{
StateEvent e = (StateEvent) event;
- EventListener[] listeners = listeners();
+ EventListener[] listeners = getEventListeners();
for( int i=0; i<listeners.length; i++ )
{
EventListener listener = listeners[i];
@@ -283,61 +453,44 @@
// Object
//-------------------------------------------------------------------

- public void finalize() throws Throwable
+ protected void finalize() throws Throwable
{
- getLogger().debug( "finalizing provider: " + this );
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "initiating finalization in " + m_tag );
+ }
+ String tag = m_tag;
dispose();
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "finalization completed in " + tag );
+ }
}

public String toString()
{
- return m_handler.getPath() + "#" + System.identityHashCode( m_value
);
+ if( null != m_tag )
+ {
+ return m_handler.getPath() + "#" + m_tag;
+ }
+ else
+ {
+ return m_handler.getPath() + "#0";
+ }
}

+ String getTag()
+ {
+ return m_tag;
+ }
+
//-------------------------------------------------------------------
// implementation
//-------------------------------------------------------------------

- private void initialize() throws InvocationTargetException,
ControlException
+ PartsManager getPartsManager()
{
- synchronized( getLock() )
- {
- ClassLoader classloader = m_handler.getClassLoader();
- Class[] services = m_handler.getServiceClassArray();
- if( allClassesAreInterfaces( services ) )
- {
- InvocationHandler invocationHandler = new
InstanceInvocationHandler( this );
- m_proxy = Proxy.newProxyInstance( classloader, services,
invocationHandler );
- }
- else
- {
- m_proxy = null;
- }
-
- if( getLogger().isDebugEnabled() )
- {
- getLogger().debug(
- "instantiating ["
- + m_handler.getImplementationClass().getName()
- + "]" );
- }
-
- m_value = m_handler.createNewObject( this );
- m_tag = createTag( m_value );
-
- if( getLogger().isDebugEnabled() )
- {
- getLogger().debug( "instantiated " + m_tag );
- }
-
- m_machine.initialize( m_value );
- m_activated = true;
-
- if( getLogger().isDebugEnabled() )
- {
- getLogger().debug( "activated " + m_tag );
- }
- }
+ return m_parts;
}

private boolean allClassesAreInterfaces( Class[] classes )
@@ -353,41 +506,37 @@
return true;
}

- boolean isAvailable()
- {
- return m_activated;
- }
-
public void dispose()
{
synchronized( getLock() )
{
- if( m_disposed )
+ if( Status.DECOMMISSIONING.equals( m_status ) ||
Status.DISPOSED.equals( m_status ) )
{
return;
}
- m_disposed = true;
- getLogger().debug( m_tag + "instance disposal" );
- deactivate();
+ m_status = Status.DECOMMISSIONING;
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "initiating disposal of " + m_tag );
+ }
+
+ m_machine.terminate( m_value );
+ m_parts.decommission();
+ //m_machine.removePropertyChangeListener( m_propergator );
m_machine.dispose();
+ if( m_parts instanceof Disposable )
+ {
+ Disposable disposable = (Disposable) m_parts;
+ disposable.dispose();
+ }
super.dispose();
- }
- }
-
- private void deactivate()
- {
- if( !m_activated )
- {
- return;
- }
-
- synchronized( getLock() )
- {
- getLogger().debug( m_tag + "deactivating instance" );
- m_machine.terminate( m_value );
+ m_status = Status.DISPOSED;
+ if( getLogger().isDebugEnabled() )
+ {
+ getLogger().debug( "instance disposal " + m_tag );
+ }
m_tag = null;
m_value = null;
- m_activated = false;
}
}

@@ -396,17 +545,27 @@
return m_handler;
}

+ /*
void addPropertyChangeListener( PropertyChangeListener listener )
{
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "adding property change listener to " + m_tag
);
+ }
m_machine.addPropertyChangeListener( listener );
m_handler.addPropertyChangeListener( listener );
}

void removePropertyChangeListener( PropertyChangeListener listener )
{
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "removing property change listener from " +
m_tag );
+ }
m_machine.removePropertyChangeListener( listener );
m_handler.removePropertyChangeListener( listener );
}
+ */

private String createTag( Object instance )
{
@@ -420,30 +579,45 @@
/**
* State event propergator implementation.
*/
- private final class StateEventPropergator implements
PropertyChangeListener
+ //private final class StateEventPropergator implements
PropertyChangeListener
+ //{
+ // /**
+ // * Handle a property change notification.
+ // * @param event the property change event
+ // */
+ // public void propertyChange( PropertyChangeEvent event )
+ // {
+ // //
+ // // fire a state change event to remote listeners
+ // //
+ //
+ // State oldState = (State) event.getOldValue();
+ // State newState = (State) event.getNewValue();
+ // fireStateEvent( oldState, newState );
+ // }
+ //}
+
+ //private void fireStateEvent( State oldState, State newState )
+ //{
+ // getLogger().debug( "state changing from: " + oldState + " to: " +
newState + " in " + m_tag );
+ // StateEvent event = new StateEvent( this, oldState, newState );
+ // enqueueEvent( event );
+ //}
+
+ /**
+ * Invoke the specified method on underlying object.
+ * This is called by the proxy object.
+ *
+ * @param proxy the proxy object
+ * @param method the method invoked on proxy object
+ * @param args the arguments supplied to method
+ * @return the return value of method
+ * @throws Throwable if an error occurs
+ */
+ public Object invoke( final Object proxy, final Method method, final
Object[] args )
+ throws InvocationTargetException, IllegalAccessException
{
- private final DefaultProvider m_holder;
-
- private StateEventPropergator( DefaultProvider holder )
- {
- m_holder = holder;
- }
-
- /**
- * Handle a property change notification.
- * @param event the property change event
- */
- public void propertyChange( PropertyChangeEvent event )
- {
- //
- // fire a state change event to remote listeners
- //
-
- State oldState = (State) event.getOldValue();
- State newState = (State) event.getNewValue();
- getLogger().debug( m_tag + " state changing from: " + oldState +
" to: " + newState );
- StateEvent stateEvent = new StateEvent( m_holder, oldState,
newState );
- m_holder.enqueueEvent( stateEvent );
- }
+ checkAvailable();
+ return method.invoke( m_value, args );
}
}

Deleted:
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/InstanceInvocationHandler.java
===================================================================
---
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/InstanceInvocationHandler.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/InstanceInvocationHandler.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,88 +0,0 @@
-/*
- * Copyright 2005 Stephen J. McConnell.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- * implied.
- *
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.dpml.metro.runtime;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-/**
- * Utility class that supports instance isolation.
- *
- * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
- * @version @PROJECT-VERSION@
- */
-final class InstanceInvocationHandler implements InvocationHandler
-{
- //-------------------------------------------------------------------
- // state
- //-------------------------------------------------------------------
-
- private final DefaultProvider m_instance;
-
- //-------------------------------------------------------------------
- // constructor
- //-------------------------------------------------------------------
-
- /**
- * Create a proxy invocation handler.
- *
- * @param instance the instance
- */
- public InstanceInvocationHandler( DefaultProvider instance )
- {
- if( null == instance )
- {
- throw new NullPointerException( "instance" );
- }
- m_instance = instance;
- }
-
- /**
- * Invoke the specified method on underlying object.
- * This is called by the proxy object.
- *
- * @param proxy the proxy object
- * @param method the method invoked on proxy object
- * @param args the arguments supplied to method
- * @return the return value of method
- * @throws Throwable if an error occurs
- */
- public Object invoke( final Object proxy, final Method method, final
Object[] args )
- throws InvocationTargetException, IllegalAccessException
- {
- DefaultProvider instance = getProvider();
- if( instance.isAvailable() )
- {
- Object target = instance.getValue( false );
- return method.invoke( target, args );
- }
- else
- {
- final String error =
- "Resource unavailable: " + instance;
- throw new IllegalStateException( error );
- }
- }
-
- protected DefaultProvider getProvider()
- {
- return m_instance;
- }
-}

Modified:
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/PartsInvocationHandler.java
===================================================================
---
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/PartsInvocationHandler.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/PartsInvocationHandler.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,5 +1,5 @@
/*
- * Copyright 2004 Stephen J. McConnell.
+ * Copyright 2004-2006 Stephen J. McConnell.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,7 +46,7 @@
/**
* The component.
*/
- private final PartsManager m_manager;
+ private final DefaultProvider m_provider;

//-------------------------------------------------------------------
// constructor
@@ -57,9 +57,9 @@
*
* @param manager the parts manager
*/
- PartsInvocationHandler( PartsManager manager )
+ PartsInvocationHandler( DefaultProvider provider )
{
- m_manager = manager;
+ m_provider = provider;
}

//-------------------------------------------------------------------
@@ -78,6 +78,7 @@
*/
public Object invoke( final Object proxy, final Method method, final
Object[] args ) throws Throwable
{
+ PartsManager manager = m_provider.getPartsManager();
final Class source = method.getDeclaringClass();
if( Object.class == source )
{
@@ -85,14 +86,14 @@
}
else if( PartsManager.class == source )
{
- return method.invoke( m_manager, args );
+ return method.invoke( manager, args );
}

final int semantic = getPartSemantic( method );
final String postfix = getPartPostfix( method );
final String key = getPartKey( method, semantic, postfix );

- final ComponentHandler handler = m_manager.getComponentHandler( key
);
+ final ComponentHandler handler = manager.getComponentHandler( key );

if( GET == semantic )
{
@@ -344,6 +345,14 @@
}
}

+ protected void finalize() throws Throwable
+ {
+ if( m_provider.getLogger().isTraceEnabled() )
+ {
+ m_provider.getLogger().trace( "finalizing parts invocation
handler" );
+ }
+ }
+
public static final int GET = 1;
public static final int RELEASE = -1;
public static final String GET_KEY = "get";
@@ -352,4 +361,4 @@
public static final String PROVIDER_KEY = "Provider";
public static final String HANDLER_KEY = "Handler";
public static final String MAP_KEY = "Map";
-}
\ No newline at end of file
+}

Modified:
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/StandardLogger.java
===================================================================
---
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/StandardLogger.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/StandardLogger.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,5 +1,5 @@
/*
- * Copyright 2004 Stephen J. McConnell.
+ * Copyright 2004-2006 Stephen J. McConnell.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

Modified:
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/UnicastEventSource.java
===================================================================
---
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/UnicastEventSource.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/UnicastEventSource.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,5 +1,5 @@
/*
- * Copyright 2005 Stephen J. McConnell.
+ * Copyright 2005-2006 Stephen J. McConnell.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,11 +21,16 @@
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.NoSuchObjectException;
+import java.lang.ref.WeakReference;
import java.util.EventObject;
import java.util.EventListener;
+import java.util.WeakHashMap;
+import java.util.List;
+import java.util.LinkedList;

import net.dpml.component.Disposable;

+import net.dpml.util.EventQueue;
import net.dpml.util.Logger;

/**
@@ -35,136 +40,26 @@
* @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
* @version @PROJECT-VERSION@
*/
-public abstract class UnicastEventSource extends UnicastRemoteObject
implements Disposable
+public abstract class UnicastEventSource extends
net.dpml.util.UnicastEventSource implements Disposable
{
- /**
- * Registered event listeners.
- */
- private EventListener[] m_listeners = new EventListener[0];
-
- /**
- * Internal synchronization lock.
- */
- private final Object m_lock = new Object();
-
- private final Logger m_logger;
-
private boolean m_disposed = false;

/**
* Creation of a new <tt>UnicastEventSource</tt>.
+ * @param queue the system event queue
* @param logger the assigned logging channel
* @exception RemoteException if a remote I/O exception occurs
*/
- protected UnicastEventSource( Logger logger ) throws RemoteException
+ protected UnicastEventSource( EventQueue queue, Logger logger ) throws
RemoteException
{
- super();
- m_logger = logger;
+ super( queue, logger );
}


//--------------------------------------------------------------------------
- // internal
+ // Disposable

//--------------------------------------------------------------------------

/**
- * Return the logging channel assigned to the event source.
- * @return the logging channel
- */
- protected Logger getLogger()
- {
- return m_logger;
- }
-
- /**
- * Abstract operation to be implemented by classes extending this base
class.
- * An implementation is reposible for the posting of the event to
associated
- * listeners. Event posting will be executed under a separate thread to
the
- * thread that initiated the event post.
- *
- * @param event the event to process
- */
- protected abstract void processEvent( EventObject event );
-
- /**
- * Add a listener to the set of listeners handled by this producer.
- * @param listener the event listener
- */
- protected void addListener( EventListener listener )
- {
- if( m_disposed )
- {
- throw new IllegalStateException( "disposed" );
- }
-
- if( null == listener )
- {
- throw new NullPointerException( "listener" );
- }
-
- synchronized( m_lock )
- {
- Object[] old = m_listeners;
- m_listeners = new EventListener[ old.length + 1 ];
- System.arraycopy( old, 0, m_listeners, 0, old.length );
- m_listeners[old.length] = listener;
- }
- }
-
- /**
- * Remove a listener to the set of listeners handled by this producer.
- * @param listener the event listener
- */
- protected void removeListener( EventListener listener )
- {
- if( null == listener )
- {
- throw new NullPointerException( "listener" );
- }
-
- if( m_disposed )
- {
- throw new IllegalStateException( "disposed" );
- }
-
- synchronized( m_lock )
- {
- if( m_listeners.length == 0 )
- {
- throw new IllegalArgumentException( "Listener not
registered." );
- }
- // create the copy
- EventListener[] replacement = new EventListener[
m_listeners.length - 1 ];
- // copy listeners from 0 up to the listener being removed
- int i=0;
- while( i < replacement.length && m_listeners[i] != listener )
- {
- replacement[i] = m_listeners[i++];
- }
- // check that the listener has been located
- if( i == replacement.length && m_listeners[i] != listener )
- {
- throw new IllegalArgumentException( "Listener not
registered." );
- }
- // complete the copy operation
- while( i < replacement.length )
- {
- replacement[i] = m_listeners[++i];
- }
- // commit the copy
- m_listeners = replacement;
- }
- }
-
- /**
- * Return the internal synchronization lock.
- * @return the lock object
- */
- protected Object getLock()
- {
- return m_lock;
- }
-
- /**
* Retun the disposed state of this event source.
* @return true if disposed
*/
@@ -172,102 +67,29 @@
{
return m_disposed;
}
-
+
/**
- * Dispose of the event source.
+ * Handle instance disposal.
*/
public void dispose()
{
- if( m_disposed )
+ if( !m_disposed )
{
- return;
- }
-
- synchronized( m_lock )
- {
- EventListener[] listeners = listeners();
- for( int i=0; i < listeners.length; i++ )
- {
- EventListener listener = listeners[i];
- removeListener( listener );
- }
+ super.terminate();
m_disposed = true;
- getLogger().debug( "disposed" );
}
-
- Thread thread = new Terminator( this, m_logger );
- thread.start();
}

- /**
- * Internal class that handles instance retraction for the RMI runtime.
- */
- private class Terminator extends Thread
- {
- private final UnicastEventSource m_source;
- private final Logger m_logger;
-
- /**
- * Internal class terminator that handles unexport of an event source
- * under a separate thread.
- * @param source the event source instance
- * @param logger the event source logger
- */
- Terminator( UnicastEventSource source, Logger logger )
- {
- m_source = source;
- m_logger = logger;
- }
-
- /**
- * Terminator execution.
- */
- public void run()
- {
- try
- {
- UnicastRemoteObject.unexportObject( m_source, true );
- m_logger.debug( "terminated" );
- }
- catch( NoSuchObjectException e )
- {
- boolean ignoreThis = true; // objct has not been exported
- }
- catch( RemoteException e )
- {
- final String error =
- "Unexpected remote exception while retracting component
handler remote reference.";
- m_logger.warn( error, e );
- }
- }
- }
+
//--------------------------------------------------------------------------
+ // internal
+
//--------------------------------------------------------------------------

/**
- * Return this node's preference/node change listeners. Even though
- * we're using a copy-on-write lists, we use synchronized accessors to
- * ensure information transmission from the writing thread to the
- * reading thread.
- * @return the event listeners
+ * Return the logging channel assigned to the event source.
+ * @return the logging channel
*/
- protected EventListener[] listeners()
+ Logger getLogger()
{
- synchronized( m_lock )
- {
- return m_listeners;
- }
+ return super.getLocalLogger();
}
-
- /**
- * Enqueue an event for delivery to registered
- * listeners unless there are no registered
- * listeners.
- * @param event the event to enqueue
- */
- protected void enqueueEvent( EventObject event )
- {
- if( m_listeners.length != 0 )
- {
- CompositionController.enqueueEvent( event );
- }
- }
}

Modified: trunk/main/metro/state/api/src/main/net/dpml/state/StateMachine.java
===================================================================
--- trunk/main/metro/state/api/src/main/net/dpml/state/StateMachine.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/metro/state/api/src/main/net/dpml/state/StateMachine.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -59,13 +59,25 @@
* Add a property change listener to the state machine.
* @param listener the property change listener
*/
- void addPropertyChangeListener( final PropertyChangeListener listener );
+ //void addPropertyChangeListener( final PropertyChangeListener listener
);

/**
* Remove a property change listener from the state machine.
* @param listener the property change listener
*/
- void removePropertyChangeListener( final PropertyChangeListener listener
);
+ //void removePropertyChangeListener( final PropertyChangeListener
listener );
+
+ /**
+ * Add a state change listener to the state machine.
+ * @param listener the state listener
+ */
+ void addStateListener( final StateListener listener );
+
+ /**
+ * Remove a state listener from the state machine.
+ * @param listener the state listener
+ */
+ void removeStateListener( final StateListener listener );

/**
* Return the current state.

Modified: trunk/main/metro/state/impl/build.xml
===================================================================
--- trunk/main/metro/state/impl/build.xml 2006-06-08 08:10:50 UTC (rev
1512)
+++ trunk/main/metro/state/impl/build.xml 2006-06-19 03:26:47 UTC (rev
1513)
@@ -24,10 +24,13 @@
<transit:import uri="local:template:dpml/tools/standard"/>

<target name="build" depends="standard.build">
+ <!--
<rmic base="${project.target.classes.main.dir}"
classpathref="project.compile.path">
+ <include name="**/DefaultStateMachine.class"/>
<include name="**/DefaultStateListener.class"/>
</rmic>
+ -->
</target>

</project>

Deleted:
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultStateListener.java
===================================================================
---
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultStateListener.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultStateListener.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,120 +0,0 @@
-/*
- * Copyright 2005 Stephen J. McConnell.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- * implied.
- *
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.dpml.state.impl;
-
-import java.beans.PropertyChangeSupport;
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeEvent;
-import java.rmi.server.UnicastRemoteObject;
-import java.rmi.RemoteException;
-
-import net.dpml.state.State;
-import net.dpml.state.StateEvent;
-import net.dpml.state.StateListener;
-
-
-/**
- * State listener that listens to a remote state change source and
propergates
- * events locally as PropertyChangeEvent instances. Consumers should
register
- * PropertyChangeListener instances and track 'state' events as required.
- *
- * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
- * @version @PROJECT-VERSION@
- */
-public final class DefaultStateListener extends UnicastRemoteObject
implements StateListener
-{
- private static final String PROPERTY_NAME = "state";
-
- private final PropertyChangeSupport m_support;
-
- /**
- * Creation of a new state listener.
- * @exception RemoteException if a remote error occurs
- */
- public DefaultStateListener() throws RemoteException
- {
- super();
- m_support = new PropertyChangeSupport( this );
- }
-
- /**
- * Notify the listener of a state change.
- *
- * @param event the state change event
- */
- public void stateChanged( final StateEvent event )
- {
- final Object source = event.getSource();
- final State oldValue = event.getFromState();
- final State newValue = event.getToState();
- final PropertyChangeEvent e =
- new PropertyChangeEvent( source, PROPERTY_NAME, oldValue, newValue
);
- m_support.firePropertyChange( e );
- }
-
- /**
- * Add a local property change listener to this remote listener.
- * @param listener the property change listener to add
- */
- public void addPropertyChangeListener( final PropertyChangeListener
listener )
- {
- m_support.addPropertyChangeListener( listener );
- }
-
- /**
- * Remove a local property change listener from this remote listener.
- * @param listener the property change listener to remove
- */
- public void removePropertyChangeListener( final PropertyChangeListener
listener )
- {
- m_support.removePropertyChangeListener( listener );
- }
-
- /**
- * Compare this object to another for equality.
- * @param other the other object
- * @return true if the object is equal to this object
- */
- public boolean equals( Object other )
- {
- if( null == other )
- {
- return false;
- }
- else if( getClass().equals( other.getClass() ) )
- {
- DefaultStateListener listener = (DefaultStateListener) other;
- return m_support.equals( listener.m_support );
- }
- else
- {
- return false;
- }
- }
-
- /**
- * Compute the hashcode for this instance.
- * @return the hashcode value
- */
- public int hashCode()
- {
- return m_support.hashCode();
- }
-}
-

Modified:
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultStateMachine.java
===================================================================
---
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultStateMachine.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultStateMachine.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -28,6 +28,10 @@
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
+import java.util.WeakHashMap;
+import java.util.EventObject;
+import java.util.EventListener;
+import java.rmi.RemoteException;

import net.dpml.state.State;
import net.dpml.state.Transition;
@@ -40,14 +44,21 @@
import net.dpml.state.UnknownOperationException;
import net.dpml.state.UnknownTransitionException;
import net.dpml.state.IntegrityRuntimeException;
+import net.dpml.state.StateListener;
+import net.dpml.state.StateEvent;

+import net.dpml.util.Logger;
+import net.dpml.util.UnicastEventSource;
+import net.dpml.util.EventQueue;
+import net.dpml.util.EventHandler;
+
/**
* Default state-machine implementation.
*
* @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
* @version @PROJECT-VERSION@
*/
-public class DefaultStateMachine implements StateMachine
+public class DefaultStateMachine implements StateMachine, EventHandler
{
/**
* Constant name used to reference a state change in a property event.
@@ -67,12 +78,20 @@
// state

//-------------------------------------------------------------------------------

- private final PropertyChangeSupport m_support;
+ //private final PropertyChangeSupport m_support;

private State m_state;
private boolean m_active = false;
private boolean m_disposed = false;
+
+ private final Object m_lock = new Object();

+ private final EventQueue m_queue;
+
+ private final WeakHashMap m_listeners = new WeakHashMap();
+
+ private final Logger m_logger;
+

//-------------------------------------------------------------------------------
// constructor

//-------------------------------------------------------------------------------
@@ -81,33 +100,92 @@
* Creation of a new state machine using a state graph.
* @param state the state graph
*/
- public DefaultStateMachine( State state )
+ public DefaultStateMachine( EventQueue queue, Logger logger, State state
) throws RemoteException
{
+ m_queue = queue;
+ m_logger = logger;
m_state = state;
- m_support = new PropertyChangeSupport( this );
}


//-------------------------------------------------------------------------------
// StateMachine

//-------------------------------------------------------------------------------

+ private Logger getLogger()
+ {
+ return m_logger;
+ }
+
/**
- * Add a property change listener to the state machine.
- * @param listener the property change listener
+ * Add a state change listener to the state machine.
+ * @param listener the state listener
*/
- public void addPropertyChangeListener( final PropertyChangeListener
listener )
+ public void addStateListener( final StateListener listener )
{
- m_support.addPropertyChangeListener( listener );
+ if( null == listener )
+ {
+ throw new NullPointerException( "listener" );
+ }
+ checkDisposed();
+ synchronized( m_lock )
+ {
+ m_listeners.put( listener, null );
+ }
}

/**
- * Remove a property change listener from the state machine.
- * @param listener the property change listener
+ * Remove a state listener from the state machine.
+ * @param listener the state listener
*/
- public void removePropertyChangeListener( final PropertyChangeListener
listener )
+ public void removeStateListener( final StateListener listener )
{
- m_support.removePropertyChangeListener( listener );
+ if( null == listener )
+ {
+ throw new NullPointerException( "listener" );
+ }
+ checkDisposed();
+ synchronized( m_lock )
+ {
+ m_listeners.remove( listener );
+ }
}
+
+ public EventListener[] getEventListeners()
+ {
+ return getStateListeners();
+ }
+
+ private StateListener[] getStateListeners()
+ {
+ checkDisposed();
+ synchronized( m_lock )
+ {
+ return (StateListener[]) m_listeners.keySet().toArray( new
StateListener[0] );
+ }
+ }
+
+ public void processEvent( EventObject event )
+ {
+ StateListener[] listeners = getStateListeners();
+ for( int i=0; i < listeners.length; i++ )
+ {
+ StateListener listener = listeners[i];
+ if( event instanceof StateEvent )
+ {
+ try
+ {
+ StateEvent e = (StateEvent) event;
+ listener.stateChanged( e );
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "StateListener notification error.";
+ getLogger().error( error, e );
+ }
+ }
+ }
+ }

/**
* Return the current state.
@@ -401,14 +479,17 @@
*/
public void dispose()
{
+ synchronized( m_lock )
+ {
+ StateListener[] listeners = getStateListeners();
+ for( int i=0; i<listeners.length; i++ )
+ {
+ StateListener listener = listeners[i];
+ removeStateListener( listener );
+ }
+ }
m_disposed = true;
m_state = null;
- PropertyChangeListener[] listeners =
m_support.getPropertyChangeListeners();
- for( int i=0; i<listeners.length; i++ )
- {
- PropertyChangeListener listener = listeners[i];
- m_support.removePropertyChangeListener( listener );
- }
}


//-------------------------------------------------------------------------------
@@ -480,6 +561,7 @@
throw new InvocationTargetException( e );
}
}
+
private State terminate( List list, Object object ) throws Exception
{
Action action = getTerminationAction();
@@ -580,10 +662,9 @@
{
final State oldState = m_state;
m_state = state;
- final PropertyChangeEvent event =
- new PropertyChangeEvent(
- this, PROPERTY_NAME, oldState, state );
- m_support.firePropertyChange( event );
+
+ final StateEvent event = new StateEvent( this, oldState,
state );
+ m_queue.enqueueEvent( event );
}
}
}
@@ -920,4 +1001,5 @@
return new URI( path );
}
}
+
}

Modified:
trunk/main/metro/state/impl/src/test/net/dpml/state/test/DefaultStateMachineTestCase.java
===================================================================
---
trunk/main/metro/state/impl/src/test/net/dpml/state/test/DefaultStateMachineTestCase.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/state/impl/src/test/net/dpml/state/test/DefaultStateMachineTestCase.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -31,6 +31,10 @@
import net.dpml.state.impl.DefaultStateMachine;
import net.dpml.state.impl.StateDecoder;

+import net.dpml.util.EventQueue;
+import net.dpml.util.Logger;
+import net.dpml.util.DefaultLogger;
+
/**
* Default state machine test-case.
*
@@ -39,7 +43,9 @@
public class DefaultStateMachineTestCase extends AbstractEncodingTestCase
{
private State m_state;
+ private EventQueue m_queue;
private DefaultStateMachine m_machine;
+ private Logger m_logger;

/**
* Testcase setup.
@@ -54,7 +60,9 @@
{
StateDecoder builder = new StateDecoder();
m_state = builder.loadState( example.toURI() );
- m_machine = new DefaultStateMachine( m_state );
+ m_logger = new DefaultLogger( "test" );
+ m_queue = new EventQueue( m_logger );
+ m_machine = new DefaultStateMachine( m_queue, m_logger, m_state
);
}
catch( Throwable e )
{

Modified: trunk/main/metro/test/build.xml
===================================================================
--- trunk/main/metro/test/build.xml 2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/metro/test/build.xml 2006-06-19 03:26:47 UTC (rev 1513)
@@ -48,19 +48,6 @@
<state name="terminated" terminal="true"/>
</state>
</c:type>
- <c:type class="net.dpml.test.ObserverComponent" name="observer">
- <state>
- <trigger event="initialization">
- <transition name="init" target="available"/>
- </trigger>
- <state name="available">
- <trigger event="termination">
- <transition name="terminate" target="../terminated"/>
- </trigger>
- </state>
- <state name="terminated" terminal="true"/>
- </state>
- </c:type>
<c:type class="net.dpml.test.SingletonComponent" name="example"
threadsafe="true"/>
<c:type class="net.dpml.test.ContextTestComponent" name="context"
threadsafe="true"/>

@@ -73,13 +60,6 @@
</context>
</c:component>

- <c:component dest="target/test/observer.part" test="true"
- type="net.dpml.test.ObserverComponent">
- <context>
- <entry key="color" method="RED"/>
- </context>
- </c:component>
-
<c:component dest="target/test/example-2.part" test="true"
type="net.dpml.test.ExampleComponent" name="transient"
collection="SOFT" lifestyle="transient">
<context>
@@ -91,7 +71,7 @@
</context>
</c:component>

- <c:component dest="target/test/example-3.part" test="true"
+ <c:component dest="target/test/example-3.part" test="true" name="weak"
type="net.dpml.test.SingletonComponent" lifestyle="SINGLETON"
collection="WEAK">
<context>
<entry key="color" method="RED"/>

Modified: trunk/main/metro/test/etc/data/logging.properties
===================================================================
--- trunk/main/metro/test/etc/data/logging.properties 2006-06-08 08:10:50
UTC (rev 1512)
+++ trunk/main/metro/test/etc/data/logging.properties 2006-06-19 03:26:47
UTC (rev 1513)
@@ -1,3 +1,4 @@
.level=INFO
sun.rmi.level=INFO
sun.rmi.transport.tcp.level=INFO
+weak.level=FINE
\ No newline at end of file

Deleted: trunk/main/metro/test/src/main/net/dpml/test/ObserverComponent.java
===================================================================
--- trunk/main/metro/test/src/main/net/dpml/test/ObserverComponent.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/metro/test/src/main/net/dpml/test/ObserverComponent.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,161 +0,0 @@
-/*
- * Copyright 2005 Stephen J. McConnell.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- * implied.
- *
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.dpml.test;
-
-import java.awt.Color;
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeEvent;
-import java.util.List;
-import java.util.LinkedList;
-
-import net.dpml.logging.Logger;
-
-/**
- * Component implementation that demonstrates the use of a context
inner-class.
- *
- * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
- * @version @PROJECT-VERSION@
- */
-public class ObserverComponent implements ColorManager,
PropertyChangeListener
-{
- //------------------------------------------------------------------
- // concerns
- //------------------------------------------------------------------
-
- /**
- * Component driven context criteria specification.
- */
- public interface Context
- {
- /**
- * Return a non-optional color value.
- * @return the color
- */
- Color getColor();
-
- /**
- * Add a property change listener to the context object.
- * @param listener the property change listener
- */
- void addPropertyChangeListener( PropertyChangeListener listener );
-
- /**
- * Remove a property change listener from the context object.
- * @param listener the property change listener
- */
- void removePropertyChangeListener( PropertyChangeListener listener );
- }
-
- //------------------------------------------------------------------
- // state
- //------------------------------------------------------------------
-
- /**
- * The logging channel.
- */
- private final Logger m_logger;
-
- /**
- * The assigned context instance.
- */
- private final Context m_context;
-
- /**
- * Internal list of events we receive.
- */
- private final List m_list = new LinkedList();
-
- //------------------------------------------------------------------
- // constructor
- //------------------------------------------------------------------
-
- /**
- * Creation of a new <tt>ExampleComponent</tt> using a supplied
- * logging channel and context.
- *
- * @param logger the assigned logging channel
- * @param context the assigned context
- */
- public ObserverComponent( final Logger logger, final Context context )
- {
- m_context = context;
- m_logger = logger;
-
- m_context.addPropertyChangeListener( this );
-
- getLogger().debug( "example component created" );
- }
-
- //------------------------------------------------------------------
- // PropertyChangeListener
- //------------------------------------------------------------------
-
- /**
- * Property change notification form the content implementation.
- * @param event the property change event
- */
- public void propertyChange( PropertyChangeEvent event )
- {
- m_list.add( event );
- String name = event.getPropertyName();
- Object oldValue = event.getOldValue();
- Object newValue = event.getNewValue();
- getLogger().info(
- "property [" + name + "] changed." );
- }
-
- //------------------------------------------------------------------
- // Testcase hook
- //------------------------------------------------------------------
-
- /**
- * Return the event list (used by testcase).
- * @return the event list
- */
- public List getEventList()
- {
- return m_list;
- }
-
- //------------------------------------------------------------------
- // Example
- //------------------------------------------------------------------
-
- /**
- * Return the color value from the supplied context.
- * @return the color value
- */
- public Color getColor()
- {
- return m_context.getColor();
- }
-
- //------------------------------------------------------------------
- // internal
- //------------------------------------------------------------------
-
- /**
- * Return the assigned logging channel.
- * @return the logging channel
- */
- private Logger getLogger()
- {
- return m_logger;
- }
-}

Modified:
trunk/main/metro/test/src/test/net/dpml/test/runtime/ComponentModelTestCase.java
===================================================================
---
trunk/main/metro/test/src/test/net/dpml/test/runtime/ComponentModelTestCase.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/test/src/test/net/dpml/test/runtime/ComponentModelTestCase.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,5 +1,5 @@
/*
- * Copyright 2005 Stephen J. McConnell.
+ * Copyright 2005-2006 Stephen J. McConnell.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -105,7 +105,7 @@
*/
public void testLifestylePolicy() throws Exception
{
- assertEquals( "initial-lifestyle", LifestylePolicy.THREAD,
m_model.getLifestylePolicy() );
+ assertEquals( "initial-lifestyle", LifestylePolicy.SYSTEM,
m_model.getLifestylePolicy() );
}

/**

Deleted:
trunk/main/metro/test/src/test/net/dpml/test/runtime/ObserverTestCase.java
===================================================================
---
trunk/main/metro/test/src/test/net/dpml/test/runtime/ObserverTestCase.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/test/src/test/net/dpml/test/runtime/ObserverTestCase.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,72 +0,0 @@
-/*
- * Copyright 2005 Stephen J. McConnell.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- * implied.
- *
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.dpml.test.runtime;
-
-import java.awt.Color;
-import java.io.File;
-import java.net.URI;
-
-import junit.framework.TestCase;
-
-import net.dpml.component.Component;
-import net.dpml.component.Controller;
-import net.dpml.component.Provider;
-
-import net.dpml.metro.data.ValueDirective;
-import net.dpml.metro.ComponentModel;
-import net.dpml.metro.ComponentModelManager;
-import net.dpml.metro.ContextModelManager;
-
-/**
- * Test aspects of the component model implementation.
- * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
- * @version @PROJECT-VERSION@
- */
-public class ObserverTestCase extends TestCase
-{
- private ComponentModelManager m_model;
-
- /**
- * Test case setup.
- * @exception Exception if an error occurs
- */
- public void setUp() throws Exception
- {
- final String path = "observer.part";
- final File test = new File( System.getProperty( "project.test.dir" )
);
- final URI uri = new File( test, path ).toURI();
- m_model = (ComponentModelManager) Controller.STANDARD.createModel(
uri );
- }
-
- /**
- * Test mutation of the context model.
- * @exception Exception if an error occurs
- */
- public void testContextModel() throws Exception
- {
- ContextModelManager context = (ContextModelManager)
m_model.getContextManager();
- Component component = Controller.STANDARD.createComponent(
(ComponentModel) m_model );
- Provider provider = component.getProvider();
- Object instance = provider.getValue( false );
- String key = "color";
- ValueDirective newDirective = new ValueDirective(
Color.class.getName(), "BLUE", (String) null );
- context.setEntryDirective( key, newDirective );
- component.decommission();
- }
-}

Modified:
trunk/main/metro/test/src/test/net/dpml/test/runtime/ProviderTestCase.java
===================================================================
---
trunk/main/metro/test/src/test/net/dpml/test/runtime/ProviderTestCase.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/test/src/test/net/dpml/test/runtime/ProviderTestCase.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,5 +1,5 @@
/*
- * Copyright 2005 Stephen J. McConnell.
+ * Copyright 2005-2006 Stephen J. McConnell.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,11 +31,14 @@
import net.dpml.component.Provider;
import net.dpml.state.State;
import net.dpml.state.StateListener;
-import net.dpml.state.impl.DefaultStateListener;
+import net.dpml.state.StateEvent;

import net.dpml.test.ColorManager;
import net.dpml.test.ExampleComponent;

+import net.dpml.util.Logger;
+import net.dpml.util.DefaultLogger;
+
/**
* Test general behaviour of a Provider without consideration for lifestyle.
* @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
@@ -122,31 +125,6 @@
}

/**
- * Test invalid listener removal.
- * @exception Exception if an error occurs
- */
- public void testUnknownListenerRemoval() throws Exception
- {
- Component component = CONTROLLER.createComponent( m_uri );
- component.commission();
- Provider instance = component.getProvider();
- try
- {
- StateListener listener = new DefaultStateListener();
- instance.removeStateListener( listener );
- fail( "IllegalArgumentException was not thown" );
- }
- catch( IllegalArgumentException e )
- {
- // success
- }
- finally
- {
- component.decommission();
- }
- }
-
- /**
* Test activation/deactivation cycle.
* @exception Exception if an error occurs
*/
@@ -154,15 +132,6 @@
{
Component component = CONTROLLER.createComponent( m_uri );
DefaultStateListener listener = new DefaultStateListener();
- listener.addPropertyChangeListener(
- new PropertyChangeListener()
- {
- public void propertyChange( PropertyChangeEvent event )
- {
- State oldState = (State) event.getOldValue();
- State state = (State) event.getNewValue();
- }
- } );
component.commission();
assertTrue( "is-active", component.isActive() );
Provider instance = component.getProvider();
@@ -215,4 +184,13 @@
component.decommission();
}
}
+
+ private class DefaultStateListener implements StateListener
+ {
+ private Logger m_logger = new DefaultLogger( "test" );
+ public void stateChanged( StateEvent event )
+ {
+ m_logger.info( "event: " + event );
+ }
+ }
}

Modified:
trunk/main/metro/test/src/test/net/dpml/test/runtime/WeakCollectionPolicyTestCase.java
===================================================================
---
trunk/main/metro/test/src/test/net/dpml/test/runtime/WeakCollectionPolicyTestCase.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/metro/test/src/test/net/dpml/test/runtime/WeakCollectionPolicyTestCase.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -1,5 +1,5 @@
/*
- * Copyright 2005 Stephen J. McConnell.
+ * Copyright 2005-2006 Stephen J. McConnell.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -60,6 +60,7 @@
assertTrue( "is-active", component.isActive() );
Provider one = component.getProvider();
Provider two = component.getProvider();
+
int count = component.size();

//

Modified: trunk/main/transit/core/src/main/net/dpml/lang/Part.java
===================================================================
--- trunk/main/transit/core/src/main/net/dpml/lang/Part.java 2006-06-08
08:10:50 UTC (rev 1512)
+++ trunk/main/transit/core/src/main/net/dpml/lang/Part.java 2006-06-19
03:26:47 UTC (rev 1513)
@@ -75,7 +75,7 @@
private final Logger m_logger;

/**
- * Load a part from an external XML source.
+ * Load a part from an external XML source with part caching.
* @param uri the external part source
* @return the resolved part
* @exception IOException of an I/O error occurs
@@ -423,14 +423,15 @@
{
int id = System.identityHashCode( classloader );
StringBuffer buffer = new StringBuffer();
- buffer.append( "created classloader " );
- buffer.append( m_info.getURI().toString() );
- buffer.append( "#" + category.toString() );
- buffer.append( " (" + id + ")" );
+ buffer.append( "created new " );
+ buffer.append( category.toString() );
+ buffer.append( " classloader" );
+ buffer.append( "\n ID: " + id );
+ buffer.append( "\n URI: " + m_info.getURI().toString() );
ClassLoader parent = classloader.getParent();
if( null != parent )
{
- buffer.append( " extends (" + System.identityHashCode(
parent ) + ")" );
+ buffer.append( "\n Extends: " + System.identityHashCode(
parent ) );
}
if( classloader instanceof URLClassLoader )
{

Modified: trunk/main/transit/core/src/main/net/dpml/lang/PartDecoder.java
===================================================================
--- trunk/main/transit/core/src/main/net/dpml/lang/PartDecoder.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/transit/core/src/main/net/dpml/lang/PartDecoder.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -65,12 +65,13 @@
}

private Map m_map = new Hashtable();
+ private Map m_builders = new Hashtable();

private Logger m_logger;

private PartDecoder()
{
- m_logger = new DefaultLogger();
+ m_logger = new DefaultLogger( "dpml.lang" );
}

/**
@@ -86,9 +87,17 @@
{
throw new NullPointerException( "uri" );
}
+ if( getLogger().isDebugEnabled() )
+ {
+ getLogger().debug( "loading part [" + uri + "]" );
+ }
String key = buildKey( uri );
if( cache )
{
+ if( getLogger().isDebugEnabled() )
+ {
+ getLogger().debug( "using cache key part [" + key + "]" );
+ }
WeakReference ref = (WeakReference) m_map.get( key );
if( null != ref )
{
@@ -97,18 +106,17 @@
{
if( getLogger().isDebugEnabled() )
{
- getLogger().debug( "loading part [" + uri + "] from
cache." );
+ getLogger().debug( "located part in cache" );
}
return part;
}
}
}
+
+ // cache based retrival was either not requested or no cache value
present
+
try
{
- if( getLogger().isDebugEnabled() )
- {
- getLogger().debug( "loading part [" + uri + "] from source."
);
- }
final Document document = DOCUMENT_BUILDER.parse( uri );
final Element root = document.getDocumentElement();
Part value = decodePart( uri, root );
@@ -116,6 +124,12 @@
{
WeakReference reference = new WeakReference( value );
m_map.put( key, reference );
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "caching part"
+ + "\n URI: " + uri
+ + "\n Key: " + key );
+ }
}
return value;
}
@@ -123,7 +137,7 @@
{
final String error =
"An error while attempting to load a part."
- + "\nURI: " + uri;
+ + "\n URI: " + uri;
IOException exception = new IOException( error );
exception.initCause( e );
throw exception;
@@ -210,6 +224,10 @@
String name = info.getTypeName();
if( "plugin".equals( name ) )
{
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "reading plugin definition" );
+ }
String classname = ElementHelper.getAttribute( strategy,
"class" );
Element[] elements = ElementHelper.getChildren( strategy );
Value[] values = VALUE_DECODER.decodeValues( elements );
@@ -217,6 +235,10 @@
}
else if( "resource".equals( name ) )
{
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "reading resource definition" );
+ }
String urn = ElementHelper.getAttribute( strategy, "urn" );
String path = ElementHelper.getAttribute( strategy, "path" );
return new Resource( logger, information, classpath, urn,
path );
@@ -236,10 +258,21 @@
{
// this is a foreign part

+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "reading foreign part definition" );
+ }
try
{
URI uri = getDecoderURI( strategy );
Builder builder = loadForeignBuilder( uri );
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace(
+ "loaded forign builder ["
+ + builder.getClass().getName()
+ + "]" );
+ }
return builder.build( information, classpath, strategy );
}
catch( Exception ioe )
@@ -297,9 +330,37 @@
return m_logger;
}

+ /**
+ * Load a forign part builder. The implementation will attempt to
resolve a
+ * plugin defintion from the supplied uri, caching a reference to
+ * the builder, and returning the plugin instance as a builder instance.
+ *
+ * @param uri the part builder uri
+ * @see Builder
+ * @exception DecodingException if a part decoding error occurs
+ * @exception Exception if part loading error occurs
+ */
private Builder loadForeignBuilder( URI uri ) throws DecodingException,
Exception
{
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "loading builder [" + uri + "]" );
+ }
Part part = loadPart( uri, true );
+ WeakReference ref = (WeakReference) m_builders.get( uri );
+ if( null != ref )
+ {
+ Builder builder = (Builder) ref.get();
+ if( null != builder )
+ {
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "located builder in cache" );
+ }
+ return builder;
+ }
+ }
+
if( part instanceof Plugin )
{
Plugin plugin = (Plugin) part;
@@ -308,7 +369,14 @@
Object object = plugin.instantiate( args );
if( object instanceof Builder )
{
- return (Builder) object;
+ Builder builder = (Builder) object;
+ WeakReference reference = new WeakReference( builder );
+ m_builders.put( uri, reference );
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "added builder in cache" );
+ }
+ return builder;
}
else
{

Modified:
trunk/main/transit/core/src/main/net/dpml/transit/DefaultCacheModel.java
===================================================================
--- trunk/main/transit/core/src/main/net/dpml/transit/DefaultCacheModel.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/transit/core/src/main/net/dpml/transit/DefaultCacheModel.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -43,11 +43,13 @@
import net.dpml.transit.model.CacheListener;
import net.dpml.transit.model.CacheDirectoryChangeEvent;
import net.dpml.transit.model.CacheEvent;
-import net.dpml.util.PropertyResolver;

import net.dpml.lang.DuplicateKeyException;
import net.dpml.lang.UnknownKeyException;

+import net.dpml.util.PropertyResolver;
+import net.dpml.util.EventQueue;
+
/**
* Default implementation of the cache model that maintains information
* about the current cache directory and the associated hosts.
@@ -84,10 +86,10 @@
* @param directive the cache configuration directive
* @exception Exception if an error occurs
*/
- public DefaultCacheModel( Logger logger, CacheDirective directive )
+ public DefaultCacheModel( EventQueue queue, Logger logger,
CacheDirective directive )
throws Exception
{
- super( logger );
+ super( queue, logger );

if( null == directive )
{
@@ -98,7 +100,7 @@
{
Logger log = logger.getChildLogger( "layout" );
LayoutDirective[] layouts = directive.getLayoutDirectives();
- m_registry = new DefaultLayoutRegistryModel( log, layouts );
+ m_registry = new DefaultLayoutRegistryModel( queue, log, layouts
);
String layout = directive.getCacheLayout();
m_layout = m_registry.getLayoutModel( layout );
}
@@ -314,7 +316,8 @@
String id = directive.getID();
Logger logger = getLogger().getChildLogger( id );
LayoutRegistryModel registry = getLayoutRegistryModel();
- HostModel model = new DefaultHostModel( logger, directive,
registry );
+ EventQueue queue = getEventQueue();
+ HostModel model = new DefaultHostModel( queue, logger,
directive, registry );
addHostModel( model, notify );
}
catch( RemoteException e )
@@ -361,7 +364,7 @@
* Internal processing of an event.
* @param event the event
*/
- protected void processEvent( EventObject event )
+ public void processEvent( EventObject event )
{
if( event instanceof CacheEvent )
{
@@ -375,7 +378,7 @@

private void processCacheEvent( CacheEvent event )
{
- EventListener[] listeners = super.listeners();
+ EventListener[] listeners = super.getEventListeners();
for( int i=0; i < listeners.length; i++ )
{
EventListener eventListener = listeners[i];
@@ -414,7 +417,7 @@

private void processCacheDirectoryChangeEvent( CacheDirectoryChangeEvent
event )
{
- EventListener[] listeners = super.listeners();
+ EventListener[] listeners = super.getEventListeners();
for( int i=0; i < listeners.length; i++ )
{
EventListener listener = listeners[i];

Modified:
trunk/main/transit/core/src/main/net/dpml/transit/DefaultCodeBaseModel.java
===================================================================
---
trunk/main/transit/core/src/main/net/dpml/transit/DefaultCodeBaseModel.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/transit/core/src/main/net/dpml/transit/DefaultCodeBaseModel.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -26,7 +26,6 @@
import net.dpml.lang.Value;
import net.dpml.lang.ValueDirective;
import net.dpml.lang.Construct;
-import net.dpml.util.Logger;

import net.dpml.transit.info.CodeBaseDirective;
import net.dpml.transit.model.CodeBaseModel;
@@ -35,6 +34,9 @@
import net.dpml.transit.model.LocationEvent;
import net.dpml.transit.model.ParametersEvent;

+import net.dpml.util.Logger;
+import net.dpml.util.EventQueue;
+
/**
* The abstract codebase is an implementation that monitors configuration
changes
* to a a codebase storage unit containg a uri attribute. Modifications to
the uri value
@@ -63,10 +65,10 @@
* @param directive the codebase storage directive
* @exception RemoteException if a remote exception occurs
*/
- public DefaultCodeBaseModel( Logger logger, CodeBaseDirective directive )
+ public DefaultCodeBaseModel( EventQueue queue, Logger logger,
CodeBaseDirective directive )
throws RemoteException
{
- super( logger );
+ super( queue, logger );
if( null == directive )
{
throw new NullPointerException( "directive" );
@@ -136,7 +138,7 @@
* Internal event handler.
* @param eventObject the event
*/
- protected void processEvent( EventObject eventObject )
+ public void processEvent( EventObject eventObject )
{
if( eventObject instanceof CodeBaseEvent )
{
@@ -153,7 +155,7 @@

private void processCodeBaseEvent( CodeBaseEvent event )
{
- EventListener[] listeners = super.listeners();
+ EventListener[] listeners = super.getEventListeners();
for( int i=0; i < listeners.length; i++ )
{
EventListener listener = listeners[i];

Modified:
trunk/main/transit/core/src/main/net/dpml/transit/DefaultHostModel.java
===================================================================
--- trunk/main/transit/core/src/main/net/dpml/transit/DefaultHostModel.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/transit/core/src/main/net/dpml/transit/DefaultHostModel.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -36,10 +36,12 @@
import net.dpml.transit.model.HostPriorityEvent;
import net.dpml.transit.model.HostNameEvent;
import net.dpml.transit.model.RequestIdentifier;
-import net.dpml.util.PropertyResolver;

import net.dpml.lang.UnknownKeyException;
+
+import net.dpml.util.PropertyResolver;
import net.dpml.util.Logger;
+import net.dpml.util.EventQueue;

/**
* Default implementation of a host manager.
@@ -81,10 +83,10 @@
* @exception MalformedURLException if the host base url path is malformed
* @exception RemoteException if a remote exception occurs
*/
- public DefaultHostModel( Logger logger, HostDirective directive,
LayoutRegistryModel registry )
+ public DefaultHostModel( EventQueue queue, Logger logger, HostDirective
directive, LayoutRegistryModel registry )
throws RemoteException, UnknownKeyException, MalformedURLException
{
- super( logger );
+ super( queue, logger );

m_registry = registry;

@@ -326,7 +328,7 @@
* Internal event handler.
* @param event the event to handle
*/
- protected void processEvent( EventObject event )
+ public void processEvent( EventObject event )
{
if( event instanceof HostChangeEvent )
{
@@ -425,7 +427,7 @@
private HostListener[] getHostListeners()
{
ArrayList list = new ArrayList();
- EventListener[] listeners = super.listeners();
+ EventListener[] listeners = super.getEventListeners();
for( int i=0; i < listeners.length; i++ )
{
EventListener eventListener = listeners[i];

Modified:
trunk/main/transit/core/src/main/net/dpml/transit/DefaultLayoutModel.java
===================================================================
--- trunk/main/transit/core/src/main/net/dpml/transit/DefaultLayoutModel.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/transit/core/src/main/net/dpml/transit/DefaultLayoutModel.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -27,6 +27,7 @@
import net.dpml.transit.model.LayoutListener;
import net.dpml.transit.model.LayoutEvent;

+import net.dpml.util.EventQueue;
import net.dpml.util.Logger;

/**
@@ -57,10 +58,10 @@
* @param directive the layout configuration
* @exception RemoteException if a remote exception occurs
*/
- public DefaultLayoutModel( final Logger logger, final LayoutDirective
directive )
+ public DefaultLayoutModel( final EventQueue queue, final Logger logger,
final LayoutDirective directive )
throws RemoteException
{
- super( logger, directive );
+ super( queue, logger, directive );

m_id = directive.getID();
m_title = directive.getTitle();
@@ -135,7 +136,7 @@
* Internal event handler.
* @param event the event to handle
*/
- protected void processEvent( EventObject event )
+ public void processEvent( EventObject event )
{
if( event instanceof LayoutEvent )
{
@@ -149,7 +150,7 @@

private void processLayoutEvent( LayoutEvent event )
{
- EventListener[] listeners = super.listeners();
+ EventListener[] listeners = super.getEventListeners();
for( int i=0; i < listeners.length; i++ )
{
EventListener eventListener = listeners[i];

Modified:
trunk/main/transit/core/src/main/net/dpml/transit/DefaultLayoutRegistryModel.java
===================================================================
---
trunk/main/transit/core/src/main/net/dpml/transit/DefaultLayoutRegistryModel.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/transit/core/src/main/net/dpml/transit/DefaultLayoutRegistryModel.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -35,7 +35,9 @@

import net.dpml.lang.UnknownKeyException;
import net.dpml.lang.DuplicateKeyException;
+
import net.dpml.util.Logger;
+import net.dpml.util.EventQueue;

/**
* Default implementation of a layout registry model that maitains
@@ -64,26 +66,26 @@
* @exception DuplicateKeyException if a duplicate layout is declared
* @exception RemoteException if a remote exception occurs
*/
- public DefaultLayoutRegistryModel( Logger logger, LayoutDirective[]
layouts )
+ public DefaultLayoutRegistryModel( EventQueue queue, Logger logger,
LayoutDirective[] layouts )
throws DuplicateKeyException, RemoteException
{
- super( logger );
+ super( queue, logger );

// add the standard layouts

LayoutModel modern =
new StandardLayoutModel(
- logger.getChildLogger( "modern" ),
+ queue, logger.getChildLogger( "modern" ),
"modern", "Modern", ModernLayout.class.getName() );
addLayoutModel( modern, false );
LayoutModel classic =
new StandardLayoutModel(
- logger.getChildLogger( "classic" ),
+ queue, logger.getChildLogger( "classic" ),
"classic", "Classic", ClassicLayout.class.getName() );
addLayoutModel( classic, false );
LayoutModel eclipse =
new StandardLayoutModel(
- logger.getChildLogger( "eclipse" ),
+ queue, logger.getChildLogger( "eclipse" ),
"eclipse", "Eclipse", EclipseLayout.class.getName() );
addLayoutModel( eclipse, false );

@@ -221,7 +223,8 @@
Logger logger = getLogger().getChildLogger( id );
try
{
- LayoutModel model = new DefaultLayoutModel( logger, directive );
+ EventQueue queue = getEventQueue();
+ LayoutModel model = new DefaultLayoutModel( queue, logger,
directive );
addLayoutModel( model, notify );
}
catch( RemoteException e )
@@ -261,7 +264,7 @@
* Internal event handler.
* @param event the event to handle
*/
- protected void processEvent( EventObject event )
+ public void processEvent( EventObject event )
{
if( event instanceof LayoutRegistryEvent )
{
@@ -271,7 +274,7 @@

private void processLayoutRegistryEvent( LayoutRegistryEvent event )
{
- EventListener[] listeners = super.listeners();
+ EventListener[] listeners = super.getEventListeners();
for( int i=0; i < listeners.length; i++ )
{
EventListener listener = listeners[i];

Modified: trunk/main/transit/core/src/main/net/dpml/transit/DefaultModel.java
===================================================================
--- trunk/main/transit/core/src/main/net/dpml/transit/DefaultModel.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/transit/core/src/main/net/dpml/transit/DefaultModel.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -30,6 +30,8 @@
import net.dpml.transit.monitor.LoggingAdapter;

import net.dpml.util.Logger;
+import net.dpml.util.UnicastEventSource;
+import net.dpml.util.EventQueue;

/**
* A abstract base class that established an event queue and handles event
dispatch
@@ -38,24 +40,14 @@
* @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
* @version @PROJECT-VERSION@
*/
-public abstract class DefaultModel extends UnicastRemoteObject implements
Disposable
+public abstract class DefaultModel extends UnicastEventSource implements
Disposable
{
//
------------------------------------------------------------------------
// state
//
------------------------------------------------------------------------

- /**
- * Internal logging channel.
- */
- private final Logger m_logger;
-
private Map m_listeners = new WeakHashMap();

- /**
- * Internal synchronization lock.
- */
- private final Object m_lock = new Object();
-
//
------------------------------------------------------------------------
// constructor
//
------------------------------------------------------------------------
@@ -65,10 +57,10 @@
* @param name the name used to construct a logging channel
* @exception RemoteException if a remote exception occurs
*/
- public DefaultModel( String name )
+ public DefaultModel( EventQueue queue, String name )
throws RemoteException
{
- this( getLoggerForCategory( name ) );
+ this( queue, getLoggerForCategory( name ) );
}

/**
@@ -77,330 +69,54 @@
* @exception NullPointerException if the supplied logging channel is null
* @exception RemoteException if a remote exception occurs
*/
- public DefaultModel( Logger logger )
+ public DefaultModel( EventQueue queue, Logger logger )
throws NullPointerException, RemoteException
{
- super();
-
- if( null == logger )
- {
- throw new NullPointerException( "logger" );
- }
- m_logger = logger;
+ super( queue, logger );
}

//
------------------------------------------------------------------------
// DefaultModel
//
------------------------------------------------------------------------

- /**
- * Abstract method that must be implemented by classes extending this
class.
- * An implementation is responsible for handling the processing of events
- * it is aware of or throwing an llegalArgumentException in the case of
- * unrecognized event types. A typical implementation is shown in the
following
- * code fragment:
- *
- * <pre>
- * protected void processEvent( EventObject eventObject )
- * {
- * if( eventObject instanceof ProxyEvent )
- * {
- * ProxyEvent event = (ProxyEvent) eventObject;
- * processProxyEvent( event );
- * }
- * else
- * {
- * final String error =
- * "Event class not recognized: " +
eventObject.getClass().getName();
- * throw new IllegalArgumentException( error );
- * }
- * }
- *
- * private void processProxyEvent( ProxyEvent event )
- * {
- * EventListener[] listeners = super.listeners();
- * for( int i=0; i&lt;listeners.length; i++ )
- * {
- * EventListener listener = listeners[i];
- * if( listener instanceof ProxyListener )
- * {
- * ProxyListener pl = (ProxyListener) listener;
- * try
- * {
- * pl.proxyChanged( event );
- * }
- * catch( Throwable e )
- * {
- * final String error =
- * "Proxy listener notification error.";
- * getLogger().error( error, e );
- * }
- * }
- * }
- * }
- * </pre>
- *
- * @param event the event to process
- */
- protected abstract void processEvent( EventObject event );
-
- /**
- * Return the assigned logging channel.
- * @return the logging channel
- */
protected Logger getLogger()
{
- return m_logger;
+ return super.getLocalLogger();
}

- Logger getLoggingChannel()
- {
- return getLogger();
- }
-
/**
* Dispose of the model.
*/
public synchronized void dispose()
{
- EventListener[] listeners = listeners();
+ EventListener[] listeners = getEventListeners();
for( int i=0; i < listeners.length; i++ )
{
EventListener listener = listeners[i];
removeListener( listener );
}
+ super.terminate();
getLogger().debug( "disposed" );
}

- /**
- * Terminate the dispatch thread.
- */
- synchronized void terminateDispatchThread()
- {
- if( null != m_EVENT_DISPATCH_THREAD )
- {
- m_EVENT_DISPATCH_THREAD.dispose();
- }
- }
-
- /**
- * Add a listener to the set of listeners handled by the model.
- * @param listener the event listener
- * @exception NullPointerException if the supplied listener is null
- */
- protected void addListener( EventListener listener ) throws
NullPointerException
- {
- if( null == listener )
- {
- throw new NullPointerException( "listener" );
- }
- synchronized( m_lock )
- {
- m_listeners.put( listener, null );
- }
- Logger logger = getLogger();
- startEventDispatchThread( logger );
- }
-
- /**
- * Remove a listener to the set of listeners handled by this producer.
- * @param listener the event listener
- * @exception NullPointerException if the supplied listener is null
- */
- protected void removeListener( EventListener listener ) throws
NullPointerException
- {
- if( null == listener )
- {
- throw new NullPointerException( "listener" );
- }
-
- synchronized( m_lock )
- {
- m_listeners.remove( listener );
- }
- }
-
/**
- * Queue of pending notification events. When an event for which
- * there are one or more listeners occurs, it is placed on this queue
- * and the queue is notified. A background thread waits on this queue
- * and delivers the events. This decouples event delivery from
- * the application concern, greatly simplifying locking and reducing
- * opportunity for deadlock.
- */
- private static final List EVENT_QUEUE = new LinkedList();
-
- /**
- * A single background thread ("the event notification thread") monitors
- * the event queue and delivers events that are placed on the queue.
- */
- private static class EventDispatchThread extends Thread
- {
- private boolean m_continue = true;
-
- private Logger m_logger;
-
- EventDispatchThread( Logger logger )
- {
- m_logger = logger;
- }
-
- void dispose()
- {
- synchronized( EVENT_QUEUE )
- {
- m_continue = false;
- EVENT_QUEUE.notify();
- }
- }
-
- private Logger getLogger()
- {
- return m_logger;
- }
-
- public void run()
- {
- while( m_continue )
- {
- // Wait on EVENT_QUEUE till an event is present
- EventObject event = null;
- synchronized( EVENT_QUEUE )
- {
- try
- {
- while( m_continue && EVENT_QUEUE.isEmpty() )
- {
- EVENT_QUEUE.wait();
- }
- if ( !m_continue )
- {
- break;
- }
- Object object = EVENT_QUEUE.remove( 0 );
- try
- {
- event = (EventObject) object;
- }
- catch( ClassCastException cce )
- {
- final String error =
- "Unexpected class cast exception while
processing an event."
- + "\nEvent: " + object;
- throw new IllegalStateException( error );
- }
- }
- catch( InterruptedException e )
- {
- return;
- }
- }
-
- Object source = event.getSource();
- if( source instanceof DefaultModel )
- {
- DefaultModel producer = (DefaultModel) source;
- try
- {
- producer.processEvent( event );
- }
- catch( Throwable e )
- {
- final String error =
- "Unexpected error while processing event."
- + "\nEvent: " + event
- + "\nSource: " + this;
- getLogger().error( error );
- }
- }
- else
- {
- final String error =
- "Event source is not an instance of "
- + DefaultModel.class.getName();
- throw new IllegalStateException( error );
- }
- }
- }
- }
-
- private static EventDispatchThread m_EVENT_DISPATCH_THREAD = null;
-
- /**
- * This method starts the event dispatch thread the first time it
- * is called. The event dispatch thread will be started only
- * if someone registers a listener.
- */
- private static synchronized void startEventDispatchThread( Logger logger
)
- {
- if( m_EVENT_DISPATCH_THREAD == null )
- {
- m_EVENT_DISPATCH_THREAD = new EventDispatchThread( logger );
- m_EVENT_DISPATCH_THREAD.setDaemon( true );
- m_EVENT_DISPATCH_THREAD.start();
- }
- }
-
- /**
- * Return the internal synchronization lock object.
- * @return the lock object
- */
- protected Object getLock()
- {
- return m_lock;
- }
-
- /**
- * Return the set of registered listeners.
- * @return an array of registered listeners
- */
- protected EventListener[] listeners()
- {
- synchronized( m_lock )
- {
- return (EventListener[]) m_listeners.keySet().toArray( new
EventListener[0] );
- }
- }
-
- /**
* Enqueue an event for delivery to registered
* listeners unless there are no registered
* listeners.
*
* @param event the event object to add to the queue
+ * @param waitForCompletion if TRUE the implementation will apply
+ * the event to the event source event handler and return on
+ * copmpletion of evetn delivery
*/
- protected void enqueueEvent( EventObject event )
+ protected void enqueueEvent( EventObject event, boolean
waitForCompletion )
{
- enqueueEvent( event, true );
- }
-
- /**
- * Enqueue an event for delivery to registered
- * listeners unless there are no registered
- * listeners.
- *
- * @param event the event object to add to the queue
- * @param asynchronouse TRUE if asynchronouse delivery
- */
- protected void enqueueEvent( EventObject event, boolean asynchronouse )
- {
- if( m_listeners.size() != 0 )
+ if( m_listeners.size() > 0 )
{
- if( asynchronouse )
- {
- synchronized( EVENT_QUEUE )
- {
- EVENT_QUEUE.add( event );
- EVENT_QUEUE.notify();
- }
- }
- else
- {
- processEvent( event );
- }
+ getEventQueue().enqueueEvent( event, waitForCompletion );
}
}
-
+
/**
* Return a logging channel for the supplied name.
* @param name the name to use in construction of the logging channel

Modified:
trunk/main/transit/core/src/main/net/dpml/transit/DefaultProxyModel.java
===================================================================
--- trunk/main/transit/core/src/main/net/dpml/transit/DefaultProxyModel.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/transit/core/src/main/net/dpml/transit/DefaultProxyModel.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -31,6 +31,7 @@
import net.dpml.transit.model.ProxyEvent;
import net.dpml.transit.model.RequestIdentifier;

+import net.dpml.util.EventQueue;
import net.dpml.util.Logger;

/**
@@ -61,10 +62,10 @@
* @exception NullPointerException if the logging channel or directive
arguments are null
* @exception RemoteException if a remote exception occurs
*/
- public DefaultProxyModel( Logger logger, ProxyDirective directive )
+ public DefaultProxyModel( EventQueue queue, Logger logger,
ProxyDirective directive )
throws NullPointerException, MalformedURLException, RemoteException
{
- super( logger );
+ super( queue, logger );

if( null == directive )
{
@@ -149,7 +150,7 @@

public void dispose()
{
- EventListener[] listeners = super.listeners();
+ EventListener[] listeners = super.getEventListeners();
for( int i=0; i<listeners.length; i++ )
{
EventListener listener = listeners[i];
@@ -161,7 +162,7 @@
* Internal event handler.
* @param eventObject the event to handle
*/
- protected void processEvent( EventObject eventObject )
+ public void processEvent( EventObject eventObject )
{
if( eventObject instanceof ProxyEvent )
{
@@ -178,7 +179,7 @@

private void processProxyEvent( ProxyEvent event )
{
- EventListener[] listeners = super.listeners();
+ EventListener[] listeners = super.getEventListeners();
for( int i=0; i < listeners.length; i++ )
{
EventListener listener = listeners[i];

Modified:
trunk/main/transit/core/src/main/net/dpml/transit/DefaultTransitModel.java
===================================================================
---
trunk/main/transit/core/src/main/net/dpml/transit/DefaultTransitModel.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/transit/core/src/main/net/dpml/transit/DefaultTransitModel.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -37,6 +37,7 @@
import net.dpml.transit.model.DisposalListener;
import net.dpml.transit.monitor.LoggingAdapter;

+import net.dpml.util.EventQueue;
import net.dpml.util.Logger;

/**
@@ -67,6 +68,8 @@
*/
public static final String PROFILE_KEY = "dpml.transit.profile";

+ private static final EventQueue EVENT_QUEUE = new EventQueue(
"dpml.transit" );
+
/**
* Return a model that is restricted to the secure local environment with
* no proxy setting or external hosts.
@@ -78,7 +81,7 @@
try
{
TransitDirective directive = new TransitDirective( null, new
CacheDirective() );
- return new DefaultTransitModel( logger, directive );
+ return new DefaultTransitModel( EVENT_QUEUE, logger, directive );
}
catch( Exception e )
{
@@ -133,7 +136,7 @@
URL url = Artifact.createArtifact( path ).toURL();
TransitBuilder builder = new TransitBuilder( logger );
TransitDirective directive = builder.load( url );
- return new DefaultTransitModel( logger, directive );
+ return new DefaultTransitModel( EVENT_QUEUE, logger, directive );
}
else
{
@@ -144,7 +147,7 @@
URL url = config.toURL();
TransitBuilder builder = new TransitBuilder( logger );
TransitDirective directive = builder.load( url );
- return new DefaultTransitModel( logger, directive );
+ return new DefaultTransitModel( EVENT_QUEUE, logger,
directive );
}
else
{
@@ -178,7 +181,24 @@
public DefaultTransitModel( Logger logger, TransitDirective directive )
throws RemoteException, NullPointerException
{
- super( logger );
+ this( EVENT_QUEUE, logger, directive );
+ }
+
+ /**
+ * Creation of a new TransitModel using a supplied configuration
+ * and logging channel. The implementation will construct a proxy
+ * model, layout registry model, cache model, and repository codebase
+ * model using the supplied configuration.
+ *
+ * @param logger the assigned loging channel
+ * @param directive the transit configuration
+ * @exception NullPointerException if the logger or directive arguments
are null
+ * @exception RemoteException if a remote exception occurs
+ */
+ public DefaultTransitModel( EventQueue queue, Logger logger,
TransitDirective directive )
+ throws RemoteException, NullPointerException
+ {
+ super( queue, logger );

if( null == directive )
{
@@ -233,7 +253,7 @@
* Internal event handler.
* @param eventObject the event to handle
*/
- protected void processEvent( EventObject eventObject )
+ public void processEvent( EventObject eventObject )
{
if( eventObject instanceof DisposalEvent )
{
@@ -244,7 +264,7 @@

private void processDisposalEvent( DisposalEvent event )
{
- EventListener[] listeners = super.listeners();
+ EventListener[] listeners = super.getEventListeners();
for( int i=0; i < listeners.length; i++ )
{
EventListener listener = listeners[i];
@@ -269,6 +289,11 @@
// impl
//
------------------------------------------------------------------------

+ Logger getLoggingChannel()
+ {
+ return getLogger();
+ }
+
/**
* Trigger disposal of the transit model.
*/
@@ -279,7 +304,7 @@
disposeCacheModel();
disposeProxyModel();
super.dispose();
- terminateDispatchThread();
+ EVENT_QUEUE.terminateDispatchThread();
Thread thread = new Terminator( this );
thread.start();
}
@@ -368,7 +393,7 @@
else
{
Logger logger = getLogger().getChildLogger( "proxy" );
- return new DefaultProxyModel( logger, config );
+ return new DefaultProxyModel( EVENT_QUEUE, logger, config );
}
}
catch( Throwable e )
@@ -385,7 +410,7 @@
{
Logger logger = getLogger().getChildLogger( "cache" );
CacheDirective config = directive.getCacheDirective();
- return new DefaultCacheModel( logger, config );
+ return new DefaultCacheModel( EVENT_QUEUE, logger, config );
}
catch( Throwable e )
{
@@ -404,7 +429,7 @@
static DefaultTransitModel getClassicModel( Logger logger ) throws
Exception
{
TransitDirective directive = TransitDirective.CLASSIC_PROFILE;
- return new DefaultTransitModel( logger, directive );
+ return new DefaultTransitModel( EVENT_QUEUE, logger, directive );
}

private static URI createStaticURI( String path )
@@ -418,5 +443,6 @@
return null;
}
}
+
}


Modified:
trunk/main/transit/core/src/main/net/dpml/transit/SecuredTransitContext.java
===================================================================
---
trunk/main/transit/core/src/main/net/dpml/transit/SecuredTransitContext.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/transit/core/src/main/net/dpml/transit/SecuredTransitContext.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -237,15 +237,6 @@
}

/**
- * Return the Transit repository service.
- * @return the repository service
- */
- //public Repository getRepository()
- //{
- // return m_repository;
- //}
-
- /**
* Return the cache handler.
* @return the cache handler
*/
@@ -311,8 +302,6 @@
protected void initialize() throws IOException
{
m_linkManager = new ArtifactLinkManager();
- //Logger logger = getLogger().getChildLogger( "cache" );
- //m_repository = new StandardLoader( logger ); // this needs to be
configured
initializeCache();
}


Modified:
trunk/main/transit/core/src/main/net/dpml/transit/StandardLayoutModel.java
===================================================================
---
trunk/main/transit/core/src/main/net/dpml/transit/StandardLayoutModel.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/transit/core/src/main/net/dpml/transit/StandardLayoutModel.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -24,13 +24,15 @@
import java.util.EventListener;

import net.dpml.lang.Value;
-import net.dpml.util.Logger;

import net.dpml.transit.model.LayoutModel;
import net.dpml.transit.model.LayoutListener;
import net.dpml.transit.model.LayoutEvent;
import net.dpml.transit.model.CodeBaseListener;

+import net.dpml.util.EventQueue;
+import net.dpml.util.Logger;
+
/**
* The StandardLayoutModel represents a standard layout included with the
* core Transit system.
@@ -61,10 +63,10 @@
* @exception RemoteException if a remote exception occurs
*/
public StandardLayoutModel(
- final Logger logger, final String id, final String title, final String
classname )
+ final EventQueue queue, final Logger logger, final String id, final
String title, final String classname )
throws RemoteException
{
- super( logger );
+ super( queue, logger );

m_id = id;
m_title = title;
@@ -175,7 +177,7 @@
* Internal event handler.
* @param event the event to handle
*/
- protected void processEvent( EventObject event )
+ public void processEvent( EventObject event )
{
if( event instanceof LayoutEvent )
{
@@ -185,7 +187,7 @@

private void processLayoutEvent( LayoutEvent event )
{
- EventListener[] listeners = super.listeners();
+ EventListener[] listeners = super.getEventListeners();
for( int i=0; i < listeners.length; i++ )
{
EventListener eventListener = listeners[i];

Modified: trunk/main/transit/core/src/main/net/dpml/transit/Transit.java
===================================================================
--- trunk/main/transit/core/src/main/net/dpml/transit/Transit.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/transit/core/src/main/net/dpml/transit/Transit.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -147,7 +147,7 @@
{
try
{
- Logger logger = new LoggingAdapter( "transit" );
+ Logger logger = new LoggingAdapter( "dpml.transit" );
TransitModel model =
DefaultTransitModel.getDefaultModel( logger );
return getInstance( model );
}

Modified:
trunk/main/transit/core/src/main/net/dpml/transit/monitor/LoggingAdapter.java
===================================================================
---
trunk/main/transit/core/src/main/net/dpml/transit/monitor/LoggingAdapter.java
2006-06-08 08:10:50 UTC (rev 1512)
+++
trunk/main/transit/core/src/main/net/dpml/transit/monitor/LoggingAdapter.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -44,7 +44,7 @@
/**
* The logging channel.
*/
- private static final String CATEGORY = "transit";
+ private static final String CATEGORY = "";

private static final PID ID = new PID();


Added: trunk/main/transit/core/src/main/net/dpml/util/EventHandler.java
===================================================================
--- trunk/main/transit/core/src/main/net/dpml/util/EventHandler.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/transit/core/src/main/net/dpml/util/EventHandler.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.util;
+
+import java.util.EventObject;
+import java.util.EventListener;
+
+/**
+ * Interface implemented by objects that maintain a collection of event
listeners
+ * and support for operational event propergation.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface EventHandler
+{
+ EventListener[] getEventListeners();
+
+ void processEvent( EventObject event );
+}

Added: trunk/main/transit/core/src/main/net/dpml/util/EventQueue.java
===================================================================
--- trunk/main/transit/core/src/main/net/dpml/util/EventQueue.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/transit/core/src/main/net/dpml/util/EventQueue.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.util;
+
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.EventObject;
+import java.util.EventListener;
+import java.util.List;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import net.dpml.transit.monitor.LoggingAdapter;
+
+import net.dpml.util.Logger;
+
+/**
+ * A abstract base class that established an event queue and handles event
dispatch
+ * operations for listeners declared in classes extending this base class.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class EventQueue
+{
+ //
------------------------------------------------------------------------
+ // state
+ //
------------------------------------------------------------------------
+
+ private final EventDispatchThread m_thread;
+
+ private final Logger m_logger;
+
+ private final List m_queue;
+
+ //
------------------------------------------------------------------------
+ // constructor
+ //
------------------------------------------------------------------------
+
+ /**
+ * Creation of a new event queue.
+ * @param name the name used to construct a logging channel
+ */
+ public EventQueue( String name )
+ {
+ this( getLoggerForCategory( name ) );
+ }
+
+ /**
+ * Creation of a new model.
+ * @param logger the assigned logging channel
+ * @exception NullPointerException if the supplied logging channel is null
+ */
+ public EventQueue( Logger logger )
+ throws NullPointerException
+ {
+ if( null == logger )
+ {
+ throw new NullPointerException( "logger" );
+ }
+ m_logger = logger;
+ m_queue = new LinkedList();
+ m_thread = new EventDispatchThread();
+ m_thread.setDaemon( true );
+ m_thread.start();
+ }
+
+ //
------------------------------------------------------------------------
+ // EventQueue
+ //
------------------------------------------------------------------------
+
+ /**
+ * Terminate the dispatch thread.
+ */
+ public synchronized void terminateDispatchThread()
+ {
+ if( null != m_thread )
+ {
+ m_thread.dispose();
+ }
+ }
+
+ /**
+ * Return the assigned logging channel.
+ * @return the logging channel
+ */
+ private Logger getLogger()
+ {
+ return m_logger;
+ }
+
+ /**
+ * A single background thread ("the event notification thread") monitors
+ * the event queue and delivers events that are placed on the queue.
+ */
+ private class EventDispatchThread extends Thread
+ {
+ private boolean m_continue = true;
+
+ void dispose()
+ {
+ synchronized( m_queue )
+ {
+ m_continue = false;
+ m_queue.notify();
+ }
+ }
+
+ public void run()
+ {
+ while( m_continue )
+ {
+ // Wait on m_queue till an event is present
+ EventObject event = null;
+ synchronized( m_queue )
+ {
+ try
+ {
+ while( m_continue && m_queue.isEmpty() )
+ {
+ m_queue.wait();
+ }
+ if ( !m_continue )
+ {
+ break;
+ }
+ Object object = m_queue.remove( 0 );
+ try
+ {
+ event = (EventObject) object;
+ }
+ catch( ClassCastException cce )
+ {
+ final String error =
+ "Unexpected class cast exception while
processing an event."
+ + "\nEvent: " + object;
+ throw new IllegalStateException( error );
+ }
+ }
+ catch( InterruptedException e )
+ {
+ return;
+ }
+ }
+
+ Object source = event.getSource();
+ if( source instanceof EventHandler )
+ {
+ EventHandler handler = (EventHandler) source;
+ try
+ {
+ handler.processEvent( event );
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "Unexpected error while processing event."
+ + "\nEvent: " + event
+ + "\nSource: " + this;
+ getLogger().error( error, e );
+ }
+ }
+ else
+ {
+ final String error =
+ "Event source is not an instance of "
+ + EventHandler.class.getName();
+ getLogger().error( error );
+ }
+ }
+ }
+ }
+
+ /**
+ * Enqueue an event for delivery to registered
+ * listeners unless there are no registered
+ * listeners.
+ *
+ * @param event the event object to add to the queue
+ */
+ public void enqueueEvent( EventObject event )
+ {
+ enqueueEvent( event, false );
+ }
+
+ /**
+ * Enqueue an event for delivery to registered
+ * listeners unless there are no registered
+ * listeners.
+ *
+ * @param event the event object to add to the queue
+ * @param waitForCompletion if TRUE the implementation will apply
+ * the event to the event source event handler and return on
+ * copmpletion of evetn delivery
+ */
+ public void enqueueEvent( EventObject event, boolean waitForCompletion )
+ {
+ if( !waitForCompletion )
+ {
+ synchronized( m_queue )
+ {
+ m_queue.add( event );
+ m_queue.notify();
+ }
+ }
+ else
+ {
+ Object source = event.getSource();
+ if( source instanceof EventHandler )
+ {
+ EventHandler handler = (EventHandler) source;
+ try
+ {
+ handler.processEvent( event );
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "Unexpected error while processing event."
+ + "\nEvent: " + event
+ + "\nSource: " + source;
+ getLogger().error( error );
+ }
+ }
+ else
+ {
+ final String error =
+ "Event source is not an instance of "
+ + EventHandler.class.getName()
+ + "\nSource: " + source.getClass().getName();
+ throw new IllegalStateException( error );
+ }
+ }
+ }
+
+ /**
+ * Return a logging channel for the supplied name.
+ * @param name the name to use in construction of the logging channel
+ * @return the logging channel
+ */
+ static Logger getLoggerForCategory( String name )
+ {
+ if( null == name )
+ {
+ return new LoggingAdapter( "" );
+ }
+ else
+ {
+ return new LoggingAdapter( name );
+ }
+ }
+}

Added: trunk/main/transit/core/src/main/net/dpml/util/UnicastEventSource.java
===================================================================
--- trunk/main/transit/core/src/main/net/dpml/util/UnicastEventSource.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/transit/core/src/main/net/dpml/util/UnicastEventSource.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2005-2006 Stephen J. McConnell.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.util;
+
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+import java.rmi.NoSuchObjectException;
+import java.util.EventObject;
+import java.util.EventListener;
+import java.util.WeakHashMap;
+import java.util.List;
+import java.util.LinkedList;
+
+import net.dpml.util.Logger;
+
+/**
+ * A abstract base class that established an event queue and handles event
dispatch
+ * operations for listeners declared in a class extending this base class.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public abstract class UnicastEventSource extends UnicastRemoteObject
implements EventHandler
+{
+ /**
+ * Internal synchronization lock.
+ */
+ private final Object m_lock = new Object();
+
+ /**
+ * The controller that provides the main event dispath thread.
+ */
+ private final EventQueue m_queue;
+
+ private final WeakHashMap m_listeners = new WeakHashMap();
+
+ private final Logger m_logger;
+
+ /**
+ * Creation of a new <tt>UnicastEventSource</tt>.
+ * @param queue the event queue
+ * @param logger the assigned logging channel
+ * @exception RemoteException if a remote I/O exception occurs
+ */
+ protected UnicastEventSource( EventQueue queue, Logger logger ) throws
RemoteException
+ {
+ super();
+ m_queue = queue;
+ m_logger = logger;
+ }
+
+
//--------------------------------------------------------------------------
+ // internal
+
//--------------------------------------------------------------------------
+
+ /**
+ * Return the logging channel assigned to the event source.
+ * @return the logging channel
+ */
+ protected Logger getLocalLogger()
+ {
+ return m_logger;
+ }
+
+ /**
+ * Return the event queue.
+ * @return the queue
+ */
+ protected EventQueue getEventQueue()
+ {
+ return m_queue;
+ }
+
+ /**
+ * Abstract operation to be implemented by classes extending this base
class.
+ * An implementation is reposible for the posting of the event to
associated
+ * listeners. Event posting will be executed under a separate thread to
the
+ * thread that initiated the event post.
+ *
+ * @param event the event to process
+ */
+ public abstract void processEvent( EventObject event );
+
+ /**
+ * Add a listener to the set of listeners handled by this producer.
+ * @param listener the event listener
+ */
+ protected void addListener( EventListener listener )
+ {
+ if( null == listener )
+ {
+ throw new NullPointerException( "listener" );
+ }
+ synchronized( m_lock )
+ {
+ m_listeners.put( listener, null );
+ }
+ }
+
+ /**
+ * Remove a listener to the set of listeners handled by this producer.
+ * @param listener the event listener
+ */
+ protected void removeListener( EventListener listener )
+ {
+ if( null == listener )
+ {
+ throw new NullPointerException( "listener" );
+ }
+ synchronized( m_lock )
+ {
+ m_listeners.remove( listener );
+ }
+ }
+
+
+ /**
+ * Return the array of registered event listeners.
+ *
+ * @return the event listeners
+ */
+ public EventListener[] getEventListeners()
+ {
+ synchronized( m_lock )
+ {
+ return (EventListener[]) m_listeners.keySet().toArray( new
EventListener[0] );
+ }
+ }
+
+ /**
+ * Enqueue an event for delivery to registered
+ * listeners unless there are no registered
+ * listeners.
+ * @param event the event to enqueue
+ */
+ protected void enqueueEvent( EventObject event )
+ {
+ if( m_listeners.size() > 0 )
+ {
+ m_queue.enqueueEvent( event );
+ }
+ }
+
+ /**
+ * Return the internal synchronization lock.
+ * @return the lock object
+ */
+ protected Object getLock()
+ {
+ return m_lock;
+ }
+
+ /**
+ * Terminate the event source.
+ */
+ public void terminate()
+ {
+ synchronized( m_lock )
+ {
+ EventListener[] listeners = getEventListeners();
+ for( int i=0; i < listeners.length; i++ )
+ {
+ EventListener listener = listeners[i];
+ removeListener( listener );
+ }
+ }
+
+ Thread thread = new Terminator( this, m_logger );
+ thread.start();
+ }
+
+ /**
+ * Internal class that handles instance retraction for the RMI runtime.
+ */
+ private class Terminator extends Thread
+ {
+ private final UnicastEventSource m_source;
+ private final Logger m_logger;
+
+ /**
+ * Internal class terminator that handles unexport of an event source
+ * under a separate thread.
+ * @param source the event source instance
+ * @param logger the event source logger
+ */
+ Terminator( UnicastEventSource source, Logger logger )
+ {
+ m_source = source;
+ m_logger = logger;
+ }
+
+ /**
+ * Terminator execution.
+ */
+ public void run()
+ {
+ try
+ {
+ UnicastRemoteObject.unexportObject( m_source, true );
+ m_logger.debug( "terminated" );
+ }
+ catch( NoSuchObjectException e )
+ {
+ boolean ignoreThis = true; // objct has not been exported
+ }
+ catch( RemoteException e )
+ {
+ final String error =
+ "Unexpected remote exception while retracting component
handler remote reference.";
+ m_logger.warn( error, e );
+ }
+ }
+ }
+}

Modified:
trunk/main/transit/tools/src/main/net/dpml/transit/tools/PluginTask.java
===================================================================
--- trunk/main/transit/tools/src/main/net/dpml/transit/tools/PluginTask.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/transit/tools/src/main/net/dpml/transit/tools/PluginTask.java
2006-06-19 03:26:47 UTC (rev 1513)
@@ -274,7 +274,7 @@

private Part getPart( URI uri ) throws IOException
{
- return Part.load( uri );
+ return Part.load( uri, true );
}

/**




  • r1513 - in trunk/main: depot/core/src/main/net/dpml/depot depot/tools/builder/src/main/net/dpml/tools/tasks metro/component/src/main/net/dpml/component metro/model/src/main/net/dpml/metro metro/model/src/main/net/dpml/metro/data metro/model/src/main/net/dpml/metro/info metro/model/src/test/net/dpml/metro/info/test metro/runtime/src/main/net/dpml/metro/builder metro/runtime/src/main/net/dpml/metro/runtime metro/state/api/src/main/net/dpml/state metro/state/impl metro/state/impl/src/main/net/dpml/state/impl metro/state/impl/src/test/net/dpml/state/test metro/test metro/test/etc/data metro/test/src/main/net/dpml/test metro/test/src/test/net/dpml/test/runtime transit/core/src/main/net/dpml/lang transit/core/src/main/net/dpml/transit transit/core/src/main/net/dpml/transit/monitor transit/core/src/main/net/dpml/util transit/tools/src/main/net/dpml/transit/tools, mcconnell at BerliOS, 06/18/2006

Archive powered by MHonArc 2.6.24.

Top of Page