Admin Service is able to query all the ApplicationManager objects in the container context for application statuses.

StarterServiceDeployer now creates a working directory for each service and places the File for that directory into the service's configuration as $workingDirectory.

The StartupDeployer has been renamed to FolderBasedAppRunner which is more descriptive of its function.  It scans a folder at startup and runs any application archives that it finds.  Similarly, the ClientAppDeployer has been renamed to CommandLineAppRunner, since it runs the application specified on the command line.

The Context class now supports getting all components that implement a given interface.  This functionality is used to find all the ApplicationManager implementations that can be polled for applications.
diff --git a/admin-svc/admin-svc-api/src/main/java/org/apache/river/container/admin/api/ApplicationInfo.java b/admin-svc/admin-svc-api/src/main/java/org/apache/river/container/admin/api/ApplicationInfo.java
index df3f73b..74e2945 100644
--- a/admin-svc/admin-svc-api/src/main/java/org/apache/river/container/admin/api/ApplicationInfo.java
+++ b/admin-svc/admin-svc-api/src/main/java/org/apache/river/container/admin/api/ApplicationInfo.java
@@ -1,7 +1,19 @@
 /*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.river.container.admin.api;
@@ -9,16 +21,35 @@
 import java.io.Serializable;
 
 /**
- *
- * @author trasukg
+ * Transfer object for information about applications running in the container.
+ * 
  */
 public class ApplicationInfo implements Serializable {
     String name;
     ApplicationStatus status;
+    String deployer;
 
-    public ApplicationInfo(String name, ApplicationStatus status) {
+    public ApplicationInfo(String deployer, String name, ApplicationStatus status) {
+        this.deployer=deployer;
         this.name = name;
         this.status = status;
     }
+
+    public String getName() {
+        return name;
+    }
+
+    public ApplicationStatus getStatus() {
+        return status;
+    }
+
+    /**
+     * The name of the deployer that launched this service.
+     * @return 
+     */
+    public String getDeployer() {
+        return deployer;
+    }
+    
     
 }
diff --git a/admin-svc/admin-svc-impl/src/main/java/org/apache/river/container/admin/impl/AdminImpl.java b/admin-svc/admin-svc-impl/src/main/java/org/apache/river/container/admin/impl/AdminImpl.java
index b137e94..82e206a 100644
--- a/admin-svc/admin-svc-impl/src/main/java/org/apache/river/container/admin/impl/AdminImpl.java
+++ b/admin-svc/admin-svc-impl/src/main/java/org/apache/river/container/admin/impl/AdminImpl.java
@@ -19,9 +19,14 @@
 
 import com.sun.jini.config.Config;
 import com.sun.jini.start.LifeCycle;
+import java.io.File;
 import java.io.IOException;
 import java.rmi.server.ExportException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
 import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import net.jini.config.Configuration;
@@ -34,11 +39,12 @@
 import net.jini.lookup.JoinManager;
 import net.jini.lookup.ServiceIDListener;
 import net.jini.security.ProxyPreparer;
+import org.apache.river.container.ApplicationManager;
+import org.apache.river.container.Context;
 import org.apache.river.container.MessageNames;
 import org.apache.river.container.Utils;
 import org.apache.river.container.admin.api.Admin;
 import org.apache.river.container.admin.api.ApplicationInfo;
-import org.apache.river.container.admin.api.ApplicationStatus;
 import org.apache.river.container.admin.dl.AdminRemote;
 
 /**
@@ -53,17 +59,28 @@
     private static final String COMPONENT_ID = "basic";
 
     Configuration config = null;
+    Context ctx = null;
+
     Admin myProxy = null;
     Exporter exporter = null;
     ProxyPreparer registrarPreparer = null;
     JoinManager joinManager = null;
     DiscoveryManagement discoveryManager = null;
     Entry[] attributes = null;
-    ScheduledExecutorService executor=null;
+    volatile ScheduledExecutorService executor = null;
+    File workingDirectory=null;
     
     public AdminImpl(String args[], final LifeCycle lc) throws ConfigurationException, ExportException, IOException {
 
         config = ConfigurationProvider.getInstance(args);
+        try {
+            ctx = (Context) config.getEntry(COMPONENT_ID, "context", Context.class);
+        } catch(Throwable t) {
+            t.printStackTrace();
+        }
+
+        workingDirectory=(File) Config.getNonNullEntry(config, COMPONENT_ID, "workingDirectory", File.class);
+        
         // Get the exporter and create our proxy.
         exporter = (Exporter) Config.getNonNullEntry(config, COMPONENT_ID, "exporter", Exporter.class);
         Utils.logGrantsToClass(log, Level.FINE, this.getClass());
@@ -78,16 +95,31 @@
         // Publish it using the join manager.
         // We don't have to do anything with it - just creating it starts the join process.
         joinManager = new JoinManager(myProxy, attributes, this, discoveryManager, null, config);
-        log.info("Started the admin service");
-        
+
         /* For local clients, we don't want to be dependent on the Jini infrastructure being setup
-        correctly.  For this reason, we stash a copy of the proxy's MarshalledObject in the local 
-        file system.
-        */
-        synchronized(this) {
-            executor=(ScheduledExecutorService) Config.getNonNullEntry(config, COMPONENT_ID, "$executor", ScheduledExecutorService.class);
+         correctly.  For this reason, we stash a copy of the proxy's MarshalledObject in the local 
+         file system.
+         */
+        try {
+            synchronized (this) {
+                executor = (ScheduledExecutorService) Config.getNonNullEntry(config, COMPONENT_ID,
+                        "scheduledExecutorService", ScheduledExecutorService.class);
+                executor.schedule(new Runnable() {
+                    public void run() {
+                        System.out.println("Hooray! we're on the executor!");
+                        System.out.println("Applications:");
+                        try {
+                            printApps(listApplications());
+                        } catch(Exception ex) {
+                            ex.printStackTrace();
+                        }
+                    }
+                }, 4, TimeUnit.SECONDS);
+            }
+            log.info("Started the admin service");
+        } catch (Throwable t) {
+            t.printStackTrace();
         }
-        
     }
 
     ServiceID sid = null;
@@ -97,9 +129,19 @@
     }
 
     public ApplicationInfo[] listApplications() throws IOException {
-        return new ApplicationInfo[]{
-            new ApplicationInfo("abc", ApplicationStatus.UNKNOWN)
-        };
+
+        Collection<ApplicationManager> managers = ctx.getAll(ApplicationManager.class);
+        List<ApplicationInfo> info = new ArrayList<ApplicationInfo>();
+        for (ApplicationManager manager : managers) {
+            info.addAll(manager.getApplicationInfo());
+        }
+        return info.toArray(new ApplicationInfo[0]);
     }
 
+    void printApps(ApplicationInfo[] apps) {
+        for (ApplicationInfo app:apps) {
+            System.out.printf("   %s - %s - %s\n", app.getDeployer(), app.getName(), app.getStatus().toString());
+        }
+        System.out.printf("Working directory is %s and writable=%b\n", workingDirectory.getAbsolutePath(), workingDirectory.canWrite());
+    }
 }
diff --git a/admin-svc/admin-svc-module/src/assemble/module.xml b/admin-svc/admin-svc-module/src/assemble/module.xml
index d8f36d3..a051d78 100644
--- a/admin-svc/admin-svc-module/src/assemble/module.xml
+++ b/admin-svc/admin-svc-module/src/assemble/module.xml
@@ -47,6 +47,9 @@
             <!-- jsk jars are already provided by the container. -->
             <excludes>
                 <exclude>*:jsk-*</exclude>
+                <!-- This jar is in the parent, so we can't have it in the 
+                module -->
+                <exclude>org.apache.river.container:admin-svc-api</exclude>
             </excludes>
         </dependencySet>
         
diff --git a/admin-svc/admin-svc-module/src/main/root/admin-svc.config b/admin-svc/admin-svc-module/src/main/root/admin-svc.config
index 7b6854f..0ed2d46 100644
--- a/admin-svc/admin-svc-module/src/main/root/admin-svc.config
+++ b/admin-svc/admin-svc-module/src/main/root/admin-svc.config
@@ -29,6 +29,12 @@
 
     static attributes = new Entry[] { new Name("admin-service") };
 
+    scheduledExecutorService=$scheduledExecutorService;
+
+    context=$context;
+
+    workingDirectory=$workingDirectory;
+
 }
 
 net.jini.lookup.JoinManager {
diff --git a/product/src/main/root/bin/logging.properties b/product/src/main/root/bin/logging.properties
index 66e0a0c..4586c3b 100644
--- a/product/src/main/root/bin/logging.properties
+++ b/product/src/main/root/bin/logging.properties
@@ -77,6 +77,7 @@
 org.apache.river.container.admin.level=INFO
 org.apache.river.container.deployer.level=INFO
 org.apache.river.container.deployer.ClasspathFilterBuilder.level=INFO
-org.apache.river.container.deployer.DeployerConfigParser=INFO
+org.apache.river.container.deployer.DeployerConfigParser.level=INFO
+org.apache.river.container.deployer.FolderBasedAppRunner.level=FINE
 org.apache.river.container.hsm.level=SEVERE
 net.jini.config.level=INFO
diff --git a/product/src/main/root/profile/admin-client/config.xml b/product/src/main/root/profile/admin-client/config.xml
index dc607fe..914ca41 100644
--- a/product/src/main/root/profile/admin-client/config.xml
+++ b/product/src/main/root/profile/admin-client/config.xml
@@ -45,7 +45,7 @@
     <!-- Deployer for 'service-starter'-style applications. 
     This is the 'admin-app' profile, so set the clientAppName to 'admin'
     -->
-    <cfg:component class="org.apache.river.container.deployer.ClientAppDeployer">
+    <cfg:component class="org.apache.river.container.deployer.CommandLineAppRunner">
         <cfg:property name="deployDirectory" value="deploy"/>
         <cfg:property name="clientAppName" value="admin"/>
     </cfg:component>
diff --git a/product/src/main/root/profile/client/config.xml b/product/src/main/root/profile/client/config.xml
index 9b01480..b46200f 100644
--- a/product/src/main/root/profile/client/config.xml
+++ b/product/src/main/root/profile/client/config.xml
@@ -43,7 +43,7 @@
     </cfg:component>
     
     <!-- Deployer for 'service-starter'-style applications. -->
-    <cfg:component class="org.apache.river.container.deployer.ClientAppDeployer">
+    <cfg:component class="org.apache.river.container.deployer.CommandLineAppRunner">
         <cfg:property name="deployDirectory" value="deploy"/>
     </cfg:component>
     
diff --git a/product/src/main/root/profile/default/config.xml b/product/src/main/root/profile/default/config.xml
index 69488e2..cd21bc2 100644
--- a/product/src/main/root/profile/default/config.xml
+++ b/product/src/main/root/profile/default/config.xml
@@ -38,13 +38,15 @@
     <cfg:component class="org.apache.river.container.codebase.ClassServer"/>
 
     <!-- Deployer for 'service-starter'-style applications. -->
-    <cfg:component class="org.apache.river.container.deployer.StarterServiceDeployer">
+    <cfg:component class="org.apache.river.container.deployer.StarterServiceDeployer"
+        name="starter-service-deployer">
         <cfg:property name="config" value="service-starter.cfg"/>
     </cfg:component>
     
     <!-- Deployer for applications that are in the 'deploy' directory
     at startup. -->
-    <cfg:component class="org.apache.river.container.deployer.StartupDeployer">
+    <cfg:component class="org.apache.river.container.deployer.FolderBasedAppRunner" name="deploy">
+        <cfg:property name="deployerName" value="starter-service-deployer"/>
         <cfg:property name="deployDirectory" value="deploy"/>
         <cfg:property name="autoDeploy" value="true"/>
     </cfg:component>
@@ -59,7 +61,8 @@
     
     <!-- Deployer for applications that are in the 'deploy' directory
     at startup. -->
-    <cfg:component class="org.apache.river.container.deployer.StartupDeployer">
+    <cfg:component class="org.apache.river.container.deployer.FolderBasedAppRunner"
+        name="deploy-privileged">
         <cfg:property name="deployDirectory" value="deploy-privileged"/>
         <cfg:property name="autoDeploy" value="true"/>
         <cfg:property name="deployerName" value="privileged-deployer"/>
diff --git a/product/src/main/root/profile/outrigger/config.xml b/product/src/main/root/profile/outrigger/config.xml
index 7d81f52..5dcd2e0 100644
--- a/product/src/main/root/profile/outrigger/config.xml
+++ b/product/src/main/root/profile/outrigger/config.xml
@@ -44,7 +44,7 @@
     
     <!-- Deployer for applications that are in the 'deploy' directory
     at startup. -->
-    <cfg:component class="org.apache.river.container.deployer.StartupDeployer">
+    <cfg:component class="org.apache.river.container.deployer.FolderBasedAppRunner">
         <cfg:property name="deployDirectory" value="deploy"/>
         <cfg:property name="autoDeploy" value="true"/>
     </cfg:component>
diff --git a/river-container-core/pom.xml b/river-container-core/pom.xml
index 1bce606..e3c5727 100644
--- a/river-container-core/pom.xml
+++ b/river-container-core/pom.xml
@@ -61,9 +61,17 @@
     
         <dependency>
             <groupId>org.apache.river.container</groupId>
-            <artifactId>reggie-module</artifactId>
+            <artifactId>admin-svc-api</artifactId>
             <version>1.0-SNAPSHOT</version>
             
+            <scope>compile</scope>
+        </dependency>
+        
+        <dependency>
+            <groupId>org.apache.river.container</groupId>
+            <artifactId>reggie-module</artifactId>
+            <version>${project.version}</version>
+            
             <scope>test</scope>
         </dependency>
         
diff --git a/river-container-core/src/main/java/org/apache/river/container/deployer/StarterServiceDeployerMXBean.java b/river-container-core/src/main/java/org/apache/river/container/ApplicationManager.java
similarity index 79%
rename from river-container-core/src/main/java/org/apache/river/container/deployer/StarterServiceDeployerMXBean.java
rename to river-container-core/src/main/java/org/apache/river/container/ApplicationManager.java
index b091746..346c388 100644
--- a/river-container-core/src/main/java/org/apache/river/container/deployer/StarterServiceDeployerMXBean.java
+++ b/river-container-core/src/main/java/org/apache/river/container/ApplicationManager.java
@@ -1,26 +1,30 @@
-/*

- * Licensed to the Apache Software Foundation (ASF) under one

- * or more contributor license agreements.  See the NOTICE file

- * distributed with this work for additional information

- * regarding copyright ownership. The ASF licenses this file

- * to you 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.river.container.deployer;

-

-/**

- *

- * @author trasukg

- */

-public interface StarterServiceDeployerMXBean {

-

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.river.container;
+
+import java.util.List;
+import org.apache.river.container.admin.api.ApplicationInfo;
+
+/**
+ *
+ * @author trasukg
+ */
+public interface ApplicationManager {
+    List<ApplicationInfo> getApplicationInfo();
+}
diff --git a/river-container-core/src/main/java/org/apache/river/container/Context.java b/river-container-core/src/main/java/org/apache/river/container/Context.java
index bbf2de6..89047e1 100644
--- a/river-container-core/src/main/java/org/apache/river/container/Context.java
+++ b/river-container-core/src/main/java/org/apache/river/container/Context.java
@@ -19,6 +19,7 @@
 package org.apache.river.container;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -65,6 +66,17 @@
         return contents.get(name);
     }
     
+    public <T extends Object> Collection<T> getAll(Class<T> type) {
+        List<T> list=new ArrayList<T>();
+        for (Object item:contents.values()) {
+            if (type.isAssignableFrom(item.getClass())) {
+                list.add((T) item);
+            }
+        }
+        return list;
+    }
+    
+
     /**
      Called by the bootstrapper to tell us that processing of the initialization
      file is now complete.
diff --git a/river-container-core/src/main/java/org/apache/river/container/MessageNames.java b/river-container-core/src/main/java/org/apache/river/container/MessageNames.java
index 95828e8..7c404b8 100644
--- a/river-container-core/src/main/java/org/apache/river/container/MessageNames.java
+++ b/river-container-core/src/main/java/org/apache/river/container/MessageNames.java
@@ -78,6 +78,7 @@
             DUPLICATE_CLASSPATH="duplicateClasspath",
             EXCEPTION_THROWN="exceptionThrown",
             EXCEPTION_WHILE_STOPPING="exceptionWhileStopping",
+            EXECUTOR_NAME_IS="executorNameIs",
             FAILED_CLEAN_SHUTDOWN="failedCleanShutdown",
             FAILED_DEPLOY_SERVICE="failedDeployService",
             FAILED_READ_PROPERTIES="failedReadProperties",
diff --git a/river-container-core/src/main/java/org/apache/river/container/Strings.java b/river-container-core/src/main/java/org/apache/river/container/Strings.java
index 76510b3..48dfa55 100644
--- a/river-container-core/src/main/java/org/apache/river/container/Strings.java
+++ b/river-container-core/src/main/java/org/apache/river/container/Strings.java
@@ -80,6 +80,7 @@
             UNKNOWN="unknown",
             UNNAMED="unnamed",
             WHITESPACE_SEPARATORS=" \t\n\r",
-            WORK="work";
+            WORK="work",
+            WORKING_DIRECTORY="workingDirectory";
 
 }
diff --git a/river-container-core/src/main/java/org/apache/river/container/deployer/ApplicationEnvironment.java b/river-container-core/src/main/java/org/apache/river/container/deployer/ApplicationEnvironment.java
index dc9dab3..47f1c3f 100644
--- a/river-container-core/src/main/java/org/apache/river/container/deployer/ApplicationEnvironment.java
+++ b/river-container-core/src/main/java/org/apache/river/container/deployer/ApplicationEnvironment.java
@@ -18,6 +18,7 @@
 
 package org.apache.river.container.deployer;
 
+import java.io.File;
 import org.apache.commons.vfs2.FileObject;
 import org.apache.river.container.classloading.VirtualFileSystemClassLoader;
 import org.apache.river.container.codebase.CodebaseContext;
@@ -30,6 +31,16 @@
 public class ApplicationEnvironment {
     VirtualFileSystemClassLoader classLoader=null;
 
+    String applicationManagerName=null;
+
+    public String getApplicationManagerName() {
+        return applicationManagerName;
+    }
+
+    public void setApplicationManagerName(String applicationManagerName) {
+        this.applicationManagerName = applicationManagerName;
+    }
+    
     String serviceName=null;
 
     public String getServiceName() {
@@ -95,4 +106,15 @@
         this.workingContext = workingContext;
     }
     
+    File workingDirectory=null;
+
+    public File getWorkingDirectory() {
+        return workingDirectory;
+    }
+
+    public void setWorkingDirectory(File workingDirectory) {
+        this.workingDirectory = workingDirectory;
+    }
+    
+    
 }
diff --git a/river-container-core/src/main/java/org/apache/river/container/deployer/ClientAppDeployer.java b/river-container-core/src/main/java/org/apache/river/container/deployer/CommandLineAppRunner.java
similarity index 93%
rename from river-container-core/src/main/java/org/apache/river/container/deployer/ClientAppDeployer.java
rename to river-container-core/src/main/java/org/apache/river/container/deployer/CommandLineAppRunner.java
index f3c3638..ed2abf6 100644
--- a/river-container-core/src/main/java/org/apache/river/container/deployer/ClientAppDeployer.java
+++ b/river-container-core/src/main/java/org/apache/river/container/deployer/CommandLineAppRunner.java
@@ -45,13 +45,15 @@
 
 /**
  *
- * A Deployer task that deploys all the applications in a given directory when
- * the container is started up.
+ * A runner task that looks at the command line to determine the name of an
+ * application to run from a deployment folder.  Generally used to run "client"
+ * apps where the name of the app is supplied on the command line, for instance
+ * the browser app or the admin client app.
  */
-public class ClientAppDeployer {
+public class CommandLineAppRunner {
 
     private static final Logger log
-            = Logger.getLogger(ClientAppDeployer.class.getName(), MessageNames.BUNDLE_NAME);
+            = Logger.getLogger(CommandLineAppRunner.class.getName(), MessageNames.BUNDLE_NAME);
 
     @Injected
     ResourceBundle messages;
@@ -184,7 +186,7 @@
             /*
              * Create the ApplicationEnvironment for the archive.
              */
-            ServiceLifeCycle deployedApp = deployer.deployServiceArchive(archiveFile);
+            ServiceLifeCycle deployedApp = deployer.deployServiceArchive(myName, archiveFile);
 
             deployedApp.startWithArgs(commandLineArgs);
         } catch (Throwable t) {
diff --git a/river-container-core/src/main/java/org/apache/river/container/deployer/StartupDeployer.java b/river-container-core/src/main/java/org/apache/river/container/deployer/FolderBasedAppRunner.java
similarity index 88%
rename from river-container-core/src/main/java/org/apache/river/container/deployer/StartupDeployer.java
rename to river-container-core/src/main/java/org/apache/river/container/deployer/FolderBasedAppRunner.java
index 92c78ac..1204420 100644
--- a/river-container-core/src/main/java/org/apache/river/container/deployer/StartupDeployer.java
+++ b/river-container-core/src/main/java/org/apache/river/container/deployer/FolderBasedAppRunner.java
@@ -27,7 +27,6 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
 import javax.management.MBeanRegistrationException;
 import javax.management.MalformedObjectNameException;
 import javax.management.NotCompliantMBeanException;
@@ -35,6 +34,7 @@
 import org.apache.commons.vfs2.FileObject;
 import org.apache.commons.vfs2.FileSystemException;
 import org.apache.commons.vfs2.FileType;
+import org.apache.river.container.ApplicationManager;
 import org.apache.river.container.ConfigurationException;
 import org.apache.river.container.Context;
 import org.apache.river.container.FileUtility;
@@ -45,16 +45,18 @@
 import org.apache.river.container.MessageNames;
 import org.apache.river.container.Name;
 import org.apache.river.container.Utils;
+import org.apache.river.container.admin.api.ApplicationInfo;
+import org.apache.river.container.admin.api.ApplicationStatus;
 
 /**
  *
- * A Deployer task that deploys all the applications in a given directory when
+ * A task that deploys and runs all the applications in a given directory when
  * the container is started up.
  */
-public class StartupDeployer {
+public class FolderBasedAppRunner implements ApplicationManager  {
 
     private static final Logger log
-            = Logger.getLogger(StartupDeployer.class.getName(), MessageNames.BUNDLE_NAME);
+            = Logger.getLogger(FolderBasedAppRunner.class.getName(), MessageNames.BUNDLE_NAME);
 
     private String deployDirectory = org.apache.river.container.Strings.DEFAULT_DEPLOY_DIRECTORY;
 
@@ -227,7 +229,7 @@
         }
     }
 
-    private void synchDeployedServices(Map<String, DeploymentRecord> currentList,
+    private synchronized void synchDeployedServices(Map<String, DeploymentRecord> currentList,
             Map<String, DeploymentRecord> newList) {
         // For each entry
         for (DeploymentRecord rec : newList.values()) {
@@ -273,7 +275,7 @@
             /*
              * Create the ApplicationEnvironment for the archive.
              */
-            dr.serviceLifeCycle = deployer.deployServiceArchive(dr.fileObject);
+            dr.serviceLifeCycle = deployer.deployServiceArchive(myName, dr.fileObject);
             // Register it as an MBean
             registerApplication(dr.serviceLifeCycle);
             dr.serviceLifeCycle.start();
@@ -288,4 +290,27 @@
         dr.serviceLifeCycle.stop();
         unregisterApplication(dr.serviceLifeCycle);
     }
+
+    public synchronized List<ApplicationInfo> getApplicationInfo() {
+        List<ApplicationInfo> info=new ArrayList<ApplicationInfo>(deployedServices.size());
+        for (DeploymentRecord rec: deployedServices.values()) {
+            ApplicationInfo item=new ApplicationInfo(myName, rec.name, toApplicationStatus(rec.serviceLifeCycle));
+            info.add(item);
+        }
+        return info;
+    }
+    
+    ApplicationStatus toApplicationStatus(ServiceLifeCycle lc) {
+        String status=lc.getStatus();
+        if (Strings.RUNNING.equals(status)) {
+            return ApplicationStatus.RUNNING;
+        }
+        if (Strings.IDLE.equals(status)) {
+            return ApplicationStatus.STOPPED;
+        }
+        if (Strings.FAILED.equals(status)) {
+            return ApplicationStatus.FAILED;
+        }
+        return ApplicationStatus.UNKNOWN;
+    }
 }
diff --git a/river-container-core/src/main/java/org/apache/river/container/deployer/StarterServiceDeployer.java b/river-container-core/src/main/java/org/apache/river/container/deployer/StarterServiceDeployer.java
index 500bf90..8016c6a 100644
--- a/river-container-core/src/main/java/org/apache/river/container/deployer/StarterServiceDeployer.java
+++ b/river-container-core/src/main/java/org/apache/river/container/deployer/StarterServiceDeployer.java
@@ -73,7 +73,7 @@
  * Deployer that instantiates applications or services based on the
  * com.sun.jini.starter API
  */
-public class StarterServiceDeployer implements StarterServiceDeployerMXBean {
+public class StarterServiceDeployer  {
 
     private static final Logger log
             = Logger.getLogger(StarterServiceDeployer.class.getName(), MessageNames.BUNDLE_NAME);
@@ -276,13 +276,18 @@
             Thread.currentThread().setContextClassLoader(env.getClassLoader());
             File workingDir = null;
             if (env.getServiceArchive() != null) {
-                /* TODO: Is this right?  Shouldn't the working directory be created
-                by the file manager under the 'work' dir?
+                /* This variable, and the method we're calling on VirtualFileSystemConfiguration,
+                is named in an unfortunate manner for 
+                historical reasons.  What we're really doing here is telling the 
+                VirtualFileSystemConfiguration where to read its configuration 
+                file from.  Iternally to VFSConfig, it's called the "root" directory.
+                It has nothing to do with the "working" directory where the service
+                should be allowed to write its own data.
                 */
                 workingDir = new File(env.getServiceArchive().getURL().toURI());
             } else {
                 workingDir = new File(env.getServiceArchive().getURL().toURI());
-
+            
             }
 
             grantPermissions(env.getClassLoader(),
@@ -311,7 +316,16 @@
                             new Object[]{getConfig(), varName, contextVarName});
                 }
             }
+            
+            /* 
+            One extra "special" variable is the File that gives the working directory.
+            */
+            invokeStatic(env.getClassLoader(), configName, Strings.PUT_SPECIAL_ENTRY,
+                    new Class[]{String.class, Object.class},
+                    Strings.DOLLAR + Strings.WORKING_DIRECTORY, env.getWorkingDirectory());
             /* Install the Executor. */
+            log.log(Level.INFO, MessageNames.EXECUTOR_NAME_IS, 
+                    new Object[]{Strings.DOLLAR + Strings.EXECUTOR_NAME});
             invokeStatic(env.getClassLoader(), configName,
                     Strings.PUT_SPECIAL_ENTRY,
                     new Class[]{String.class, Object.class
@@ -341,9 +355,10 @@
                 new Object[]{myName});
     }
 
-    public ServiceLifeCycle deployServiceArchive(FileObject serviceArchive) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
+    public ServiceLifeCycle deployServiceArchive(String managerName, FileObject serviceArchive) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
         // Create an application environment
         ApplicationEnvironment env = new ApplicationEnvironment();
+        env.setApplicationManagerName(managerName);
         env.setServiceArchive(serviceArchive);
         env.setServiceRoot(
                 serviceArchive.getFileSystem().getFileSystemManager().createFileSystem(Strings.JAR, serviceArchive));
@@ -398,6 +413,12 @@
         grantPermissions(cl, perms);
         
         /*
+         Create the service's working directory and grant permissions to it.
+        */
+        createWorkDirectoryFor(env);
+        grantPermissionsToWorkDirectoryFor(env);
+        
+        /*
          * Create a working context (work manager).
          */
         env.setWorkingContext(contextualWorkManager.createContext(env.getServiceName(), env.getClassLoader()));
@@ -580,4 +601,21 @@
         }
 
     }
+    
+    void createWorkDirectoryFor(ApplicationEnvironment env) throws IOException {
+        FileObject managerDir=fileUtility.getWorkingDirectory(env.getApplicationManagerName());
+        FileObject workingDir=managerDir.resolveFile(env.getServiceName());
+        if (!workingDir.exists()) {
+            workingDir.createFolder();
+        }
+        File workingDirFile=new File(workingDir.getName().getPath());
+        env.setWorkingDirectory(workingDirFile);
+    }
+    
+    void grantPermissionsToWorkDirectoryFor(ApplicationEnvironment env) {
+        Permission[] perms=new Permission[] {
+            new FilePermission(env.getWorkingDirectory().getAbsolutePath()+"/-","read,write,delete")
+        };
+        grantPermissions(env.getClassLoader(), perms);
+    }
 }
diff --git a/river-container-core/src/main/java/org/apache/river/container/deployer/Strings.java b/river-container-core/src/main/java/org/apache/river/container/deployer/Strings.java
index 3f48d84..b7158f9 100644
--- a/river-container-core/src/main/java/org/apache/river/container/deployer/Strings.java
+++ b/river-container-core/src/main/java/org/apache/river/container/deployer/Strings.java
@@ -25,7 +25,10 @@
 public class Strings {
     public static final String
             EMPTY="",
+            FAILED="Failed",
+            IDLE="Idle",
             LPAREN="(",
             RPAREN=")",
+            RUNNING="Running",
             SPACE=" ";
 }
diff --git a/river-container-core/src/main/resources/org/apache/river/container/Messages.properties b/river-container-core/src/main/resources/org/apache/river/container/Messages.properties
index 2dcf8c2..f700f4a 100644
--- a/river-container-core/src/main/resources/org/apache/river/container/Messages.properties
+++ b/river-container-core/src/main/resources/org/apache/river/container/Messages.properties
@@ -57,6 +57,7 @@
 duplicateClasspath=Duplicate class path entry for id ''{0}''.
 exceptionThrown=Exception thrown:\n{0}
 exceptionWhileStopping=Exception thrown during stop operation:\n{0}
+executorNameIs=Executor name is ''{0}''.
 failedCleanShutdown=Application ''{0}'' failed to shutdown cleanly, so we're interrupting it.
 failedDeployService=Deployment of service archive at ''{0}'' failed.
 failedReadProperties=Failed to read one or more properties files.
diff --git a/river-container-core/src/main/resources/org/apache/river/container/core-config.xml b/river-container-core/src/main/resources/org/apache/river/container/core-config.xml
index d4bb419..05db56a 100644
--- a/river-container-core/src/main/resources/org/apache/river/container/core-config.xml
+++ b/river-container-core/src/main/resources/org/apache/river/container/core-config.xml
@@ -55,6 +55,7 @@
         lib/jsk-resources-${jsk-version}.jar
         lib/regexp-1.3.jar
         lib/river-hsm-${project.version}.jar
+        lib/admin-svc-api-${project.version}.jar
     </cfg:classpath>
 
     <!--cfg:component class="org.apache.river.container.ShowContextToConsole"/-->
diff --git a/river-container-core/src/test/java/org/apache/river/container/ContextTest.java b/river-container-core/src/test/java/org/apache/river/container/ContextTest.java
new file mode 100644
index 0000000..9d62ee3
--- /dev/null
+++ b/river-container-core/src/test/java/org/apache/river/container/ContextTest.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.river.container;
+
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import org.apache.river.container.admin.api.ApplicationInfo;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author trasukg
+ */
+public class ContextTest {
+    
+    Context UUT=new Context();
+    
+    public ContextTest() {
+    }
+    
+    @BeforeClass
+    public static void setUpClass() {
+    }
+    
+    @AfterClass
+    public static void tearDownClass() {
+    }
+    
+    @Before
+    public void setUp() {
+    }
+    
+    @After
+    public void tearDown() {
+    }
+
+    @Test
+    public void testGetByClass() {
+        UUT.put(new Object());
+        UUT.put(new Date());
+        ApplicationManager am=new ApplicationManager() {
+            public List<ApplicationInfo> getApplicationInfo() {
+                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+            }
+        };
+        UUT.put(am);
+        Collection<ApplicationManager> ams=UUT.getAll(ApplicationManager.class);
+        assertEquals("Count of ApplicationManagers",1, ams.size());
+        assertEquals("ApplicationManagerInstance", am, ams.iterator().next());
+    }
+}
diff --git a/test-container/src/main/root/profile/client/config.xml b/test-container/src/main/root/profile/client/config.xml
index 1c108d1..941d075 100644
--- a/test-container/src/main/root/profile/client/config.xml
+++ b/test-container/src/main/root/profile/client/config.xml
@@ -44,7 +44,7 @@
     </cfg:component>
     
     <!-- Deployer for 'service-starter'-style applications. -->
-    <cfg:component class="org.apache.river.container.deployer.ClientAppDeployer">
+    <cfg:component class="org.apache.river.container.deployer.CommandLineAppRunner">
         <cfg:property name="config" value="client-app.cfg"/>
         <cfg:property name="deployDirectory" value="deploy"/>
     </cfg:component>
diff --git a/test-container/src/main/root/profile/default/config.xml b/test-container/src/main/root/profile/default/config.xml
index 06108ed..8525202 100644
--- a/test-container/src/main/root/profile/default/config.xml
+++ b/test-container/src/main/root/profile/default/config.xml
@@ -45,7 +45,7 @@
     
     <!-- Deployer for applications that are in the 'deploy' directory
     at startup. -->
-    <cfg:component class="org.apache.river.container.deployer.StartupDeployer">
+    <cfg:component class="org.apache.river.container.deployer.FolderBasedAppRunner">
         <cfg:property name="config" value="service-starter.cfg"/>
         <cfg:property name="deployDirectory" value="deploy"/>
     </cfg:component>