From a10633370206b6060f58a5723478e2cbf72c1248 Mon Sep 17 00:00:00 2001 From: antelder Date: Fri, 4 Dec 2009 15:11:00 +0000 Subject: Update the Tomcat distribution so that SCA contributions can be deployed to exsiting Hosts instead of running in the Tuscany webapp. This means they run just like a regular web application and can be managed with the usual Tomcat admin and use all the usual Tomcat Host and Context features. Also update to configure the domain from the context so the domain nad be customized fro the Tomcat instance and each contribution via a context parameter. That removes the need for the singleton install option so that is removed. Also update the install page to have a bit of text about whats going on in the intsall git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@887223 13f79535-47bb-0310-9956-ffa450edef68 --- .../src/main/java/testing/HelloworldService.java | 3 + .../tuscany/sca/tomcat/TuscanyContextConfig.java | 183 +++++++++++++++++++++ .../org/apache/tuscany/sca/tomcat/TuscanyHost.java | 167 +++++++++++++++++++ .../tuscany/sca/tomcat/foo/TuscanyTomcatNode.java | 74 --------- .../java/org/apache/tuscany/sca/war/Installer.java | 26 +-- .../apache/tuscany/sca/war/InstallerServlet.java | 4 +- .../tomcat-war/src/main/webapp/installer.jsp | 34 +++- 7 files changed, 393 insertions(+), 98 deletions(-) create mode 100644 sca-java-2.x/trunk/distribution/tomcat/tomcat-hook/src/main/java/org/apache/tuscany/sca/tomcat/TuscanyContextConfig.java create mode 100644 sca-java-2.x/trunk/distribution/tomcat/tomcat-hook/src/main/java/org/apache/tuscany/sca/tomcat/TuscanyHost.java delete mode 100644 sca-java-2.x/trunk/distribution/tomcat/tomcat-servlet/src/main/java/org/apache/tuscany/sca/tomcat/foo/TuscanyTomcatNode.java (limited to 'sca-java-2.x') diff --git a/sca-java-2.x/trunk/distribution/tomcat/testing/helloworld-service-contribution/src/main/java/testing/HelloworldService.java b/sca-java-2.x/trunk/distribution/tomcat/testing/helloworld-service-contribution/src/main/java/testing/HelloworldService.java index 65e95f275c..eec9d63da8 100644 --- a/sca-java-2.x/trunk/distribution/tomcat/testing/helloworld-service-contribution/src/main/java/testing/HelloworldService.java +++ b/sca-java-2.x/trunk/distribution/tomcat/testing/helloworld-service-contribution/src/main/java/testing/HelloworldService.java @@ -18,6 +18,9 @@ */ package testing; +import org.oasisopen.sca.annotation.Remotable; + +@Remotable public interface HelloworldService { String sayHello(String name); diff --git a/sca-java-2.x/trunk/distribution/tomcat/tomcat-hook/src/main/java/org/apache/tuscany/sca/tomcat/TuscanyContextConfig.java b/sca-java-2.x/trunk/distribution/tomcat/tomcat-hook/src/main/java/org/apache/tuscany/sca/tomcat/TuscanyContextConfig.java new file mode 100644 index 0000000000..5e7905d246 --- /dev/null +++ b/sca-java-2.x/trunk/distribution/tomcat/tomcat-hook/src/main/java/org/apache/tuscany/sca/tomcat/TuscanyContextConfig.java @@ -0,0 +1,183 @@ +/* + * 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.tomcat; + +import java.io.File; +import java.io.IOException; +import java.net.URL; + +import org.apache.catalina.Host; +import org.apache.catalina.core.StandardContext; +import org.apache.catalina.core.StandardHost; +import org.apache.catalina.startup.ContextConfig; +import org.apache.catalina.startup.ExpandWar; + +public class TuscanyContextConfig extends ContextConfig{ + + /** + * Return the location of the default deployment descriptor + * + * Override the super class method to use the Tuscany specific + * default web.xml which has the Tuscany listener and filer config + */ + @Override + public String getDefaultWebXml() { + if( defaultWebXml == null ) { + defaultWebXml="conf/tuscany-web.xml"; + } + return (this.defaultWebXml); + } + + /** + * Adjust docBase. + * + * This is cutNpaste of the Tomcat method but changed on the lines marked with // TUSCANY: + * to override the default that only works for file names ending with .war + * + */ + @Override + protected void fixDocBase() + throws IOException { + + Host host = (Host) context.getParent(); + String appBase = host.getAppBase(); + + boolean unpackWARs = true; + if (host instanceof StandardHost) { + unpackWARs = ((StandardHost) host).isUnpackWARs() + && ((StandardContext) context).getUnpackWAR(); + } + + File canonicalAppBase = new File(appBase); + if (canonicalAppBase.isAbsolute()) { + canonicalAppBase = canonicalAppBase.getCanonicalFile(); + } else { + canonicalAppBase = + new File(System.getProperty("catalina.base"), appBase) + .getCanonicalFile(); + } + + String docBase = context.getDocBase(); + if (docBase == null) { + // Trying to guess the docBase according to the path + String path = context.getPath(); + if (path == null) { + return; + } + if (path.equals("")) { + docBase = "ROOT"; + } else { + if (path.startsWith("/")) { + docBase = path.substring(1); + } else { + docBase = path; + } + } + } + + File file = new File(docBase); + if (!file.isAbsolute()) { + docBase = (new File(canonicalAppBase, docBase)).getPath(); + } else { + docBase = file.getCanonicalPath(); + } + file = new File(docBase); + String origDocBase = docBase; + + String contextPath = context.getPath(); + if (contextPath.equals("")) { + contextPath = "ROOT"; + } else { + if (contextPath.lastIndexOf('/') > 0) { + contextPath = "/" + contextPath.substring(1).replace('/','#'); + } + } + // TUSCANY: update from .war to also support .jar and .zip SCA contributions + if ((docBase.toLowerCase().endsWith(".war") || docBase.toLowerCase().endsWith(".jar")||docBase.toLowerCase().endsWith(".zip")) && !file.isDirectory() && unpackWARs) { + URL war = new URL("jar:" + (new File(docBase)).toURI().toURL() + "!/"); + docBase = ExpandWar.expand(host, war, contextPath); + file = new File(docBase); + docBase = file.getCanonicalPath(); + if (context instanceof StandardContext) { + ((StandardContext) context).setOriginalDocBase(origDocBase); + } + } else { + File docDir = new File(docBase); + if (!docDir.exists()) { + // TUSCANY: update from .war to also support .jar and .zip SCA contributions + File warFile = new File(docBase + ".war"); + if (warFile.exists()) { + if (unpackWARs) { + URL war = + new URL("jar:" + warFile.toURI().toURL() + "!/"); + docBase = ExpandWar.expand(host, war, contextPath); + file = new File(docBase); + docBase = file.getCanonicalPath(); + } else { + docBase = warFile.getCanonicalPath(); + } + } else { + warFile = new File(docBase + ".jar"); + if (warFile.exists()) { + if (unpackWARs) { + URL war = + new URL("jar:" + warFile.toURI().toURL() + "!/"); + docBase = ExpandWar.expand(host, war, contextPath); + file = new File(docBase); + docBase = file.getCanonicalPath(); + } else { + docBase = warFile.getCanonicalPath(); + } + } else { + warFile = new File(docBase + ".zip"); + if (warFile.exists()) { + if (unpackWARs) { + URL war = + new URL("jar:" + warFile.toURI().toURL() + "!/"); + docBase = ExpandWar.expand(host, war, contextPath); + file = new File(docBase); + docBase = file.getCanonicalPath(); + } else { + docBase = warFile.getCanonicalPath(); + } + } + } + } + if (context instanceof StandardContext) { + ((StandardContext) context).setOriginalDocBase(origDocBase); + } + } + } + + if (docBase.startsWith(canonicalAppBase.getPath())) { + docBase = docBase.substring(canonicalAppBase.getPath().length()); + docBase = docBase.replace(File.separatorChar, '/'); + if (docBase.startsWith("/")) { + docBase = docBase.substring(1); + } + } else { + docBase = docBase.replace(File.separatorChar, '/'); + } + + context.setDocBase(docBase); + + } + +} diff --git a/sca-java-2.x/trunk/distribution/tomcat/tomcat-hook/src/main/java/org/apache/tuscany/sca/tomcat/TuscanyHost.java b/sca-java-2.x/trunk/distribution/tomcat/tomcat-hook/src/main/java/org/apache/tuscany/sca/tomcat/TuscanyHost.java new file mode 100644 index 0000000000..d6042c5902 --- /dev/null +++ b/sca-java-2.x/trunk/distribution/tomcat/tomcat-hook/src/main/java/org/apache/tuscany/sca/tomcat/TuscanyHost.java @@ -0,0 +1,167 @@ +/* + * 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.tomcat; + +import java.io.File; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import org.apache.catalina.Context; +import org.apache.catalina.Lifecycle; +import org.apache.catalina.LifecycleListener; +import org.apache.catalina.startup.HostConfig; + +/** + * A Tuscany customized HostConfig that adds support for SCA contributions + * to be deployed along with the usual .war files. + */ +public class TuscanyHost extends HostConfig { + + protected File scaBase = null; + + @Override + protected void deployApps() { + + File appBase = appBase(); + File configBase = configBase(); + // Deploy XML descriptors from configBase + deployDescriptors(configBase, configBase.list()); + // Deploy WARs, and loop if additional descriptors are found + deployWARs(appBase, appBase.list()); + // TUSCANY: Deploy any SCA contibutions + deploySCAContributions(appBase, appBase.list()); + // Deploy expanded folders + deployDirectories(appBase, appBase.list()); + } + + protected void deploySCAContributions(File appBase, String[] files) { + if (files == null) + return; + + for (int i = 0; i < files.length; i++) { + + File scafile = new File(appBase, files[i]); + + if (scafile.isFile() && isSCAContribution(scafile)) { + + // Calculate the context path and make sure it is unique + String contextPath = "/" + files[i].replace('#','/'); + int period = contextPath.lastIndexOf("."); + if (period >= 0) + contextPath = contextPath.substring(0, period); + + if (isServiced(contextPath)) + continue; + + String file = files[i]; + + deploySCAContribution(contextPath, scafile, file); + + } + + } + + } + + protected String tuscanyContextClass = "org.apache.tuscany.sca.tomcat.TuscanyContextConfig"; + + protected void deploySCAContribution(String contextPath, File dir, String file) { + if (deploymentExists(contextPath)) + return; + + DeployedApplication deployedApp = new DeployedApplication(contextPath); + + // Deploy the application in this WAR file + if(log.isInfoEnabled()) + log.info("Deploying SCA contibution: " + file); + + // Populate redeploy resources with the WAR file + deployedApp.redeployResources.put(dir.getAbsolutePath(), new Long(dir.lastModified())); + + try { + Context context = (Context) Class.forName(contextClass).newInstance(); + if (context instanceof Lifecycle) { + + // Tuscany: change to use the Tuscany ContextConfig class + Class clazz = Class.forName(tuscanyContextClass); + + LifecycleListener listener = + (LifecycleListener) clazz.newInstance(); + ((Lifecycle) context).addLifecycleListener(listener); + } + context.setPath(contextPath); + context.setDocBase(file); + + host.addChild(context); + // If we're unpacking WARs, the docBase will be mutated after + // starting the context + if (unpackWARs && (context.getDocBase() != null)) { + String name = null; + String path = context.getPath(); + if (path.equals("")) { + name = "ROOT"; + } else { + if (path.startsWith("/")) { + name = path.substring(1); + } else { + name = path; + } + } + name = name.replace('/', '#'); + File docBase = new File(name); + if (!docBase.isAbsolute()) { + docBase = new File(appBase(), name); + } + deployedApp.redeployResources.put(docBase.getAbsolutePath(), + new Long(docBase.lastModified())); + addWatchedResources(deployedApp, docBase.getAbsolutePath(), context); + } else { + addWatchedResources(deployedApp, null, context); + } + } catch (Throwable t) { + log.error(sm.getString("hostConfig.deployJar.error", file), t); + } + + deployed.put(contextPath, deployedApp); + } + + protected boolean isSCAContribution(File file) { + ZipFile zip = null; + ZipEntry entry = null; + try { + try { + zip = new ZipFile(file); + entry = zip.getEntry("META-INF/sca-contribution.xml"); + } catch (Exception e) { + } + + return (entry != null); + + } finally { + if (zip != null) { + try { + zip.close(); + } catch (Throwable t) { + } + } + } + } + +} diff --git a/sca-java-2.x/trunk/distribution/tomcat/tomcat-servlet/src/main/java/org/apache/tuscany/sca/tomcat/foo/TuscanyTomcatNode.java b/sca-java-2.x/trunk/distribution/tomcat/tomcat-servlet/src/main/java/org/apache/tuscany/sca/tomcat/foo/TuscanyTomcatNode.java deleted file mode 100644 index 972aafd8b6..0000000000 --- a/sca-java-2.x/trunk/distribution/tomcat/tomcat-servlet/src/main/java/org/apache/tuscany/sca/tomcat/foo/TuscanyTomcatNode.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.tomcat.foo; - -import java.io.File; -import java.net.MalformedURLException; - -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; - -import org.apache.tuscany.sca.node.Contribution; -import org.apache.tuscany.sca.node.Node; -import org.apache.tuscany.sca.node.NodeFactory; -import org.apache.tuscany.sca.war.Installer; - -public class TuscanyTomcatNode implements ServletContextListener { - - protected Node tomcatNode; - - public void contextInitialized(ServletContextEvent arg0) { - if (!Installer.isTuscanyHookRunning()) { - return; - } - - // TODO: this relys on the location of webapp folder, find way to get actual catalina base - File tomcatBase = new File(arg0.getServletContext().getRealPath("/")).getParentFile().getParentFile(); - - File contributionDir = new File(tomcatBase, "sca-contributions"); - if (!contributionDir.exists()) { - return; - } - File[] contributionFiles = contributionDir.listFiles(); - if (contributionFiles.length < 1) { - return; - } - - Contribution[] nodeContributions = new Contribution[contributionFiles.length]; - for (int i = 0; i\r\n" - + ""; + + " "; private void updateServerXml(File serverXmlFile) { String serverXML = readAll(serverXmlFile); diff --git a/sca-java-2.x/trunk/distribution/tomcat/tomcat-servlet/src/main/java/org/apache/tuscany/sca/war/InstallerServlet.java b/sca-java-2.x/trunk/distribution/tomcat/tomcat-servlet/src/main/java/org/apache/tuscany/sca/war/InstallerServlet.java index a7e5c7e3d7..efcc2711f3 100644 --- a/sca-java-2.x/trunk/distribution/tomcat/tomcat-servlet/src/main/java/org/apache/tuscany/sca/war/InstallerServlet.java +++ b/sca-java-2.x/trunk/distribution/tomcat/tomcat-servlet/src/main/java/org/apache/tuscany/sca/war/InstallerServlet.java @@ -31,6 +31,7 @@ import javax.servlet.http.HttpServletResponse; public class InstallerServlet extends HttpServlet { private static final long serialVersionUID = 1L; + private transient ServletConfig servletConfig; private transient Installer installer; @@ -56,8 +57,7 @@ public class InstallerServlet extends HttpServlet { protected void doIt(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { if ("Install".equalsIgnoreCase(req.getParameter("action"))) { - String singleton = req.getParameter("singleton"); - installer.install(singleton!=null && singleton.equalsIgnoreCase("true")); + installer.install(); } else if ("Uninstall".equalsIgnoreCase(req.getParameter("action"))) { installer.uninstall(); } diff --git a/sca-java-2.x/trunk/distribution/tomcat/tomcat-war/src/main/webapp/installer.jsp b/sca-java-2.x/trunk/distribution/tomcat/tomcat-war/src/main/webapp/installer.jsp index a6c3e4acaa..355976676b 100644 --- a/sca-java-2.x/trunk/distribution/tomcat/tomcat-war/src/main/webapp/installer.jsp +++ b/sca-java-2.x/trunk/distribution/tomcat/tomcat-war/src/main/webapp/installer.jsp @@ -48,7 +48,6 @@ Install Tuscany
To install Tuscany into Tomcat, click:
- The Tuscany runtime is shared by all web applications if checked.


@@ -70,5 +69,38 @@ <% }%> + +

+

What does this do?

+ + This Tuscany install makes two updates to Tomcat: +
    +
  • copies the jars from the tomcat-lib directory in this webapp into the Tomcat lib directory +
  • updates the Tomcat conf/server.xml to include a <Listener> definition for Tuscany +
+ Those changes cause the Tuscany listener to be called at Tomcat startup and that locates all the Host + defiinitions and patches them to use the TuscanyStandardContext. This enables support for deploying + SCA enabled webapps and plain SCA jar, zip, or folder contributions to the Host in the same way + that .war files are deployed. +

+ The SCA domain used for running the contributions defaults to "vm:default". This can be configured + by using an initilization parameter, most easiliy by defining that parameter in a context.xml file. + The Tomcat file conf/context.xml file defines the global defaults so that can be used for setting the + deafult domain for all SCA contributions. Individual contributions can also use their own context.xml + files to override that default. + See the Tomcat doc for more information on using context.xml files. +

+ An example of setting the domain as a context.xml parameter: +
<Context> +
. . . +
<Parameter name="org.apache.tuscany.sca.defaultDomainURI" value="tribes:myDomain" override="false"/> +
. . . +
</Context> +

+ For more information visit the Tuscany website page on Tomcat Integration. +

+ Note also that this is work in progress so is liable to change as Tuscany 2.0 is developed. Feedback is welcome and appreciated so if you've any comments or requests on this Tomcat integration please email dev@tuscany.apache.org. +

+ -- cgit v1.2.3