/* * 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.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 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 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( "wcm.seo"); } /** *{@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 pageReference = metaModel.getPageReference(); // 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 = getHash(uri + language); else hash = getHash(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 = getHash(pageReference + language); } if (hash != null) cache.put(hash, metaModel); } session.save(); } 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 = getHash(node.getUUID() + language); if (cache.get(hash) != null) metaModel = (PageMetadataModel) cache.get(hash); if(metaModel != null) return metaModel.getFullStatus(); } else { hash = getHash(path + language); if (cache.get(hash) != null) metaModel = (PageMetadataModel) cache.get(hash); 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; } 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 = getHash(contentNode.getUUID() + language); if (cache.get(hash) != null) metaModel = (PageMetadataModel) cache.get(hash); 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 = getHash(pageUri + language); if (cache.get(hash) != null) metaModel = (PageMetadataModel) cache.get(hash); 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 = getHash(portalName + SITEMAP_NAME); 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(getHash(portalName + ROBOTS_NAME), robotsContent.toString()); } } /** * {@inheritDoc} */ public String getSitemap(String portalName) throws Exception { String sitemapContent = null; String hash = getHash(portalName + SITEMAP_NAME); if (cache.get(hash) != null) sitemapContent = (String) cache.get(hash); 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; } /** * {@inheritDoc} */ public String getRobots(String portalName) throws Exception { String hash = getHash(portalName + ROBOTS_NAME); String robotsCache = null; if (cache.get(hash) != null) robotsCache = (String) cache.get(hash); 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; } }