Package com.esri.gpt.control.sitemap

Source Code of com.esri.gpt.control.sitemap.SitemapHandler

/* See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* Esri Inc. 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 com.esri.gpt.control.sitemap;
import com.esri.gpt.framework.collection.StringAttributeMap;
import com.esri.gpt.framework.context.ConfigurationException;
import com.esri.gpt.framework.context.RequestContext;
import com.esri.gpt.framework.sql.BaseDao;
import com.esri.gpt.framework.util.Val;

import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* Handles the generation of sitemap files based upon the content of the metadata catalog.
*/
public class SitemapHandler extends BaseDao {

  /** class variables ========================================================= */
 
  /** ISO 8601 data formatter. */
  private static SimpleDateFormat ISO8601FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
 
  /** The Logger. */
  private static final Logger LOGGER = Logger.getLogger(SitemapHandler.class.getName());
   
  /** Standard XML header. */
  private static String XMLHEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";

  /** instance variables ====================================================== */
  private String baseUrl = "";
  private String changefreq = "weekly";
  private String documentUrlPattern = "/rest/document/{0}?f=html";
  private String namespaceUri = "http://www.sitemaps.org/schemas/sitemap/0.9";
  private String priority = "";
  private int    startRecord = -1;
  private int    urlsPerIndexFile = 1000;
  private int    urlsPerSitemapFile = 40000;

  /** constructors ============================================================ */

  /** Default constructor. */
  protected SitemapHandler() {}
     
  /** methods ================================================================= */
 
  /**
   * Counts the number of records that are publically available for the sitemap.
   * @return the record count
   * @throws SQLException if a database related exception occurs
   */
  private int countRecords() throws SQLException {
    PreparedStatement st = null;
    try {
      Connection con = this.returnConnection().getJdbcConnection();
      String sql = this.makeQuery(true);
      this.logExpression(sql);
      st = con.prepareStatement(sql);
      ResultSet rs = st.executeQuery();
      if (rs.next()) {
        return rs.getInt(1);
      }
    } finally {
      closeStatement(st);
    }
    return 0;
  }
 
  /**
   * Handles a sitemap request.
   * @param request the HTTP request
   * @param response the HTTP response
   * @param context the request context
   * @throws Exception if an exception occurs
   */
  protected void handle(HttpServletRequest request,
                        HttpServletResponse response,
                        RequestContext context)
    throws Exception {
    PrintWriter out = null;
    try {
      initialize(request,response,context);
      out = response.getWriter();
      if (this.startRecord > 0) {
        this.writeSitemapFile(out);
      } else {
        int recordCount = this.countRecords();
        if (recordCount <= this.urlsPerSitemapFile) {
          this.writeSitemapFile(out);
        } else {
          this.writeIndexFile(out,recordCount);
        }
      }
    } finally {
      try {if (out != null) out.close();} catch (Exception ef) {}
    }
  }
 
  /**
   * Initializes the request.
   * @param request the HTTP request
   * @param response the HTTP response
   * @param context the request context
   */
  private void initialize(HttpServletRequest request,
      HttpServletResponse response, RequestContext context) {
   
    String sTmp;
    int nTmp = 0;
    this.setRequestContext(context);
    StringAttributeMap params = context.getCatalogConfiguration().getParameters();
   
    String baseContextPath = RequestContext.resolveBaseContextPath(request);
    this.baseUrl = baseContextPath+"/sitemap";
    this.startRecord = Val.chkInt(request.getParameter("startRecord"),-1);
    response.setContentType("text/xml; charset=UTF-8");
   
   
    sTmp = Val.chkStr(params.getValue("sitemap.baseUrl"));
    if (sTmp.length() > 0) this.baseUrl = sTmp;
    if (this.baseUrl.endsWith("&")) {
      this.baseUrl = this.baseUrl.substring(0,this.baseUrl.length() - 1);
    }
    if (this.baseUrl.endsWith("?")) {
      this.baseUrl = this.baseUrl.substring(0,this.baseUrl.length() - 1);
    }
   
    sTmp = Val.chkStr(params.getValue("sitemap.documentUrlPattern"));
    if (sTmp.length() > 0) this.documentUrlPattern = sTmp;
    if (!this.documentUrlPattern.startsWith("http")) {
      if (!this.documentUrlPattern.startsWith("/")) {
        this.documentUrlPattern = "/"+this.documentUrlPattern;
      }
      this.documentUrlPattern = baseContextPath+this.documentUrlPattern;
    }
   
    nTmp = Val.chkInt(params.getValue("sitemap.urlsPerIndexFile"),0);
    if ((nTmp > 0) && (nTmp < 1000)) this.urlsPerIndexFile = nTmp;
   
    nTmp = Val.chkInt(params.getValue("sitemap.urlsPerSitemapFile"),0);
    if ((nTmp > 0) && (nTmp < 50000)) this.urlsPerSitemapFile = nTmp;
   
    sTmp = Val.chkStr(params.getValue("sitemap.namespaceUri"));
    if (sTmp.length() > 0) this.namespaceUri = sTmp;
   
    sTmp = Val.chkStr(params.getValue("sitemap.changefreq"));
    if (sTmp.length() > 0) this.changefreq = sTmp;
   
    sTmp = Val.chkStr(params.getValue("sitemap.priority"));
    if (sTmp.length() > 0) this.priority = sTmp;
   

    // error check
    String errPfx = "gpt.xml: gptConfig/catalog/parameter/";
    if (this.documentUrlPattern.indexOf("{0}") == -1) {
      throw new ConfigurationException(errPfx+"@key=sitemap.documentUrlPattern must contain {0}");
    }
  }
 
  /**
   * Builds the SQL query string.
   * @param countOnly if true a COUNT(*) query is returned
   * @return the SQL query string
   */
  private String makeQuery(boolean countOnly) {
    String resourceTable = this.getRequestContext().getCatalogConfiguration().getResourceTableName();
    StringBuilder sql = new StringBuilder();
    if (countOnly) {
      sql.append("SELECT COUNT(*) FROM ");
    } else {
      sql.append("SELECT DOCUUID,UPDATEDATE FROM ");
    }
    sql.append(resourceTable);
    sql.append(" WHERE ");
    sql.append(" AND ((APPROVALSTATUS = 'approved') OR (APPROVALSTATUS = 'reviewed'))");
    sql.append(" AND (ACL IS NULL)");
    return sql.toString();
  }
 
  /**
   * Writes the sitemap index file response.
   * @param out the HTTP response writer
   * @param recordCount the number of sitemap records
   */
  private void writeIndexFile(PrintWriter out, int recordCount) {
    LOGGER.log(Level.INFO, "Writing sitemap index file response, recordCount={0}", recordCount);
    out.println(SitemapHandler.XMLHEADER);
    out.println("<sitemapindex xmlns=\""+this.namespaceUri+"\">");
   
    String url;
    int nWritten = 0;
    for (int start = 1; start <= recordCount; start += this.urlsPerSitemapFile) {
      if (this.baseUrl.indexOf("?") == -1) {
        url = this.baseUrl+"?startRecord="+start;
      } else {
        url = this.baseUrl+"&startRecord="+start;
      }
      String modified = this.toIso8601(new Timestamp(System.currentTimeMillis()));
      out.println("<sitemap>");
      writeTag(out,"loc",url);
      writeTag(out,"lastmod",modified);
      out.println("</sitemap>");
      out.flush();
      nWritten++;
      if (nWritten >= this.urlsPerIndexFile) break;
      if (Thread.interrupted()) {break;}
    }
   
    out.println("</sitemapindex>");
  }
 
  /**
   * Writes a sitemap file response.
   * @param out the HTTP response writer
   * @throws SQLException if a database exception occurs
   */
  private void writeSitemapFile(PrintWriter out) throws SQLException {
    if (this.startRecord > 0) {
      LOGGER.log(Level.INFO, "Writing sitemap file response, startRecord={0}", this.startRecord);
    } else {
      LOGGER.info("Writing sitemap file response.");
    }
    PreparedStatement st = null;
   
    try {
      out.println(SitemapHandler.XMLHEADER);
      out.println("<urlset xmlns=\""+this.namespaceUri+"\">");
     
      // construct the query
      int nRecord = 0;
      int nWritten = 0;
      String sql = this.makeQuery(false);
     
      // execute thq query
      Connection con = this.returnConnection().getJdbcConnection();
      this.logExpression(sql);
      st = con.prepareStatement(sql);
      ResultSet rs = st.executeQuery();
      while (rs.next()) {
        nRecord++;
        if (nRecord >= this.startRecord) {
          String uuid = rs.getString(1);
         
          // determine the document URL
          String url = "";
          try {url = this.documentUrlPattern.replace("{0}",URLEncoder.encode(uuid,"UTF-8"));}
          catch (UnsupportedEncodingException uee) {}
         
          // determine the modification timestamp
          Timestamp tsMod = rs.getTimestamp(2);
          String modified = this.toIso8601(tsMod);
       
          // write the URL element
          out.println("<url>");
          writeTag(out,"loc",url);
          writeTag(out,"lastmod",modified);
          writeTag(out,"changefreq",this.changefreq);
          writeTag(out,"priority",this.priority);
          out.println("</url>");
          out.flush();
          nWritten++;
          if (nWritten >= this.urlsPerSitemapFile) break;
          if (Thread.interrupted()) break;
       
      }
       
    } finally {
      closeStatement(st);
      try {out.println("</urlset>");} catch (Exception ef) {}
    }
  }
 
  /**
   * Converts a Timestamp to ISO-8601 format.
   * @param timestamp the timestamp
   * @return the formatted restlt
   */
  private String toIso8601(Timestamp timestamp) {
    String sTimestamp = "";
    if (timestamp != null) {
      sTimestamp = ISO8601FORMAT.format(timestamp);
      sTimestamp = sTimestamp.substring(0,sTimestamp.length()-2)+":"+sTimestamp.substring(sTimestamp.length()-2);
    }
    return sTimestamp;
  }
   
  /**
   * Writes an XML tag with text node content to the response.
   * @param out the HTTP response writer
   * @param tag the name of the tag
   * @param content the text node content
   */
  private void writeTag(PrintWriter out, String tag, String content) {
    if ((content != null) && (content.length() > 0)) {
      out.println("<"+tag+">"+Val.escapeXml(content)+"</"+tag+">");
    }
  }
 
}
TOP

Related Classes of com.esri.gpt.control.sitemap.SitemapHandler

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.