| /* |
| * 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.war; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.Closeable; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.io.PrintWriter; |
| |
| import org.apache.tuscany.sca.tomcat.TuscanyLifecycleListener; |
| import org.codehaus.swizzle.stream.DelimitedTokenReplacementInputStream; |
| import org.codehaus.swizzle.stream.StringTokenHandler; |
| |
| public class Installer { |
| |
| private static boolean restartRequired; |
| private static boolean tuscanyHookRunning; |
| static { |
| try { |
| tuscanyHookRunning = TuscanyLifecycleListener.isRunning(); |
| } catch (Throwable e) { |
| tuscanyHookRunning = false; |
| } |
| } |
| |
| public static boolean isTuscanyHookRunning() { |
| return tuscanyHookRunning; |
| } |
| |
| public static boolean isRestartRequired() { |
| return restartRequired; |
| } |
| |
| private File tuscanyWAR; |
| private File catalinaBase; |
| private String status = ""; |
| |
| public Installer(File tuscanyWAR, File catalinaBase) { |
| this.tuscanyWAR = tuscanyWAR; |
| this.catalinaBase = catalinaBase; |
| } |
| |
| public static boolean isInstalled() { |
| return false; |
| } |
| |
| public String getStatus() { |
| return status; |
| } |
| |
| public boolean install() { |
| try { |
| |
| doInstall(); |
| status = "Install successful, Tomcat restart required."; |
| restartRequired = true; |
| return true; |
| |
| } catch (Throwable e) { |
| status = "Exception during install\n"; |
| ByteArrayOutputStream os = new ByteArrayOutputStream(); |
| PrintWriter pw = new PrintWriter(os); |
| e.printStackTrace(pw); |
| pw.close(); |
| status += new String(os.toByteArray()); |
| return false; |
| } |
| } |
| |
| public boolean uninstall() { |
| try { |
| |
| doUnintsall(); |
| status = "Tuscany removed from server.xml, please restart Tomcat and manually remove Tuscany jars from Tomcat lib"; |
| restartRequired = true; |
| return true; |
| |
| } catch (Throwable e) { |
| status = "Exception during install"; |
| ByteArrayOutputStream os = new ByteArrayOutputStream(); |
| PrintWriter pw = new PrintWriter(os); |
| e.printStackTrace(pw); |
| status += "/n" + new String(os.toByteArray()); |
| return false; |
| } |
| } |
| |
| private void doUnintsall() { |
| File serverXml = new File(catalinaBase, "/conf/server.xml"); |
| if (!(serverXml.exists())) { |
| throw new IllegalStateException("conf/server.xml not found: " + serverXml.getAbsolutePath()); |
| } |
| removeServerXml(serverXml); |
| removeHostConfigXml(serverXml); |
| removeContextXml(); |
| } |
| |
| private boolean doInstall() { |
| // First verify all the file locations are as expected |
| if (!tuscanyWAR.exists()) { |
| throw new IllegalStateException("Tuscany war missing: " + tuscanyWAR.getAbsolutePath()); |
| } |
| if (!catalinaBase.exists()) { |
| throw new IllegalStateException("Catalina base does not exist: " + catalinaBase.getAbsolutePath()); |
| } |
| File serverLib = new File(catalinaBase, "/lib"); |
| if (!(serverLib.exists())) { |
| // try Tomcat 5 server/lib |
| if (new File(catalinaBase, "/server").exists()) { |
| serverLib = new File(new File(catalinaBase, "/server"), "/lib"); |
| } |
| } |
| if (!(serverLib.exists())) { |
| throw new IllegalStateException("Tomcat lib not found: " + serverLib.getAbsolutePath()); |
| } |
| File serverXml = new File(catalinaBase, "/conf/server.xml"); |
| if (!(serverXml.exists())) { |
| throw new IllegalStateException("conf/server.xml not found: " + serverXml.getAbsolutePath()); |
| } |
| |
| File tuscanyTomcatJar = findTuscanyTomcatJar(tuscanyWAR); |
| if (tuscanyTomcatJar == null || !tuscanyTomcatJar.exists()) { |
| throw new IllegalStateException("Can't find tuscany-tomcat-*.jar in: " + tuscanyWAR.getAbsolutePath()); |
| } |
| |
| // Copy tuscany-tomcat jar from the tuscany webapp web-inf/lib to Tomcat server/lib |
| copyFile(tuscanyTomcatJar, new File(serverLib, tuscanyTomcatJar.getName())); |
| |
| // Add Tuscany LifecycleListener to Tomcat server.xml |
| updateServerXml(serverXml); |
| |
| // Add Tuscany HostConfig to Hosts definitions in server.xml |
| updateHostConfigXml(serverXml); |
| |
| // Add Tuscany specific default web.xml and context.xml definitions |
| addTuscanyWebXml(); |
| addTuscanyContextXml(); |
| |
| return true; |
| } |
| |
| private static final String tuscanyWebXML = |
| "\r\n\r\n" + " <!-- Tuscany Listener and Filter definitions -->\r\n" + |
| " <listener>\r\n" + |
| " <listener-class>org.apache.tuscany.sca.host.webapp.TuscanyContextListener</listener-class>\r\n" + |
| " </listener>\r\n" + |
| "\r\n" + |
| " <filter>\r\n" + |
| " <filter-name>tuscany</filter-name>\r\n" + |
| " <filter-class>org.apache.tuscany.sca.host.webapp.TuscanyServletFilter</filter-class>\r\n" + |
| " </filter>\r\n" + |
| "\r\n" + |
| " <filter-mapping>\r\n" + |
| " <filter-name>tuscany</filter-name>\r\n" + |
| " <url-pattern>/*</url-pattern>\r\n" + |
| " </filter-mapping>"; |
| |
| private void addTuscanyWebXml() { |
| File tuscanyWebXmlFile = new File(catalinaBase, "/conf/tuscany-web.xml"); |
| if (!(tuscanyWebXmlFile.exists())) { |
| File webXmlFile = new File(catalinaBase, "/conf/web.xml"); |
| if (!(webXmlFile.exists())) { |
| throw new IllegalStateException("conf/web.xml not found: " + webXmlFile.getAbsolutePath()); |
| } |
| String webXML = readAll(webXmlFile); |
| String newWebXml = replace(webXML, "<web-app", "<web-app", ">", ">" + tuscanyWebXML); |
| writeAll(tuscanyWebXmlFile, newWebXml); |
| } |
| } |
| |
| private static final String tuscanyContextXML = |
| "\r\n\r\n <!-- The Tuscany SCA default domain URI.\r\n" + |
| " Individual contributions may used different domains by having their \r\n" + |
| " context.xml files overriding this parameter. -->\r\n" + |
| " <Parameter name=\"org.apache.tuscany.sca.defaultDomainURI\" value=\"default\"/>"; |
| |
| private void addTuscanyContextXml() { |
| File contextXmlFile = new File(catalinaBase, "/conf/context.xml"); |
| if ((contextXmlFile.exists())) { |
| String contextXML = readAll(contextXmlFile); |
| String newcontextXml = replace(contextXML, "<Context>", "<Context>" + tuscanyContextXML, "<", "<"); |
| backup(contextXmlFile); |
| writeAll(contextXmlFile, newcontextXml); |
| } |
| } |
| private void removeContextXml() { |
| File contextXmlFile = new File(catalinaBase, "/conf/context.xml"); |
| if ((contextXmlFile.exists())) { |
| String contextXML = readAll(contextXmlFile); |
| String oldContextXml = replace(contextXML, "<Context>" + tuscanyContextXML, "<Context>", "<", "<"); |
| writeAll(contextXmlFile, oldContextXml); |
| } |
| } |
| |
| private File findTuscanyTomcatJar(File tuscanyWAR) { |
| File lib = new File(tuscanyWAR, "/tomcat-lib"); |
| for (File f : lib.listFiles()) { |
| if (f.getName().startsWith("tuscany-tomcat-hook-") && f.getName().endsWith(".jar")) { |
| return f; |
| } |
| } |
| return null; |
| } |
| |
| private static final String tuscanyListener = |
| "\r\n" + " <!-- Tuscany plugin for Tomcat -->\r\n" |
| + " <Listener className=\"org.apache.tuscany.sca.tomcat.TuscanyLifecycleListener\" />"; |
| |
| private void updateServerXml(File serverXmlFile) { |
| String serverXML = readAll(serverXmlFile); |
| if (!serverXML.contains(tuscanyListener)) { |
| String newServerXml = replace(serverXML, "<Server", "<Server", ">", ">" + tuscanyListener); |
| backup(serverXmlFile); |
| writeAll(serverXmlFile, newServerXml); |
| } |
| } |
| |
| private void removeServerXml(File serverXmlFile) { |
| String serverXML = readAll(serverXmlFile); |
| if (serverXML.contains(tuscanyListener)) { |
| String newServerXml = replace(serverXML, "<Server", "<Server", ">" + tuscanyListener, ">"); |
| writeAll(serverXmlFile, newServerXml); |
| } |
| } |
| |
| static final String tuscanyHostConfig = " hostConfigClass=\"org.apache.tuscany.sca.tomcat.TuscanyHostConfig\" >"; |
| |
| private void updateHostConfigXml(File serverXmlFile) { |
| String serverXML = readAll(serverXmlFile); |
| String newServerXml = replace(serverXML, "<Host", "<Host", ">", tuscanyHostConfig); |
| backup(serverXmlFile); |
| writeAll(serverXmlFile, newServerXml); |
| } |
| |
| private void removeHostConfigXml(File serverXmlFile) { |
| String serverXML = readAll(serverXmlFile); |
| if (serverXML.contains(tuscanyHostConfig)) { |
| String newServerXml = replace(serverXML, "<Host", "<Host", tuscanyHostConfig, ">"); |
| writeAll(serverXmlFile, newServerXml); |
| } |
| } |
| |
| private String replace(String inputText, String begin, String newBegin, String end, String newEnd) { |
| BeginEndTokenHandler tokenHandler = new BeginEndTokenHandler(newBegin, newEnd); |
| |
| ByteArrayInputStream in = new ByteArrayInputStream(inputText.getBytes()); |
| |
| InputStream replacementStream = new DelimitedTokenReplacementInputStream(in, begin, end, tokenHandler, true); |
| String newServerXml = readAll(replacementStream); |
| close(replacementStream); |
| return newServerXml; |
| } |
| |
| private boolean backup(File source) { |
| File backupFile = new File(source.getParent(), source.getName() + ".b4Tuscany"); |
| if (!backupFile.exists()) { |
| copyFile(source, backupFile); |
| } |
| return true; |
| } |
| |
| private String readAll(File file) { |
| FileInputStream in = null; |
| try { |
| in = new FileInputStream(file); |
| String text = readAll(in); |
| return text; |
| } catch (Exception e) { |
| return null; |
| } finally { |
| close(in); |
| } |
| } |
| |
| private String readAll(InputStream in) { |
| try { |
| // SwizzleStream block read methods are broken so read byte at a time |
| StringBuilder sb = new StringBuilder(); |
| int i = in.read(); |
| while (i != -1) { |
| sb.append((char)i); |
| i = in.read(); |
| } |
| return sb.toString(); |
| } catch (IOException e) { |
| throw new IllegalStateException(e); |
| } |
| } |
| |
| private void copyFile(File source, File destination) { |
| InputStream in = null; |
| OutputStream out = null; |
| try { |
| in = new FileInputStream(source); |
| out = new FileOutputStream(destination); |
| writeAll(in, out); |
| } catch (IOException e) { |
| throw new IllegalStateException(e); |
| } finally { |
| close(in); |
| close(out); |
| } |
| } |
| |
| private boolean writeAll(File file, String text) { |
| FileOutputStream fileOutputStream = null; |
| try { |
| fileOutputStream = new FileOutputStream(file); |
| writeAll(new ByteArrayInputStream(text.getBytes()), fileOutputStream); |
| return true; |
| } catch (Exception e) { |
| return false; |
| } finally { |
| close(fileOutputStream); |
| } |
| } |
| |
| private void writeAll(InputStream in, OutputStream out) throws IOException { |
| byte[] buffer = new byte[4096]; |
| int count; |
| while ((count = in.read(buffer)) > 0) { |
| out.write(buffer, 0, count); |
| } |
| out.flush(); |
| } |
| |
| private void close(Closeable thing) { |
| if (thing != null) { |
| try { |
| thing.close(); |
| } catch (Exception ignored) { |
| } |
| } |
| } |
| |
| private class BeginEndTokenHandler extends StringTokenHandler { |
| private final String begin; |
| private final String end; |
| |
| public BeginEndTokenHandler(String begin, String end) { |
| this.begin = begin; |
| this.end = end; |
| } |
| |
| public String handleToken(String token) throws IOException { |
| String result = begin + token + end; |
| return result; |
| } |
| } |
| |
| } |