You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuscany.apache.org by jb...@apache.org on 2006/03/02 21:35:10 UTC

svn commit: r382507 - in /incubator/tuscany/java/sca: core/src/main/java/org/apache/tuscany/core/webapp/ tomcat/src/test/java/org/apache/tuscany/tomcat/integration/ tomcat/src/test/resources/app2/ tomcat/src/test/resources/app2/WEB-INF/ tomcat/src/test...

Author: jboynes
Date: Thu Mar  2 12:35:06 2006
New Revision: 382507

URL: http://svn.apache.org/viewcvs?rev=382507&view=rev
Log:
add basic servlet context listener that boots a runtime in a webapp

Added:
    incubator/tuscany/java/sca/core/src/main/java/org/apache/tuscany/core/webapp/
    incubator/tuscany/java/sca/core/src/main/java/org/apache/tuscany/core/webapp/TuscanyServletListener.java   (with props)
    incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/AbstractTomcatTest.java   (with props)
    incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatStandaloneTestCase.java   (with props)
    incubator/tuscany/java/sca/tomcat/src/test/resources/app2/
    incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/
    incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/classes/
    incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/classes/sca.module
    incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/web.xml   (with props)
    incubator/tuscany/java/sca/tomcat/src/test/resources/app2/index.html   (with props)
Modified:
    incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatIntegrationTestCase.java

Added: incubator/tuscany/java/sca/core/src/main/java/org/apache/tuscany/core/webapp/TuscanyServletListener.java
URL: http://svn.apache.org/viewcvs/incubator/tuscany/java/sca/core/src/main/java/org/apache/tuscany/core/webapp/TuscanyServletListener.java?rev=382507&view=auto
==============================================================================
--- incubator/tuscany/java/sca/core/src/main/java/org/apache/tuscany/core/webapp/TuscanyServletListener.java (added)
+++ incubator/tuscany/java/sca/core/src/main/java/org/apache/tuscany/core/webapp/TuscanyServletListener.java Thu Mar  2 12:35:06 2006
@@ -0,0 +1,145 @@
+/**
+ *
+ *  Copyright 2005 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  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.tuscany.core.webapp;
+
+import org.apache.tuscany.common.monitor.MonitorFactory;
+import org.apache.tuscany.common.monitor.impl.NullMonitorFactory;
+import org.apache.tuscany.common.resource.ResourceLoader;
+import org.apache.tuscany.common.resource.impl.ResourceLoaderImpl;
+import org.apache.tuscany.core.builder.RuntimeConfigurationBuilder;
+import org.apache.tuscany.core.builder.impl.DefaultWireBuilder;
+import org.apache.tuscany.core.config.ConfigurationException;
+import org.apache.tuscany.core.config.ModuleComponentConfigurationLoader;
+import org.apache.tuscany.core.config.impl.ModuleComponentConfigurationLoaderImpl;
+import org.apache.tuscany.core.context.AggregateContext;
+import org.apache.tuscany.core.context.EventContext;
+import org.apache.tuscany.core.runtime.RuntimeContext;
+import org.apache.tuscany.core.runtime.RuntimeContextImpl;
+import org.apache.tuscany.core.system.builder.SystemComponentContextBuilder;
+import org.apache.tuscany.core.system.builder.SystemEntryPointBuilder;
+import org.apache.tuscany.core.system.builder.SystemExternalServiceBuilder;
+import org.apache.tuscany.core.system.loader.SystemSCDLModelLoader;
+import org.apache.tuscany.model.assembly.AssemblyFactory;
+import org.apache.tuscany.model.assembly.AssemblyModelContext;
+import org.apache.tuscany.model.assembly.ModuleComponent;
+import org.apache.tuscany.model.assembly.impl.AssemblyFactoryImpl;
+import org.apache.tuscany.model.assembly.impl.AssemblyModelContextImpl;
+import org.apache.tuscany.model.assembly.loader.AssemblyModelLoader;
+import org.apache.tuscany.model.scdl.loader.SCDLModelLoader;
+import org.apache.tuscany.model.scdl.loader.impl.SCDLAssemblyModelLoaderImpl;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * ServletContextListener that can be added to a standard web application to boot
+ * a Tuscany runtime inside that application. All implementation classes should
+ * be located in the web application itself.
+ *
+ * @version $Rev: 380792 $ $Date: 2006-02-24 11:25:11 -0800 (Fri, 24 Feb 2006) $
+ */
+public class TuscanyServletListener implements ServletContextListener {
+    public static final String SCA_COMPONENT_NAME = "org.apache.tuscany.core.webapp.ModuleComponentName";
+    public static final String TUSCANY_RUNTIME_NAME = RuntimeContext.class.getName();
+
+    private final Object sessionKey = new Object();
+
+    private RuntimeContext runtimeContext;
+    private AggregateContext systemModuleComponentContext;
+    private AggregateContext moduleContext;
+
+    private final static String SYSTEM_MODULE_COMPONENT = "org.apache.tuscany.core.system";
+
+    public void contextInitialized(ServletContextEvent servletContextEvent) {
+        ServletContext servletContext = servletContextEvent.getServletContext();
+        String name = servletContext.getInitParameter(SCA_COMPONENT_NAME);
+        String uri = name; // todo get from context path
+        MonitorFactory monitorFactory = new NullMonitorFactory(); // todo have one that writes to the servlet log
+
+        try {
+            bootRuntime(name, uri, monitorFactory);
+        } catch (ConfigurationException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+
+        servletContext.setAttribute(TUSCANY_RUNTIME_NAME, runtimeContext);
+    }
+
+    public void contextDestroyed(ServletContextEvent servletContextEvent) {
+        servletContextEvent.getServletContext().removeAttribute(TUSCANY_RUNTIME_NAME);
+        moduleContext.fireEvent(EventContext.MODULE_STOP, null);
+        moduleContext.stop();
+        systemModuleComponentContext.fireEvent(EventContext.MODULE_STOP, null);
+        systemModuleComponentContext.stop();
+        runtimeContext.stop();
+    }
+
+    private void bootRuntime(String name, String uri, MonitorFactory monitorFactory) throws ConfigurationException {
+        // Create a resource loader from the current classloader
+        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+        ResourceLoader resourceLoader = new ResourceLoaderImpl(classLoader);
+
+        // Create an assembly model factory
+        AssemblyFactory modelFactory=new AssemblyFactoryImpl();
+
+        // Create an assembly model loader
+        List<SCDLModelLoader> scdlLoaders=new ArrayList<SCDLModelLoader>();
+        scdlLoaders.add(new SystemSCDLModelLoader());
+        AssemblyModelLoader modelLoader=new SCDLAssemblyModelLoaderImpl(scdlLoaders);
+
+        // Create an assembly model context
+        AssemblyModelContext modelContext = new AssemblyModelContextImpl(modelFactory, modelLoader, resourceLoader);
+
+        // Create system configuration builders
+        List<RuntimeConfigurationBuilder> configBuilders = new ArrayList();
+        configBuilders.add((new SystemComponentContextBuilder()));
+        configBuilders.add(new SystemEntryPointBuilder());
+        configBuilders.add(new SystemExternalServiceBuilder());
+
+        // Create a runtime context and start it
+        runtimeContext = new RuntimeContextImpl(monitorFactory, scdlLoaders, configBuilders,new DefaultWireBuilder());
+        runtimeContext.start();
+
+        // Get the system context
+        AggregateContext systemContext = runtimeContext.getSystemContext();
+
+        // Load the system module component
+        ModuleComponentConfigurationLoader loader = new ModuleComponentConfigurationLoaderImpl(modelContext);
+        ModuleComponent systemModuleComponent = loader.loadSystemModuleComponent(SYSTEM_MODULE_COMPONENT, SYSTEM_MODULE_COMPONENT);
+
+        // Register it with the system context
+        systemContext.registerModelObject(systemModuleComponent);
+
+        // Get the aggregate context representing the system module component
+        systemModuleComponentContext = (AggregateContext) systemContext.getContext(SYSTEM_MODULE_COMPONENT);
+        systemModuleComponentContext.registerModelObject(systemModuleComponent.getComponentImplementation());
+        systemModuleComponentContext.fireEvent(EventContext.MODULE_START, null);
+
+        // Load the SCDL configuration of the application module
+        ModuleComponent moduleComponent = loader.loadModuleComponent(name, uri);
+
+        // Register it under the root application context
+        runtimeContext.getRootContext().registerModelObject(moduleComponent);
+        moduleContext=(AggregateContext)runtimeContext.getContext(moduleComponent.getName());
+        moduleContext.registerModelObject(moduleComponent.getComponentImplementation());
+
+        moduleContext.fireEvent(EventContext.MODULE_START, null);
+    }
+}

Propchange: incubator/tuscany/java/sca/core/src/main/java/org/apache/tuscany/core/webapp/TuscanyServletListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/tuscany/java/sca/core/src/main/java/org/apache/tuscany/core/webapp/TuscanyServletListener.java
------------------------------------------------------------------------------
    svn:keywords = Rev,Date

Added: incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/AbstractTomcatTest.java
URL: http://svn.apache.org/viewcvs/incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/AbstractTomcatTest.java?rev=382507&view=auto
==============================================================================
--- incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/AbstractTomcatTest.java (added)
+++ incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/AbstractTomcatTest.java Thu Mar  2 12:35:06 2006
@@ -0,0 +1,48 @@
+package org.apache.tuscany.tomcat.integration;
+
+import junit.framework.TestCase;
+import org.apache.catalina.Host;
+import org.apache.catalina.connector.Connector;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.catalina.core.StandardEngine;
+
+import java.io.File;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: jboynes
+ * Date: Mar 2, 2006
+ * Time: 12:20:07 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class AbstractTomcatTest extends TestCase {
+    protected Host host;
+    protected Request request;
+    protected Response response;
+    protected StandardEngine engine;
+
+    protected void setupTomcat(File baseDir, Host host) throws Exception {
+        File appBase = new File(baseDir, "webapps").getCanonicalFile();
+
+        // Configure a Tomcat Engine
+        engine = new StandardEngine();
+        engine.setName("Catalina");
+        engine.setDefaultHost("localhost");
+        engine.setBaseDir(baseDir.getAbsolutePath());
+
+        this.host = host;
+        host.setName("localhost");
+        host.setAppBase(appBase.getAbsolutePath());
+        engine.addChild(host);
+
+        // build a empty request/response
+        Connector connector = new Connector("HTTP/1.1");
+        request = connector.createRequest();
+        org.apache.coyote.Request coyoteRequest = new org.apache.coyote.Request();
+        request.setCoyoteRequest(coyoteRequest);
+        response = connector.createResponse();
+        org.apache.coyote.Response coyoteResponse = new org.apache.coyote.Response();
+        response.setCoyoteResponse(coyoteResponse);
+    }
+}

Propchange: incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/AbstractTomcatTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/AbstractTomcatTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev,Date

Modified: incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatIntegrationTestCase.java
URL: http://svn.apache.org/viewcvs/incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatIntegrationTestCase.java?rev=382507&r1=382506&r2=382507&view=diff
==============================================================================
--- incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatIntegrationTestCase.java (original)
+++ incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatIntegrationTestCase.java Thu Mar  2 12:35:06 2006
@@ -16,31 +16,20 @@
  */
 package org.apache.tuscany.tomcat.integration;
 
-import java.io.File;
-
-import junit.framework.TestCase;
 import org.apache.catalina.Valve;
-import org.apache.catalina.connector.Connector;
-import org.apache.catalina.connector.Request;
-import org.apache.catalina.connector.Response;
 import org.apache.catalina.core.StandardContext;
-import org.apache.catalina.core.StandardEngine;
-import org.apache.catalina.core.StandardHost;
 import org.apache.catalina.core.StandardWrapper;
 import org.apache.catalina.startup.ContextConfig;
-
 import org.apache.tuscany.tomcat.TuscanyHost;
 import org.apache.tuscany.tomcat.TuscanyValve;
 
+import java.io.File;
+
 /**
  * @version $Rev$ $Date$
  */
-public class TomcatIntegrationTestCase extends TestCase {
-    private File app1;
-    private StandardHost host;
-    private Request request;
-    private Response response;
-    private StandardEngine engine;
+public class TomcatIntegrationTestCase extends AbstractTomcatTest {
+    protected File app1;
 
     public void testRuntimeIntegration() throws Exception {
         StandardContext ctx = new StandardContext();
@@ -76,7 +65,8 @@
     protected void setUp() throws Exception {
         super.setUp();
         app1 = new File(getClass().getResource("/app1").toURI());
-        setupTomcat();
+        File baseDir = new File(app1, "../../tomcat").getCanonicalFile();
+        setupTomcat(baseDir, new TuscanyHost());
         engine.start();
     }
 
@@ -85,28 +75,4 @@
         super.tearDown();
     }
 
-    private void setupTomcat() throws Exception {
-        File baseDir = new File(app1, "../../tomcat").getCanonicalFile();
-        File appBase = new File(baseDir, "webapps").getCanonicalFile();
-
-        // Configure a Tomcat Engine
-        engine = new StandardEngine();
-        engine.setName("Catalina");
-        engine.setDefaultHost("localhost");
-        engine.setBaseDir(baseDir.getAbsolutePath());
-
-        host = new TuscanyHost();
-        host.setName("localhost");
-        host.setAppBase(appBase.getAbsolutePath());
-        engine.addChild(host);
-
-        // build a empty request/response
-        Connector connector = new Connector("HTTP/1.1");
-        request = connector.createRequest();
-        org.apache.coyote.Request coyoteRequest = new org.apache.coyote.Request();
-        request.setCoyoteRequest(coyoteRequest);
-        response = connector.createResponse();
-        org.apache.coyote.Response coyoteResponse = new org.apache.coyote.Response();
-        response.setCoyoteResponse(coyoteResponse);
-    }
 }

Added: incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatStandaloneTestCase.java
URL: http://svn.apache.org/viewcvs/incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatStandaloneTestCase.java?rev=382507&view=auto
==============================================================================
--- incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatStandaloneTestCase.java (added)
+++ incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatStandaloneTestCase.java Thu Mar  2 12:35:06 2006
@@ -0,0 +1,65 @@
+package org.apache.tuscany.tomcat.integration;
+
+import org.apache.catalina.core.StandardContext;
+import org.apache.catalina.core.StandardWrapper;
+import org.apache.catalina.core.StandardHost;
+import org.apache.catalina.startup.ContextConfig;
+import org.apache.catalina.Valve;
+import org.apache.tuscany.tomcat.TuscanyValve;
+import org.apache.tuscany.tomcat.TuscanyHost;
+
+import java.io.File;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class TomcatStandaloneTestCase extends AbstractTomcatTest {
+    protected File app2;
+
+    public void testRuntimeIntegration() throws Exception {
+        StandardContext ctx = new StandardContext();
+
+        // caution: this sets the parent of the webapp loader to the test classloader so it can find TestServlet
+        // anything that relies on the TCCL may not work correctly
+        ClassLoader cl = TestServlet.class.getClassLoader();
+        ctx.setParentClassLoader(cl);
+
+        ctx.addLifecycleListener(new ContextConfig());
+        ctx.setName("testContext");
+        ctx.setDocBase(app2.getAbsolutePath());
+/*
+        StandardWrapper wrapper = new StandardWrapper();
+        wrapper.setServletClass(TestServlet.class.getName());
+        ctx.addChild(wrapper);
+*/
+        host.addChild(ctx);
+        boolean found = false;
+        for (Valve valve: ctx.getPipeline().getValves()) {
+            if (valve instanceof TuscanyValve) {
+                found = true;
+                break;
+            }
+        }
+        assertFalse("TuscanyValve in pipeline", found);
+
+        request.setContext(ctx);
+//        request.setWrapper(wrapper);
+//        host.invoke(request, response);
+
+        host.removeChild(ctx);
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        app2 = new File(getClass().getResource("/app2").toURI());
+        File baseDir = new File(app2, "../../tomcat").getCanonicalFile();
+        setupTomcat(baseDir, new StandardHost());
+        engine.start();
+    }
+
+    protected void tearDown() throws Exception {
+        engine.stop();
+        super.tearDown();
+    }
+
+}

Propchange: incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatStandaloneTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatStandaloneTestCase.java
------------------------------------------------------------------------------
    svn:keywords = Rev,Date

Added: incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/classes/sca.module
URL: http://svn.apache.org/viewcvs/incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/classes/sca.module?rev=382507&view=auto
==============================================================================
--- incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/classes/sca.module (added)
+++ incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/classes/sca.module Thu Mar  2 12:35:06 2006
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright (c) 2005 BEA Sytems Inc.
+  Copyright (c) 2005 International Business Machines
+
+  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.
+ -->
+<module xmlns="http://www.osoa.org/xmlns/sca/0.9" xmlns:v="http://www.osoa.org/xmlns/sca/values/0.9"
+        name="testModule">
+
+</module>

Added: incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/web.xml
URL: http://svn.apache.org/viewcvs/incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/web.xml?rev=382507&view=auto
==============================================================================
--- incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/web.xml (added)
+++ incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/web.xml Thu Mar  2 12:35:06 2006
@@ -0,0 +1,13 @@
+<!DOCTYPE web-app
+    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+    "http://java.sun.com/dtd/web-app_2_3.dtd">
+
+<web-app>
+    <context-param>
+        <param-name>org.apache.tuscany.core.webapp.ModuleComponentName</param-name>
+        <param-value>testStandalone</param-value>
+    </context-param>
+    <listener>
+        <listener-class>org.apache.tuscany.core.webapp.TuscanyServletListener</listener-class>
+    </listener>
+</web-app>
\ No newline at end of file

Propchange: incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/web.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/web.xml
------------------------------------------------------------------------------
    svn:keywords = Rev,Date

Added: incubator/tuscany/java/sca/tomcat/src/test/resources/app2/index.html
URL: http://svn.apache.org/viewcvs/incubator/tuscany/java/sca/tomcat/src/test/resources/app2/index.html?rev=382507&view=auto
==============================================================================
--- incubator/tuscany/java/sca/tomcat/src/test/resources/app2/index.html (added)
+++ incubator/tuscany/java/sca/tomcat/src/test/resources/app2/index.html Thu Mar  2 12:35:06 2006
@@ -0,0 +1,3 @@
+<html>
+<body>Hello World</body>
+</html>
\ No newline at end of file

Propchange: incubator/tuscany/java/sca/tomcat/src/test/resources/app2/index.html
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/tuscany/java/sca/tomcat/src/test/resources/app2/index.html
------------------------------------------------------------------------------
    svn:keywords = Rev,Date



Re: svn commit: r382507 - in /incubator/tuscany/java/sca: core/src/main/java/org/apache/tuscany/core/webapp/ tomcat/src/test/java/org/apache/tuscany/tomcat/integration/ tomcat/src/test/resources/app2/ tomcat/src/test/resources/app2/WEB-INF/ tomcat/src/test...

Posted by Jeremy Boynes <jb...@apache.org>.
In response to unasked the question, "what is this?", I added a pacakge
to the core module that is similar to "client" but contains interface
code for booting a Tuscant runtime in a generic web container. This code
only relies on portable APIs and does not integrate with any specific
container.

I expect there will only be 2 or 3 classes so it did not seem worth
creating a new "webapp" module just to hold them. If things get bigger
we should consider moving them out.

--
Jeremy

jboynes@apache.org wrote:
> Author: jboynes
> Date: Thu Mar  2 12:35:06 2006
> New Revision: 382507
> 
> URL: http://svn.apache.org/viewcvs?rev=382507&view=rev
> Log:
> add basic servlet context listener that boots a runtime in a webapp
> 
> Added:
>     incubator/tuscany/java/sca/core/src/main/java/org/apache/tuscany/core/webapp/
>     incubator/tuscany/java/sca/core/src/main/java/org/apache/tuscany/core/webapp/TuscanyServletListener.java   (with props)
>     incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/AbstractTomcatTest.java   (with props)
>     incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatStandaloneTestCase.java   (with props)
>     incubator/tuscany/java/sca/tomcat/src/test/resources/app2/
>     incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/
>     incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/classes/
>     incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/classes/sca.module
>     incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/web.xml   (with props)
>     incubator/tuscany/java/sca/tomcat/src/test/resources/app2/index.html   (with props)
> Modified:
>     incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatIntegrationTestCase.java
> 
> Added: incubator/tuscany/java/sca/core/src/main/java/org/apache/tuscany/core/webapp/TuscanyServletListener.java
> URL: http://svn.apache.org/viewcvs/incubator/tuscany/java/sca/core/src/main/java/org/apache/tuscany/core/webapp/TuscanyServletListener.java?rev=382507&view=auto
> ==============================================================================
> --- incubator/tuscany/java/sca/core/src/main/java/org/apache/tuscany/core/webapp/TuscanyServletListener.java (added)
> +++ incubator/tuscany/java/sca/core/src/main/java/org/apache/tuscany/core/webapp/TuscanyServletListener.java Thu Mar  2 12:35:06 2006
> @@ -0,0 +1,145 @@
> +/**
> + *
> + *  Copyright 2005 The Apache Software Foundation or its licensors, as applicable.
> + *
> + *  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.tuscany.core.webapp;
> +
> +import org.apache.tuscany.common.monitor.MonitorFactory;
> +import org.apache.tuscany.common.monitor.impl.NullMonitorFactory;
> +import org.apache.tuscany.common.resource.ResourceLoader;
> +import org.apache.tuscany.common.resource.impl.ResourceLoaderImpl;
> +import org.apache.tuscany.core.builder.RuntimeConfigurationBuilder;
> +import org.apache.tuscany.core.builder.impl.DefaultWireBuilder;
> +import org.apache.tuscany.core.config.ConfigurationException;
> +import org.apache.tuscany.core.config.ModuleComponentConfigurationLoader;
> +import org.apache.tuscany.core.config.impl.ModuleComponentConfigurationLoaderImpl;
> +import org.apache.tuscany.core.context.AggregateContext;
> +import org.apache.tuscany.core.context.EventContext;
> +import org.apache.tuscany.core.runtime.RuntimeContext;
> +import org.apache.tuscany.core.runtime.RuntimeContextImpl;
> +import org.apache.tuscany.core.system.builder.SystemComponentContextBuilder;
> +import org.apache.tuscany.core.system.builder.SystemEntryPointBuilder;
> +import org.apache.tuscany.core.system.builder.SystemExternalServiceBuilder;
> +import org.apache.tuscany.core.system.loader.SystemSCDLModelLoader;
> +import org.apache.tuscany.model.assembly.AssemblyFactory;
> +import org.apache.tuscany.model.assembly.AssemblyModelContext;
> +import org.apache.tuscany.model.assembly.ModuleComponent;
> +import org.apache.tuscany.model.assembly.impl.AssemblyFactoryImpl;
> +import org.apache.tuscany.model.assembly.impl.AssemblyModelContextImpl;
> +import org.apache.tuscany.model.assembly.loader.AssemblyModelLoader;
> +import org.apache.tuscany.model.scdl.loader.SCDLModelLoader;
> +import org.apache.tuscany.model.scdl.loader.impl.SCDLAssemblyModelLoaderImpl;
> +
> +import javax.servlet.ServletContext;
> +import javax.servlet.ServletContextEvent;
> +import javax.servlet.ServletContextListener;
> +import java.util.ArrayList;
> +import java.util.List;
> +
> +/**
> + * ServletContextListener that can be added to a standard web application to boot
> + * a Tuscany runtime inside that application. All implementation classes should
> + * be located in the web application itself.
> + *
> + * @version $Rev: 380792 $ $Date: 2006-02-24 11:25:11 -0800 (Fri, 24 Feb 2006) $
> + */
> +public class TuscanyServletListener implements ServletContextListener {
> +    public static final String SCA_COMPONENT_NAME = "org.apache.tuscany.core.webapp.ModuleComponentName";
> +    public static final String TUSCANY_RUNTIME_NAME = RuntimeContext.class.getName();
> +
> +    private final Object sessionKey = new Object();
> +
> +    private RuntimeContext runtimeContext;
> +    private AggregateContext systemModuleComponentContext;
> +    private AggregateContext moduleContext;
> +
> +    private final static String SYSTEM_MODULE_COMPONENT = "org.apache.tuscany.core.system";
> +
> +    public void contextInitialized(ServletContextEvent servletContextEvent) {
> +        ServletContext servletContext = servletContextEvent.getServletContext();
> +        String name = servletContext.getInitParameter(SCA_COMPONENT_NAME);
> +        String uri = name; // todo get from context path
> +        MonitorFactory monitorFactory = new NullMonitorFactory(); // todo have one that writes to the servlet log
> +
> +        try {
> +            bootRuntime(name, uri, monitorFactory);
> +        } catch (ConfigurationException e) {
> +            throw new RuntimeException(e.getMessage(), e);
> +        }
> +
> +        servletContext.setAttribute(TUSCANY_RUNTIME_NAME, runtimeContext);
> +    }
> +
> +    public void contextDestroyed(ServletContextEvent servletContextEvent) {
> +        servletContextEvent.getServletContext().removeAttribute(TUSCANY_RUNTIME_NAME);
> +        moduleContext.fireEvent(EventContext.MODULE_STOP, null);
> +        moduleContext.stop();
> +        systemModuleComponentContext.fireEvent(EventContext.MODULE_STOP, null);
> +        systemModuleComponentContext.stop();
> +        runtimeContext.stop();
> +    }
> +
> +    private void bootRuntime(String name, String uri, MonitorFactory monitorFactory) throws ConfigurationException {
> +        // Create a resource loader from the current classloader
> +        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
> +        ResourceLoader resourceLoader = new ResourceLoaderImpl(classLoader);
> +
> +        // Create an assembly model factory
> +        AssemblyFactory modelFactory=new AssemblyFactoryImpl();
> +
> +        // Create an assembly model loader
> +        List<SCDLModelLoader> scdlLoaders=new ArrayList<SCDLModelLoader>();
> +        scdlLoaders.add(new SystemSCDLModelLoader());
> +        AssemblyModelLoader modelLoader=new SCDLAssemblyModelLoaderImpl(scdlLoaders);
> +
> +        // Create an assembly model context
> +        AssemblyModelContext modelContext = new AssemblyModelContextImpl(modelFactory, modelLoader, resourceLoader);
> +
> +        // Create system configuration builders
> +        List<RuntimeConfigurationBuilder> configBuilders = new ArrayList();
> +        configBuilders.add((new SystemComponentContextBuilder()));
> +        configBuilders.add(new SystemEntryPointBuilder());
> +        configBuilders.add(new SystemExternalServiceBuilder());
> +
> +        // Create a runtime context and start it
> +        runtimeContext = new RuntimeContextImpl(monitorFactory, scdlLoaders, configBuilders,new DefaultWireBuilder());
> +        runtimeContext.start();
> +
> +        // Get the system context
> +        AggregateContext systemContext = runtimeContext.getSystemContext();
> +
> +        // Load the system module component
> +        ModuleComponentConfigurationLoader loader = new ModuleComponentConfigurationLoaderImpl(modelContext);
> +        ModuleComponent systemModuleComponent = loader.loadSystemModuleComponent(SYSTEM_MODULE_COMPONENT, SYSTEM_MODULE_COMPONENT);
> +
> +        // Register it with the system context
> +        systemContext.registerModelObject(systemModuleComponent);
> +
> +        // Get the aggregate context representing the system module component
> +        systemModuleComponentContext = (AggregateContext) systemContext.getContext(SYSTEM_MODULE_COMPONENT);
> +        systemModuleComponentContext.registerModelObject(systemModuleComponent.getComponentImplementation());
> +        systemModuleComponentContext.fireEvent(EventContext.MODULE_START, null);
> +
> +        // Load the SCDL configuration of the application module
> +        ModuleComponent moduleComponent = loader.loadModuleComponent(name, uri);
> +
> +        // Register it under the root application context
> +        runtimeContext.getRootContext().registerModelObject(moduleComponent);
> +        moduleContext=(AggregateContext)runtimeContext.getContext(moduleComponent.getName());
> +        moduleContext.registerModelObject(moduleComponent.getComponentImplementation());
> +
> +        moduleContext.fireEvent(EventContext.MODULE_START, null);
> +    }
> +}
> 
> Propchange: incubator/tuscany/java/sca/core/src/main/java/org/apache/tuscany/core/webapp/TuscanyServletListener.java
> ------------------------------------------------------------------------------
>     svn:eol-style = native
> 
> Propchange: incubator/tuscany/java/sca/core/src/main/java/org/apache/tuscany/core/webapp/TuscanyServletListener.java
> ------------------------------------------------------------------------------
>     svn:keywords = Rev,Date
> 
> Added: incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/AbstractTomcatTest.java
> URL: http://svn.apache.org/viewcvs/incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/AbstractTomcatTest.java?rev=382507&view=auto
> ==============================================================================
> --- incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/AbstractTomcatTest.java (added)
> +++ incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/AbstractTomcatTest.java Thu Mar  2 12:35:06 2006
> @@ -0,0 +1,48 @@
> +package org.apache.tuscany.tomcat.integration;
> +
> +import junit.framework.TestCase;
> +import org.apache.catalina.Host;
> +import org.apache.catalina.connector.Connector;
> +import org.apache.catalina.connector.Request;
> +import org.apache.catalina.connector.Response;
> +import org.apache.catalina.core.StandardEngine;
> +
> +import java.io.File;
> +
> +/**
> + * Created by IntelliJ IDEA.
> + * User: jboynes
> + * Date: Mar 2, 2006
> + * Time: 12:20:07 PM
> + * To change this template use File | Settings | File Templates.
> + */
> +public class AbstractTomcatTest extends TestCase {
> +    protected Host host;
> +    protected Request request;
> +    protected Response response;
> +    protected StandardEngine engine;
> +
> +    protected void setupTomcat(File baseDir, Host host) throws Exception {
> +        File appBase = new File(baseDir, "webapps").getCanonicalFile();
> +
> +        // Configure a Tomcat Engine
> +        engine = new StandardEngine();
> +        engine.setName("Catalina");
> +        engine.setDefaultHost("localhost");
> +        engine.setBaseDir(baseDir.getAbsolutePath());
> +
> +        this.host = host;
> +        host.setName("localhost");
> +        host.setAppBase(appBase.getAbsolutePath());
> +        engine.addChild(host);
> +
> +        // build a empty request/response
> +        Connector connector = new Connector("HTTP/1.1");
> +        request = connector.createRequest();
> +        org.apache.coyote.Request coyoteRequest = new org.apache.coyote.Request();
> +        request.setCoyoteRequest(coyoteRequest);
> +        response = connector.createResponse();
> +        org.apache.coyote.Response coyoteResponse = new org.apache.coyote.Response();
> +        response.setCoyoteResponse(coyoteResponse);
> +    }
> +}
> 
> Propchange: incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/AbstractTomcatTest.java
> ------------------------------------------------------------------------------
>     svn:eol-style = native
> 
> Propchange: incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/AbstractTomcatTest.java
> ------------------------------------------------------------------------------
>     svn:keywords = Rev,Date
> 
> Modified: incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatIntegrationTestCase.java
> URL: http://svn.apache.org/viewcvs/incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatIntegrationTestCase.java?rev=382507&r1=382506&r2=382507&view=diff
> ==============================================================================
> --- incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatIntegrationTestCase.java (original)
> +++ incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatIntegrationTestCase.java Thu Mar  2 12:35:06 2006
> @@ -16,31 +16,20 @@
>   */
>  package org.apache.tuscany.tomcat.integration;
>  
> -import java.io.File;
> -
> -import junit.framework.TestCase;
>  import org.apache.catalina.Valve;
> -import org.apache.catalina.connector.Connector;
> -import org.apache.catalina.connector.Request;
> -import org.apache.catalina.connector.Response;
>  import org.apache.catalina.core.StandardContext;
> -import org.apache.catalina.core.StandardEngine;
> -import org.apache.catalina.core.StandardHost;
>  import org.apache.catalina.core.StandardWrapper;
>  import org.apache.catalina.startup.ContextConfig;
> -
>  import org.apache.tuscany.tomcat.TuscanyHost;
>  import org.apache.tuscany.tomcat.TuscanyValve;
>  
> +import java.io.File;
> +
>  /**
>   * @version $Rev$ $Date$
>   */
> -public class TomcatIntegrationTestCase extends TestCase {
> -    private File app1;
> -    private StandardHost host;
> -    private Request request;
> -    private Response response;
> -    private StandardEngine engine;
> +public class TomcatIntegrationTestCase extends AbstractTomcatTest {
> +    protected File app1;
>  
>      public void testRuntimeIntegration() throws Exception {
>          StandardContext ctx = new StandardContext();
> @@ -76,7 +65,8 @@
>      protected void setUp() throws Exception {
>          super.setUp();
>          app1 = new File(getClass().getResource("/app1").toURI());
> -        setupTomcat();
> +        File baseDir = new File(app1, "../../tomcat").getCanonicalFile();
> +        setupTomcat(baseDir, new TuscanyHost());
>          engine.start();
>      }
>  
> @@ -85,28 +75,4 @@
>          super.tearDown();
>      }
>  
> -    private void setupTomcat() throws Exception {
> -        File baseDir = new File(app1, "../../tomcat").getCanonicalFile();
> -        File appBase = new File(baseDir, "webapps").getCanonicalFile();
> -
> -        // Configure a Tomcat Engine
> -        engine = new StandardEngine();
> -        engine.setName("Catalina");
> -        engine.setDefaultHost("localhost");
> -        engine.setBaseDir(baseDir.getAbsolutePath());
> -
> -        host = new TuscanyHost();
> -        host.setName("localhost");
> -        host.setAppBase(appBase.getAbsolutePath());
> -        engine.addChild(host);
> -
> -        // build a empty request/response
> -        Connector connector = new Connector("HTTP/1.1");
> -        request = connector.createRequest();
> -        org.apache.coyote.Request coyoteRequest = new org.apache.coyote.Request();
> -        request.setCoyoteRequest(coyoteRequest);
> -        response = connector.createResponse();
> -        org.apache.coyote.Response coyoteResponse = new org.apache.coyote.Response();
> -        response.setCoyoteResponse(coyoteResponse);
> -    }
>  }
> 
> Added: incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatStandaloneTestCase.java
> URL: http://svn.apache.org/viewcvs/incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatStandaloneTestCase.java?rev=382507&view=auto
> ==============================================================================
> --- incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatStandaloneTestCase.java (added)
> +++ incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatStandaloneTestCase.java Thu Mar  2 12:35:06 2006
> @@ -0,0 +1,65 @@
> +package org.apache.tuscany.tomcat.integration;
> +
> +import org.apache.catalina.core.StandardContext;
> +import org.apache.catalina.core.StandardWrapper;
> +import org.apache.catalina.core.StandardHost;
> +import org.apache.catalina.startup.ContextConfig;
> +import org.apache.catalina.Valve;
> +import org.apache.tuscany.tomcat.TuscanyValve;
> +import org.apache.tuscany.tomcat.TuscanyHost;
> +
> +import java.io.File;
> +
> +/**
> + * @version $Rev$ $Date$
> + */
> +public class TomcatStandaloneTestCase extends AbstractTomcatTest {
> +    protected File app2;
> +
> +    public void testRuntimeIntegration() throws Exception {
> +        StandardContext ctx = new StandardContext();
> +
> +        // caution: this sets the parent of the webapp loader to the test classloader so it can find TestServlet
> +        // anything that relies on the TCCL may not work correctly
> +        ClassLoader cl = TestServlet.class.getClassLoader();
> +        ctx.setParentClassLoader(cl);
> +
> +        ctx.addLifecycleListener(new ContextConfig());
> +        ctx.setName("testContext");
> +        ctx.setDocBase(app2.getAbsolutePath());
> +/*
> +        StandardWrapper wrapper = new StandardWrapper();
> +        wrapper.setServletClass(TestServlet.class.getName());
> +        ctx.addChild(wrapper);
> +*/
> +        host.addChild(ctx);
> +        boolean found = false;
> +        for (Valve valve: ctx.getPipeline().getValves()) {
> +            if (valve instanceof TuscanyValve) {
> +                found = true;
> +                break;
> +            }
> +        }
> +        assertFalse("TuscanyValve in pipeline", found);
> +
> +        request.setContext(ctx);
> +//        request.setWrapper(wrapper);
> +//        host.invoke(request, response);
> +
> +        host.removeChild(ctx);
> +    }
> +
> +    protected void setUp() throws Exception {
> +        super.setUp();
> +        app2 = new File(getClass().getResource("/app2").toURI());
> +        File baseDir = new File(app2, "../../tomcat").getCanonicalFile();
> +        setupTomcat(baseDir, new StandardHost());
> +        engine.start();
> +    }
> +
> +    protected void tearDown() throws Exception {
> +        engine.stop();
> +        super.tearDown();
> +    }
> +
> +}
> 
> Propchange: incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatStandaloneTestCase.java
> ------------------------------------------------------------------------------
>     svn:eol-style = native
> 
> Propchange: incubator/tuscany/java/sca/tomcat/src/test/java/org/apache/tuscany/tomcat/integration/TomcatStandaloneTestCase.java
> ------------------------------------------------------------------------------
>     svn:keywords = Rev,Date
> 
> Added: incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/classes/sca.module
> URL: http://svn.apache.org/viewcvs/incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/classes/sca.module?rev=382507&view=auto
> ==============================================================================
> --- incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/classes/sca.module (added)
> +++ incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/classes/sca.module Thu Mar  2 12:35:06 2006
> @@ -0,0 +1,21 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<!--
> +  Copyright (c) 2005 BEA Sytems Inc.
> +  Copyright (c) 2005 International Business Machines
> +
> +  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.
> + -->
> +<module xmlns="http://www.osoa.org/xmlns/sca/0.9" xmlns:v="http://www.osoa.org/xmlns/sca/values/0.9"
> +        name="testModule">
> +
> +</module>
> 
> Added: incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/web.xml
> URL: http://svn.apache.org/viewcvs/incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/web.xml?rev=382507&view=auto
> ==============================================================================
> --- incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/web.xml (added)
> +++ incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/web.xml Thu Mar  2 12:35:06 2006
> @@ -0,0 +1,13 @@
> +<!DOCTYPE web-app
> +    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
> +    "http://java.sun.com/dtd/web-app_2_3.dtd">
> +
> +<web-app>
> +    <context-param>
> +        <param-name>org.apache.tuscany.core.webapp.ModuleComponentName</param-name>
> +        <param-value>testStandalone</param-value>
> +    </context-param>
> +    <listener>
> +        <listener-class>org.apache.tuscany.core.webapp.TuscanyServletListener</listener-class>
> +    </listener>
> +</web-app>
> \ No newline at end of file
> 
> Propchange: incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/web.xml
> ------------------------------------------------------------------------------
>     svn:eol-style = native
> 
> Propchange: incubator/tuscany/java/sca/tomcat/src/test/resources/app2/WEB-INF/web.xml
> ------------------------------------------------------------------------------
>     svn:keywords = Rev,Date
> 
> Added: incubator/tuscany/java/sca/tomcat/src/test/resources/app2/index.html
> URL: http://svn.apache.org/viewcvs/incubator/tuscany/java/sca/tomcat/src/test/resources/app2/index.html?rev=382507&view=auto
> ==============================================================================
> --- incubator/tuscany/java/sca/tomcat/src/test/resources/app2/index.html (added)
> +++ incubator/tuscany/java/sca/tomcat/src/test/resources/app2/index.html Thu Mar  2 12:35:06 2006
> @@ -0,0 +1,3 @@
> +<html>
> +<body>Hello World</body>
> +</html>
> \ No newline at end of file
> 
> Propchange: incubator/tuscany/java/sca/tomcat/src/test/resources/app2/index.html
> ------------------------------------------------------------------------------
>     svn:eol-style = native
> 
> Propchange: incubator/tuscany/java/sca/tomcat/src/test/resources/app2/index.html
> ------------------------------------------------------------------------------
>     svn:keywords = Rev,Date
> 
>