SEOServiceImpl.java
/*
* Copyright (C) 2003-2011 eXo Platform SAS.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even 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, see<http://www.gnu.org/licenses/>.
*/
package org.exoplatform.services.seo.impl;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Session;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.exoplatform.container.xml.InitParams;
import org.exoplatform.container.xml.ObjectParameter;
import org.exoplatform.ecm.utils.MessageDigester;
import org.exoplatform.management.annotations.Managed;
import org.exoplatform.management.annotations.ManagedDescription;
import org.exoplatform.management.annotations.ManagedName;
import org.exoplatform.portal.application.PortalRequestContext;
import org.exoplatform.portal.webui.util.Util;
import org.exoplatform.services.cache.CacheService;
import org.exoplatform.services.cache.ExoCache;
import org.exoplatform.services.jcr.config.WorkspaceEntry;
import org.exoplatform.services.jcr.core.ManageableRepository;
import org.exoplatform.services.jcr.ext.common.SessionProvider;
import org.exoplatform.services.seo.PageMetadataModel;
import org.exoplatform.services.seo.SEOConfig;
import org.exoplatform.services.seo.SEOService;
import org.exoplatform.services.wcm.portal.LivePortalManagerService;
import org.exoplatform.services.wcm.utils.WCMCoreUtils;
import org.apache.commons.lang.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* Created by The eXo Platform SAS Author : eXoPlatform exo@exoplatform.com Jun
* 17, 2011
*/
public class SEOServiceImpl implements SEOService {
private ExoCache<String, Object> cache;
public static final String EMPTY_CACHE_ENTRY = "EMPTY";
public static String METADATA_BASE_PATH = "SEO";
final static public String LANGUAGES = "seo-languages";
public static String METADATA_PAGE_PATH = "pages";
public static String METADATA_CONTENT_PATH = "contents";
public static String SITEMAP_NAME = "sitemaps";
public static String ROBOTS_NAME = "robots";
private static String PUBLIC_MODE = "public";
private static String PRIVATE_MODE = "private";
private final static String CACHE_NAME = "ecms.seo";
private List<String> robotsindex = new ArrayList<String>();
private List<String> robotsfollow = new ArrayList<String>();
private List<String> frequency = new ArrayList<String>();
private SEOConfig seoConfig = null;
private boolean isCached = true;
/**
* Constructor method
*
* @param initParams
* The initial parameters
* @throws Exception
*/
public SEOServiceImpl(InitParams initParams) throws Exception {
ObjectParameter param = initParams.getObjectParam("seo.config");
if (param != null) {
seoConfig = (SEOConfig) param.getObject();
robotsindex = seoConfig.getRobotsIndex();
robotsfollow = seoConfig.getRobotsFollow();
frequency = seoConfig.getFrequency();
}
cache = WCMCoreUtils.getService(CacheService.class).getCacheInstance(
CACHE_NAME);
}
/**
*{@inheritDoc}
*/
public List<String> getRobotsIndexOptions() {
return robotsindex;
}
/**
* {@inheritDoc}
*/
public List<String> getRobotsFollowOptions() {
return robotsfollow;
}
/**
* {@inheritDoc}
*/
public List<String> getFrequencyOptions() {
return frequency;
}
/**
* {@inheritDoc}
*/
public void storeMetadata(PageMetadataModel metaModel, String portalName,
boolean onContent, String language) throws Exception {
String uri = metaModel.getUri();
String cachedHash = getPageOrContentCacheKey(uri, language);
if (cache.get(cachedHash) != null) {
cache.remove(cachedHash);
}
String pageReference = metaModel.getPageReference();
cachedHash = getPageOrContentCacheKey(metaModel.getPageReference(), language);
if (cache.get(cachedHash) != null) {
cache.remove(cachedHash);
}
// Inherit from parent page
/*
* if(!onContent) { if(metaModel.getPageParent() != null &&
* metaModel.getPageParent().length() > 0) { PageMetadataModel parentModel =
* this.getPageMetadata(metaModel.getPageParent()); if(parentModel != null)
* { metaModel = parentModel; metaModel.setUri(uri);
* metaModel.setPageReference(pageReference); } } }
*/
String title = metaModel.getTitle();
String keyword = metaModel.getKeywords();
String description = metaModel.getDescription();
String robots = metaModel.getRobotsContent();
String fullStatus = metaModel.getFullStatus();
boolean sitemap = metaModel.getSitemap();
float priority = metaModel.getPriority();
String frequency = metaModel.getFrequency();
SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
Session session = null;
LivePortalManagerService livePortalManagerService = WCMCoreUtils
.getService(LivePortalManagerService.class);
Node dummyNode = livePortalManagerService.getLivePortal(sessionProvider,
portalName);
session = dummyNode.getSession();
if (!dummyNode.hasNode(METADATA_BASE_PATH)) {
dummyNode.addNode(METADATA_BASE_PATH);
session.save();
}
//Store robots data
updateRobots(dummyNode, portalName);
// Store sitemap data
Node node = null;
if (onContent) {
node = session.getNodeByUUID(uri);
if (!node.isNodeType("mix:referenceable")) {
node.addMixin("mix:referenceable");
}
} else {
session = sessionProvider.getSession("portal-system", WCMCoreUtils
.getRepository());
String uuid = Util.getUIPortal().getSelectedUserNode().getId();
node = session.getNodeByUUID(uuid);
if (!node.isNodeType("exo:seoMetadata")) {
node.addMixin("exo:seoMetadata");
}
}
Node languageNode = null;
if(node.hasNode(LANGUAGES))
languageNode = node.getNode(LANGUAGES);
else
languageNode = node.addNode(LANGUAGES);
if(languageNode.canAddMixin("exo:hiddenable"))
languageNode.addMixin("exo:hiddenable");
session.save();
Node seoNode = null;
if(languageNode.hasNode(language)) seoNode = languageNode.getNode(language);
else seoNode = languageNode.addNode(language);
if (!seoNode.isNodeType("mix:referenceable")) {
seoNode.addMixin("mix:referenceable");
}
if (seoNode.isNodeType("exo:pageMetadata")) {
seoNode.setProperty("exo:metaKeywords", keyword);
seoNode.setProperty("exo:metaDescription", description);
seoNode.setProperty("exo:metaFully", fullStatus);
if (!onContent) {
seoNode.setProperty("exo:metaTitle", title);
seoNode.setProperty("exo:metaRobots", robots);
seoNode.setProperty("exo:metaSitemap", sitemap);
seoNode.setProperty("exo:metaPriority", priority);
seoNode.setProperty("exo:metaFrequency", frequency);
updateSiteMap(uri, priority, frequency, sitemap, portalName);
}
String hash = null;
if (onContent)
hash = cachedHash;
else
hash = getPageOrContentCacheKey(pageReference, language);
if (hash != null)
cache.put(hash, metaModel);
} else {
String hash = null;
seoNode.addMixin("exo:pageMetadata");
seoNode.setProperty("exo:metaKeywords", keyword);
seoNode.setProperty("exo:metaDescription", description);
seoNode.setProperty("exo:metaFully", fullStatus);
if (onContent) {
seoNode.setProperty("exo:metaUri", seoNode.getUUID());
hash = getHash(seoNode.getUUID() + language);
} else {
seoNode.setProperty("exo:metaTitle", title);
seoNode.setProperty("exo:metaUri", pageReference);
seoNode.setProperty("exo:metaRobots", robots);
seoNode.setProperty("exo:metaSitemap", sitemap);
seoNode.setProperty("exo:metaPriority", priority);
seoNode.setProperty("exo:metaFrequency", frequency);
updateSiteMap(uri, priority, frequency, sitemap, portalName);
hash = getPageOrContentCacheKey(pageReference, language);
}
if (hash != null)
cache.put(hash, metaModel);
}
session.save();
}
private String getPageOrContentCacheKey(String uri, String language) throws Exception {
return getHash(uri + language);
}
public String getState(String path, String language, boolean onContent) throws Exception{
String state = "Empty";
Node node = null;
String hash = null;
PageMetadataModel metaModel = null;
if(onContent) {
node = getContentNode(path);
hash = node == null ? StringUtils.EMPTY : getPageOrContentCacheKey(node.getUUID(), language);
metaModel = (PageMetadataModel) getCachedEntry(hash, false);
if(metaModel != null) return metaModel.getFullStatus();
} else {
hash = getPageOrContentCacheKey(path, language);
metaModel = (PageMetadataModel) getCachedEntry(hash, true);
if (isNullObject(metaModel)) {
return null;
}
if(metaModel != null) return metaModel.getFullStatus();
SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
Session session = sessionProvider.getSession("portal-system",
WCMCoreUtils.getRepository());
String uuid = Util.getUIPortal().getSelectedUserNode().getId();
node = session.getNodeByUUID(uuid);
}
if(node.hasNode(LANGUAGES+"/"+language)) {
Node seoNode = node.getNode(LANGUAGES+"/"+language);
if (seoNode.isNodeType("exo:pageMetadata") && seoNode.hasProperty("exo:metaFully"))
return seoNode.getProperty("exo:metaFully").getString();
}
return state;
}
private boolean isNullObject(PageMetadataModel metaModel) {
return metaModel == PageMetadataModel.NULL_PAGE_METADATA_MODEL;
}
private Object getCachedEntry(String hash, boolean cacheNull) {
Object object = cache.get(hash);
if (cacheNull) {
if( object == null) {
cache.put(hash, EMPTY_CACHE_ENTRY);
} else if(EMPTY_CACHE_ENTRY.equals(object)) {
return PageMetadataModel.NULL_PAGE_METADATA_MODEL;
}
}
return object;
}
public PageMetadataModel getMetadata(ArrayList<String> params,
String pageReference, String language) throws Exception {
PageMetadataModel metaModel = null;
if (params != null) {
metaModel = getContentMetadata(params, language);
if(metaModel == null) metaModel = getPageMetadata(pageReference, language);
} else {
metaModel = getPageMetadata(pageReference, language);
}
return metaModel;
}
/**
* {@inheritDoc}
*/
public PageMetadataModel getContentMetadata(ArrayList<String> params, String language)
throws Exception {
PageMetadataModel metaModel = null;
String pageUri = null;
Node contentNode = null;
for (int i = 0; i < params.size(); i++) {
contentNode = this.getContentNode(params.get(i).toString());
if (contentNode != null)
break;
}
if (contentNode == null)
return null;
if (!contentNode.isNodeType("mix:referenceable")) {
contentNode.addMixin("mix:referenceable");
}
String hash = getPageOrContentCacheKey(contentNode.getUUID(), language);
metaModel = (PageMetadataModel) getCachedEntry(hash, false);
if (metaModel == null && contentNode.hasNode(LANGUAGES+"/"+language)) {
//Getting seo node by language
Node seoNode = contentNode.getNode(LANGUAGES+"/"+language);
if (!seoNode.isNodeType("mix:referenceable")) {
seoNode.addMixin("mix:referenceable");
}
if (seoNode.isNodeType("exo:pageMetadata")) {
metaModel = new PageMetadataModel();
metaModel.setUri(pageUri);
if (seoNode.hasProperty("exo:metaKeywords"))
metaModel.setKeywords((seoNode.getProperty("exo:metaKeywords"))
.getString());
if (seoNode.hasProperty("exo:metaDescription"))
metaModel.setDescription((seoNode
.getProperty("exo:metaDescription")).getString());
if (seoNode.hasProperty("exo:metaRobots"))
metaModel
.setRobotsContent((seoNode.getProperty("exo:metaRobots"))
.getString());
if (seoNode.hasProperty("exo:metaSitemap"))
metaModel.setSiteMap(Boolean.parseBoolean((seoNode
.getProperty("exo:metaSitemap")).getString()));
if (seoNode.hasProperty("exo:metaPriority"))
metaModel.setPriority(Long.parseLong((seoNode
.getProperty("exo:metaPriority")).getString()));
if (seoNode.hasProperty("exo:metaFrequency"))
metaModel.setFrequency((seoNode.getProperty("exo:metaFrequency"))
.getString());
if (seoNode.hasProperty("exo:metaFully"))
metaModel.setFullStatus((seoNode.getProperty("exo:metaFully"))
.getString());
cache.put(hash, metaModel);
}
}
return metaModel;
}
/**
* {@inheritDoc}
*/
public PageMetadataModel getPageMetadata(String pageUri, String language) throws Exception {
PageMetadataModel metaModel = null;
String hash = getPageOrContentCacheKey(pageUri, language);
metaModel = (PageMetadataModel) getCachedEntry(hash, true);
if (isNullObject(metaModel)) {
return null;
}
if (metaModel == null) {
SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
Session session = sessionProvider.getSession("portal-system",
WCMCoreUtils.getRepository());
String uuid = Util.getUIPortal().getSelectedUserNode().getId();
Node pageNode = session.getNodeByUUID(uuid);
if (pageNode != null && pageNode.hasNode(LANGUAGES+"/"+language)) {
Node seoNode = pageNode.getNode(LANGUAGES+"/"+language);
if(seoNode.isNodeType("exo:pageMetadata")) {
metaModel = new PageMetadataModel();
if (seoNode.hasProperty("exo:metaTitle"))
metaModel.setTitle((seoNode.getProperty("exo:metaTitle")).getString());
if (seoNode.hasProperty("exo:metaKeywords"))
metaModel.setKeywords((seoNode.getProperty("exo:metaKeywords"))
.getString());
if (seoNode.hasProperty("exo:metaDescription"))
metaModel
.setDescription((seoNode.getProperty("exo:metaDescription"))
.getString());
if (seoNode.hasProperty("exo:metaRobots"))
metaModel.setRobotsContent((seoNode.getProperty("exo:metaRobots"))
.getString());
if (seoNode.hasProperty("exo:metaSitemap"))
metaModel.setSiteMap(Boolean.parseBoolean((seoNode
.getProperty("exo:metaSitemap")).getString()));
if (seoNode.hasProperty("exo:metaPriority"))
metaModel.setPriority(Long.parseLong((seoNode
.getProperty("exo:metaPriority")).getString()));
if (seoNode.hasProperty("exo:metaFrequency"))
metaModel.setFrequency((seoNode.getProperty("exo:metaFrequency"))
.getString());
if (seoNode.hasProperty("exo:metaFully"))
metaModel.setFullStatus((seoNode.getProperty("exo:metaFully"))
.getString());
cache.put(hash, metaModel);
}
}
}
return metaModel;
}
public List<Locale> getSEOLanguages(String portalName, String seoPath, boolean onContent) throws Exception {
List<Locale> languages = new ArrayList<Locale>();
Node languagesNode = null;
if(onContent) {
Node contentNode = null;
contentNode = getContentNode(seoPath);
if (contentNode != null && contentNode.hasNode(LANGUAGES)) languagesNode = contentNode.getNode(LANGUAGES);
} else {
SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
Session session = sessionProvider.getSession("portal-system",
WCMCoreUtils.getRepository());
String uuid = Util.getUIPortal().getSelectedUserNode().getId();
Node pageNode = session.getNodeByUUID(uuid);
if (pageNode != null && pageNode.hasNode(LANGUAGES)) languagesNode = pageNode.getNode(LANGUAGES);
}
if(languagesNode != null) {
NodeIterator iter = languagesNode.getNodes();
while(iter.hasNext()) {
String lang = iter.nextNode().getName();
String[] arr = lang.split("_");
if(arr.length > 1) {
languages.add(new Locale(arr[0],arr[1]));
} else languages.add(new Locale(lang));
}
Collections.sort(languages, new SEOItemComparator());
return languages;
}
return languages;
}
class SEOItemComparator implements Comparator<Locale> {
@Override
public int compare(Locale locale1, Locale locale2) {
return locale1.getDisplayName().compareTo(locale2.getDisplayName());
}
}
/**
* {@inheritDoc}
*/
public void removePageMetadata(PageMetadataModel metaModel,
String portalName, boolean onContent, String language) throws Exception {
SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
ManageableRepository currentRepo = WCMCoreUtils.getRepository();
Session session = sessionProvider.getSession(currentRepo.getConfiguration()
.getDefaultWorkspaceName(), currentRepo);
String hash = "";
Node node = null;
if (onContent) {
node = session.getNodeByUUID(metaModel.getUri());
} else {
session = sessionProvider.getSession("portal-system", WCMCoreUtils
.getRepository());
String uuid = Util.getUIPortal().getSelectedUserNode().getId();
node = session.getNodeByUUID(uuid);
}
Node seoNode = null;
if(node.hasNode(LANGUAGES+"/"+language))
seoNode = node.getNode(LANGUAGES+"/"+language);
if (seoNode != null) {
seoNode.remove();
if (onContent)
hash = getHash(metaModel.getUri() + language);
else
hash = getHash(metaModel.getPageReference() + language);
cache.remove(hash);
}
session.save();
}
/**
* Update sitemap content for portal
*
* @param uri
* The uri of page
* @param priority
* The priority of page
* @param frequency
* The frequency of page
* @param visibleSitemap
* visibleSitemap = true page is visible on sitemap visibleSitemap =
* false page is invisible on sitemap
* @param portalName
* The portal name
* @throws Exception
*/
public void updateSiteMap(String uri, float priority, String frequency,
boolean visibleSitemap, String portalName) throws Exception {
SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
LivePortalManagerService livePortalManagerService = WCMCoreUtils
.getService(LivePortalManagerService.class);
Node dummyNode = livePortalManagerService.getLivePortal(sessionProvider,
portalName);
Session session = dummyNode.getSession();
uri = getStandardURL(uri);
if(uri == null) uri = "";
String uri_clone = "";
String public_path = "/" + PUBLIC_MODE + "/";
String private_path = "/" + PRIVATE_MODE + "/";
if (uri.indexOf(public_path) > 0)
uri_clone = uri.replaceFirst(public_path, private_path);
else if (uri.indexOf(private_path) > 0)
uri_clone = uri.replaceFirst(private_path, public_path);
String sitemapData = "";
if (!dummyNode.getNode(METADATA_BASE_PATH).hasNode(SITEMAP_NAME)) {
dummyNode.getNode(METADATA_BASE_PATH).addNode(SITEMAP_NAME, "nt:file");
Node simapFolder = dummyNode.getNode(METADATA_BASE_PATH + "/"
+ SITEMAP_NAME);
Node sitemapNode = simapFolder.addNode("jcr:content", "nt:resource");
sitemapNode.setProperty("jcr:mimeType", "text/xml");
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
// root elements
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("urlset");
rootElement.setAttribute("xmlns",
"http://www.sitemaps.org/schemas/sitemap/0.9");
rootElement.setAttribute("xmlns:xsi",
"http://www.w3.org/2001/XMLSchema-instance");
rootElement
.setAttribute(
"xsi:schemaLocation",
"http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd");
doc.appendChild(rootElement);
if (visibleSitemap) {
// Create element in sitemap for uri
Element urlElement = doc.createElement("url");
rootElement.appendChild(urlElement);
Element locElement = doc.createElement("loc");
locElement.setTextContent(uri);
urlElement.appendChild(locElement);
Element freqElement = doc.createElement("changefreq");
freqElement.setTextContent(frequency);
urlElement.appendChild(freqElement);
Element priorityElement = doc.createElement("priority");
if(priority >= 0) {
priorityElement.setTextContent(String.valueOf(priority));
urlElement.appendChild(priorityElement);
}
// Create element in sitemap for uri_clone
if (uri_clone != null && uri_clone.length() > 0) {
urlElement = doc.createElement("url");
rootElement.appendChild(urlElement);
locElement = doc.createElement("loc");
locElement.setTextContent(uri_clone);
urlElement.appendChild(locElement);
freqElement = doc.createElement("changefreq");
freqElement.setTextContent(frequency);
urlElement.appendChild(freqElement);
if(priority >= 0) {
priorityElement = doc.createElement("priority");
priorityElement.setTextContent(String.valueOf(priority));
urlElement.appendChild(priorityElement);
}
}
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StringWriter writer = new StringWriter();
transformer.transform(source, new StreamResult(writer));
sitemapData = writer.toString();
sitemapNode.setProperty("jcr:data", sitemapData);
sitemapNode.setProperty("jcr:lastModified", new GregorianCalendar());
session.save();
} else {
Node sitemapFolder = dummyNode.getNode(METADATA_BASE_PATH + "/"
+ SITEMAP_NAME);
Node sitemapNode = sitemapFolder.getNode("jcr:content");
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
InputStream stream = sitemapNode.getProperty("jcr:data").getStream();
Document doc = docBuilder.parse(stream);
// normalize text representation
boolean fLoc = false;
doc.getDocumentElement().normalize();
Element root = doc.getDocumentElement();
ArrayList<org.w3c.dom.Node> arrNodes = new ArrayList<org.w3c.dom.Node>();
org.w3c.dom.NodeList listOfUrls = doc.getElementsByTagName("url");
for (int i = 0; i < listOfUrls.getLength(); i++) {
org.w3c.dom.Node urlNode = listOfUrls.item(i);
if (urlNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
Element urlElement = (Element) urlNode;
org.w3c.dom.NodeList locList = urlElement.getElementsByTagName("loc");
Element locElement = (Element) locList.item(0);
// The location is exist
if(locElement.getChildNodes().item(0) != null) {
String locationValue = locElement.getChildNodes().item(0).getNodeValue();
if (locationValue != null & (locationValue.trim().equals(uri) || locationValue.trim().equals(uri_clone))) {
fLoc = true;
if (visibleSitemap) {
org.w3c.dom.Node freqNode = urlElement.getElementsByTagName(
"changefreq").item(0);
freqNode.setTextContent(frequency);
if(priority >= 0) {
org.w3c.dom.Node priorityNode = urlElement.getElementsByTagName("priority").item(0);
if(priorityNode == null) {
Element priorityElement = doc.createElement("priority");
priorityElement.setTextContent(String.valueOf(priority));
urlElement.appendChild(priorityElement);
} else priorityNode.setTextContent(String.valueOf(priority));
}
} else {
arrNodes.add(urlNode);
}
}
}
}
}
// Remove element from sitemap.xml
if (arrNodes != null && arrNodes.size() > 0) {
for (int i = 0; i < arrNodes.size(); i++) {
root.removeChild(arrNodes.get(i));
}
}
// Update xml document for sitemap
if (!fLoc && visibleSitemap) {
// Create element in sitemap for uri
Element urlElement = doc.createElement("url");
Element locElement = doc.createElement("loc");
locElement.setTextContent(uri);
Element freqElement = doc.createElement("changefreq");
freqElement.setTextContent(frequency);
urlElement.appendChild(locElement);
urlElement.appendChild(freqElement);
Element priorityElement = doc.createElement("priority");
if(priority >= 0) {
priorityElement.setTextContent(String.valueOf(priority));
urlElement.appendChild(priorityElement);
}
root.appendChild(urlElement);
// create element in sitemap for uri_clone
if (uri_clone != null && uri_clone.length() > 0) {
urlElement = doc.createElement("url");
locElement = doc.createElement("loc");
locElement.setTextContent(uri_clone);
freqElement = doc.createElement("changefreq");
freqElement.setTextContent(frequency);
urlElement.appendChild(locElement);
urlElement.appendChild(freqElement);
if(priority >= 0) {
priorityElement = doc.createElement("priority");
priorityElement.setTextContent(String.valueOf(priority));
urlElement.appendChild(priorityElement);
}
root.appendChild(urlElement);
}
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StringWriter writer = new StringWriter();
transformer.transform(source, new StreamResult(writer));
sitemapData = writer.toString();
sitemapNode.setProperty("jcr:data", sitemapData);
sitemapNode.setProperty("jcr:lastModified", new GregorianCalendar());
}
if (sitemapData != null && sitemapData.length() > 0) {
String hash = getSiteMapCacheKey(portalName);
cache.put(hash, sitemapData);
}
session.save();
}
public void updateRobots(Node dummyNode, String portalName) throws Exception {
if (!dummyNode.getNode(METADATA_BASE_PATH).hasNode(ROBOTS_NAME)) {
dummyNode.getNode(METADATA_BASE_PATH).addNode(ROBOTS_NAME, "nt:file");
Node robotsFolder = dummyNode.getNode(METADATA_BASE_PATH + "/"
+ ROBOTS_NAME);
Node robotsNode = robotsFolder.addNode("jcr:content", "nt:resource");
robotsNode.setProperty("jcr:mimeType", "text/plain");
PortalRequestContext ctx = Util.getPortalRequestContext();
StringBuffer robotsContent = new StringBuffer("# robots.txt \n");
robotsContent.append("User-agent: * \n");
robotsContent.append("Disallow: \n");
if(ctx.getRequest() != null) {
if (ctx.getRequest().getServerPort() != 80) {
robotsContent.append("Sitemap: ")
.append(ctx.getRequest().getScheme())
.append("://")
.append(ctx.getRequest().getServerName())
.append(":")
.append(ctx.getRequest().getServerPort())
.append(ctx.getPortalURI())
.append("sitemaps.xml \n");
} else {
robotsContent.append("Sitemap: ")
.append(ctx.getRequest().getScheme())
.append("://")
.append(ctx.getRequest().getServerName())
.append(ctx.getPortalURI())
.append("sitemaps.xml \n");
}
}
robotsNode.setProperty("jcr:data", robotsContent.toString());
robotsNode.setProperty("jcr:lastModified", new GregorianCalendar());
cache.put(getRobotsCacheKey(portalName), robotsContent.toString());
}
}
private String getRobotsCacheKey(String portalName) throws Exception {
return getHash(portalName + ROBOTS_NAME);
}
/**
* {@inheritDoc}
*/
public String getSitemap(String portalName) throws Exception {
String hash = getSiteMapCacheKey(portalName);
String sitemapContent = (String) getCachedEntry(hash, false);
if (sitemapContent == null || sitemapContent.length() == 0) {
SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
LivePortalManagerService livePortalManagerService = WCMCoreUtils
.getService(LivePortalManagerService.class);
Node dummyNode = livePortalManagerService.getLivePortal(sessionProvider,
portalName);
Session session = dummyNode.getSession();
if (dummyNode.hasNode(METADATA_BASE_PATH)
&& dummyNode.getNode(METADATA_BASE_PATH).hasNode(SITEMAP_NAME)) {
Node sitemapFolder = dummyNode.getNode(METADATA_BASE_PATH + "/"
+ SITEMAP_NAME);
Node sitemapNode = sitemapFolder.getNode("jcr:content");
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
InputStream stream = sitemapNode.getProperty("jcr:data").getStream();
Document doc = docBuilder.parse(stream);
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StringWriter writer = new StringWriter();
transformer.transform(source, new StreamResult(writer));
sitemapContent = writer.toString();
} else {
DocumentBuilderFactory docFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("urlset");
doc.appendChild(rootElement);
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StringWriter writer = new StringWriter();
transformer.transform(source, new StreamResult(writer));
sitemapContent = writer.toString();
}
session.save();
cache.put(hash, sitemapContent);
}
return sitemapContent;
}
private String getSiteMapCacheKey(String portalName) throws Exception {
return getHash(portalName + SITEMAP_NAME);
}
/**
* {@inheritDoc}
*/
public String getRobots(String portalName) throws Exception {
String hash = getRobotsCacheKey(portalName);
String robotsCache = (String) getCachedEntry(hash, false);
if (robotsCache != null && robotsCache.trim().length() > 0) {
return robotsCache;
}
StringBuffer robotsContent = null;
SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
LivePortalManagerService livePortalManagerService = WCMCoreUtils.getService(LivePortalManagerService.class);
Node dummyNode = livePortalManagerService.getLivePortal(sessionProvider, portalName);
Session session = dummyNode.getSession();
if (dummyNode.hasNode(METADATA_BASE_PATH)
&& dummyNode.getNode(METADATA_BASE_PATH).hasNode(ROBOTS_NAME)) {
Node robotsFolder = dummyNode.getNode(METADATA_BASE_PATH + "/" + ROBOTS_NAME);
Node robotsNode = robotsFolder.getNode("jcr:content");
robotsContent = new StringBuffer(robotsNode.getProperty("jcr:data").getValue().getString());
} else {
robotsContent = new StringBuffer("# robots.txt \n");
robotsContent.append("User-agent: * \n");
robotsContent.append("Disallow: \n");
}
session.save();
cache.put(hash, robotsContent.toString());
return robotsContent.toString();
}
/**
* Returns hash
*
* @param uri The uri of page
* @return
* @throws Exception
*/
public String getHash(String uri) throws Exception {
String key = uri;
return MessageDigester.getHash(key);
}
private String getStandardURL(String path) throws Exception {
if(path != null) {
if (path.substring(path.length() - 1, path.length()).equals("/"))
path = path.substring(0, path.length() - 1);
}
return path;
}
public Node getContentNode(String seoPath) throws Exception {
Node seoNode = null;
if (seoPath != null && seoPath.length() > 0) {
String tmpPath = seoPath.trim();
if (tmpPath.startsWith("/"))
tmpPath = tmpPath.substring(1, tmpPath.length());
String[] arrPath = tmpPath.split("/");
if (arrPath != null && arrPath.length > 3) {
String repo = arrPath[0];
String ws = arrPath[1];
if (repo != null && ws != null) {
boolean isWs = false;
String nodePath = tmpPath.substring(
tmpPath.indexOf(ws) + ws.length(), tmpPath.length());
if (nodePath != null && nodePath.length() > 0) {
ManageableRepository manageRepo = WCMCoreUtils.getRepository();
List<WorkspaceEntry> wsList = manageRepo.getConfiguration().getWorkspaceEntries();
for (int i = 0; i < wsList.size(); i++) {
WorkspaceEntry wsEntry = (WorkspaceEntry) wsList.get(i);
if (wsEntry.getName().equals(ws)) {
isWs = true;
break;
}
}
if (isWs) {
Session session = WCMCoreUtils.getUserSessionProvider()
.getSession(ws, manageRepo);
nodePath = nodePath.replaceAll("//", "/");
if (session.getItem(nodePath) != null) {
if (session.getItem(nodePath).isNode()) {
seoNode = (Node) session.getItem(nodePath);
}
}
}
}
}
}
}
return seoNode;
}
@Managed
@ManagedDescription("Is the cache used ?")
public boolean isCached() {
return isCached;
}
@Managed
@ManagedDescription("How many nodes in the cache ?")
public int getCachedEntries() {
return this.cache.getCacheSize();
}
@Managed
@ManagedDescription("Activate/deactivate the composer cache ?")
public void setCached(
@ManagedDescription("Enable/Disable the cache ?") @ManagedName("isCached") boolean isCached) {
this.isCached = isCached;
}
}