diff options
Diffstat (limited to 'branches/sca-java-20080910/distribution/webapp/src/main')
7 files changed, 561 insertions, 0 deletions
diff --git a/branches/sca-java-20080910/distribution/webapp/src/main/java/org/apache/tuscany/sca/webapp/ContributionUploaderServlet.java b/branches/sca-java-20080910/distribution/webapp/src/main/java/org/apache/tuscany/sca/webapp/ContributionUploaderServlet.java new file mode 100644 index 0000000000..9a0c66a776 --- /dev/null +++ b/branches/sca-java-20080910/distribution/webapp/src/main/java/org/apache/tuscany/sca/webapp/ContributionUploaderServlet.java @@ -0,0 +1,116 @@ +/* + * 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.IOException; +import java.io.PrintWriter; +import java.util.Iterator; +import java.util.List; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.FileItemFactory; +import org.apache.commons.fileupload.FileUploadException; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; + +import org.apache.tuscany.sca.host.webapp.HotUpdateContextListener; + +/** + * A Servlet to upload a contribution file. + */ +public class ContributionUploaderServlet extends HttpServlet { + + private static final long serialVersionUID = System.currentTimeMillis(); + + private File repository; + + @Override + public void init(ServletConfig config) throws ServletException { + ServletContext servletContext = config.getServletContext(); + repository = new File(servletContext.getRealPath(HotUpdateContextListener.REPOSITORY_FOLDER_NAME)); + } + + @Override + public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { + // Check that we have a file upload request + boolean isMultipart = ServletFileUpload.isMultipartContent(request); + if (!isMultipart) { + throw new RuntimeException("Need multipart content"); + } + + // Create a factory for disk-based file items + FileItemFactory factory = new DiskFileItemFactory(); + + // Create a new file upload handler + ServletFileUpload upload = new ServletFileUpload(factory); + + try { + // Parse the request + List /* FileItem */ items = upload.parseRequest(request); + // Process the uploaded items + Iterator iter = items.iterator(); + while (iter.hasNext()) { + FileItem item = (FileItem) iter.next(); + + if (!item.isFormField()) { + String fileName = item.getName(); + int index = fileName.lastIndexOf("\\") + 1; + String uploadedFileName = repository.getAbsolutePath() + "/" + fileName.substring(index); + File uploadedFile = new File(uploadedFileName); + item.write(uploadedFile); + } + } + } + catch(FileUploadException e) { + throw new RuntimeException(e); + } + catch(Throwable e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + + setResponse(response, request); + } + + private void setResponse(HttpServletResponse response, HttpServletRequest request) throws IOException { + response.setContentType("text/html"); + PrintWriter out = response.getWriter(); + out.println("<html>"); + out.println("<head>"); + out.println("<title>Apache Tuscany WebApp Runtime</title>"); + out.println("</head>"); + out.println("<body>"); + out.println("<h2>Composite file uploaded</h2>"); + int port = request.getServerPort(); + String portSubStr = ((port == -1) ? "" : (":" + request.getServerPort())); + String backPath = request.getScheme() + "://" + request.getServerName() + portSubStr + request.getContextPath(); + out.println("Go <a href=\"" + backPath + "\">back</a>"); + out.println("</body>"); + out.println("</html>"); + } +} diff --git a/branches/sca-java-20080910/distribution/webapp/src/main/java/org/apache/tuscany/sca/webapp/WarContextListener.java b/branches/sca-java-20080910/distribution/webapp/src/main/java/org/apache/tuscany/sca/webapp/WarContextListener.java new file mode 100644 index 0000000000..e46cadfa3d --- /dev/null +++ b/branches/sca-java-20080910/distribution/webapp/src/main/java/org/apache/tuscany/sca/webapp/WarContextListener.java @@ -0,0 +1,304 @@ +/* + * 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.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.domain.SCADomain; +import org.apache.tuscany.sca.node.NodeException; +import org.apache.tuscany.sca.node.SCANode; +import org.apache.tuscany.sca.node.SCANodeFactory; + +/** + * A ServletContextListener for the Tuscany WAR distribution. + * + * Starts and stops a Tuscany SCA domain Node for the webapp. + */ +public class WarContextListener implements ServletContextListener { + private final static Logger logger = Logger.getLogger(WarContextListener.class.getName()); + + protected SCANode node; + protected SCADomain domain; + 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); + } + } + + 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 initNode() throws NodeException, URISyntaxException { + logger.log(Level.INFO, "SCA node starting"); + + classLoader = new AddableURLClassLoader(new URL[] {}, Thread.currentThread().getContextClassLoader()); + Thread.currentThread().setContextClassLoader(classLoader); + + SCANodeFactory nodeFactory = SCANodeFactory.newInstance(); + node = nodeFactory.createSCANode(nodeName, domainName); + domain = node.getDomain(); + + existingContributions = new HashMap<URL, Long>(); + URL[] contributions = getContributionJarURLs(repository); + for (URL contribution : contributions) { + addContribution(contribution); + } + + node.start(); + + initHotDeploy(repository); + } + + protected void addContribution(URL contribution) throws URISyntaxException, NodeException { + classLoader.addURL(contribution); + node.addContribution(contribution.toString(), contribution); + existingContributions.put(contribution, new Long(new File(contribution.toURI()).lastModified())); + logger.log(Level.INFO, "Added contribution: " + contribution); + } + + protected URL[] getContributionJarURLs(File repositoryDir) { + + String[] jarNames = repositoryDir.list(new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.endsWith(".jar"); + }}); + + List<URL> contributionJars = new ArrayList<URL>(); + if (jarNames != null) { + for (String jar : jarNames) { + 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); + // node.startContribution(contribution.toString()); + } catch (Throwable e) { + e.printStackTrace(); + logger.log(Level.WARNING, "Exception adding contribution: " + e); + } + } + if (addedContributions.size() > 0) { + try { + node.start(); + } catch (NodeException e) { + e.printStackTrace(); + logger.log(Level.WARNING, "Exception restarting node for added contributions: " + 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); + } + } + 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 = null; + } + + if (servletContext.getInitParameter("nodeName") != null) { + nodeName = servletContext.getInitParameter("nodeName"); + } else { + nodeName = "DefaultNode"; + } + + if (servletContext.getInitParameter("hotDeployInterval") != null) { + hotDeployInterval = Long.parseLong(servletContext.getInitParameter("hotDeployInterval")); + } + + useHotUpdate = Boolean.valueOf(servletContext.getInitParameter("hotUpdate")).booleanValue(); + + if (servletContext.getInitParameter("repositoryFolder") != null) { + repository = new File(servletContext.getInitParameter("repositoryFolder")); + } else { + repository = new File(servletContext.getRealPath(REPOSITORY_FOLDER_NAME)); + } + logger.info("Tuscany Contribution Repository -> " + repository); + } + +} + +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); + } + +} diff --git a/branches/sca-java-20080910/distribution/webapp/src/main/webapp/WEB-INF/web.xml b/branches/sca-java-20080910/distribution/webapp/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..8e65a9b96d --- /dev/null +++ b/branches/sca-java-20080910/distribution/webapp/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<!-- + * 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. +--> + +<!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> + + <display-name>Apache Tuscany WebApp Runtime</display-name> + + <listener> + <listener-class>org.apache.tuscany.sca.webapp.WarContextListener</listener-class> + </listener> + + <context-param> + <param-name>repositoryFolder</param-name> + <param-value>/TuscanyRepository</param-value> + </context-param> + + <!-- context-param> + <param-name>domainName</param-name> + <param-value>http://localhost:8877/</param-value> + </context-param --> + + <context-param> + <param-name>nodeName</param-name> + <param-value>http://localhost:8080/</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> + + <filter> + <filter-name>tuscany</filter-name> + <filter-class>org.apache.tuscany.sca.host.webapp.TuscanyServletFilter</filter-class> + </filter> + + <filter-mapping> + <filter-name>tuscany</filter-name> + <url-pattern>/*</url-pattern> + </filter-mapping> + +</web-app> diff --git a/branches/sca-java-20080910/distribution/webapp/src/main/webapp/sca-contributions/safeToDelete.tmp b/branches/sca-java-20080910/distribution/webapp/src/main/webapp/sca-contributions/safeToDelete.tmp new file mode 100644 index 0000000000..4efe4b5db3 --- /dev/null +++ b/branches/sca-java-20080910/distribution/webapp/src/main/webapp/sca-contributions/safeToDelete.tmp @@ -0,0 +1 @@ +File just to get the sca-contributions folder included in webapp
\ No newline at end of file diff --git a/branches/sca-java-20080910/distribution/webapp/src/main/webapp/sca-contributions/sample-calculator-nodeB.jar b/branches/sca-java-20080910/distribution/webapp/src/main/webapp/sca-contributions/sample-calculator-nodeB.jar Binary files differnew file mode 100644 index 0000000000..0df7ab8d74 --- /dev/null +++ b/branches/sca-java-20080910/distribution/webapp/src/main/webapp/sca-contributions/sample-calculator-nodeB.jar diff --git a/branches/sca-java-20080910/distribution/webapp/src/main/webapp/sca-contributions/sample-helloworld-ws-service.jar b/branches/sca-java-20080910/distribution/webapp/src/main/webapp/sca-contributions/sample-helloworld-ws-service.jar Binary files differnew file mode 100644 index 0000000000..acf47451b3 --- /dev/null +++ b/branches/sca-java-20080910/distribution/webapp/src/main/webapp/sca-contributions/sample-helloworld-ws-service.jar diff --git a/branches/sca-java-20080910/distribution/webapp/src/main/webapp/scaDomainInfo.jsp b/branches/sca-java-20080910/distribution/webapp/src/main/webapp/scaDomainInfo.jsp new file mode 100644 index 0000000000..c92c164cfb --- /dev/null +++ b/branches/sca-java-20080910/distribution/webapp/src/main/webapp/scaDomainInfo.jsp @@ -0,0 +1,74 @@ +<%-- + * 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. +--%> + +<%@ page import="org.apache.tuscany.sca.host.embedded.SCADomain"%> +<%@ page import="org.apache.tuscany.sca.host.embedded.management.ComponentManager"%> +<%@ page import="org.apache.tuscany.sca.assembly.ComponentService"%> +<%@ page import="org.apache.tuscany.sca.assembly.Binding"%> + +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<% + SCADomain scaDomain = (SCADomain) application.getAttribute("org.apache.tuscany.sca.SCADomain"); + ComponentManager componentManager = scaDomain.getComponentManager(); +%> +<html> +<head><title>Apache Tuscany WebApp Runtime</title></head> + +<body> +Apache Tuscany WebApp Runtime +<br> +Components in SCA Domain: + <% + java.util.Iterator i = componentManager.getComponentNames().iterator(); + while (i.hasNext()) { + String compName = i.next().toString(); + + %><br><%=compName%><br><% + + org.apache.tuscany.sca.assembly.Component comp = componentManager.getComponent(compName); + java.util.Iterator j = comp.getServices().iterator(); + while (j.hasNext()) { + ComponentService compService = (ComponentService)j.next(); + + %><%=" - Service: " + compService.getName()%><br><% + + java.util.Iterator k = compService.getBindings().iterator(); + while (k.hasNext()) { + Binding b = (Binding)k.next(); + String bindingType = b.getClass().getName(); + + %><%="-- Binding: " + b.getName() + "(" + bindingType.substring(bindingType.lastIndexOf('.')+1) + ") URI: " + b.getURI()%><br><% + } + } + } + %> +<br> + +<hr> +You can fill in a composite file to upload + +<form method='POST' enctype='multipart/form-data' action='/tuscany/ContributionUploader'> +Composite file to upload: <input type=file name=upfile><br> +<br> +<input type=submit value=Press> to upload the composite file +</form> + +</body> +</html> + |