Package org.spiffyui.spsample.server

Source Code of org.spiffyui.spsample.server.SiteMapServlet

/*******************************************************************************
*
* Copyright 2011 Spiffy UI Team  
*
* 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 org.spiffyui.spsample.server;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.logging.Logger;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.Namespace;
import javax.xml.stream.events.StartDocument;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

/**
* The main purpose of this servlet is to improve our SEO (Search
* Engine Optimization).  To that end it server three basic functions:
* 1. Generate a Google Sitemap for our site.  Since
* the entire application is generated with JavaScript the search
* engines can't index the site very well.  This servlet generates
* a sitemap.xml file and adds the source HTML files to it.  That
* makes it possible to index all of the content in those files.
* 2. Server the index.html and index-debug.html pages.  This servet
* handles both pages since we need to serve at those URL to fulfill
* the  contract for AJAX crawling outlined here:
*     http://code.google.com/web/ajaxcrawling/
* This is especially complicated since Google AppEngine won't allow us
* to serve any page with a servlet if there is a real file at that URL.
* 3. Server the individual files or HTML snapshots of each page when
* requested with the _escaped_fragment_ fragment parameter.
*/
public class SiteMapServlet extends HttpServlet
{
    private static final Map<String, String> HASHES = new HashMap<String, String>();
   
    static {
        HASHES.put("landing", "/ajax/LandingPanel.html");
        HASHES.put("overview", "/ajax/OverviewPanel.html");
        HASHES.put("getStarted", "/ajax/GetStartedPanel.html");
        HASHES.put("hostedMode", "/ajax/HostedModePanel.html");
        HASHES.put("css", "/ajax/CSSPanel.html");
        HASHES.put("speed", "/ajax/BuildPanel.html");
        HASHES.put("rest", "/ajax/RESTPanel.html");
        HASHES.put("samples", "/ajax/SamplesPanel.html");
        HASHES.put("help", "/ajax/HelpPanel.html");
        HASHES.put("getInvolved", "/ajax/GetInvolvedPanel.html");
        HASHES.put("auth", "/ajax/AuthPanel.html");
        HASHES.put("l10n", "/ajax/DatePanel.html");
        HASHES.put("forms", "/ajax/FormPanel.html");
        HASHES.put("widgets", "/ajax/WidgetsPanel.html");
        HASHES.put("authTest", "/ajax/AuthPanel.html");
        HASHES.put("license", "/ajax/LicensePanel.html");
    }
   
    private static final Logger LOGGER = Logger.getLogger(SiteMapServlet.class.getName());
    private static final long serialVersionUID = -1L;
   
    private static final ResourceBundle BUILD_BUNDLE =
        ResourceBundle.getBundle("org/spiffyui/spsample/server/buildnum", Locale.getDefault());
   
    private static String g_siteMap = null;

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException
    {
        if (request.getParameter("_escaped_fragment_") != null) {
            /*
             This means someone is the special escaped fragment version.
             This is probably a search engine and we'll give them the file
             */
            String file = request.getParameter("_escaped_fragment_");
            if (file.startsWith("b=")) {
                file = file.substring(2);
            }
           
            returnFile(file, response);
            return;
        } else if (request.getRequestURI().indexOf("sitemap.xml") > -1) {
            response.setContentType("text/xml");
            PrintWriter out = new PrintWriter(new OutputStreamWriter(response.getOutputStream(), "UTF-8"));
           
            try {
                if (g_siteMap == null) {
                    /*
                     If we haven't created the sitemap yet we'll create it and cache it
                     */
                    createSiteMap(request);
                }
            } catch (Exception e) {
                LOGGER.throwing(SiteMapServlet.class.getName(), "service", e);
                e.printStackTrace();
            }
           
            out.write(g_siteMap);
            out.flush();
        } else {
            returnFile(request.getServletPath(), response);
        }
    }
   
    private void returnFile(String name, HttpServletResponse response) throws ServletException, IOException
    {
        boolean addHeader = false;
       
        String file = null;
       
        if (name.equals("") || name.equals("/") ||
            name.equals("index.html") || name.equals("/index.html")) {
            /*
             Google AppEngine won't let us use a servlet in place if a real file.
             The solution is to serve at index.html, but return the contents of the
             real file at index.htm.  This is super hacky, but I can't find a better
             way around it.  Hackito Ergo Sum.
             */
            file = "/index.htm";
        } else if (name.equals("index-debug.html") || name.equals("/index-debug.html")) {
            file = "/index-debug.htm";
        } else if (HASHES.containsKey(name)) {
            addHeader = true;
            file = HASHES.get(name);
        }
       
        if (file == null) {
            file = name;
        }
       
        response.setContentType("text/html; charset=utf-8");
        InputStream in = getServletConfig().getServletContext().getResourceAsStream(file);

        if (in == null) {
            /*
             This means they requested a file that doesn't exist so they get a
             404
             */
            in = getServletConfig().getServletContext().getResourceAsStream("/404.html");
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
        } else {
            response.setStatus(HttpServletResponse.SC_OK);
        }
       
        InputStreamReader reader = new InputStreamReader(in, "UTF-8");
       
        try {
            char buf[] = new char[512];
            OutputStreamWriter out = new OutputStreamWriter(response.getOutputStream(), "UTF-8");
           
            if (addHeader) {
                addHeader(out, name);
            }
           
            int numRead;
            while ((numRead = reader.read(buf)) >= 0) {
                out.write(buf, 0, numRead);
            }
           
            if (addHeader) {
                addFooter(out);
            }
           
            out.flush();
        } finally {
            if (reader != null) {
                reader.close();
            }
        }
    }
   
    private void addHeader(Writer out, String name) throws IOException
    {
        /*
         The snippets are not full HTML pages so we add the header
         information to them. 
         */
       
        String header = "<!DOCTYPE html>\n\n" +
            "<html>\n" +
            "<head>\n" +
            "<title>Spiffy UI Framework - " + name + "</title>\n" +
            "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n" +
            //"<script type=\"text/javascript\" src=\"jquery.min.js\"></script>\n" +
            //"<script type=\"text/javascript\" src=\"spsample.min.js\"></script>\n" +
            //"<script type=\"text/javascript\">\n" +
            //"spiffyui.autoloadCSS = false;\n" +
            //"spiffyui.autoloadHTML = false;\n" +
            //"</script>\n" +
            //"</head>\n" +
            "<body>\n";
       
        out.write(header);
    }
   
    private void addFooter(Writer out) throws IOException
    {
        /*
         The snippets are not full HTML pages so we add the footer
         information to them. 
         */
       
        String footer = "</body>\n" +
            "</html>";
       
        out.write(footer);
    }
   
    private synchronized void createSiteMap(HttpServletRequest request) throws Exception
    {
        if (g_siteMap != null) {
            /*
             then we've already created the sitemap
             */
            return;
        }
       
        StringWriter out = new StringWriter();
        XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
        XMLEventWriter eventWriter = outputFactory.createXMLEventWriter(out);
        XMLEventFactory eventFactory = XMLEventFactory.newInstance();
        XMLEvent end = eventFactory.createDTD("\n");
       
        StartDocument startDocument = eventFactory.createStartDocument();
        eventWriter.add(startDocument);
       
        eventWriter.add(end);
       
        ArrayList<Namespace> ns = new ArrayList<Namespace>();
       
        ArrayList<Attribute> atts = new ArrayList<Attribute>();
        atts.add(eventFactory.createAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"));
        atts.add(eventFactory.createAttribute("xsi:schemaLocation", "http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"));
        atts.add(eventFactory.createAttribute("xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9"));
        StartElement urlSetStartElement = eventFactory.createStartElement("", "", "urlset", atts.iterator(), ns.iterator());
       
        eventWriter.add(urlSetStartElement);
        eventWriter.add(end);
        findFiles(request, getServletConfig().getServletContext(), eventWriter);
       
        eventWriter.add(eventFactory.createEndElement("", "", "urlset"));
        eventWriter.add(end);
        eventWriter.add(eventFactory.createEndDocument());
        eventWriter.close();
       
        g_siteMap = out.toString();
    }
   
    private void findFiles(HttpServletRequest request, ServletContext context, XMLEventWriter eventWriter) throws XMLStreamException
    {
        /*
         First we add a node for the home page
         */
        createNode(eventWriter, request.getRequestURL().substring(0, request.getRequestURL().length() - 11), "1.0");
       
        for (String key : HASHES.keySet()) {
            createNode(eventWriter, request.getRequestURL().substring(0, request.getRequestURL().length() - 11+
                       "#!" + key, "0.8");
        }
       
        /*
         Now we return all the content from the JavaDoc directory
         */
        createNode(eventWriter, request.getRequestURL().substring(0, request.getRequestURL().length() - 11) + "javadoc", "0.7");
        findStaticFiles(request, context, eventWriter, "/javadoc");
       
        /*
         We also want to include the content from the Maven plugin documentation
         */
        createNode(eventWriter, request.getRequestURL().substring(0, request.getRequestURL().length() - 11) + "maven-plugin", "0.7");
        findStaticFiles(request, context, eventWriter, "/maven-plugin");
       
    }
   
    private void findStaticFiles(HttpServletRequest request, ServletContext context,
                                 XMLEventWriter eventWriter, String ref) throws XMLStreamException
    {
        Set set = context.getResourcePaths(ref);
        Iterator iter = set.iterator();
        while (iter.hasNext()) {
            String file = iter.next().toString();
            if (file.endsWith("/")) {
                /*
                 Then this is a directory and we want to look into it
                 */
                file = file.substring(0, file.length() - 1);
                file = file.substring(file.lastIndexOf('/') + 1);
                findStaticFiles(request, context, eventWriter, ref + "/" + file);
            } else {
                if (file.endsWith(".html") || file.endsWith(".htm")) {
                    file = file.substring(file.lastIndexOf('/'));
                    createNode(eventWriter, request.getRequestURL().substring(0, request.getRequestURL().length() - 12+
                               ref + file, "0.6");
                }
            }
        }
    }

    private void createNode(XMLEventWriter eventWriter, String loc, String priority) throws XMLStreamException
    {
        XMLEventFactory eventFactory = XMLEventFactory.newInstance();
        XMLEvent end = eventFactory.createDTD("\n");
        XMLEvent tab = eventFactory.createDTD("\t");
       
        eventWriter.add(tab);
        eventWriter.add(eventFactory.createStartElement("", "", "url"));
       
        /*
         Generate the location element
         */
        eventWriter.add(end);
        eventWriter.add(tab);
        eventWriter.add(tab);
        eventWriter.add(eventFactory.createStartElement("", "", "loc"));
       
        Characters characters = eventFactory.createCharacters(loc);
        eventWriter.add(characters);
       
        eventWriter.add(eventFactory.createEndElement("", "", "loc"));
        eventWriter.add(end);
       
        /*
         Add the last modification date of this page
         */
        eventWriter.add(tab);
        eventWriter.add(tab);
        eventWriter.add(eventFactory.createStartElement("", "", "lastmod"));
       
        /*
         We need to use the W3C date time format here
         */
        characters = eventFactory.createCharacters(
            new SimpleDateFormat("yyyy-MM-dd").format(new Date(Long.parseLong(BUILD_BUNDLE.getString("build.date")))));
        eventWriter.add(characters);
       
        eventWriter.add(eventFactory.createEndElement("", "", "lastmod"));
        eventWriter.add(end);
       
        /*
         Add the change frequency
         */
        eventWriter.add(tab);
        eventWriter.add(tab);
        eventWriter.add(eventFactory.createStartElement("", "", "changefreq"));
       
        characters = eventFactory.createCharacters("daily");
        eventWriter.add(characters);
       
        eventWriter.add(eventFactory.createEndElement("", "", "changefreq"));
        eventWriter.add(end);
       
        /*
         Add the priority of this page
         */
        eventWriter.add(tab);
        eventWriter.add(tab);
        eventWriter.add(eventFactory.createStartElement("", "", "priority"));
       
        characters = eventFactory.createCharacters(priority);
        eventWriter.add(characters);
       
        eventWriter.add(eventFactory.createEndElement("", "", "priority"));
        eventWriter.add(end);
       
        eventWriter.add(tab);
        eventWriter.add(eventFactory.createEndElement("", "", "url"));
        eventWriter.add(end);

    }
}
TOP

Related Classes of org.spiffyui.spsample.server.SiteMapServlet

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.