/* ===============================================================================
*
* 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.applications.databeans;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.infoglue.cms.util.CmsPropertyHandler;
import org.infoglue.deliver.util.CacheController;
/**
* @author Mattias Bogeblad
*
* This class is used to store the context of a page and get and set information that is central to it.
* TODO - write more
*/
public class DeliveryContext implements UsageListener
{
private static final SimpleDateFormat HTTP_DATE_FORMAT = new SimpleDateFormat( "EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH );
private final static Logger logger = Logger.getLogger(DeliveryContext.class.getName());
public static final String META_INFO_BINDING_NAME = "Meta information";
public static final String TEMPLATE_ATTRIBUTE_NAME = "Template";
public static final String TITLE_ATTRIBUTE_NAME = "Title";
public static final String NAV_TITLE_ATTRIBUTE_NAME = "NavigationTitle";
/*
protected static final String DISABLE_PAGE_CACHE_ATTRIBUTE_NAME = "DisablePageCache";
protected static final String PAGE_CONTENT_TYPE_ATTRIBUTE_NAME = "ContentType";
protected static final String ENABLE_PAGE_PROTECTION_ATTRIBUTE_NAME = "ProtectPage";
protected static final String DISABLE_EDIT_ON_SIGHT_ATTRIBUTE_NAME = "DisableEditOnSight";
*/
public static final boolean USE_LANGUAGE_FALLBACK = true;
public static final boolean DO_NOT_USE_LANGUAGE_FALLBACK = false;
public static final boolean USE_INHERITANCE = true;
public static final boolean DO_NOT_USE_INHERITANCE = false;
//These are the standard parameters which uniquely defines which page to show.
private Integer siteNodeId = null;
private Integer contentId = null;
private Integer languageId = null;
//This sets the content type
private String contentType = null;
//Lets one disable caching of this page if needed for some requests.
private boolean disablePageCache = false;
//This decides if to show a minimalistic version of the page structure - not render all compoents etc.
private boolean showSimple = false;
//This parameter are set if you want to access a certain repository startpage
private String repositoryName = null;
private String pageKey = null;
private String pagePath = null;
private HttpServletResponse httpServletResponse = null;
private HttpServletRequest httpServletRequest = null;
//private Session session = null;
//private InfoGlueAbstractAction infoglueAbstractAction = null;
//This section has control over what contents and sitenodes are used where so the pagecache can be selectively updated.
private List usageListeners = new ArrayList();
private Set usedContents = Collections.synchronizedSet(new HashSet());
private Set usedContentVersions = Collections.synchronizedSet(new HashSet());
private Set usedSiteNodes = Collections.synchronizedSet(new HashSet());
private Set usedSiteNodeVersions = Collections.synchronizedSet(new HashSet());
private Set usedPageMetaInfoContentVersionIdSet = Collections.synchronizedSet(new HashSet());
private Set usedPageComponentsMetaInfoContentVersionIdSet = Collections.synchronizedSet(new HashSet());
private Date lastModifiedDateTime = null;
private boolean registerLastModifiedDate = false;
private boolean cachedResponse = false;
//private InfoGluePrincipal infoGluePrincipal = null;
//This variable sets if all urls generated should contain the server name etc.
private boolean useFullUrl = false;
//The variable sets if url generation should skip niceUris
private boolean disableNiceUri = false;
//The variable sets if the response string should be trimmed to avoid problems with xml-responses etc.
private boolean trimResponse = false;
//The variable sets if the full page should be rendered once more after all components have been rendered.
private boolean evaluateFullPage = true;
//The variable sets if the rendering should consider publish/expire dates when validating contents. Used in preview actions.
private boolean validateOnDates = false;
//This variable controls if digitalAssetUrl:s generated are directed to the DownloadAsset.action
private boolean useDownloadAction = false;
private Integer pageCacheTimeout = null;
//This variable controls if tags and logic should consider the logged in editor principal even if the ordinary principal is anonymous when checking for access rights etc.
private boolean considerEditorInDecoratedMode = true;
//The variable sets if methods should skip using caches if possible
private boolean defeatCaches = false;
private String operatingMode = null;
private Map pageAttributes = new HashMap();
private List<String> htmlHeadItems = new ArrayList<String>();
private List<String> htmlBodyEndItems = new ArrayList<String>();
private Map<String, Set<String>> scriptExtensionHeadBundles = new HashMap<String, Set<String>>();
private Map<String, Set<String>> scriptExtensionBodyBundles = new HashMap<String, Set<String>>();
private Map<String, Set<String>> cssExtensionBundles = new HashMap<String, Set<String>>();
private Map httpHeaders = new HashMap();
//Possible place to put debug data for a request. It's limiting and should only be used for compact targeted debug.
private boolean debugMode = false;
private String debugInformation = "";
public static DeliveryContext getDeliveryContext()
{
return new DeliveryContext();
}
public static DeliveryContext getDeliveryContext(boolean registerLastModifiedDate)
{
return new DeliveryContext(registerLastModifiedDate);
}
private DeliveryContext()
{
this(false);
}
private DeliveryContext(boolean registerLastModifiedDate)
{
this.registerLastModifiedDate = registerLastModifiedDate;
}
public void clear()
{
try
{
this.htmlHeadItems.clear();
this.htmlBodyEndItems.clear();
this.httpHeaders.clear();
this.httpServletRequest = null;
this.httpServletResponse = null;
this.pageAttributes.clear();
this.usageListeners.clear();
this.usedContents.clear();
this.usedContentVersions.clear();
this.usedPageMetaInfoContentVersionIdSet.clear();
this.usedSiteNodes.clear();
this.usedSiteNodeVersions.clear();
this.usedContents = null;
this.usedContentVersions = null;
this.usedPageMetaInfoContentVersionIdSet = null;
this.usedSiteNodes = null;
this.usedSiteNodeVersions = null;
this.debugInformation = "";
}
catch (Exception e)
{
e.printStackTrace();
}
}
/*
public static DeliveryContext getDeliveryContext(InfoGluePrincipal infoGluePrincipal)
{
return new DeliveryContext(infoGluePrincipal);
}
private DeliveryContext(InfoGluePrincipal infoGluePrincipal)
{
this.infoGluePrincipal = infoGluePrincipal;
}
*/
public java.lang.Integer getSiteNodeId()
{
return this.siteNodeId;
}
public void setSiteNodeId(Integer siteNodeId)
{
this.siteNodeId = siteNodeId;
}
public Integer getContentId()
{
return this.contentId;
}
public void setContentId(Integer contentId)
{
this.contentId = contentId;
}
public Integer getLanguageId()
{
return this.languageId;
}
public void setLanguageId(Integer languageId)
{
this.languageId = languageId;
}
public String getRepositoryName()
{
return this.repositoryName;
}
public void setRepositoryName(String repositoryName)
{
this.repositoryName = repositoryName;
}
public String getPageKey()
{
return this.pageKey;
}
public String getPagePath()
{
return this.pagePath;
}
public void setPageKey(String pageKey)
{
this.pageKey = pageKey;
}
public void setPagePath(String pagePath)
{
this.pagePath = pagePath;
}
/*
public InfoGluePrincipal getPrincipal()
{
return this.infoGluePrincipal;
}
*/
public String toString()
{
StringBuffer sb = new StringBuffer();
sb.append("siteNodeId:" + this.siteNodeId);
sb.append("languageId:" + this.languageId);
sb.append("contentId:" + this.contentId);
//sb.append("InfoGluePrincipal:" + this.infoGluePrincipal);
return sb.toString();
}
/*
public Session getSession()
{
return this.session;
}
public void setSession(Session session)
{
this.session = session;
}
public InfoGlueAbstractAction getInfoGlueAbstractAction()
{
return infoglueAbstractAction;
}
public void setInfoGlueAbstractAction(InfoGlueAbstractAction action)
{
infoglueAbstractAction = action;
}
*/
public HttpServletRequest getHttpServletRequest()
{
return httpServletRequest;
}
public void setHttpServletRequest(HttpServletRequest httpServletRequest)
{
this.httpServletRequest = httpServletRequest;
}
public HttpServletResponse getHttpServletResponse()
{
return httpServletResponse;
}
public void setHttpServletResponse(HttpServletResponse httpServletResponse)
{
this.httpServletResponse = httpServletResponse;
}
public void addUsedContent(String usedContent)
{
this.usedContents.add(usedContent);
if(usedContent.indexOf("_", 8) > -1)
this.usedContents.add(usedContent.substring(0, usedContent.indexOf("_", 8)));
try
{
Iterator iterator = this.getUsageListeners().iterator();
while(iterator.hasNext())
{
UsageListener usageListener = (UsageListener)iterator.next();
usageListener.addUsedContent(usedContent);
}
}
catch(Exception e)
{
logger.warn("Sync issue when adding usedContent:" + e.getMessage());
}
}
public void addUsedSiteNode(String usedSiteNode)
{
this.usedSiteNodes.add(usedSiteNode);
try
{
Iterator iterator = this.getUsageListeners().iterator();
while(iterator.hasNext())
{
UsageListener usageListener = (UsageListener)iterator.next();
usageListener.addUsedSiteNode(usedSiteNode);
}
}
catch(Exception e)
{
logger.warn("Sync issue when adding usedSiteNode:" + e.getMessage());
}
}
public void addUsedContentVersion(String usedContentVersion)
{
this.usedContentVersions.add(usedContentVersion);
try
{
Iterator iterator = this.getUsageListeners().iterator();
while(iterator.hasNext())
{
UsageListener usageListener = (UsageListener)iterator.next();
usageListener.addUsedContentVersion(usedContentVersion);
}
}
catch(Exception e)
{
logger.warn("Sync issue when adding usedContentVersion:" + e.getMessage());
}
}
public void addUsedSiteNodeVersion(String usedSiteNodeVersion)
{
this.usedSiteNodeVersions.add(usedSiteNodeVersion);
try
{
Iterator iterator = this.getUsageListeners().iterator();
while(iterator.hasNext())
{
UsageListener usageListener = (UsageListener)iterator.next();
usageListener.addUsedSiteNodeVersion(usedSiteNodeVersion);
}
}
catch(Exception e)
{
logger.warn("Sync issue when adding usedSiteNodeVersion:" + e.getMessage());
}
}
public String[] getAllUsedEntities()
{
List list = new ArrayList();
list.addAll(this.usedContents);
list.addAll(this.usedContentVersions);
list.addAll(this.usedSiteNodes);
list.addAll(this.usedSiteNodeVersions);
Object[] array = list.toArray();
String[] groups = new String[array.length];
for(int i=0; i<array.length; i++)
groups[i] = array[i].toString();
return groups;
}
public List<String> getAllUsedEntitiesAsSet()
{
List<String> set = new ArrayList<String>();
set.addAll(this.usedContents);
set.addAll(this.usedContentVersions);
set.addAll(this.usedSiteNodes);
set.addAll(this.usedSiteNodeVersions);
return set;
}
public List getUsageListeners()
{
return usageListeners;
}
public boolean getShowSimple()
{
return showSimple;
}
public void setShowSimple(boolean showSimple)
{
this.showSimple = showSimple;
}
public String getContentType()
{
return contentType;
}
public void setContentType(String contentType)
{
this.contentType = contentType;
}
public boolean getDisablePageCache()
{
return disablePageCache;
}
public void setDisablePageCache(boolean disablePageCache)
{
this.disablePageCache = disablePageCache;
}
public boolean getUseFullUrl()
{
return useFullUrl;
}
public void setUseFullUrl(boolean useFullUrl)
{
this.useFullUrl = useFullUrl;
}
public boolean getDisableNiceUri()
{
return this.disableNiceUri;
}
public void setDisableNiceUri(boolean disableNiceUri)
{
this.disableNiceUri = disableNiceUri;
}
public boolean getTrimResponse()
{
return this.trimResponse;
}
public void setTrimResponse(boolean trimResponse)
{
this.trimResponse = trimResponse;
}
public boolean getEvaluateFullPage()
{
return evaluateFullPage;
}
public void setEvaluateFullPage(boolean evaluateFullPage)
{
this.evaluateFullPage = evaluateFullPage;
}
public void setDefeatCaches(boolean defeatCaches, Map<Class, List<Object>> entities)
{
this.defeatCaches = defeatCaches;
CacheController.setDefeatCaches(defeatCaches, entities);
}
public boolean getDefeatCaches()
{
return this.defeatCaches;
}
public boolean getValidateOnDates()
{
return validateOnDates;
}
public void setValidateOnDates(boolean validateOnDates)
{
this.validateOnDates = validateOnDates;
}
public void setConsiderEditorInDecoratedMode(boolean considerEditorInDecoratedMode)
{
this.considerEditorInDecoratedMode = considerEditorInDecoratedMode;
}
public boolean getConsiderEditorInDecoratedMode()
{
return this.considerEditorInDecoratedMode;
}
public Set getUsedPageMetaInfoContentVersionIdSet()
{
return usedPageMetaInfoContentVersionIdSet;
}
public void addUsedPageComponentsMetaInfoContentVersionId(Integer contentVersionId)
{
if(contentVersionId == null)
logger.warn("Null was sent in...");
else
this.usedPageComponentsMetaInfoContentVersionIdSet.add(contentVersionId);
}
public Set getUsedPageComponentsMetaInfoContentVersionIdSet()
{
return usedPageComponentsMetaInfoContentVersionIdSet;
}
public Map getPageAttributes()
{
return pageAttributes;
}
public boolean getUseDownloadAction()
{
return useDownloadAction;
}
public void setUseDownloadAction(boolean useDownloadAction)
{
this.useDownloadAction = useDownloadAction;
}
public List<String> getHtmlHeadItems()
{
return htmlHeadItems;
}
public List<String> getHtmlBodyEndItems()
{
return htmlBodyEndItems;
}
public void addHtmlHeadItem(String item, boolean prepend)
{
if(!getHtmlHeadItems().contains(item))
{
if(prepend) getHtmlHeadItems().add(0, item);
else getHtmlHeadItems().add(item);
}
}
public void addHtmlBodyEndItem(String item, boolean prepend)
{
if(!getHtmlBodyEndItems().contains(item))
{
if(prepend) getHtmlBodyEndItems().add(0, item);
else getHtmlBodyEndItems().add(item);
}
}
public Map getHttpHeaders()
{
return httpHeaders;
}
public Map<String,Set<String>> getScriptExtensionHeadBundles()
{
return scriptExtensionHeadBundles;
}
public Map<String,Set<String>> getScriptExtensionBodyBundles()
{
return scriptExtensionBodyBundles;
}
public Map<String,Set<String>> getCSSExtensionBundles()
{
return cssExtensionBundles;
}
/*
* Adds a file to the named bundle
*/
public void addScriptExtensionHeadBundleFile(String bundleName, String filePath)
{
Set<String> files = scriptExtensionHeadBundles.get(bundleName);
if(files == null)
{
files = new HashSet<String>();
scriptExtensionHeadBundles.put(bundleName, files);
}
files.add(filePath);
}
/*
* Adds a file to the named bundle
*/
public void addScriptExtensionBodyBundleFile(String bundleName, String filePath)
{
Set<String> files = scriptExtensionBodyBundles.get(bundleName);
if(files == null)
{
files = new HashSet<String>();
scriptExtensionBodyBundles.put(bundleName, files);
}
files.add(filePath);
}
/*
* Adds a file to the named bundle
*/
public void addCSSExtensionBundleFile(String bundleName, String filePath)
{
Set<String> files = cssExtensionBundles.get(bundleName);
if(files == null)
{
files = new HashSet<String>();
cssExtensionBundles.put(bundleName, files);
}
files.add(filePath);
}
public Object getExtraData()
{
Map extraData = new HashMap();
Map newHeaders = new HashMap();
newHeaders.putAll(getHttpHeaders());
extraData.put("contentType", this.getContentType());
extraData.put("headers", newHeaders);
//extraData.put("pageAttributes", this.getPageAttributes());
extraData.put("lastModifiedDateTime", this.lastModifiedDateTime);
extraData.put("pageCacheTimeout", this.pageCacheTimeout);
return extraData;
}
public void populateExtraData(Map extraData)
{
String contentType = (String)extraData.get("contentType");
if(contentType != null)
this.setContentType(contentType);
Map headers = (Map)extraData.get("headers");
if(headers != null)
this.getHttpHeaders().putAll(headers);
/*
Map pageAttributes = (Map)extraData.get("pageAttributes");
if(pageAttributes != null)
this.getPageAttributes().putAll(pageAttributes);
*/
Date lastModifiedDateTime = (Date)extraData.get("lastModifiedDateTime");
if(lastModifiedDateTime != null && (this.lastModifiedDateTime == null || this.lastModifiedDateTime.before(lastModifiedDateTime)))
{
this.lastModifiedDateTime = lastModifiedDateTime;
}
if (this.lastModifiedDateTime != null)
{
this.getHttpHeaders().put("Last-Modified", HTTP_DATE_FORMAT.format(this.lastModifiedDateTime));
}
Integer pageCacheTimeout = (Integer)extraData.get("pageCacheTimeout");
if(pageCacheTimeout != null)
this.pageCacheTimeout = pageCacheTimeout;
}
public Date getLastModifiedDateTime()
{
return lastModifiedDateTime;
}
public void setLastModifiedDateTime(Date lastModifiedDateTime)
{
this.lastModifiedDateTime = lastModifiedDateTime;
getHttpHeaders().put("Last-Modified", HTTP_DATE_FORMAT.format(lastModifiedDateTime));
}
public String getOperatingMode()
{
if(this.operatingMode == null)
{
//logger.info("No local operating mode. Using global:" + CmsPropertyHandler.getOperatingMode());
this.operatingMode = CmsPropertyHandler.getOperatingMode();
}
//logger.info("Returning " + this.operatingMode);
return this.operatingMode;
}
public void setOperatingMode(String operatingMode)
{
this.operatingMode = operatingMode;
}
public Integer getPageCacheTimeout()
{
return pageCacheTimeout;
}
public void setPageCacheTimeout(Integer pageCacheTimeout)
{
this.pageCacheTimeout = pageCacheTimeout;
}
public Set getUsedContentVersions()
{
return Collections.unmodifiableSet(usedContentVersions);
}
public Set getUsedContents()
{
return Collections.unmodifiableSet(usedContents);
}
/**
* This method returns the exact full url excluding query string from the original request - not modified
* @return
*/
public String getOriginalURL()
{
String originalRequestURL = this.getHttpServletRequest().getParameter("originalRequestURL");
if(originalRequestURL == null || originalRequestURL.length() == 0)
originalRequestURL = this.getHttpServletRequest().getRequestURL().toString();
return originalRequestURL;
}
/**
* This method returns the exact querystring from the original request - not modified
* @return
*/
public String getOriginalQueryString()
{
String originalQueryString = this.getHttpServletRequest().getParameter("originalQueryString");
if(originalQueryString == null || originalQueryString.length() == 0)
originalQueryString = this.getHttpServletRequest().getQueryString();
return originalQueryString;
}
/**
* This method returns the exact full url from the original request - not modified
* @return
*/
public String getOriginalFullURL()
{
String originalRequestURL = getOriginalURL();
String originalQueryString = getOriginalQueryString();
return originalRequestURL + (originalQueryString == null ? "" : "?" + originalQueryString);
}
/**
* This method returns the debug information
*/
public String getDebugInformation()
{
return this.debugInformation;
}
/**
* This method adds debug information for eventual later use
*/
public void addDebugInformation(String debug)
{
if(this.debugMode)
this.debugInformation = this.debugInformation + "\n" + debug;
}
/**
* This method adds debug information for eventual later use
*/
public void setDebugMode(boolean debugMode)
{
this.debugMode = debugMode;
}
/**
* This method adds debug information for eventual later use
*/
public void resetDebugMode()
{
this.debugInformation = "";
}
/**
* @return the cachedResponse
*/
public boolean getIsCachedResponse()
{
return cachedResponse;
}
/**
* @param cachedResponse the cachedResponse to set
*/
public void setIsCachedResponse(boolean cachedResponse)
{
this.cachedResponse = cachedResponse;
}
private Boolean languageCanBeOverridden = false;
private Integer sessionLanguageId = -1;
private List<Integer> acceptableLanguageIds = new ArrayList<Integer>();
public void setLanguageCanBeOverridden(boolean languageCanBeOverridden)
{
this.languageCanBeOverridden = languageCanBeOverridden;
}
public Boolean getLanguageCanBeOverridden()
{
return this.languageCanBeOverridden;
}
public Integer getSessionLanguageId()
{
return sessionLanguageId;
}
public void setSessionLanguageId(Integer sessionLanguageId)
{
this.sessionLanguageId = sessionLanguageId;
}
public List<Integer> getAcceptableLanguageIds()
{
return acceptableLanguageIds;
}
public void setAcceptableLanguageIds(List<Integer> acceptableLanguageIds)
{
this.acceptableLanguageIds = acceptableLanguageIds;
}
}