You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2007/10/21 20:58:04 UTC

svn commit: r586932 - in /tapestry/tapestry5/trunk: tapestry-core/src/main/java/org/apache/tapestry/corelib/pages/ tapestry-core/src/main/resources/org/apache/tapestry/corelib/pages/ tapestry-core/src/site/ tapestry-core/src/site/apt/guide/ tapestry-co...

Author: hlship
Date: Sun Oct 21 11:58:02 2007
New Revision: 586932

URL: http://svn.apache.org/viewvc?rev=586932&view=rev
Log:
TAPESTRY-1848: Make status of Tapestry IoC services available programattically and via a simple user interface

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/pages/ServiceStatus.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/pages/ServiceStatus.tml
    tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/servicestatus.apt
    tapestry/tapestry5/trunk/tapestry-core/src/site/resources/images/servicestatus.png   (with props)
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceActivityTracker.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceActivityTrackerImpl.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/ServiceActivity.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/ServiceActivityScoreboard.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/Status.java
Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/site/site.xml
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/IOCInternalTestCase.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ModuleImpl.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/JustInTimeObjectCreator.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/IntegrationTest.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/ModuleImplTest.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/JustInTimeObjectCreatorTest.java

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/pages/ServiceStatus.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/pages/ServiceStatus.java?rev=586932&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/pages/ServiceStatus.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/pages/ServiceStatus.java Sun Oct 21 11:58:02 2007
@@ -0,0 +1,88 @@
+// Copyright 2007 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.
+// 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 org.apache.tapestry.corelib.pages;
+
+import java.util.List;
+
+import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.beaneditor.BeanModel;
+import org.apache.tapestry.ioc.Registry;
+import org.apache.tapestry.ioc.annotations.Inject;
+import org.apache.tapestry.ioc.services.ServiceActivity;
+import org.apache.tapestry.ioc.services.ServiceActivityScoreboard;
+import org.apache.tapestry.services.BeanModelSource;
+
+/**
+ * Page used to see the status of all services defined by the {@link Registry}.
+ * <p>
+ * TODO: Add filters to control which services are displayed.
+ * <p>
+ * TODO: Disable this page if in production mode (or not, as it does no harm).
+ */
+public class ServiceStatus
+{
+    @Inject
+    private ServiceActivityScoreboard _scoreboard;
+
+    private List<ServiceActivity> _activity;
+
+    private ServiceActivity _row;
+
+    @Inject
+    private BeanModelSource _source;
+
+    private final BeanModel _model;
+
+    @Inject
+    private ComponentResources _resources;
+
+    public ServiceStatus()
+    {
+        _model = _source.create(ServiceActivity.class, false, _resources);
+
+        _model.add("serviceInterface", null);
+
+        // There's no line number information for interfaces, so we'll reorder the
+        // propreties manually.
+
+        _model.reorder("serviceId", "serviceInterface", "scope", "status");
+    }
+
+    public ServiceActivity getRow()
+    {
+        return _row;
+    }
+
+    public void setRow(ServiceActivity row)
+    {
+        _row = row;
+    }
+
+    void setupRender()
+    {
+        _activity = _scoreboard.getServiceActivity();
+    }
+
+    public List<ServiceActivity> getActivity()
+    {
+        return _activity;
+    }
+
+    public BeanModel getModel()
+    {
+        return _model;
+    }
+
+}

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/pages/ServiceStatus.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/pages/ServiceStatus.tml?rev=586932&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/pages/ServiceStatus.tml (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/pages/ServiceStatus.tml Sun Oct 21 11:58:02 2007
@@ -0,0 +1,72 @@
+<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+  <head>
+    <title>Tapestry IoC Services Status</title>
+    <style>
+TR.defined {
+  color: #666666;
+  font-style: italic;
+}
+
+TR.virtual
+{
+ color: blue;
+}
+
+TR.real
+{
+  color: green;
+}
+
+    
+    </style>
+  </head>
+  <body>
+
+    <h1>Tapestry IoC Services Status</h1>
+
+    <p>${activity.size()} services defined in the IoC Registry.</p>
+
+    <t:grid rowsperpage="100" model="model" pagerposition="top" rowClass="row.status"
+      source="activity" row="row">
+
+      <t:parameter name="serviceInterfaceCell">
+        ${row.serviceInterface}
+      </t:parameter>
+
+    </t:grid>
+
+    <p>
+      Explanation of status:
+      <dl>
+        <dt>Builtin</dt>
+        <dd>
+          A fundamental service that exists even before the Registry is
+          created.
+        </dd>
+
+        <dt>Defined</dt>
+        <dd>
+          The service is defined, but has not yet been referenced.
+        </dd>
+
+        <dt>Virtual</dt>
+        <dd>
+          The service has been referenced (usually for injection into
+          another service) but has not yet been
+          <em>realized</em>
+          into an instantiated service. Realization occurs with the
+          first method invocation on the proxy.
+        </dd>
+
+        <dt>Real</dt>
+        <dd>
+          The service has been realized: instantiated, dependencies
+          injected, decorated with interceptors and is fully in
+          operation.
+        </dd>
+
+      </dl>
+    </p>
+
+  </body>
+</html>
\ No newline at end of file

Added: tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/servicestatus.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/servicestatus.apt?rev=586932&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/servicestatus.apt (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/servicestatus.apt Sun Oct 21 11:58:02 2007
@@ -0,0 +1,25 @@
+ ----
+  IoC Services Status
+ ----
+
+IoC Services Status
+
+  Using Tapestry there will often be a large number of services defined in the registry; a mix of the builtin services provided by the framework
+  and your own.
+  
+  Built in to every Tapestry application is a page, ServiceStatus, that can present this information to you.
+  
+  The page "ServiceStatus" presents the list of services within the appication's Registry.
+   
+[../images/servicestatus.png] Service Status Page
+
+  Services may be builtin, defined, virtual or real.
+  
+  Builtin only applies to a few special services that are part of Tapestry IoC.
+  
+  Defined services are defined in some module, but have not yet been referenced in any way.
+  
+  Virtual services have been referenced and have gotten as far as creating a service proxy.
+  
+  Real services have had methods invoked, this forces the <realization> of the service which includes
+  instantiating the service, injecting dependencies, and decorating with any applicable interceptors.
\ No newline at end of file

Added: tapestry/tapestry5/trunk/tapestry-core/src/site/resources/images/servicestatus.png
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/site/resources/images/servicestatus.png?rev=586932&view=auto
==============================================================================
Binary file - no diff available.

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/site/resources/images/servicestatus.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: tapestry/tapestry5/trunk/tapestry-core/src/site/site.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/site/site.xml?rev=586932&r1=586931&r2=586932&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/site/site.xml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/site/site.xml Sun Oct 21 11:58:02 2007
@@ -77,7 +77,8 @@
             <item name="DOM" href="guide/dom.html"/>
             <item name="Class Reloading" href="guide/reload.html"/>
             <item name="Unit testing pages/components" href="guide/unit-testing-pages.html"/>
-            <item name="Logging" href="guide/logging.html"/>
+            <item name="Logging" href="guide/logging.html"/>
+            <item name="Service Status" href="guide/servicestatus.html"/>
         </menu> 
                         
         <menu ref="reports"/>

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java?rev=586932&r1=586931&r2=586932&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java Sun Oct 21 11:58:02 2007
@@ -1158,4 +1158,13 @@
 
         assertTextPresent("Howard Lewis Ship", "Dec 24, 1966");
     }
+
+    /** This basically checks that the services status page does not error. */
+    @Test
+    public void services_status()
+    {
+        open(BASE_URL + "servicestatus");
+
+        assertTextPresent("Tapestry IoC Services Status");
+    }
 }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/IOCInternalTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/IOCInternalTestCase.java?rev=586932&r1=586931&r2=586932&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/IOCInternalTestCase.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/IOCInternalTestCase.java Sun Oct 21 11:58:02 2007
@@ -144,4 +144,9 @@
         expect(registry.getService(serviceId, serviceInterface)).andReturn(service);
     }
 
+    protected ServiceActivityTracker mockServiceActivityTracker()
+    {
+        return newMock(ServiceActivityTracker.class);
+    }
+
 }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ModuleImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ModuleImpl.java?rev=586932&r1=586931&r2=586932&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ModuleImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ModuleImpl.java Sun Oct 21 11:58:02 2007
@@ -46,6 +46,7 @@
 import org.apache.tapestry.ioc.services.ClassFab;
 import org.apache.tapestry.ioc.services.ClassFactory;
 import org.apache.tapestry.ioc.services.MethodSignature;
+import org.apache.tapestry.ioc.services.Status;
 import org.apache.tapestry.ioc.services.TapestryIOCModule;
 import org.slf4j.Logger;
 
@@ -53,6 +54,8 @@
 {
     private final InternalRegistry _registry;
 
+    private final ServiceActivityTracker _tracker;
+
     private final ModuleDef _moduleDef;
 
     private final ClassFactory _classFactory;
@@ -77,10 +80,11 @@
     /** Keyed on fully qualified service id; values are instantiated services (proxies). */
     private final Map<String, Object> _services = newCaseInsensitiveMap();
 
-    public ModuleImpl(InternalRegistry registry, ModuleDef moduleDef, ClassFactory classFactory,
-            Logger logger)
+    public ModuleImpl(InternalRegistry registry, ServiceActivityTracker tracker,
+            ModuleDef moduleDef, ClassFactory classFactory, Logger logger)
     {
         _registry = registry;
+        _tracker = tracker;
         _moduleDef = moduleDef;
         _classFactory = classFactory;
         _logger = logger;
@@ -242,7 +246,8 @@
 
             creator = new RecursiveServiceCreationCheckWrapper(def, creator, logger);
 
-            JustInTimeObjectCreator delegate = new JustInTimeObjectCreator(creator, serviceId);
+            JustInTimeObjectCreator delegate = new JustInTimeObjectCreator(_tracker, creator,
+                    serviceId);
 
             Object proxy = createProxy(resources, delegate);
 
@@ -255,6 +260,8 @@
             // is being realized anyway.
 
             if (def.isEagerLoad() && eagerLoadProxies != null) eagerLoadProxies.add(delegate);
+
+            _tracker.setStatus(serviceId, Status.VIRTUAL);
 
             return proxy;
         }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java?rev=586932&r1=586931&r2=586932&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java Sun Oct 21 11:58:02 2007
@@ -55,6 +55,8 @@
 import org.apache.tapestry.ioc.services.RegistryShutdownHub;
 import org.apache.tapestry.ioc.services.RegistryShutdownListener;
 import org.apache.tapestry.ioc.services.ServiceLifecycleSource;
+import org.apache.tapestry.ioc.services.ServiceActivityScoreboard;
+import org.apache.tapestry.ioc.services.Status;
 import org.apache.tapestry.ioc.services.SymbolSource;
 import org.apache.tapestry.ioc.services.TapestryIOCModule;
 import org.apache.tapestry.ioc.services.ThreadCleanupHub;
@@ -70,6 +72,8 @@
 
     static final String THREAD_CLEANUP_HUB_SERVICE_ID = "ThreadCleanupHub";
 
+    private static final String SERVICE_ACTIVITY_SCOREBOARD_SERVICE_ID = "ServiceActivityScoreboard";
+
     /**
      * Used to obtain the {@link org.apache.tapestry.ioc.services.ClassFactory} service, which is
      * crucial when creating runtime classes for proxies and the like.
@@ -99,6 +103,8 @@
 
     private final ClassFactory _classFactory;
 
+    private final ServiceActivityTracker _tracker;
+
     private SymbolSource _symbolSource;
 
     private final List<Module> _modules = newList();
@@ -139,11 +145,51 @@
     {
         _loggerSource = loggerSource;
 
+        final ServiceActivityTrackerImpl scoreboardAndTracker = new ServiceActivityTrackerImpl();
+
+        _tracker = scoreboardAndTracker;
+
+        addBuiltin(
+                SERVICE_ACTIVITY_SCOREBOARD_SERVICE_ID,
+                ServiceActivityScoreboard.class,
+                scoreboardAndTracker);
+
+        addBuiltin(LOG_SOURCE_SERVICE_ID, LoggerSource.class, _loggerSource);
+
+        _classFactory = classFactory;
+
+        addBuiltin(CLASS_FACTORY_SERVICE_ID, ClassFactory.class, _classFactory);
+
+        Logger logger = loggerForBuiltinService(THREAD_CLEANUP_HUB_SERVICE_ID);
+
+        _cleanupHub = new ThreadCleanupHubImpl(logger);
+
+        addBuiltin(THREAD_CLEANUP_HUB_SERVICE_ID, ThreadCleanupHub.class, _cleanupHub);
+
+        logger = loggerForBuiltinService(REGISTRY_SHUTDOWN_HUB_SERVICE_ID);
+
+        _registryShutdownHub = new RegistryShutdownHubImpl(logger);
+
+        addBuiltin(
+                REGISTRY_SHUTDOWN_HUB_SERVICE_ID,
+                RegistryShutdownHub.class,
+                _registryShutdownHub);
+
+        _lifecycles.put("singleton", new SingletonServiceLifecycle());
+
+        _registryShutdownHub.addRegistryShutdownListener(new RegistryShutdownListener()
+        {
+            public void registryDidShutdown()
+            {
+                scoreboardAndTracker.shutdown();
+            }
+        });
+
         for (ModuleDef def : moduleDefs)
         {
-            Logger logger = _loggerSource.getLogger(def.getLoggerName());
+            logger = _loggerSource.getLogger(def.getLoggerName());
 
-            Module module = new ModuleImpl(this, def, classFactory, logger);
+            Module module = new ModuleImpl(this, _tracker, def, classFactory, logger);
 
             _modules.add(module);
 
@@ -159,6 +205,9 @@
 
                 _serviceIdToModule.put(serviceId, module);
 
+                // The service is defined but will not have gone further than that.
+                _tracker.define(serviceDef, Status.DEFINED);
+
                 Class marker = serviceDef.getMarker();
 
                 if (marker != null)
@@ -167,28 +216,7 @@
             }
         }
 
-        addBuiltin(LOG_SOURCE_SERVICE_ID, LoggerSource.class, _loggerSource);
-
-        _classFactory = classFactory;
-
-        addBuiltin(CLASS_FACTORY_SERVICE_ID, ClassFactory.class, _classFactory);
-
-        Logger logger = loggerForBuiltinService(THREAD_CLEANUP_HUB_SERVICE_ID);
-
-        _cleanupHub = new ThreadCleanupHubImpl(logger);
-
-        addBuiltin(THREAD_CLEANUP_HUB_SERVICE_ID, ThreadCleanupHub.class, _cleanupHub);
-
-        logger = loggerForBuiltinService(REGISTRY_SHUTDOWN_HUB_SERVICE_ID);
-
-        _registryShutdownHub = new RegistryShutdownHubImpl(logger);
-
-        addBuiltin(
-                REGISTRY_SHUTDOWN_HUB_SERVICE_ID,
-                RegistryShutdownHub.class,
-                _registryShutdownHub);
-
-        _lifecycles.put("singleton", new SingletonServiceLifecycle());
+        scoreboardAndTracker.startup();
     }
 
     /**
@@ -265,6 +293,8 @@
         };
 
         InternalUtils.addToMapList(_markerToServiceDef, serviceDef.getMarker(), serviceDef);
+
+        _tracker.define(serviceDef, Status.BUILTIN);
     }
 
     public synchronized void shutdown()

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceActivityTracker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceActivityTracker.java?rev=586932&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceActivityTracker.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceActivityTracker.java Sun Oct 21 11:58:02 2007
@@ -0,0 +1,46 @@
+// Copyright 2007 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.
+// 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 org.apache.tapestry.ioc.internal;
+
+import org.apache.tapestry.ioc.def.ServiceDef;
+import org.apache.tapestry.ioc.services.ServiceActivityScoreboard;
+import org.apache.tapestry.ioc.services.Status;
+
+/**
+ * Used to update the status of services defined by the {@link ServiceActivityScoreboard}.
+ */
+public interface ServiceActivityTracker
+{
+
+    /**
+     * Defines a service in the tracker with an initial status.
+     * 
+     * @param serviceDef
+     *            the service being defined
+     * @param initialStatus
+     *            typically {@link Status#BUILTIN} or {@link Status#DEFINED}
+     */
+    void define(ServiceDef serviceDef, Status initialStatus);
+
+    /**
+     * Updates the status for the service.
+     * 
+     * @param serviceId
+     *            identifies the service, which must be previously defined
+     * @param status
+     *            the new status value
+     */
+    void setStatus(String serviceId, Status status);
+}

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceActivityTrackerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceActivityTrackerImpl.java?rev=586932&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceActivityTrackerImpl.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceActivityTrackerImpl.java Sun Oct 21 11:58:02 2007
@@ -0,0 +1,110 @@
+// Copyright 2007 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.
+// 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 org.apache.tapestry.ioc.internal;
+
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.tapestry.ioc.def.ServiceDef;
+import org.apache.tapestry.ioc.internal.util.CollectionFactory;
+import org.apache.tapestry.ioc.services.ServiceActivity;
+import org.apache.tapestry.ioc.services.ServiceActivityScoreboard;
+import org.apache.tapestry.ioc.services.Status;
+
+public class ServiceActivityTrackerImpl implements ServiceActivityScoreboard,
+        ServiceActivityTracker
+{
+    public static class MutableServiceActivity implements ServiceActivity
+    {
+        private final ServiceDef _serviceDef;
+
+        private Status _status;
+
+        public MutableServiceActivity(ServiceDef serviceDef, Status status)
+        {
+            _serviceDef = serviceDef;
+            _status = status;
+        }
+
+        public String getServiceId()
+        {
+            return _serviceDef.getServiceId();
+        }
+
+        public Class getServiceInterface()
+        {
+            return _serviceDef.getServiceInterface();
+        }
+
+        public String getScope()
+        {
+            return _serviceDef.getServiceScope();
+        }
+
+        // Mutable properties must be synchronized
+
+        public synchronized Status getStatus()
+        {
+            return _status;
+        }
+
+        synchronized void setStatus(Status status)
+        {
+            _status = status;
+        }
+    }
+
+    /** Tree map keeps everything in order by key (serviceId). */
+    private final Map<String, MutableServiceActivity> _serviceIdToServiceStatus = new TreeMap<String, MutableServiceActivity>();
+
+    public synchronized List<ServiceActivity> getServiceActivity()
+    {
+        // Need to wrap the values in a new list because
+        // a) we don't want people arbitrarily changing the internal state of
+        // _serviceIdtoServiceStatus
+        // b) values() is Collection and we want to return List
+
+        // Note: ugly code here to keep Sun compiler happy.
+
+        List<ServiceActivity> result = CollectionFactory.newList();
+
+        result.addAll(_serviceIdToServiceStatus.values());
+
+        return result;
+    }
+
+    void startup()
+    {
+        // Does nothing, first pass does not use a worker thread
+    }
+
+    void shutdown()
+    {
+        // Does nothing, first pass does not use a worker thread
+    }
+
+    public synchronized void define(ServiceDef serviceDef, Status initialStatus)
+    {
+        _serviceIdToServiceStatus.put(serviceDef.getServiceId(), new MutableServiceActivity(
+                serviceDef, initialStatus));
+    }
+
+    public synchronized void setStatus(String serviceId, Status status)
+    {
+        _serviceIdToServiceStatus.get(serviceId).setStatus(status);
+    }
+
+}

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/JustInTimeObjectCreator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/JustInTimeObjectCreator.java?rev=586932&r1=586931&r2=586932&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/JustInTimeObjectCreator.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/JustInTimeObjectCreator.java Sun Oct 21 11:58:02 2007
@@ -16,7 +16,9 @@
 
 import org.apache.tapestry.ioc.ObjectCreator;
 import org.apache.tapestry.ioc.internal.EagerLoadServiceProxy;
+import org.apache.tapestry.ioc.internal.ServiceActivityTracker;
 import org.apache.tapestry.ioc.services.RegistryShutdownListener;
+import org.apache.tapestry.ioc.services.Status;
 
 /**
  * Invoked from a fabricated service delegate to get or realize (instantiate and configure) the
@@ -28,6 +30,8 @@
 public class JustInTimeObjectCreator implements ObjectCreator, EagerLoadServiceProxy,
         RegistryShutdownListener
 {
+    private final ServiceActivityTracker _tracker;
+
     private ObjectCreator _creator;
 
     private boolean _shutdown;
@@ -36,8 +40,10 @@
 
     private final String _serviceId;
 
-    public JustInTimeObjectCreator(ObjectCreator creator, String serviceId)
+    public JustInTimeObjectCreator(ServiceActivityTracker tracker, ObjectCreator creator,
+            String serviceId)
     {
+        _tracker = tracker;
         _creator = creator;
         _serviceId = serviceId;
     }
@@ -59,9 +65,11 @@
             try
             {
                 _object = _creator.createObject();
-                
+
                 // And if that's successful ...
-                
+
+                _tracker.setStatus(_serviceId, Status.REAL);
+
                 _creator = null;
             }
             catch (RuntimeException ex)

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/ServiceActivity.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/ServiceActivity.java?rev=586932&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/ServiceActivity.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/ServiceActivity.java Sun Oct 21 11:58:02 2007
@@ -0,0 +1,40 @@
+// Copyright 2007 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.
+// 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 org.apache.tapestry.ioc.services;
+
+import org.apache.tapestry.ioc.def.ServiceDef;
+
+/**
+ * Provided by the {@link ServiceActivityScoreboard} to track a single service's state and activity.
+ * 
+ * @see ServiceDef
+ */
+public interface ServiceActivity
+{
+    /** The unique id for the service. */
+    String getServiceId();
+
+    /**
+     * The interface implemented by the service (this may occasionally be a class, for non-proxied
+     * services).
+     */
+    Class getServiceInterface();
+
+    /** The scope of the service (typically "singleton" or "perthread"). */
+    String getScope();
+
+    /** Indicates the lifecycle status of the service. */
+    Status getStatus();
+}

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/ServiceActivityScoreboard.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/ServiceActivityScoreboard.java?rev=586932&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/ServiceActivityScoreboard.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/ServiceActivityScoreboard.java Sun Oct 21 11:58:02 2007
@@ -0,0 +1,27 @@
+// Copyright 2007 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.
+// 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 org.apache.tapestry.ioc.services;
+
+import java.util.List;
+
+/**
+ * Provides access to the runtime details about services in the
+ * {@link org.apache.tapestry.ioc.Registry}.
+ */
+public interface ServiceActivityScoreboard
+{
+    /** Returns the status of all services, sorted alphabetically by service id. */
+    List<ServiceActivity> getServiceActivity();
+}

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/Status.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/Status.java?rev=586932&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/Status.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/Status.java Sun Oct 21 11:58:02 2007
@@ -0,0 +1,36 @@
+// Copyright 2007 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.
+// 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 org.apache.tapestry.ioc.services;
+
+import org.apache.tapestry.ioc.Registry;
+
+/**
+ * Used in {@link ServiceActivity} to identify the state of the service in terms of its overall
+ * lifecycle.
+ */
+public enum Status
+{
+    /** A builtin service that exists before the {@link Registry} is constructed. */
+    BUILTIN,
+
+    /** The service is defined in a module, but has not yet been referenced. */
+    DEFINED,
+
+    /** A proxy has been created for the service, but no methods of the proxy have been invoked. */
+    VIRTUAL,
+
+    /** A service implementation for the service has been created. */
+    REAL;
+}

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/IntegrationTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/IntegrationTest.java?rev=586932&r1=586931&r2=586932&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/IntegrationTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/IntegrationTest.java Sun Oct 21 11:58:02 2007
@@ -23,6 +23,9 @@
 
 import org.apache.tapestry.ioc.internal.ExceptionInConstructorModule;
 import org.apache.tapestry.ioc.internal.IOCInternalTestCase;
+import org.apache.tapestry.ioc.services.ServiceActivity;
+import org.apache.tapestry.ioc.services.ServiceActivityScoreboard;
+import org.apache.tapestry.ioc.services.Status;
 import org.apache.tapestry.ioc.services.TypeCoercer;
 import org.apache.tapestry.ioc.services.TapestryIOCModule.Builtin;
 import org.testng.Assert;
@@ -662,5 +665,44 @@
         assertSame(tc1, tc2);
 
         verify();
+    }
+
+    /**
+     * A cursory test for {@link ServiceActivityScoreboard}, just to see if any data has been
+     * collected.
+     */
+    @Test
+    public void service_activity_scoreboard()
+    {
+        Registry r = buildRegistry(GreeterModule.class);
+
+        ServiceActivityScoreboard scoreboard = r.getService(ServiceActivityScoreboard.class);
+
+        // Force the state of a few services.
+
+        TypeCoercer tc = r.getService("TypeCoercer", TypeCoercer.class);
+
+        tc.coerce("123", Integer.class);
+
+        r.getService("BlueGreeter", Greeter.class);
+
+        // Now get the activity list and poke around.
+
+        List<ServiceActivity> serviceActivity = scoreboard.getServiceActivity();
+
+        assertTrue(serviceActivity.size() > 0);
+
+        for (ServiceActivity a : serviceActivity)
+        {
+            String serviceId = a.getServiceId();
+
+            if (serviceId.equals("ClassFactory")) assertEquals(a.getStatus(), Status.BUILTIN);
+
+            if (serviceId.equals("RedGreeter1")) assertEquals(a.getStatus(), Status.DEFINED);
+
+            if (serviceId.equals("TypeCoercer")) assertEquals(a.getStatus(), Status.REAL);
+
+            if (serviceId.equals("BlueGreeter")) assertEquals(a.getStatus(), Status.VIRTUAL);
+        }
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/ModuleImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/ModuleImplTest.java?rev=586932&r1=586931&r2=586932&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/ModuleImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/ModuleImplTest.java Sun Oct 21 11:58:02 2007
@@ -29,6 +29,7 @@
 import org.apache.tapestry.ioc.internal.services.ClassFactoryImpl;
 import org.apache.tapestry.ioc.services.ClassFactory;
 import org.apache.tapestry.ioc.services.RegistryShutdownListener;
+import org.apache.tapestry.ioc.services.Status;
 import org.slf4j.Logger;
 import org.testng.annotations.Test;
 
@@ -40,30 +41,39 @@
         InternalRegistry registry = mockInternalRegistry();
         Logger logger = mockLogger();
         ClassFactory factory = new ClassFactoryImpl();
+        ServiceActivityTracker tracker = mockServiceActivityTracker();
 
         ModuleDef moduleDef = new DefaultModuleDefImpl(ModuleImplTestModule.class, logger,
                 getClassFactory());
 
-        Module module = new ModuleImpl(registry, moduleDef, null, logger);
+        Module module = new ModuleImpl(registry, tracker, moduleDef, null, logger);
 
         expect(registry.getServiceLogger("Upcase")).andReturn(logger);
 
         train_isDebugEnabled(logger, true);
         logger.debug("Creating service 'Upcase'.");
 
-        train_getLifecycle(registry, "singleton", new SingletonServiceLifecycle());
+        tracker.setStatus("Upcase", Status.VIRTUAL);
 
         train_newClass(registry, factory, UpcaseService.class);
 
         registry.addRegistryShutdownListener(isA(RegistryShutdownListener.class));
 
+        replay();
+
+        UpcaseService service = module.getService("Upcase", UpcaseService.class);
+
+        verify();
+
+        train_getLifecycle(registry, "singleton", new SingletonServiceLifecycle());
+
         train_isDebugEnabled(logger, false);
 
         train_findDecoratorsForService(registry);
 
-        replay();
+        tracker.setStatus("Upcase", Status.REAL);
 
-        UpcaseService service = module.getService("Upcase", UpcaseService.class);
+        replay();
 
         assertEquals(service.upcase("hello"), "HELLO");
 
@@ -84,7 +94,7 @@
 
         ModuleDef moduleDef = new DefaultModuleDefImpl(ModuleImplTestModule.class, logger, null);
 
-        Module module = new ModuleImpl(registry, moduleDef, null, logger);
+        Module module = new ModuleImpl(registry, null, moduleDef, null, logger);
 
         replay();
 
@@ -119,7 +129,7 @@
 
         replay();
 
-        Module module = new ModuleImpl(registry, moduleDef, null, logger);
+        Module module = new ModuleImpl(registry, null, moduleDef, null, logger);
 
         Set<DecoratorDef> defs = module.findMatchingDecoratorDefs(serviceDef);
 
@@ -138,7 +148,7 @@
 
         replay();
 
-        Module module = new ModuleImpl(registry, def, null, logger);
+        Module module = new ModuleImpl(registry, null, def, null, logger);
 
         try
         {
@@ -164,7 +174,7 @@
         Logger logger = mockLogger();
         ModuleDef def = new DefaultModuleDefImpl(ExtraPublicConstructorsModule.class, logger, null);
         ClassFactory factory = newMock(ClassFactory.class);
-        Module module = new ModuleImpl(registry, def, null, logger);
+        Module module = new ModuleImpl(registry, null, def, null, logger);
 
         logger.warn(contains("contains more than one public constructor"));
 

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/JustInTimeObjectCreatorTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/JustInTimeObjectCreatorTest.java?rev=586932&r1=586931&r2=586932&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/JustInTimeObjectCreatorTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/JustInTimeObjectCreatorTest.java Sun Oct 21 11:58:02 2007
@@ -16,6 +16,8 @@
 
 import org.apache.tapestry.ioc.ObjectCreator;
 import org.apache.tapestry.ioc.internal.IOCInternalTestCase;
+import org.apache.tapestry.ioc.internal.ServiceActivityTracker;
+import org.apache.tapestry.ioc.services.Status;
 import org.testng.annotations.Test;
 
 public class JustInTimeObjectCreatorTest extends IOCInternalTestCase
@@ -29,7 +31,7 @@
 
         replay();
 
-        JustInTimeObjectCreator j = new JustInTimeObjectCreator(creator, SERVICE_ID);
+        JustInTimeObjectCreator j = new JustInTimeObjectCreator(null, creator, SERVICE_ID);
 
         j.registryDidShutdown();
 
@@ -51,16 +53,19 @@
     {
         ObjectCreator creator = mockObjectCreator();
         Object service = new Object();
+        ServiceActivityTracker tracker = mockServiceActivityTracker();
 
         replay();
 
-        JustInTimeObjectCreator j = new JustInTimeObjectCreator(creator, SERVICE_ID);
+        JustInTimeObjectCreator j = new JustInTimeObjectCreator(tracker, creator, SERVICE_ID);
 
         verify();
 
         // First access: use the creator to get the actual object.
 
         train_createObject(creator, service);
+
+        tracker.setStatus(SERVICE_ID, Status.REAL);
 
         replay();