| /*========================================================================= |
| * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved. |
| * This product is protected by U.S. and international copyright |
| * and intellectual property laws. Pivotal products are covered by |
| * one or more patents listed at http://www.pivotal.io/patents. |
| *========================================================================= |
| */ |
| |
| package com.gemstone.gemfire.modules.session.installer; |
| |
| import com.gemstone.gemfire.modules.session.installer.args.Argument; |
| import com.gemstone.gemfire.modules.session.installer.args.ArgumentProcessor; |
| import com.gemstone.gemfire.modules.session.installer.args.ArgumentValues; |
| import com.gemstone.gemfire.modules.session.installer.args.UnknownArgumentHandler; |
| import com.gemstone.gemfire.modules.session.installer.args.UsageException; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.transform.OutputKeys; |
| import javax.xml.transform.Transformer; |
| import javax.xml.transform.TransformerFactory; |
| import javax.xml.transform.dom.DOMSource; |
| import javax.xml.transform.stream.StreamResult; |
| import java.io.ByteArrayOutputStream; |
| import java.io.FileInputStream; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| |
| /** |
| * |
| */ |
| public class Installer { |
| |
| private static final String GEMFIRE_FILTER_CLASS = |
| "com.gemstone.gemfire.modules.session.filter.SessionCachingFilter"; |
| |
| private static final String GEMFIRE_LISTENER_CLASS = |
| "com.gemstone.gemfire.modules.session.filter.SessionListener"; |
| |
| private ArgumentValues argValues; |
| |
| private static final Argument ARG_HELP = |
| new Argument("-h", false). |
| setDescription("Displays this help message."); |
| |
| private static Argument ARG_GEMFIRE_PARAMETERS = |
| new Argument("-p", false, "param=value"). |
| setDescription("Specific parameter for inclusion into the " |
| + "session filter definition as a regular " |
| + "init-param. Can be given multiple times."); |
| |
| private static Argument ARG_CACHE_TYPE = |
| new Argument("-t", false, "cache-type"). |
| setDescription( |
| "Type of cache. Must be one of 'peer-to-peer' or " |
| + "'client-server'. Default is peer-to-peer."). |
| setDefaults("peer-to-peer"); |
| |
| private static Argument ARG_WEB_XML_FILE = |
| new Argument("-w", true, "web.xml file"). |
| setDescription("The web.xml file to be modified."); |
| |
| |
| /** |
| * Class main method |
| * |
| * @param args Arguments passed in via the command line |
| * @throws Exception in the event of any errors |
| */ |
| public static void main(final String[] args) throws Exception { |
| new Installer(args).process(); |
| } |
| |
| public static void log(String message) { |
| System.err.println(message); |
| } |
| |
| |
| public Installer(String[] args) throws Exception { |
| final ArgumentProcessor processor = new ArgumentProcessor("Installer"); |
| |
| argValues = null; |
| try { |
| // These are ordered so as to keep the options alphabetical |
| processor.addArgument(ARG_HELP); |
| processor.addArgument(ARG_GEMFIRE_PARAMETERS); |
| processor.addArgument(ARG_CACHE_TYPE); |
| processor.addArgument(ARG_WEB_XML_FILE); |
| |
| processor.setUnknownArgumentHandler(new UnknownArgumentHandler() { |
| @Override |
| public void handleUnknownArgument( |
| final String form, final String[] params) { |
| log("Unknown argument being ignored: " |
| + form + " (" + params.length + " params)"); |
| log("Use '-h' argument to display usage"); |
| } |
| }); |
| argValues = processor.process(args); |
| |
| if (argValues.isDefined(ARG_HELP)) { |
| final UsageException usageException = |
| new UsageException("Usage requested by user"); |
| usageException.setUsage(processor.getUsage()); |
| throw (usageException); |
| } |
| |
| } catch (UsageException ux) { |
| final StringBuilder error = new StringBuilder(); |
| error.append("\nERROR: "); |
| error.append(ux.getMessage()); |
| error.append("\n"); |
| if (ux.getUsage() != null) { |
| error.append(ux.getUsage()); |
| } |
| log(error.toString()); |
| System.exit(2); |
| } |
| |
| } |
| |
| |
| /** |
| * The main entry point for processing |
| * |
| * @throws Exception if any errors occur. |
| */ |
| public void process() throws Exception { |
| String argInputFile = argValues.getFirstResult(ARG_WEB_XML_FILE); |
| |
| ByteArrayOutputStream output = new ByteArrayOutputStream(); |
| InputStream input = new FileInputStream(argInputFile); |
| |
| processWebXml(input, output); |
| input.close(); |
| |
| System.out.println(output.toString()); |
| } |
| |
| |
| private void processWebXml(final InputStream webXml, |
| final OutputStream out) throws Exception { |
| |
| Document doc = createWebXmlDoc(webXml); |
| mangleWebXml(doc); |
| |
| streamXML(doc, out); |
| } |
| |
| |
| private Document createWebXmlDoc(final InputStream webXml) |
| throws Exception { |
| Document doc; |
| final DocumentBuilderFactory factory = |
| DocumentBuilderFactory.newInstance(); |
| final DocumentBuilder builder = factory.newDocumentBuilder(); |
| doc = builder.parse(webXml); |
| |
| return doc; |
| } |
| |
| |
| private Document mangleWebXml(final Document doc) { |
| final Element docElement = doc.getDocumentElement(); |
| final NodeList nodelist = docElement.getChildNodes(); |
| Node firstFilter = null; |
| Node displayElement = null; |
| Node afterDisplayElement = null; |
| |
| for (int i = 0; i < nodelist.getLength(); i++) { |
| final Node node = nodelist.item(i); |
| final String name = node.getNodeName(); |
| if ("display-name".equals(name)) { |
| displayElement = node; |
| } else { |
| if ("filter".equals(name)) { |
| if (firstFilter == null) { |
| firstFilter = node; |
| } |
| } |
| if (displayElement != null && afterDisplayElement == null) { |
| afterDisplayElement = node; |
| } |
| } |
| } |
| |
| Node initParam; |
| final Element filter = doc.createElement("filter"); |
| append(doc, filter, "filter-name", "gemfire-session-filter"); |
| append(doc, filter, "filter-class", GEMFIRE_FILTER_CLASS); |
| |
| // Set the type of cache |
| initParam = append(doc, filter, "init-param", null); |
| append(doc, initParam, "param-name", "cache-type"); |
| append(doc, initParam, "param-value", |
| argValues.getFirstResult(ARG_CACHE_TYPE)); |
| |
| |
| if (argValues.isDefined(ARG_GEMFIRE_PARAMETERS)) { |
| for (String[] val : argValues.getAllResults(ARG_GEMFIRE_PARAMETERS)) { |
| String gfParam = val[0]; |
| int idx = gfParam.indexOf("="); |
| initParam = append(doc, filter, "init-param", null); |
| append(doc, initParam, "param-name", gfParam.substring(0, idx)); |
| append(doc, initParam, "param-value", gfParam.substring(idx + 1)); |
| } |
| } |
| |
| Node first = firstFilter; |
| if (first == null) { |
| if (afterDisplayElement != null) { |
| first = afterDisplayElement; |
| } |
| } |
| if (first == null) { |
| first = docElement.getFirstChild(); |
| } |
| docElement.insertBefore(filter, first); |
| final Element filterMapping = doc.createElement("filter-mapping"); |
| append(doc, filterMapping, "filter-name", "gemfire-session-filter"); |
| append(doc, filterMapping, "url-pattern", "/*"); |
| append(doc, filterMapping, "dispatcher", "FORWARD"); |
| append(doc, filterMapping, "dispatcher", "INCLUDE"); |
| append(doc, filterMapping, "dispatcher", "REQUEST"); |
| append(doc, filterMapping, "dispatcher", "ERROR"); |
| final Element contextListener = doc.createElement("listener"); |
| append(doc, contextListener, "listener-class", GEMFIRE_LISTENER_CLASS); |
| docElement.insertBefore(filterMapping, after(docElement, "filter")); |
| docElement.insertBefore(contextListener, |
| after(docElement, "filter-mapping")); |
| return doc; |
| } |
| |
| private Node after(final Node parent, final String nodeName) { |
| final NodeList nodelist = parent.getChildNodes(); |
| int index = -1; |
| for (int i = 0; i < nodelist.getLength(); i++) { |
| final Node node = nodelist.item(i); |
| final String name = node.getNodeName(); |
| if (nodeName.equals(name)) { |
| index = i; |
| } |
| } |
| if (index == -1) |
| return null; |
| if (nodelist.getLength() > (index + 1)) { |
| return nodelist.item(index + 1); |
| } |
| return null; |
| } |
| |
| private Node append(final Document doc, final Node parent, |
| final String element, |
| final String value) { |
| final Element child = doc.createElement(element); |
| if (value != null) |
| child.setTextContent(value); |
| parent.appendChild(child); |
| return child; |
| } |
| |
| private void streamXML(final Document doc, final OutputStream out) { |
| try {// Use a Transformer for output |
| final TransformerFactory tFactory = TransformerFactory.newInstance(); |
| final Transformer transformer = tFactory.newTransformer(); |
| if (doc.getDoctype() != null) { |
| final String systemId = doc.getDoctype().getSystemId(); |
| final String publicId = doc.getDoctype().getPublicId(); |
| transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, publicId); |
| transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, systemId); |
| } |
| transformer.setOutputProperty(OutputKeys.INDENT, "yes"); |
| transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", |
| "4"); |
| final DOMSource source = new DOMSource(doc); |
| final StreamResult result = new StreamResult(out); |
| transformer.transform(source, result); |
| } catch (final Exception e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| } |