You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuscany.apache.org by an...@apache.org on 2007/09/08 20:06:53 UTC

svn commit: r573887 - in /incubator/tuscany/java/sca/distribution/webapp: pom.xml src/main/java/org/apache/tuscany/sca/webapp/WarContextListener.java src/main/webapp/WEB-INF/web.xml src/main/webapp/sca-contributions/sample-helloworld-ws-service.jar

Author: antelder
Date: Sat Sep  8 11:06:52 2007
New Revision: 573887

URL: http://svn.apache.org/viewvc?rev=573887&view=rev
Log:
Starting getting webapp distro to work with the new distributed node api

Added:
    incubator/tuscany/java/sca/distribution/webapp/src/main/java/org/apache/tuscany/sca/webapp/WarContextListener.java   (with props)
    incubator/tuscany/java/sca/distribution/webapp/src/main/webapp/sca-contributions/sample-helloworld-ws-service.jar   (with props)
Modified:
    incubator/tuscany/java/sca/distribution/webapp/pom.xml
    incubator/tuscany/java/sca/distribution/webapp/src/main/webapp/WEB-INF/web.xml

Modified: incubator/tuscany/java/sca/distribution/webapp/pom.xml
URL: http://svn.apache.org/viewvc/incubator/tuscany/java/sca/distribution/webapp/pom.xml?rev=573887&r1=573886&r2=573887&view=diff
==============================================================================
--- incubator/tuscany/java/sca/distribution/webapp/pom.xml (original)
+++ incubator/tuscany/java/sca/distribution/webapp/pom.xml Sat Sep  8 11:06:52 2007
@@ -33,6 +33,11 @@
     <dependencies>
         <dependency>
             <groupId>${pom.groupId}</groupId>
+            <artifactId>tuscany-distributed-impl</artifactId>
+            <version>${pom.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${pom.groupId}</groupId>
             <artifactId>tuscany-assembly</artifactId>
             <version>${pom.version}</version>
         </dependency>

Added: incubator/tuscany/java/sca/distribution/webapp/src/main/java/org/apache/tuscany/sca/webapp/WarContextListener.java
URL: http://svn.apache.org/viewvc/incubator/tuscany/java/sca/distribution/webapp/src/main/java/org/apache/tuscany/sca/webapp/WarContextListener.java?rev=573887&view=auto
==============================================================================
--- incubator/tuscany/java/sca/distribution/webapp/src/main/java/org/apache/tuscany/sca/webapp/WarContextListener.java (added)
+++ incubator/tuscany/java/sca/distribution/webapp/src/main/java/org/apache/tuscany/sca/webapp/WarContextListener.java Sat Sep  8 11:06:52 2007
@@ -0,0 +1,300 @@
+/*
+ * 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.tuscany.sca.webapp;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException;
+import org.apache.tuscany.sca.contribution.service.ContributionException;
+import org.apache.tuscany.sca.core.assembly.ActivationException;
+import org.apache.tuscany.sca.distributed.node.impl.ContributionManagerImpl;
+import org.apache.tuscany.sca.distributed.node.impl.NodeImpl;
+
+/**
+ * A ServletContextListener for the Tuscany WAR distribution.
+ * 
+ * Starts and stops a Tuscany SCA domain Node for the webapp. 
+ * 
+ * TODO: Use Node instead of NodeImpl?
+ */
+public class WarContextListener implements ServletContextListener {
+    private final static Logger logger = Logger.getLogger(WarContextListener.class.getName());
+
+    protected NodeImpl node;
+    protected AddableURLClassLoader classLoader;
+    protected File repository;
+
+    protected boolean useHotUpdate;
+    protected long hotDeployInterval = 2000; // 2 seconds, 0 = no hot deploy
+    protected Thread hotDeployThread;
+    protected boolean stopHotDeployThread;
+
+    protected HashMap<URL, Long> existingContributions; // value is last modified time
+
+    private String domainName;
+
+    private String nodeName;
+
+    protected static final String NODE_ATTRIBUTE = WarContextListener.class.getName() + ".TuscanyNode";
+    protected static final String REPOSITORY_FOLDER_NAME = "sca-contributions";
+
+    public void contextInitialized(ServletContextEvent event) {
+        ServletContext servletContext = event.getServletContext();
+        initParameters(servletContext);
+        try {
+
+            initNode();
+        
+        } catch (Throwable e) {
+            e.printStackTrace();
+            servletContext.log("exception initializing SCA node", e);
+        }
+    }
+
+    protected void initNode() throws ContributionException, ActivationException, IOException, CompositeBuilderException, URISyntaxException {        logger.log(Level.INFO, "SCA node starting");
+
+        classLoader = new AddableURLClassLoader(new URL[]{}, Thread.currentThread().getContextClassLoader());
+        Thread.currentThread().setContextClassLoader(classLoader);
+        node = new NodeImpl(domainName, nodeName, classLoader);
+        node.start();
+        
+        existingContributions = new HashMap<URL, Long>();
+        URL[] contributions = getContributionJarURLs(repository);
+        for (URL contribution : contributions) {
+            try {
+                addContribution(contribution);
+            } catch (Throwable e) {
+                e.printStackTrace();
+                logger.log(Level.WARNING, "Exception adding contribution: " + e);
+            }
+        }
+
+        initHotDeploy(repository);
+        
+    }
+    
+    public void contextDestroyed(ServletContextEvent event) {
+        if (node != null) {
+            stopNode();
+        }
+    }
+
+    protected void stopNode() {
+        try {
+
+            node.stop();
+            logger.log(Level.INFO, "SCA node stopped");
+
+        } catch (Throwable e) {
+            e.printStackTrace();
+            logger.log(Level.SEVERE, "exception stopping SCA Node", e);
+        }
+    }
+
+    protected void addContribution(URL contribution) throws CompositeBuilderException, ActivationException, URISyntaxException {
+        classLoader.addURL(contribution);
+        ((ContributionManagerImpl)node.getContributionManager()).addContributionJAR(contribution);
+        existingContributions.put(contribution, new Long(new File(contribution.toURI()).lastModified()));
+        logger.log(Level.INFO, "Added contribution", contribution);
+    }
+
+    protected URL[] getContributionJarURLs(File repositoryDir) {
+
+        String[] jars = repositoryDir.list(new FilenameFilter() {
+            public boolean accept(File dir, String name) {
+                return name.endsWith(".jar");
+            }});
+
+        List<URL> contributionJars = new ArrayList<URL>();
+        if (jars != null) {
+            for (String jar : jars) {
+                try {
+                    contributionJars.add(new File(repositoryDir, jar).toURL());
+                } catch (MalformedURLException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+
+        return contributionJars.toArray(new URL[contributionJars.size()]);
+    }
+
+    private void initHotDeploy(final File repository) {
+
+        if (hotDeployInterval == 0) {
+            return; // hotUpdateInterval of 0 disables hotupdate
+        }
+
+        Runnable runable = new Runnable() {
+
+            public void run() {
+                logger.info("Contribution hot deploy activated");
+                while (!stopHotDeployThread) {
+                    try {
+                        Thread.sleep(hotDeployInterval);
+                    } catch (InterruptedException e) {
+                    }
+                    if (!stopHotDeployThread) {
+                        checkForUpdates(repository);
+                    }
+                }
+                logger.info("Tuscany contribution hot deploy stopped");
+            }
+        };
+        hotDeployThread = new Thread(runable, "TuscanyHotDeploy");
+        stopHotDeployThread = false;
+        hotDeployThread.start();
+    }
+
+    protected void checkForUpdates(File repository) {
+        URL[] currentContributions = getContributionJarURLs(repository);
+
+        List<URL> addedContributions = getAddedContributions(currentContributions);
+        for (URL contribution : addedContributions) {
+            try {
+                addContribution(contribution);
+            } catch (Throwable e) {
+                e.printStackTrace();
+                logger.log(Level.WARNING, "Exception adding contribution: " + e);
+            }
+        }
+        
+        if (useHotUpdate && areContributionsAltered(currentContributions)) {
+            stopNode();
+            try {
+                initNode();
+            } catch (Throwable e) {
+                e.printStackTrace();
+                logger.log(Level.SEVERE, "exception starting SCA Node", e);
+            }
+        }
+    }
+
+    protected List<URL> getAddedContributions(URL[] currentContrabutions) {
+        List<URL> urls = new ArrayList<URL>();
+        for (URL url : currentContrabutions) {
+            if (!existingContributions.containsKey(url)) {
+                urls.add(url);
+                try {
+                    logger.info("added contribution: " + new File(url.toURI()).getName());
+                } catch (URISyntaxException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+        return urls;
+    }
+
+    protected boolean areContributionsAltered(URL[] currentContrabutions) {
+        try {
+            
+            List removedContributions = getRemovedContributions(currentContrabutions);
+            List updatedContributions = getUpdatedContributions(currentContrabutions);
+            
+            return (removedContributions.size() > 0 || updatedContributions.size() > 0);
+
+        } catch (URISyntaxException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    protected List<URL> getUpdatedContributions(URL[] currentContrabutions) throws URISyntaxException {
+        List<URL> urls = new ArrayList<URL>();
+        for (URL url : currentContrabutions) {
+            if (existingContributions.containsKey(url)) {
+                File curentFile = new File(url.toURI());
+                if (curentFile.lastModified() != existingContributions.get(url)) {
+                    urls.add(url);
+                    logger.info("updated contribution: " + curentFile.getName());
+                }
+            }
+        }
+        return urls;
+    }
+
+    protected List getRemovedContributions(URL[] currentContrabutions) throws URISyntaxException {
+        List<URL> currentUrls = Arrays.asList(currentContrabutions);
+        List<URL> urls = new ArrayList<URL>();
+        for (URL url : existingContributions.keySet()) {
+            if (!currentUrls.contains(url)) {
+                urls.add(url);
+            }
+        }
+        for (URL url : urls) {
+            logger.info("removed contributions: " + new File(url.toURI()).getName());
+        }
+        return urls;
+    }
+
+    protected void initParameters(ServletContext servletContext) {
+        if (servletContext.getInitParameter("domainName") != null) {
+            domainName = servletContext.getInitParameter("domainName");
+        } else {
+            domainName = NodeImpl.LOCAL_DOMAIN_URI;
+        }
+
+        if (servletContext.getInitParameter("nodeName") != null) {
+            nodeName = servletContext.getInitParameter("nodeName");
+        } else {
+            nodeName = NodeImpl.LOCAL_NODE_NAME;
+        }
+
+        if (servletContext.getInitParameter("hotDeployInterval") != null) {
+            hotDeployInterval = Long.parseLong(servletContext.getInitParameter("hotDeployInterval"));
+        }
+
+        useHotUpdate = Boolean.valueOf(servletContext.getInitParameter("hotUpdate")).booleanValue();
+
+        repository = new File(servletContext.getRealPath(REPOSITORY_FOLDER_NAME));
+    }
+
+}
+
+class AddableURLClassLoader extends URLClassLoader {
+
+    public AddableURLClassLoader(URL[] urls, ClassLoader parent) {
+        super(urls, parent);
+    }
+    
+    /**
+     * Make URLClassLoader addURL public 
+     */
+    @Override
+    public void addURL(URL url) {
+        super.addURL(url);
+    }
+    
+}

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

Propchange: incubator/tuscany/java/sca/distribution/webapp/src/main/java/org/apache/tuscany/sca/webapp/WarContextListener.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: incubator/tuscany/java/sca/distribution/webapp/src/main/webapp/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/incubator/tuscany/java/sca/distribution/webapp/src/main/webapp/WEB-INF/web.xml?rev=573887&r1=573886&r2=573887&view=diff
==============================================================================
--- incubator/tuscany/java/sca/distribution/webapp/src/main/webapp/WEB-INF/web.xml (original)
+++ incubator/tuscany/java/sca/distribution/webapp/src/main/webapp/WEB-INF/web.xml Sat Sep  8 11:06:52 2007
@@ -25,35 +25,34 @@
   <display-name>Apache Tuscany WebApp Runtime</display-name>
 
   <listener>
-    <listener-class>org.apache.tuscany.sca.host.webapp.HotUpdateContextListener</listener-class>
+    <listener-class>org.apache.tuscany.sca.webapp.WarContextListener</listener-class>
   </listener>
 
-  <listener>
-    <listener-class>org.apache.commons.fileupload.servlet.FileCleanerCleanup</listener-class>
-  </listener>
-
-  <servlet>
-     <servlet-name>TuscanyServlet</servlet-name>
-     <servlet-class>org.apache.tuscany.sca.host.webapp.TuscanyServlet</servlet-class>
-  </servlet>
-  
-  <servlet>
-     <servlet-name>ContributionUploaderServlet</servlet-name>
-     <servlet-class>org.apache.tuscany.sca.webapp.ContributionUploaderServlet</servlet-class>
-  </servlet>
-  
-  <servlet-mapping>
-     <servlet-name>TuscanyServlet</servlet-name>
-     <url-pattern>/sca/*</url-pattern>
-  </servlet-mapping>
+  <context-param>
+     <param-name>domainName</param-name>
+     <param-value>localdomain</param-value>
+  </context-param>
+  <context-param>
+     <param-name>nodeName</param-name>
+     <param-value>localnode</param-value>
+  </context-param>
+  <context-param>
+     <param-name>hotDeployInterval</param-name>
+     <param-value>2000</param-value>
+  </context-param>
+  <context-param>
+     <param-name>hotUpdate</param-name>
+     <param-value>no</param-value>
+  </context-param>
 
-    <servlet-mapping>
-        <servlet-name>ContributionUploaderServlet</servlet-name>
-        <url-pattern>/ContributionUploader</url-pattern>
-    </servlet-mapping>
+  <filter>
+    <filter-name>tuscany</filter-name> 
+    <filter-class>org.apache.tuscany.sca.host.webapp.TuscanyServletFilter</filter-class> 
+  </filter>
 
-  <welcome-file-list id="WelcomeFileList">
-    <welcome-file>scaDomainInfo.jsp</welcome-file>
-  </welcome-file-list>
+  <filter-mapping>
+    <filter-name>tuscany</filter-name> 
+    <url-pattern>/*</url-pattern> 
+  </filter-mapping>
 
 </web-app>

Added: incubator/tuscany/java/sca/distribution/webapp/src/main/webapp/sca-contributions/sample-helloworld-ws-service.jar
URL: http://svn.apache.org/viewvc/incubator/tuscany/java/sca/distribution/webapp/src/main/webapp/sca-contributions/sample-helloworld-ws-service.jar?rev=573887&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/tuscany/java/sca/distribution/webapp/src/main/webapp/sca-contributions/sample-helloworld-ws-service.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream



---------------------------------------------------------------------
To unsubscribe, e-mail: tuscany-commits-unsubscribe@ws.apache.org
For additional commands, e-mail: tuscany-commits-help@ws.apache.org