Package org.infoglue.deliver.invokers

Source Code of org.infoglue.deliver.invokers.PageInvoker

/* ===============================================================================
*
* Part of the InfoGlue Content Management Platform (www.infoglue.org)
*
* ===============================================================================
*
*  Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License version 2, as published by the
* Free Software Foundation. See the file LICENSE.html for more information.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY, including the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc. / 59 Temple
* Place, Suite 330 / Boston, MA 02111-1307 / USA.
*
* ===============================================================================
*/

package org.infoglue.deliver.invokers;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.exolab.castor.jdo.Database;
import org.infoglue.cms.applications.common.VisualFormatter;
import org.infoglue.cms.controllers.kernel.impl.simple.ContentVersionController;
import org.infoglue.cms.controllers.kernel.impl.simple.PageDeliveryMetaDataController;
import org.infoglue.cms.controllers.kernel.impl.simple.RepositoryController;
import org.infoglue.cms.entities.content.ContentVersionVO;
import org.infoglue.cms.entities.content.SmallestContentVersionVO;
import org.infoglue.cms.entities.management.LanguageVO;
import org.infoglue.cms.entities.management.PageDeliveryMetaDataEntityVO;
import org.infoglue.cms.entities.management.PageDeliveryMetaDataVO;
import org.infoglue.cms.entities.management.RepositoryVO;
import org.infoglue.cms.entities.structure.SiteNode;
import org.infoglue.cms.entities.structure.SiteNodeVO;
import org.infoglue.cms.exception.Bug;
import org.infoglue.cms.exception.NoBaseTemplateFoundException;
import org.infoglue.cms.exception.SystemException;
import org.infoglue.cms.io.FileHelper;
import org.infoglue.cms.util.CmsPropertyHandler;
import org.infoglue.deliver.applications.databeans.DatabaseWrapper;
import org.infoglue.deliver.applications.databeans.DeliveryContext;
import org.infoglue.deliver.cache.PageCacheHelper;
import org.infoglue.deliver.controllers.kernel.URLComposer;
import org.infoglue.deliver.controllers.kernel.impl.simple.LanguageDeliveryController;
import org.infoglue.deliver.controllers.kernel.impl.simple.NodeDeliveryController;
import org.infoglue.deliver.controllers.kernel.impl.simple.TemplateController;
import org.infoglue.deliver.portal.PortalController;
import org.infoglue.deliver.util.CacheController;
import org.infoglue.deliver.util.CompressionHelper;
import org.infoglue.deliver.util.JSMin;
import org.infoglue.deliver.util.RequestAnalyser;
import org.infoglue.deliver.util.Timer;

/**
* @author Mattias Bogeblad
*
* This interface defines what a Invoker of a page have to be able to do.
* The invokers are used to deliver a page to the user in a certain fashion.
*
*/

public abstract class PageInvoker
    private final static Logger logger = Logger.getLogger(PageInvoker.class.getName());

  private static CompressionHelper compressionHelper = new CompressionHelper();
  private final static VisualFormatter vf = new VisualFormatter();

    private DatabaseWrapper dbWrapper        = null;
  private HttpServletRequest request        = null;
  private HttpServletResponse response       = null;
  private TemplateController templateController  = null;
  private DeliveryContext deliveryContext     = null;
 
  private String pageString             = null;
 
  /*public PageInvoker()
  {
  }
  */
 
  /**
   * The default constructor for PageInvokers.
   * @param request
   * @param response
   * @param templateController
   * @param deliveryContext
   */
  /*
  public PageInvoker(HttpServletRequest request, HttpServletResponse response, TemplateController templateController, DeliveryContext deliveryContext)
  {
    this.request = request;
    this.response = response;
    this.templateController = templateController;
    this.deliveryContext = deliveryContext;
    this.templateController.setDeliveryContext(this.deliveryContext);
  }
  */

  /**
   * This method should return an instance of the class that should be used for page editing inside the tools or in working.
   * Makes it possible to have an alternative to the ordinary delivery optimized class.
   */
 
  public abstract PageInvoker getDecoratedPageInvoker(TemplateController templateController, DeliveryContext deliveryContext) throws SystemException;
 
  /**
   * The default initializer for PageInvokers.
   * @param request
   * @param response
   * @param templateController
   * @param deliveryContext
   */

  public void setParameters(DatabaseWrapper dbWrapper, HttpServletRequest request, HttpServletResponse response, TemplateController templateController, DeliveryContext deliveryContext)
  {
      this.dbWrapper = dbWrapper;
    this.request = request;
    this.response = response;
    this.templateController = templateController;
    this.deliveryContext = deliveryContext;
    this.templateController.setDeliveryContext(this.deliveryContext);
  }
 
    public Database getDatabase() throws SystemException
    {
        /*
        if(this.db == null || this.db.isClosed() || !this.db.isActive())
        {
            beginTransaction();
        }
        */
        return dbWrapper.getDatabase();
    }

   
  /**
   * This is the method that will deliver the page to the user. It can have special
   * handling of all sorts to enable all sorts of handlers. An example of uses might be to
   * be to implement a WAP-version of page delivery where you have to set certain headers in the response
   * or a redirect page which just redirects you to another page. 
   */
 
  public abstract void invokePage() throws SystemException, Exception;
 

  /**
   * This method is used to send the page out to the browser or other device.
   * Override this if you need to set other headers or do other specialized things.
   */

  public void deliverPage() throws NoBaseTemplateFoundException, Exception
  {
    if(logger.isInfoEnabled())
    {
      logger.info("PageKey:" + this.getDeliveryContext().getPageKey());
      logger.info("PageCache:" + this.getDeliveryContext().getDisablePageCache());
    }
   
    LanguageVO languageVO = LanguageDeliveryController.getLanguageDeliveryController().getLanguageVO(getDatabase(), this.getTemplateController().getLanguageId());
   
    if(logger.isInfoEnabled())
      logger.info("languageVO:" + languageVO);
   
    if(languageVO == null)
      throw new SystemException("There was no such active language for the page with languageId:" + this.getTemplateController().getLanguageId());
   
    String isPageCacheOn = CmsPropertyHandler.getIsPageCacheOn();
    String refresh = this.getRequest().getParameter("refresh");
   
    String pageCacheName = "pageCache"; // + this.getTemplateController().getRepositoryId();
    String pageCacheExtraName = "pageCacheExtra"; // + this.getTemplateController().getRepositoryId();
   
    if(logger.isInfoEnabled())
      logger.info("isPageCacheOn:" + isPageCacheOn);
   
    if(isPageCacheOn.equalsIgnoreCase("true") && (refresh == null || !refresh.equalsIgnoreCase("true")) && getRequest().getMethod().equals("GET"))
    {
      Map cachedExtraData = null;

      Integer pageCacheTimeout = (Integer)CacheController.getCachedObjectFromAdvancedCache("pageCacheExtra", this.getDeliveryContext().getPageKey() + "_pageCacheTimeout");
      if(pageCacheTimeout == null)
        pageCacheTimeout = this.getTemplateController().getPageCacheTimeout();
     
      if(pageCacheTimeout == null)
      {
          //cachedCompressedData = (byte[])CacheController.getCachedObjectFromAdvancedCache(pageCacheName, this.getDeliveryContext().getPageKey());
        Class[] argsClasses = new Class[2];
        argsClasses[0] = String.class;
        argsClasses[1] = String.class;
       
        Object[] args = new Object[]{pageCacheName, pageCacheExtraName};
       
        this.pageString = (String)CacheController.getCachedObjectFromAdvancedCache(pageCacheName, this.getDeliveryContext().getPageKey(), true, "utf-8", true, this, this.getClass().getMethod("invokeAndDecoratePage", argsClasses), args, this);
          cachedExtraData = (Map)CacheController.getCachedObjectFromAdvancedCache(pageCacheExtraName, this.getDeliveryContext().getPageKey());
         
          if(this.pageString != null)
            this.getDeliveryContext().setIsCachedResponse(true);
      }
      else
      {
          //cachedCompressedData = (byte[])CacheController.getCachedObjectFromAdvancedCache(pageCacheName, this.getDeliveryContext().getPageKey(), pageCacheTimeout.intValue());
        //this.pageString = (String)CacheController.getCachedObjectFromAdvancedCache(pageCacheName, this.getDeliveryContext().getPageKey(), pageCacheTimeout.intValue(), true, "utf-8", false);
        Object pageCacheFileName = CacheController.getCachedObjectFromAdvancedCache(pageCacheName, this.getDeliveryContext().getPageKey(), pageCacheTimeout.intValue(), true, "utf-8", false);
          if(pageCacheFileName != null && !pageCacheFileName.equals(""))
             this.pageString = PageCacheHelper.getInstance().getCachedPageString(this.getDeliveryContext().getPageKey(), new File(pageCacheFileName.toString()));
          else
            logger.info("No page file name in memory cache:" + this.getDeliveryContext().getPageKey());
          cachedExtraData = (Map)CacheController.getCachedObjectFromAdvancedCache(pageCacheExtraName, this.getDeliveryContext().getPageKey(), pageCacheTimeout.intValue());

          this.getDeliveryContext().setPageCacheTimeout(pageCacheTimeout.intValue());
         
          if(this.pageString == null)
          {
            invokePage();
          this.pageString = getPageString();
         
          getLastModifiedDateTime(false);
         
          pageString = decorateHeadAndPageWithVarsFromComponents(pageString);

          this.getDeliveryContext().setPagePath(this.templateController.getCurrentPagePath());
          }
          else
            this.getDeliveryContext().setIsCachedResponse(true);
      }
           
      logger.info("this.getDeliveryContext().getIsCachedResponse():" + this.getDeliveryContext().getIsCachedResponse());
      if(this.getDeliveryContext().getIsCachedResponse())
      {
        String usedEntitiesString = null;
        if(CmsPropertyHandler.getOperatingMode().equals("0"))
        {
          usedEntitiesString = (String)CacheController.getCachedObjectFromAdvancedCache("pageCacheExtra", this.getDeliveryContext().getPageKey() + "_entitiesAsByte");       
        }
        else
        {
          byte[] usedEntitiesByteArray = (byte[])CacheController.getCachedObjectFromAdvancedCache("pageCacheExtra", this.getDeliveryContext().getPageKey() + "_entitiesAsByte");
          if(usedEntitiesByteArray != null)
            usedEntitiesString = compressionHelper.decompress(usedEntitiesByteArray);
        }
       
        if(logger.isInfoEnabled())
          logger.info("usedEntitiesString:" + usedEntitiesString);
        if(usedEntitiesString != null)
        {
          String[] usedEntities = StringUtils.split(usedEntitiesString, "|");
          for(String usedEntity : usedEntities)
          {
            if(usedEntity.startsWith("content_"))
              this.getDeliveryContext().addUsedContent(usedEntity);
            else if(usedEntity.startsWith("contentVersion_"))
              this.getDeliveryContext().addUsedContentVersion(usedEntity);
            else if(usedEntity.startsWith("siteNode_"))
              this.getDeliveryContext().addUsedSiteNode(usedEntity);
            else if(usedEntity.startsWith("siteNodeVersion_"))
              this.getDeliveryContext().addUsedSiteNodeVersion(usedEntity);
          }
        }
      }
     
      getLastModifiedDateTime(true);

        if(cachedExtraData != null)
          this.getDeliveryContext().populateExtraData(cachedExtraData);
       
      //Caching the pagePath
      this.getDeliveryContext().setPagePath((String)CacheController.getCachedObject("pagePathCache", this.getDeliveryContext().getPageKey()));
      if(this.getDeliveryContext().getPagePath() == null)
      {
        this.getDeliveryContext().setPagePath(this.getTemplateController().getCurrentPagePath());
     
        if(!this.getTemplateController().getIsPageCacheDisabled() && !this.getDeliveryContext().getDisablePageCache()) //Caching page path if not disabled
          CacheController.cacheObject("pagePathCache", this.getDeliveryContext().getPageKey(), this.getDeliveryContext().getPagePath());
      }
     
      if(logger.isInfoEnabled())
        logger.info("Done caching the pagePath...")
    }
    else
    {
      invokePage();
      this.pageString = getPageString();
     
      //TEST
      getLastModifiedDateTime(false);
      //END TEST

      pageString = decorateHeadAndPageWithVarsFromComponents(pageString);

      this.getDeliveryContext().setPagePath(this.templateController.getCurrentPagePath());
    }

    if(this.getRequest().getParameter("includeUsedEntities") != null && this.getRequest().getParameter("includeUsedEntities").equals("true") && (!CmsPropertyHandler.getOperatingMode().equals("3") || CmsPropertyHandler.getLivePublicationThreadClass().equalsIgnoreCase("org.infoglue.deliver.util.SelectiveLivePublicationThread")))
    {
      StringBuilder sb = new StringBuilder("<usedEntities>");
      String[] usedEntities = this.getDeliveryContext().getAllUsedEntities();
      for(int i=0; i<usedEntities.length; i++)
        sb.append(usedEntities[i]).append(",");
      sb.append("</usedEntities>");
     
      if(this.getTemplateController().getPageContentType() != null && (this.getTemplateController().getPageContentType().equalsIgnoreCase("text/css") || this.getTemplateController().getPageContentType().equalsIgnoreCase("text/javascript")))
        this.pageString = this.pageString + "/*" + sb.toString() + "*/";
      else
        this.pageString = this.pageString + "<!--" + sb.toString() + "-->";
    }
   
    String contentType = this.getTemplateController().getPageContentType();
    if(this.deliveryContext.getContentType() != null && !contentType.equalsIgnoreCase(this.deliveryContext.getContentType()))
        contentType = this.deliveryContext.getContentType();

    if(!CmsPropertyHandler.getOperatingMode().equals("3"))
    {
      getResponse().setHeader("Cache-Control","no-cache");
      getResponse().setHeader("Pragma","no-cache");
      getResponse().setDateHeader ("Expires", 0);
    }
     
    //logger.info("pageString before:" + pageString);
    //pageString = decorateHeadAndPageWithVarsFromComponents(pageString);
    //logger.info("pageString after:" + pageString);
   
    try
    {
      //logger.info("ContentType:" + contentType);
      String charSet = languageVO.getCharset();
      if(contentType.indexOf("charset=") > -1)
      {
        try
        {
          int startIndex = contentType.indexOf("charset=");
          int endIndex = contentType.indexOf(";", startIndex + 1);
       
          if(endIndex != -1)
            charSet = contentType.substring(startIndex + "charset=".length(), endIndex).trim();
          else
            charSet = contentType.substring(startIndex + "charset=".length()).trim();
       
          if(logger.isInfoEnabled())
            logger.info("Found a user defined charset: " + charSet);
        }
        catch(Exception e)
        {
          logger.warn("Error parsing charset:" + e.getMessage());
        }
        this.getResponse().setContentType(contentType);
      }
      else
        this.getResponse().setContentType(contentType + "; charset=" + languageVO.getCharset());
     
      if(logger.isInfoEnabled())
        logger.info("Using charset: " + charSet);
     
      Iterator headersIterator = this.getDeliveryContext().getHttpHeaders().keySet().iterator();
      while(headersIterator.hasNext())
      {
        String key = (String)headersIterator.next();
        Object valueObject = this.getDeliveryContext().getHttpHeaders().get(key);
        if(valueObject instanceof Date)
        {
          Date value = (Date)valueObject;
          this.getResponse().setDateHeader(key, value.getTime());
        }
        else
        {
          String value = (String)valueObject;
          this.getResponse().setHeader(key, value);       
        }
      }
     
      if(logger.isInfoEnabled())
        logger.info("contentType:" + contentType + "; charset=" + languageVO.getCharset());
     
      String compressPageResponse = CmsPropertyHandler.getCompressPageResponse();
      if(logger.isInfoEnabled())
        logger.info("compressPageResponse:" + compressPageResponse);
   
      if(compressPageResponse != null && compressPageResponse.equalsIgnoreCase("true"))
      {
        OutputStream out = null;
       
        String encodings = this.getRequest().getHeader("Accept-Encoding");
          if (encodings != null && encodings.indexOf("gzip") != -1)
          {
            this.getResponse().setHeader("Content-Encoding", "gzip");
            out = new GZIPOutputStream(this.getResponse().getOutputStream());
          }
          else if (encodings != null && encodings.indexOf("compress") != -1)
          {
            this.getResponse().setHeader("Content-Encoding", "x-compress");
            out = new ZipOutputStream(this.getResponse().getOutputStream());
            ((ZipOutputStream)out).putNextEntry(new ZipEntry("dummy name"));
          }
          else
          {
            out = this.getResponse().getOutputStream();
          }
         
          if(pageString != null)
            out.write(pageString.getBytes(charSet));
          else
            out.write("Error: got null pagestring".getBytes(charSet));
           
          out.flush();
        out.close();
      }
      else
      {     
        PrintWriter out = this.getResponse().getWriter();
        out.println(pageString);
        out.flush();
        out.close();
        }     
     
      if(logger.isInfoEnabled())
        logger.info("sent all data to client:" + pageString.length());
      }
    catch(IllegalStateException e)
    {
      logger.error("There was an IllegalStateException when trying to write output for URL: " + this.getTemplateController().getOriginalFullURL() + "\nMessage: " + e.getMessage());
    }
   
        //New solution which enables us to defeat individual page caches in flow.
    try
    {
      String pageKey = this.getDeliveryContext().getPageKey();
      if(logger.isInfoEnabled())
        logger.info("pageKey:" + pageKey);
      if(refresh != null && refresh.equalsIgnoreCase("true"))
      {
        String originalQueryString = this.getDeliveryContext().getOriginalQueryString();
        logger.info("originalQueryString:" + originalQueryString);
        logger.info("Clearing page cache....");
        if(originalQueryString.equalsIgnoreCase("refresh=true"))
          pageKey = pageKey.replaceFirst("refresh=true","null");
        else if(originalQueryString.indexOf("&refresh=true") > -1)
          pageKey = pageKey.replaceFirst("&refresh=true","");
        else if(originalQueryString.indexOf("refresh=true&") == 0)
          pageKey = pageKey.replaceFirst("refresh=true&","");
        logger.info("pageKey:" + pageKey);
        //Timer t = new Timer();
        CacheController.clearPageCache(pageKey);
        //t.printElapsedTime("Clearing page cache took...");
       
        //CacheController.clearCaches(SiteNodeImpl.class.getName(), "" + this.getTemplateController().getSiteNodeId(), null);
        //t.printElapsedTime("Clearing caches took...");
      }
    }
    catch (Exception e)
    {
      logger.error("Could not clear the pagecache:" + e.getMessage());
    }
  }

  public String invokeAndDecoratePage(String pageCacheName, String pageCacheExtraName) throws SystemException, Exception, Bug
  {
    if(this.pageString == null)
    {
      invokePage();
      this.pageString = getPageString();

      //TEST
      getLastModifiedDateTime(false);
      //END TEST
     
      this.pageString = decorateHeadAndPageWithVarsFromComponents(pageString);
    }
    else
    {
      if(logger.isInfoEnabled())
        logger.info("There was a cached copy..."); // + pageString);
    }
    return this.pageString;
  }

  private void getLastModifiedDateTime(boolean useContentLookup) throws Bug
  {
    //if(CmsPropertyHandler.getOperatingMode().equals("3") && CmsPropertyHandler.getSetDerivedLastModifiedInLive().equalsIgnoreCase("false"))
    //  return;
   
    //Integer maxNumberOfVersionsForDerivedLastModifiedInLive = CmsPropertyHandler.getMaxNumberOfVersionsForDerivedLastModifiedInLive();
   
    Date lastModifiedDateTime = null;
    logger.info("useContentLookup:" + useContentLookup);
    logger.info("UsedContentVersions:" + this.deliveryContext.getUsedContentVersions().size());
    logger.info("UsedContents:" + this.deliveryContext.getUsedContents().size());
    Timer t = new Timer();
    if(this.deliveryContext.getUsedContentVersions().size() > 0 || (useContentLookup && this.deliveryContext.getUsedContents().size() > 0))
    {
      try
      {
        SmallestContentVersionVO lastContentVersionVO = null;
        if(useContentLookup)
          lastContentVersionVO = ContentVersionController.getContentVersionController().getLatestContentVersionVOByContentIds(this.deliveryContext.getUsedContents(), getDatabase());
        else
          lastContentVersionVO = ContentVersionController.getContentVersionController().getLatestContentVersionVO(this.deliveryContext.getUsedContentVersions(), getDatabase());
        logger.info("lastContentVersionVO:" + lastContentVersionVO);
        if(lastContentVersionVO != null)
          lastModifiedDateTime = lastContentVersionVO.getModifiedDateTime();
        logger.info("lastModifiedDateTime from cvVO:" + lastContentVersionVO.getModifiedDateTime());
      }
      catch (Exception e)
      {
        e.printStackTrace();
      }
      /*
      Iterator userContentVersionIterator = this.deliveryContext.getUsedContentVersions().iterator();
      int processed = 0;
      while(userContentVersionIterator.hasNext())
      {
        String usedContentVersion = (String)userContentVersionIterator.next(); 
        if(usedContentVersion != null && usedContentVersion.startsWith("contentVersion_"))
          {
            try
                {
              String versionId = usedContentVersion.substring(15);
              if(!versionId.equals("null") && !versionId.equals(""))
              {
                processed++;
                Integer contentVersionId = new Integer(versionId);
                //SmallestContentVersionVO contentVersion = ContentVersionController.getContentVersionController().getSmallestContentVersionVOWithId(contentVersionId, getDatabase());
                ContentVersionVO contentVersion = ContentVersionController.getContentVersionController().getSmallContentVersionVOWithId(contentVersionId, getDatabase());
                if(lastModifiedDateTime == null || contentVersion.getModifiedDateTime().after(lastModifiedDateTime))
                {
                  lastModifiedDateTime = contentVersion.getModifiedDateTime();
                  System.out.println("lastModifiedDateTime:" + lastModifiedDateTime);
                }
              }
                }
            catch (Exception e)
            {
              logger.warn("Could not use the versionId:" + usedContentVersion + " - reason:" + e.getMessage());
          }
          }
        if(lastModifiedDateTime != null)
        {
          long current = System.currentTimeMillis() - lastModifiedDateTime.getTime();
          if(processed > maxNumberOfVersionsForDerivedLastModifiedInLive || current < (1000 * 60 * 10))
            break;
        }
      }
      */
     
      if(lastModifiedDateTime != null)
      {
        logger.info("The page gets " + lastModifiedDateTime);
        this.deliveryContext.setLastModifiedDateTime(lastModifiedDateTime);
      }
    }
   
    long elapsedTime = t.getElapsedTime();
    RequestAnalyser.getRequestAnalyser().registerComponentStatistics("getLastModifiedDateTime", elapsedTime);
  }

  protected String decorateHeadAndPageWithVarsFromComponents(String pageString)
  {
    if(pageString.length() < 500000)
    {
      pageString = this.getTemplateController().decoratePage(pageString);
     
      StringBuilder sb = null;
      Timer t = new Timer();
      this.generateExtensionBundles(this.getTemplateController().getDeliveryContext().getScriptExtensionHeadBundles(), "text/javascript", "head");
      this.generateExtensionBundles(this.getTemplateController().getDeliveryContext().getScriptExtensionBodyBundles(), "text/javascript", "body");
      this.generateExtensionBundles(this.getTemplateController().getDeliveryContext().getCSSExtensionBundles(), "text/css", "head");
     
      List htmlHeadItems = this.getTemplateController().getDeliveryContext().getHtmlHeadItems();
      if(htmlHeadItems != null && htmlHeadItems.size() > 0)
      {
        int indexOfHeadEndTag = pageString.indexOf("</head");
        if(indexOfHeadEndTag == -1)
          indexOfHeadEndTag = pageString.indexOf("</HEAD");
 
        if(indexOfHeadEndTag != -1)
        {
          sb = new StringBuilder(pageString);
          String headerItems = "";
          Iterator htmlHeadItemsIterator = htmlHeadItems.iterator();
          while(htmlHeadItemsIterator.hasNext())
          {
            String value = (String)htmlHeadItemsIterator.next();
            //logger.info("headItem:" + value);
            headerItems = headerItems + value + "\n";
          }
          sb.insert(indexOfHeadEndTag, headerItems);
          //pageString = sb.toString();
        }
      }

      List<String> htmlBodyEndItems = this.getTemplateController().getDeliveryContext().getHtmlBodyEndItems();
      if(htmlBodyEndItems != null && htmlBodyEndItems.size() > 0)
      {
        if(sb == null)
          sb = new StringBuilder(pageString);

        int indexOfBodyEndTag = sb.indexOf("</body");
        if(indexOfBodyEndTag == -1)
          indexOfBodyEndTag = sb.indexOf("</BODY");
 
        if(indexOfBodyEndTag != -1)
        {
          String bodyItems = "";
          Iterator htmlBodyItemsIterator = htmlBodyEndItems.iterator();
          while(htmlBodyItemsIterator.hasNext())
          {
            String value = (String)htmlBodyItemsIterator.next();
            //logger.info("headItem:" + value);
            bodyItems = bodyItems + value + "\n";
          }
          sb.insert(indexOfBodyEndTag, bodyItems);
          //pageString = sb.toString();
        }
      }
      RequestAnalyser.getRequestAnalyser().registerComponentStatistics("pageInvoker", t.getElapsedTime());
     
      try
      {
        int lastModifiedDateTimeIndex;
        if(sb == null)
          lastModifiedDateTimeIndex = pageString.indexOf("<ig:lastModifiedDateTime");
        else
          lastModifiedDateTimeIndex = sb.indexOf("<ig:lastModifiedDateTime");
         
        //logger.info("OOOOOOOOOOOOO lastModifiedDateTimeIndex:" + lastModifiedDateTimeIndex);
        if(lastModifiedDateTimeIndex > -1)
        {
          if(sb == null)
            sb = new StringBuilder(pageString);

          int lastModifiedDateTimeEndIndex = sb.indexOf("</ig:lastModifiedDateTime>", lastModifiedDateTimeIndex);
 
          String tagInfo = sb.substring(lastModifiedDateTimeIndex, lastModifiedDateTimeEndIndex);
          //logger.info("tagInfo:" + tagInfo);
          String dateFormat = "yyyy-MM-dd HH:mm";
          int formatStartIndex = tagInfo.indexOf("format");
          if(formatStartIndex > -1)
          {
            int formatEndIndex = tagInfo.indexOf("\"", formatStartIndex + 8);
            if(formatEndIndex > -1)
              dateFormat = tagInfo.substring(formatStartIndex + 8, formatEndIndex);
          }
          //logger.info("dateFormat:" + dateFormat);
           
          String dateString = vf.formatDate(this.getTemplateController().getDeliveryContext().getLastModifiedDateTime(), this.getTemplateController().getLocale(), dateFormat);
          //logger.info("dateString:" + dateString);
          sb.replace(lastModifiedDateTimeIndex, lastModifiedDateTimeEndIndex + "</ig:lastModifiedDateTime>".length(), dateString);
          //logger.info("Replaced:" + lastModifiedDateTimeIndex + " to " + lastModifiedDateTimeEndIndex + "</ig:lastModifiedDateTime>".length() + " with " + dateString);
        }
      }
      catch (Exception e)
      {
        logger.error("Problem setting lastModifiedDateTime:" + e.getMessage(), e);
      }
     
      if(sb != null)
        pageString = sb.toString();     
    }
    else
    {
      if(logger.isInfoEnabled())
        logger.info("pageString was to large (" + pageString.length() + ") so the headers was not inserted.");
    }
   
    return pageString;
  }

  private void generateExtensionBundles(Map<String,Set<String>> extensionBundles, String contentType, String targetElement)
  {
    Timer t = new Timer();
   
    Set<String> bundledSignatures = new HashSet<String>();
   
    Iterator<String> scriptExtensionBundlesIterator = extensionBundles.keySet().iterator();
    while(scriptExtensionBundlesIterator.hasNext())
    {
      String bundleName = scriptExtensionBundlesIterator.next();
      if(logger.isInfoEnabled())
        logger.info("bundleName:" + bundleName);
     
      Set<String> scriptExtensionFileNames = extensionBundles.get(bundleName);
     
      if(scriptExtensionFileNames != null && scriptExtensionFileNames.size() > 0)
      {       
        String scriptBundle = "";

        int i = 0;
        String filePath = CmsPropertyHandler.getDigitalAssetPath0();
        while(filePath != null)
        {
          try
          {
            File extensionsDirectory = new File(filePath + File.separator + "extensions");
            extensionsDirectory.mkdirs();
           
            File extensionsBundleFile = new File(filePath + File.separator + "extensions" + File.separator + bundleName + ".js");
            if(contentType.equalsIgnoreCase("text/css"))
              extensionsBundleFile = new File(filePath + File.separator + "extensions" + File.separator + bundleName + ".css");
           
            if(!extensionsBundleFile.exists())
            { 
              if(logger.isInfoEnabled())
                logger.info("No script - generating:" + bundleName);
              if(scriptBundle.equals(""))
              {
                Iterator<String> scriptExtensionFileNamesIterator = scriptExtensionFileNames.iterator();
                while(scriptExtensionFileNamesIterator.hasNext())
                {
                  String scriptExtensionFileName = scriptExtensionFileNamesIterator.next();
                  if(logger.isInfoEnabled())
                    logger.info("scriptExtensionFileName:" + scriptExtensionFileName);
                  try
                  {
                    File file = new File(filePath + File.separator + scriptExtensionFileName);
                    String signature = "" + file.getName() + "_" + file.length();
                    if(logger.isInfoEnabled())
                      logger.info("Checking file:" + filePath + File.separator + scriptExtensionFileName);
                   
                    if(file.exists() && !bundledSignatures.contains(signature))
                    {
                      StringBuffer content = new StringBuffer(FileHelper.getFileAsStringOpt(file));
                      //Wonder what is the best signature..
                      bundledSignatures.add(signature);
                     
                      //If CSS we should change url:s to point to the original folder
                      if(contentType.equalsIgnoreCase("text/css"))
                      {
                        if(logger.isInfoEnabled())
                          logger.info("contentType:" + contentType);
                        String extensionPath = file.getPath().substring(extensionsDirectory.getPath().length() + 1, file.getPath().lastIndexOf("/") + 1);
                        if(logger.isInfoEnabled())
                          logger.info("extensionPath:" + extensionPath);
                       
                        int urlStartIndex = content.indexOf("url(");
                        while(urlStartIndex > -1)
                        {
                          if(content.charAt(urlStartIndex + 4) == '"' || content.charAt(urlStartIndex + 4) == '\'')
                            content.insert(urlStartIndex + 5, extensionPath);
                          else
                            content.insert(urlStartIndex + 4, extensionPath);
                          urlStartIndex = content.indexOf("url(", urlStartIndex + extensionPath.length());
                        }
                      } 
                      //logger.info("transformed content:" + content.substring(0, 500));

                      scriptBundle = scriptBundle + "\n\n" + content;
                    }
                    else
                    {
                      if(logger.isInfoEnabled())
                        logger.info("Not adding:" + signature + " as " + file.exists() + ":" + bundledSignatures.contains(signature));
                    }
                  }
                  catch (Exception e)
                  {
                    logger.warn("Error trying to parse file and bundle it (" + scriptExtensionFileName + "):" + e.getMessage());
                  }
                }
              }
             
              if(logger.isInfoEnabled())
                logger.info("scriptBundle:" + scriptBundle.length());
              if(scriptBundle != null && !scriptBundle.equals(""))
              {
                if(contentType.equalsIgnoreCase("text/javascript"))
                {
                  try
                  {
                    JSMin jsmin = new JSMin(new ByteArrayInputStream(scriptBundle.getBytes()), new FileOutputStream(extensionsBundleFile));
                    jsmin.jsmin();
                  }
                  catch (FileNotFoundException e)
                  {
                    e.printStackTrace();
                  }
                }
                else
                {
                  FileHelper.writeToFile(extensionsBundleFile, scriptBundle, false);
                }
                if(logger.isInfoEnabled())
                  logger.info("extensionsBundleFile:" + extensionsBundleFile.length());
              }
            }
           
            i++;
            filePath = CmsPropertyHandler.getProperty("digitalAssetPath." + i);
          }
          catch (Exception e)
          {
            logger.warn("Error trying to write bundled scripts:" + e.getMessage());
          }
        }
        try
        {
          SiteNodeVO siteNodeVO = NodeDeliveryController.getNodeDeliveryController(deliveryContext).getSiteNodeVO(getDatabase(), getTemplateController().getSiteNodeId());
          String dnsName = CmsPropertyHandler.getWebServerAddress();
          if(siteNodeVO != null)
          {
            RepositoryVO repositoryVO = RepositoryController.getController().getRepositoryVOWithId(siteNodeVO.getRepositoryId(), getDatabase());
            if(repositoryVO.getDnsName() != null && !repositoryVO.getDnsName().equals(""))
              dnsName = repositoryVO.getDnsName();
          }

          String bundleUrl = "";
          String bundleUrlTag = "";
         
          if(contentType.equalsIgnoreCase("text/javascript"))
          {
            bundleUrl = URLComposer.getURLComposer().composeDigitalAssetUrl(dnsName, "extensions", bundleName + ".js", deliveryContext);
            bundleUrlTag = "<script type=\"text/javascript\" src=\"" + bundleUrl + "\"></script>";
          }
          else if(contentType.equalsIgnoreCase("text/css"))
          {
            bundleUrl = URLComposer.getURLComposer().composeDigitalAssetUrl(dnsName, "extensions", bundleName + ".css", deliveryContext);
            bundleUrlTag = "<link href=\"" + bundleUrl + "\" rel=\"stylesheet\" type=\"text/css\" />";
          }

          if(targetElement.equalsIgnoreCase("head"))
            this.getTemplateController().getDeliveryContext().getHtmlHeadItems().add(bundleUrlTag);
          else
            this.getTemplateController().getDeliveryContext().getHtmlBodyEndItems().add(bundleUrlTag);
        }
        catch (Exception e)
        {
          logger.warn("Error trying  get assetBaseUrl:" + e.getMessage());
        }
      }

    }
    if(logger.isInfoEnabled())
      t.printElapsedTime("Generating bundles took")
  }
       
  /**
   * This method is used to allow pagecaching on a general level.
   */

  public void cachePage()
  {
   
  }
 
  public final DeliveryContext getDeliveryContext()
  {
    return deliveryContext;
  }

  public final HttpServletRequest getRequest()
  {
    return request;
  }

  public final HttpServletResponse getResponse()
  {
    return response;
  }

  public final TemplateController getTemplateController()
  {
    return templateController;
  }

  public String getPageString()
  {
    return pageString;
  }

  public void setPageString(String string)
  {
      if(string != null && this.deliveryContext.getTrimResponse())
        string = string.trim();

    pageString = string;
  }

 
  /**
   * Creates and returns a defaultContext, currently with the templateLogic
   * and if the portal support is enabled the portalLogic object.
   * (Added to avoid duplication of context creation in the concrete
   * implementations of pageInvokers)
   * @author robert
   * @return A default context with the templateLogic and portalLogic object in it.
   */
 
  public Map getDefaultContext()
  {
    Map context = new HashMap();
    context.put("templateLogic", getTemplateController());   
   
    // -- check if the portal is active
        String portalEnabled = CmsPropertyHandler.getEnablePortal() ;
        boolean active = ((portalEnabled != null) && portalEnabled.equals("true"));
    if (active)
    {
        PortalController pController = new PortalController(getRequest(), getResponse(), getTemplateController().getDeliveryContext());
        context.put(PortalController.NAME, pController);
        if(logger.isInfoEnabled())
        {
          logger.info("PortalController.NAME:" + PortalController.NAME);
          logger.info("pController:" + pController);
        }
    }
   
    return context;
  }
   
}
TOP

Related Classes of org.infoglue.deliver.invokers.PageInvoker

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.