/*
 * Copyright 2009 Google Inc.
 *
 * Licensed 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 com.google.gwt.dev;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.dev.util.collect.HashSet;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Stack;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

/**
 * Validates that <code>&lt;servlet&gt;</code> tags in a GWT module match ones
 * from a <code>WEB-INF/web.xml</code>.
 */
class ServletValidator {

  /**
   * Collect servlet information from a web xml.
   */
  private static final class WebXmlDataCollector extends DefaultHandler {
    /*
     * TODO(scottb): this should have been implemented as a Schema.
     */

    private static class ElementStack {
      private final Stack<String> stack = new Stack<String>();

      public boolean exactly(String elementName, int depth) {
        return (depth == stack.size() - 1)
            && elementName.equals(stack.get(depth));
      }

      public String peek() {
        return stack.peek();
      }

      public String pop() {
        return stack.pop();
      }

      public void push(String elementName) {
        stack.push(elementName);
      }

      public boolean within(String elementName, int depth) {
        return (depth < stack.size()) && elementName.equals(stack.get(depth));
      }
    }

    private Set<String> accumulateClasses = new HashSet<String>();
    private Set<String> accumulatePaths = new HashSet<String>();
    private final TreeLogger branch;
    private final Stack<StringBuilder> cdataStack = new Stack<StringBuilder>();
    private final Map<String, String> classNameToServletName;
    private final ElementStack context = new ElementStack();
    private String currentServletName;
    private String indent = "";
    private final Map<String, Set<String>> servletNameToPaths;

    private WebXmlDataCollector(TreeLogger branch,
        Map<String, String> classNameToServletName,
        Map<String, Set<String>> servletNameToPaths) {
      this.branch = branch;
      this.classNameToServletName = classNameToServletName;
      this.servletNameToPaths = servletNameToPaths;
    }

    @Override
    public void characters(char[] ch, int start, int length)
        throws SAXException {
      cdataStack.peek().append(ch, start, length);
    }

    @Override
    public void endElement(String uri, String localName, String qName)
        throws SAXException {
      String cdata = cdataStack.pop().toString().trim();
      if (context.within("web-app", 0)) {
        if (context.within("servlet", 1)) {
          if (context.exactly("servlet-name", 2)) {
            currentServletName = cdata;
          } else if (context.exactly("servlet-class", 2)) {
            accumulateClasses.add(cdata);
          } else if (context.exactly("servlet", 1)) {
            if (currentServletName != null) {
              for (String className : accumulateClasses) {
                classNameToServletName.put(className, currentServletName);
              }
              currentServletName = null;
            }
            accumulateClasses.clear();
          }
        } else if (context.within("servlet-mapping", 1)) {
          if (context.exactly("servlet-name", 2)) {
            currentServletName = cdata;
          } else if (context.exactly("url-pattern", 2)) {
            accumulatePaths.add(cdata);
          } else if (context.exactly("servlet-mapping", 1)) {
            if (currentServletName != null) {
              Set<String> servletPaths = servletNameToPaths.get(currentServletName);
              if (servletPaths == null) {
                servletPaths = new HashSet<String>();
                servletNameToPaths.put(currentServletName, servletPaths);
              }
              servletPaths.addAll(accumulatePaths);
            }
            currentServletName = null;
            accumulatePaths.clear();
          }
        }
      }

      assert qName.equals(context.peek());
      context.pop();

      if (cdata.length() > 0) {
        if (branch.isLoggable(TreeLogger.DEBUG)) {
          branch.log(TreeLogger.DEBUG, "  characters: " + indent + cdata);
        }
      }
      indent = indent.substring(2);
      if (branch.isLoggable(TreeLogger.DEBUG)) {
        branch.log(TreeLogger.DEBUG, "  endElement: " + indent + qName);
      }
    }

    @Override
    public void startElement(String uri, String localName, String qName,
        Attributes attributes) throws SAXException {
      context.push(qName);
      cdataStack.push(new StringBuilder());

      StringBuilder sb = new StringBuilder();
      for (int i = 0; i < attributes.getLength(); ++i) {
        sb.append(' ');
        sb.append(attributes.getQName(i));
        sb.append("=\"");
        sb.append(attributes.getValue(i));
        sb.append('"');
      }
      if (branch.isLoggable(TreeLogger.DEBUG)) {
        branch.log(TreeLogger.DEBUG, "startElement: " + indent + qName
            + sb.toString());
      }
      indent += "  ";
    }
  }

  public static ServletValidator create(TreeLogger logger, File webXml) {
    try {
      return create(logger, webXml.toURI().toURL());
    } catch (MalformedURLException e) {
      logger.log(TreeLogger.WARN, "Unable to process '"
          + webXml.getAbsolutePath() + "' for servlet validation", e);
      return null;
    }
  }

  public static ServletValidator create(TreeLogger logger, URL webXmlUrl) {
    String webXmlUrlString = webXmlUrl.toExternalForm();
    try {
      final TreeLogger branch = logger.branch(TreeLogger.DEBUG, "Parsing "
          + webXmlUrlString);
      SAXParserFactory fac = SAXParserFactory.newInstance();
      fac.setValidating(false);
      fac.setNamespaceAware(false);
      fac.setFeature(
          "http://apache.org/xml/features/nonvalidating/load-external-dtd",
          false);
      SAXParser parser = fac.newSAXParser();
      parser.getXMLReader().setFeature(
          "http://xml.org/sax/features/validation", false);
      parser.getXMLReader().setFeature(
          "http://xml.org/sax/features/namespaces", false);
      parser.getXMLReader().setFeature(
          "http://xml.org/sax/features/namespace-prefixes", false);

      Map<String, String> classNameToServletName = new HashMap<String, String>();
      Map<String, Set<String>> servletNameToPaths = new HashMap<String, Set<String>>();
      parser.parse(webXmlUrlString, new WebXmlDataCollector(branch,
          classNameToServletName, servletNameToPaths));

      Map<String, Set<String>> classNameToPaths = new HashMap<String, Set<String>>();
      for (Entry<String, String> entry : classNameToServletName.entrySet()) {
        classNameToPaths.put(entry.getKey(),
            servletNameToPaths.get(entry.getValue()));
      }
      return new ServletValidator(classNameToServletName, classNameToPaths);
    } catch (Exception e) {
      logger.log(TreeLogger.WARN, "Unable to process '" + webXmlUrlString
          + "' for servlet validation", e);
      return null;
    }
  }

  static String generateMissingMappingMessage(String servletClass,
      String servletPath, String servletName) {
    return "Module declares a servlet class '"
        + servletClass
        + "' with a mapping to '"
        + servletPath
        + "', but the web.xml has no corresponding mapping; please add the following lines to your web.xml:\n"
        + ServletWriter.generateServletMappingTag(servletName, servletPath);
  }

  static String generateMissingServletMessage(String servletClass,
      String servletPath) {
    String servletName = suggestServletName(servletClass);
    return "Module declares a servlet class '"
        + servletClass
        + "', but the web.xml has no corresponding declaration; please add the following lines to your web.xml:\n"
        + ServletWriter.generateServletTag(servletName, servletClass) + "\n"
        + ServletWriter.generateServletMappingTag(servletName, servletPath);
  }

  static String suggestServletName(String servletClass) {
    int pos = servletClass.lastIndexOf('.');
    String suggest = (pos < 0) ? servletClass : servletClass.substring(pos + 1);
    String firstChar = suggest.substring(0, 1).toLowerCase(Locale.ROOT);
    suggest = firstChar + suggest.substring(1);
    return suggest;
  }

  private final Map<String, Set<String>> classNameToPaths;

  private final Map<String, String> classNameToServletName;

  private ServletValidator(Map<String, String> classNameToServletName,
      Map<String, Set<String>> classNameToPaths) {
    this.classNameToServletName = classNameToServletName;
    this.classNameToPaths = classNameToPaths;
  }

  public void validate(TreeLogger logger, String servletClass,
      String servletPath) {
    if (containsServletClass(servletClass)) {
      if (!containsServletMapping(servletClass, servletPath)) {
        String servletName = getNameForClass(servletClass);
        assert (servletName != null);
        logger.log(TreeLogger.WARN, generateMissingMappingMessage(servletClass,
            servletPath, servletName));
      }
    } else {
      logger.log(TreeLogger.WARN, generateMissingServletMessage(servletClass,
          servletPath));
    }
  }

  boolean containsServletClass(String servletClass) {
    return classNameToServletName.get(servletClass) != null;
  }

  boolean containsServletMapping(String servletClass, String servletPath) {
    Set<String> paths = classNameToPaths.get(servletClass);
    return (paths != null) && paths.contains(servletPath);
  }

  String getNameForClass(String servletClass) {
    return classNameToServletName.get(servletClass);
  }
}
