1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.exoplatform.services.seo.impl;
18
19 import java.io.InputStream;
20 import java.io.StringWriter;
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.Comparator;
24 import java.util.GregorianCalendar;
25 import java.util.List;
26 import java.util.Locale;
27
28 import javax.jcr.Node;
29 import javax.jcr.NodeIterator;
30 import javax.jcr.Session;
31 import javax.xml.parsers.DocumentBuilder;
32 import javax.xml.parsers.DocumentBuilderFactory;
33 import javax.xml.transform.Transformer;
34 import javax.xml.transform.TransformerFactory;
35 import javax.xml.transform.dom.DOMSource;
36 import javax.xml.transform.stream.StreamResult;
37
38 import org.exoplatform.container.xml.InitParams;
39 import org.exoplatform.container.xml.ObjectParameter;
40 import org.exoplatform.ecm.utils.MessageDigester;
41 import org.exoplatform.management.annotations.Managed;
42 import org.exoplatform.management.annotations.ManagedDescription;
43 import org.exoplatform.management.annotations.ManagedName;
44 import org.exoplatform.portal.application.PortalRequestContext;
45 import org.exoplatform.portal.webui.util.Util;
46 import org.exoplatform.services.cache.CacheService;
47 import org.exoplatform.services.cache.ExoCache;
48 import org.exoplatform.services.jcr.config.WorkspaceEntry;
49 import org.exoplatform.services.jcr.core.ManageableRepository;
50 import org.exoplatform.services.jcr.ext.common.SessionProvider;
51 import org.exoplatform.services.seo.PageMetadataModel;
52 import org.exoplatform.services.seo.SEOConfig;
53 import org.exoplatform.services.seo.SEOService;
54 import org.exoplatform.services.wcm.portal.LivePortalManagerService;
55 import org.exoplatform.services.wcm.utils.WCMCoreUtils;
56
57 import org.apache.commons.lang.StringUtils;
58 import org.w3c.dom.Document;
59 import org.w3c.dom.Element;
60
61
62
63
64
65 public class SEOServiceImpl implements SEOService {
66 private ExoCache<String, Object> cache;
67
68 public static final String EMPTY_CACHE_ENTRY = "EMPTY";
69 public static String METADATA_BASE_PATH = "SEO";
70 final static public String LANGUAGES = "seo-languages";
71 public static String METADATA_PAGE_PATH = "pages";
72 public static String METADATA_CONTENT_PATH = "contents";
73 public static String SITEMAP_NAME = "sitemaps";
74 public static String ROBOTS_NAME = "robots";
75 private static String PUBLIC_MODE = "public";
76 private static String PRIVATE_MODE = "private";
77
78 private final static String CACHE_NAME = "ecms.seo";
79
80 private List<String> robotsindex = new ArrayList<String>();
81 private List<String> robotsfollow = new ArrayList<String>();
82 private List<String> frequency = new ArrayList<String>();
83 private SEOConfig seoConfig = null;
84
85 private boolean isCached = true;
86
87
88
89
90
91
92
93
94 public SEOServiceImpl(InitParams initParams) throws Exception {
95 ObjectParameter param = initParams.getObjectParam("seo.config");
96 if (param != null) {
97 seoConfig = (SEOConfig) param.getObject();
98 robotsindex = seoConfig.getRobotsIndex();
99 robotsfollow = seoConfig.getRobotsFollow();
100 frequency = seoConfig.getFrequency();
101 }
102 cache = WCMCoreUtils.getService(CacheService.class).getCacheInstance(
103 CACHE_NAME);
104 }
105
106
107
108
109 public List<String> getRobotsIndexOptions() {
110 return robotsindex;
111 }
112
113
114
115
116 public List<String> getRobotsFollowOptions() {
117 return robotsfollow;
118 }
119
120
121
122
123 public List<String> getFrequencyOptions() {
124 return frequency;
125 }
126
127
128
129
130 public void storeMetadata(PageMetadataModel metaModel, String portalName,
131 boolean onContent, String language) throws Exception {
132 String uri = metaModel.getUri();
133 String cachedHash = getPageOrContentCacheKey(uri, language);
134 if (cache.get(cachedHash) != null) {
135 cache.remove(cachedHash);
136 }
137 String pageReference = metaModel.getPageReference();
138 cachedHash = getPageOrContentCacheKey(metaModel.getPageReference(), language);
139 if (cache.get(cachedHash) != null) {
140 cache.remove(cachedHash);
141 }
142
143
144
145
146
147
148
149
150
151 String title = metaModel.getTitle();
152 String keyword = metaModel.getKeywords();
153 String description = metaModel.getDescription();
154 String robots = metaModel.getRobotsContent();
155 String fullStatus = metaModel.getFullStatus();
156 boolean sitemap = metaModel.getSitemap();
157 float priority = metaModel.getPriority();
158 String frequency = metaModel.getFrequency();
159 SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
160 Session session = null;
161 LivePortalManagerService livePortalManagerService = WCMCoreUtils
162 .getService(LivePortalManagerService.class);
163 Node dummyNode = livePortalManagerService.getLivePortal(sessionProvider,
164 portalName);
165 session = dummyNode.getSession();
166 if (!dummyNode.hasNode(METADATA_BASE_PATH)) {
167 dummyNode.addNode(METADATA_BASE_PATH);
168 session.save();
169 }
170
171 updateRobots(dummyNode, portalName);
172
173 Node node = null;
174 if (onContent) {
175 node = session.getNodeByUUID(uri);
176 if (!node.isNodeType("mix:referenceable")) {
177 node.addMixin("mix:referenceable");
178 }
179 } else {
180 session = sessionProvider.getSession("portal-system", WCMCoreUtils
181 .getRepository());
182 String uuid = Util.getUIPortal().getSelectedUserNode().getId();
183 node = session.getNodeByUUID(uuid);
184 if (!node.isNodeType("exo:seoMetadata")) {
185 node.addMixin("exo:seoMetadata");
186 }
187 }
188
189 Node languageNode = null;
190 if(node.hasNode(LANGUAGES))
191 languageNode = node.getNode(LANGUAGES);
192 else
193 languageNode = node.addNode(LANGUAGES);
194 if(languageNode.canAddMixin("exo:hiddenable"))
195 languageNode.addMixin("exo:hiddenable");
196 session.save();
197 Node seoNode = null;
198 if(languageNode.hasNode(language)) seoNode = languageNode.getNode(language);
199 else seoNode = languageNode.addNode(language);
200 if (!seoNode.isNodeType("mix:referenceable")) {
201 seoNode.addMixin("mix:referenceable");
202 }
203 if (seoNode.isNodeType("exo:pageMetadata")) {
204 seoNode.setProperty("exo:metaKeywords", keyword);
205 seoNode.setProperty("exo:metaDescription", description);
206 seoNode.setProperty("exo:metaFully", fullStatus);
207 if (!onContent) {
208 seoNode.setProperty("exo:metaTitle", title);
209 seoNode.setProperty("exo:metaRobots", robots);
210 seoNode.setProperty("exo:metaSitemap", sitemap);
211 seoNode.setProperty("exo:metaPriority", priority);
212 seoNode.setProperty("exo:metaFrequency", frequency);
213 updateSiteMap(uri, priority, frequency, sitemap, portalName);
214 }
215 String hash = null;
216 if (onContent)
217 hash = cachedHash;
218 else
219 hash = getPageOrContentCacheKey(pageReference, language);
220 if (hash != null)
221 cache.put(hash, metaModel);
222 } else {
223 String hash = null;
224 seoNode.addMixin("exo:pageMetadata");
225 seoNode.setProperty("exo:metaKeywords", keyword);
226 seoNode.setProperty("exo:metaDescription", description);
227 seoNode.setProperty("exo:metaFully", fullStatus);
228 if (onContent) {
229 seoNode.setProperty("exo:metaUri", seoNode.getUUID());
230 hash = getHash(seoNode.getUUID() + language);
231 } else {
232 seoNode.setProperty("exo:metaTitle", title);
233 seoNode.setProperty("exo:metaUri", pageReference);
234 seoNode.setProperty("exo:metaRobots", robots);
235 seoNode.setProperty("exo:metaSitemap", sitemap);
236 seoNode.setProperty("exo:metaPriority", priority);
237 seoNode.setProperty("exo:metaFrequency", frequency);
238 updateSiteMap(uri, priority, frequency, sitemap, portalName);
239 hash = getPageOrContentCacheKey(pageReference, language);
240 }
241 if (hash != null)
242 cache.put(hash, metaModel);
243 }
244 session.save();
245 }
246
247 private String getPageOrContentCacheKey(String uri, String language) throws Exception {
248 return getHash(uri + language);
249 }
250
251 public String getState(String path, String language, boolean onContent) throws Exception{
252 String state = "Empty";
253 Node node = null;
254 String hash = null;
255 PageMetadataModel metaModel = null;
256 if(onContent) {
257 node = getContentNode(path);
258 hash = node == null ? StringUtils.EMPTY : getPageOrContentCacheKey(node.getUUID(), language);
259 metaModel = (PageMetadataModel) getCachedEntry(hash, false);
260 if(metaModel != null) return metaModel.getFullStatus();
261
262 } else {
263 hash = getPageOrContentCacheKey(path, language);
264 metaModel = (PageMetadataModel) getCachedEntry(hash, true);
265 if (isNullObject(metaModel)) {
266 return null;
267 }
268 if(metaModel != null) return metaModel.getFullStatus();
269 SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
270 Session session = sessionProvider.getSession("portal-system",
271 WCMCoreUtils.getRepository());
272 String uuid = Util.getUIPortal().getSelectedUserNode().getId();
273 node = session.getNodeByUUID(uuid);
274 }
275 if(node.hasNode(LANGUAGES+"/"+language)) {
276 Node seoNode = node.getNode(LANGUAGES+"/"+language);
277 if (seoNode.isNodeType("exo:pageMetadata") && seoNode.hasProperty("exo:metaFully"))
278 return seoNode.getProperty("exo:metaFully").getString();
279 }
280 return state;
281 }
282
283 private boolean isNullObject(PageMetadataModel metaModel) {
284 return metaModel == PageMetadataModel.NULL_PAGE_METADATA_MODEL;
285 }
286
287 private Object getCachedEntry(String hash, boolean cacheNull) {
288 Object object = cache.get(hash);
289 if (cacheNull) {
290 if( object == null) {
291 cache.put(hash, EMPTY_CACHE_ENTRY);
292 } else if(EMPTY_CACHE_ENTRY.equals(object)) {
293 return PageMetadataModel.NULL_PAGE_METADATA_MODEL;
294 }
295 }
296 return object;
297 }
298
299 public PageMetadataModel getMetadata(ArrayList<String> params,
300 String pageReference, String language) throws Exception {
301 PageMetadataModel metaModel = null;
302 if (params != null) {
303 metaModel = getContentMetadata(params, language);
304 if(metaModel == null) metaModel = getPageMetadata(pageReference, language);
305 } else {
306 metaModel = getPageMetadata(pageReference, language);
307 }
308 return metaModel;
309 }
310
311
312
313
314 public PageMetadataModel getContentMetadata(ArrayList<String> params, String language)
315 throws Exception {
316 PageMetadataModel metaModel = null;
317 String pageUri = null;
318 Node contentNode = null;
319 for (int i = 0; i < params.size(); i++) {
320 contentNode = this.getContentNode(params.get(i).toString());
321 if (contentNode != null)
322 break;
323 }
324
325 if (contentNode == null)
326 return null;
327 if (!contentNode.isNodeType("mix:referenceable")) {
328 contentNode.addMixin("mix:referenceable");
329 }
330 String hash = getPageOrContentCacheKey(contentNode.getUUID(), language);
331 metaModel = (PageMetadataModel) getCachedEntry(hash, false);
332
333 if (metaModel == null && contentNode.hasNode(LANGUAGES+"/"+language)) {
334
335 Node seoNode = contentNode.getNode(LANGUAGES+"/"+language);
336 if (!seoNode.isNodeType("mix:referenceable")) {
337 seoNode.addMixin("mix:referenceable");
338 }
339 if (seoNode.isNodeType("exo:pageMetadata")) {
340 metaModel = new PageMetadataModel();
341 metaModel.setUri(pageUri);
342 if (seoNode.hasProperty("exo:metaKeywords"))
343 metaModel.setKeywords((seoNode.getProperty("exo:metaKeywords"))
344 .getString());
345 if (seoNode.hasProperty("exo:metaDescription"))
346 metaModel.setDescription((seoNode
347 .getProperty("exo:metaDescription")).getString());
348 if (seoNode.hasProperty("exo:metaRobots"))
349 metaModel
350 .setRobotsContent((seoNode.getProperty("exo:metaRobots"))
351 .getString());
352 if (seoNode.hasProperty("exo:metaSitemap"))
353 metaModel.setSiteMap(Boolean.parseBoolean((seoNode
354 .getProperty("exo:metaSitemap")).getString()));
355 if (seoNode.hasProperty("exo:metaPriority"))
356 metaModel.setPriority(Long.parseLong((seoNode
357 .getProperty("exo:metaPriority")).getString()));
358 if (seoNode.hasProperty("exo:metaFrequency"))
359 metaModel.setFrequency((seoNode.getProperty("exo:metaFrequency"))
360 .getString());
361 if (seoNode.hasProperty("exo:metaFully"))
362 metaModel.setFullStatus((seoNode.getProperty("exo:metaFully"))
363 .getString());
364 cache.put(hash, metaModel);
365 }
366 }
367 return metaModel;
368 }
369
370
371
372
373 public PageMetadataModel getPageMetadata(String pageUri, String language) throws Exception {
374 PageMetadataModel metaModel = null;
375 String hash = getPageOrContentCacheKey(pageUri, language);
376 metaModel = (PageMetadataModel) getCachedEntry(hash, true);
377 if (isNullObject(metaModel)) {
378 return null;
379 }
380 if (metaModel == null) {
381 SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
382 Session session = sessionProvider.getSession("portal-system",
383 WCMCoreUtils.getRepository());
384 String uuid = Util.getUIPortal().getSelectedUserNode().getId();
385 Node pageNode = session.getNodeByUUID(uuid);
386
387 if (pageNode != null && pageNode.hasNode(LANGUAGES+"/"+language)) {
388 Node seoNode = pageNode.getNode(LANGUAGES+"/"+language);
389 if(seoNode.isNodeType("exo:pageMetadata")) {
390 metaModel = new PageMetadataModel();
391 if (seoNode.hasProperty("exo:metaTitle"))
392 metaModel.setTitle((seoNode.getProperty("exo:metaTitle")).getString());
393 if (seoNode.hasProperty("exo:metaKeywords"))
394 metaModel.setKeywords((seoNode.getProperty("exo:metaKeywords"))
395 .getString());
396 if (seoNode.hasProperty("exo:metaDescription"))
397 metaModel
398 .setDescription((seoNode.getProperty("exo:metaDescription"))
399 .getString());
400 if (seoNode.hasProperty("exo:metaRobots"))
401 metaModel.setRobotsContent((seoNode.getProperty("exo:metaRobots"))
402 .getString());
403 if (seoNode.hasProperty("exo:metaSitemap"))
404 metaModel.setSiteMap(Boolean.parseBoolean((seoNode
405 .getProperty("exo:metaSitemap")).getString()));
406 if (seoNode.hasProperty("exo:metaPriority"))
407 metaModel.setPriority(Long.parseLong((seoNode
408 .getProperty("exo:metaPriority")).getString()));
409 if (seoNode.hasProperty("exo:metaFrequency"))
410 metaModel.setFrequency((seoNode.getProperty("exo:metaFrequency"))
411 .getString());
412 if (seoNode.hasProperty("exo:metaFully"))
413 metaModel.setFullStatus((seoNode.getProperty("exo:metaFully"))
414 .getString());
415 cache.put(hash, metaModel);
416 }
417 }
418 }
419 return metaModel;
420 }
421
422 public List<Locale> getSEOLanguages(String portalName, String seoPath, boolean onContent) throws Exception {
423 List<Locale> languages = new ArrayList<Locale>();
424 Node languagesNode = null;
425 if(onContent) {
426 Node contentNode = null;
427 contentNode = getContentNode(seoPath);
428 if (contentNode != null && contentNode.hasNode(LANGUAGES)) languagesNode = contentNode.getNode(LANGUAGES);
429 } else {
430 SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
431 Session session = sessionProvider.getSession("portal-system",
432 WCMCoreUtils.getRepository());
433 String uuid = Util.getUIPortal().getSelectedUserNode().getId();
434 Node pageNode = session.getNodeByUUID(uuid);
435 if (pageNode != null && pageNode.hasNode(LANGUAGES)) languagesNode = pageNode.getNode(LANGUAGES);
436 }
437 if(languagesNode != null) {
438 NodeIterator iter = languagesNode.getNodes();
439 while(iter.hasNext()) {
440 String lang = iter.nextNode().getName();
441 String[] arr = lang.split("_");
442 if(arr.length > 1) {
443 languages.add(new Locale(arr[0],arr[1]));
444 } else languages.add(new Locale(lang));
445 }
446 Collections.sort(languages, new SEOItemComparator());
447 return languages;
448 }
449 return languages;
450 }
451
452 class SEOItemComparator implements Comparator<Locale> {
453 @Override
454 public int compare(Locale locale1, Locale locale2) {
455 return locale1.getDisplayName().compareTo(locale2.getDisplayName());
456 }
457 }
458
459
460
461
462 public void removePageMetadata(PageMetadataModel metaModel,
463 String portalName, boolean onContent, String language) throws Exception {
464 SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
465 ManageableRepository currentRepo = WCMCoreUtils.getRepository();
466 Session session = sessionProvider.getSession(currentRepo.getConfiguration()
467 .getDefaultWorkspaceName(), currentRepo);
468 String hash = "";
469 Node node = null;
470 if (onContent) {
471 node = session.getNodeByUUID(metaModel.getUri());
472 } else {
473 session = sessionProvider.getSession("portal-system", WCMCoreUtils
474 .getRepository());
475 String uuid = Util.getUIPortal().getSelectedUserNode().getId();
476 node = session.getNodeByUUID(uuid);
477 }
478 Node seoNode = null;
479 if(node.hasNode(LANGUAGES+"/"+language))
480 seoNode = node.getNode(LANGUAGES+"/"+language);
481
482 if (seoNode != null) {
483 seoNode.remove();
484 if (onContent)
485 hash = getHash(metaModel.getUri() + language);
486 else
487 hash = getHash(metaModel.getPageReference() + language);
488 cache.remove(hash);
489 }
490 session.save();
491 }
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509 public void updateSiteMap(String uri, float priority, String frequency,
510 boolean visibleSitemap, String portalName) throws Exception {
511 SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
512 LivePortalManagerService livePortalManagerService = WCMCoreUtils
513 .getService(LivePortalManagerService.class);
514 Node dummyNode = livePortalManagerService.getLivePortal(sessionProvider,
515 portalName);
516 Session session = dummyNode.getSession();
517 uri = getStandardURL(uri);
518 if(uri == null) uri = "";
519 String uri_clone = "";
520 String public_path = "/" + PUBLIC_MODE + "/";
521 String private_path = "/" + PRIVATE_MODE + "/";
522 if (uri.indexOf(public_path) > 0)
523 uri_clone = uri.replaceFirst(public_path, private_path);
524 else if (uri.indexOf(private_path) > 0)
525 uri_clone = uri.replaceFirst(private_path, public_path);
526
527 String sitemapData = "";
528 if (!dummyNode.getNode(METADATA_BASE_PATH).hasNode(SITEMAP_NAME)) {
529 dummyNode.getNode(METADATA_BASE_PATH).addNode(SITEMAP_NAME, "nt:file");
530 Node simapFolder = dummyNode.getNode(METADATA_BASE_PATH + "/"
531 + SITEMAP_NAME);
532 Node sitemapNode = simapFolder.addNode("jcr:content", "nt:resource");
533 sitemapNode.setProperty("jcr:mimeType", "text/xml");
534 DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
535 DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
536
537 Document doc = docBuilder.newDocument();
538 Element rootElement = doc.createElement("urlset");
539 rootElement.setAttribute("xmlns",
540 "http://www.sitemaps.org/schemas/sitemap/0.9");
541 rootElement.setAttribute("xmlns:xsi",
542 "http://www.w3.org/2001/XMLSchema-instance");
543 rootElement
544 .setAttribute(
545 "xsi:schemaLocation",
546 "http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd");
547 doc.appendChild(rootElement);
548 if (visibleSitemap) {
549
550 Element urlElement = doc.createElement("url");
551 rootElement.appendChild(urlElement);
552 Element locElement = doc.createElement("loc");
553 locElement.setTextContent(uri);
554 urlElement.appendChild(locElement);
555 Element freqElement = doc.createElement("changefreq");
556 freqElement.setTextContent(frequency);
557 urlElement.appendChild(freqElement);
558 Element priorityElement = doc.createElement("priority");
559 if(priority >= 0) {
560 priorityElement.setTextContent(String.valueOf(priority));
561 urlElement.appendChild(priorityElement);
562 }
563
564 if (uri_clone != null && uri_clone.length() > 0) {
565 urlElement = doc.createElement("url");
566 rootElement.appendChild(urlElement);
567 locElement = doc.createElement("loc");
568 locElement.setTextContent(uri_clone);
569 urlElement.appendChild(locElement);
570 freqElement = doc.createElement("changefreq");
571 freqElement.setTextContent(frequency);
572 urlElement.appendChild(freqElement);
573 if(priority >= 0) {
574 priorityElement = doc.createElement("priority");
575 priorityElement.setTextContent(String.valueOf(priority));
576 urlElement.appendChild(priorityElement);
577 }
578 }
579 }
580
581 TransformerFactory transformerFactory = TransformerFactory.newInstance();
582 Transformer transformer = transformerFactory.newTransformer();
583 DOMSource source = new DOMSource(doc);
584 StringWriter writer = new StringWriter();
585 transformer.transform(source, new StreamResult(writer));
586 sitemapData = writer.toString();
587 sitemapNode.setProperty("jcr:data", sitemapData);
588 sitemapNode.setProperty("jcr:lastModified", new GregorianCalendar());
589 session.save();
590 } else {
591 Node sitemapFolder = dummyNode.getNode(METADATA_BASE_PATH + "/"
592 + SITEMAP_NAME);
593 Node sitemapNode = sitemapFolder.getNode("jcr:content");
594 DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
595 .newInstance();
596 DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
597 InputStream stream = sitemapNode.getProperty("jcr:data").getStream();
598 Document doc = docBuilder.parse(stream);
599
600
601 boolean fLoc = false;
602 doc.getDocumentElement().normalize();
603 Element root = doc.getDocumentElement();
604 ArrayList<org.w3c.dom.Node> arrNodes = new ArrayList<org.w3c.dom.Node>();
605 org.w3c.dom.NodeList listOfUrls = doc.getElementsByTagName("url");
606 for (int i = 0; i < listOfUrls.getLength(); i++) {
607 org.w3c.dom.Node urlNode = listOfUrls.item(i);
608 if (urlNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
609 Element urlElement = (Element) urlNode;
610 org.w3c.dom.NodeList locList = urlElement.getElementsByTagName("loc");
611 Element locElement = (Element) locList.item(0);
612
613 if(locElement.getChildNodes().item(0) != null) {
614 String locationValue = locElement.getChildNodes().item(0).getNodeValue();
615 if (locationValue != null & (locationValue.trim().equals(uri) || locationValue.trim().equals(uri_clone))) {
616 fLoc = true;
617 if (visibleSitemap) {
618 org.w3c.dom.Node freqNode = urlElement.getElementsByTagName(
619 "changefreq").item(0);
620 freqNode.setTextContent(frequency);
621 if(priority >= 0) {
622 org.w3c.dom.Node priorityNode = urlElement.getElementsByTagName("priority").item(0);
623 if(priorityNode == null) {
624 Element priorityElement = doc.createElement("priority");
625 priorityElement.setTextContent(String.valueOf(priority));
626 urlElement.appendChild(priorityElement);
627 } else priorityNode.setTextContent(String.valueOf(priority));
628 }
629 } else {
630 arrNodes.add(urlNode);
631 }
632 }
633 }
634 }
635 }
636
637 if (arrNodes != null && arrNodes.size() > 0) {
638 for (int i = 0; i < arrNodes.size(); i++) {
639 root.removeChild(arrNodes.get(i));
640 }
641 }
642
643 if (!fLoc && visibleSitemap) {
644
645 Element urlElement = doc.createElement("url");
646 Element locElement = doc.createElement("loc");
647 locElement.setTextContent(uri);
648 Element freqElement = doc.createElement("changefreq");
649 freqElement.setTextContent(frequency);
650 urlElement.appendChild(locElement);
651 urlElement.appendChild(freqElement);
652 Element priorityElement = doc.createElement("priority");
653 if(priority >= 0) {
654 priorityElement.setTextContent(String.valueOf(priority));
655 urlElement.appendChild(priorityElement);
656 }
657 root.appendChild(urlElement);
658
659 if (uri_clone != null && uri_clone.length() > 0) {
660 urlElement = doc.createElement("url");
661 locElement = doc.createElement("loc");
662 locElement.setTextContent(uri_clone);
663 freqElement = doc.createElement("changefreq");
664 freqElement.setTextContent(frequency);
665 urlElement.appendChild(locElement);
666 urlElement.appendChild(freqElement);
667 if(priority >= 0) {
668 priorityElement = doc.createElement("priority");
669 priorityElement.setTextContent(String.valueOf(priority));
670 urlElement.appendChild(priorityElement);
671 }
672 root.appendChild(urlElement);
673 }
674 }
675 TransformerFactory transformerFactory = TransformerFactory.newInstance();
676 Transformer transformer = transformerFactory.newTransformer();
677 DOMSource source = new DOMSource(doc);
678 StringWriter writer = new StringWriter();
679 transformer.transform(source, new StreamResult(writer));
680 sitemapData = writer.toString();
681 sitemapNode.setProperty("jcr:data", sitemapData);
682 sitemapNode.setProperty("jcr:lastModified", new GregorianCalendar());
683 }
684
685 if (sitemapData != null && sitemapData.length() > 0) {
686 String hash = getSiteMapCacheKey(portalName);
687 cache.put(hash, sitemapData);
688 }
689 session.save();
690 }
691
692 public void updateRobots(Node dummyNode, String portalName) throws Exception {
693 if (!dummyNode.getNode(METADATA_BASE_PATH).hasNode(ROBOTS_NAME)) {
694 dummyNode.getNode(METADATA_BASE_PATH).addNode(ROBOTS_NAME, "nt:file");
695 Node robotsFolder = dummyNode.getNode(METADATA_BASE_PATH + "/"
696 + ROBOTS_NAME);
697 Node robotsNode = robotsFolder.addNode("jcr:content", "nt:resource");
698 robotsNode.setProperty("jcr:mimeType", "text/plain");
699 PortalRequestContext ctx = Util.getPortalRequestContext();
700 StringBuffer robotsContent = new StringBuffer("# robots.txt \n");
701 robotsContent.append("User-agent: * \n");
702 robotsContent.append("Disallow: \n");
703 if(ctx.getRequest() != null) {
704 if (ctx.getRequest().getServerPort() != 80) {
705 robotsContent.append("Sitemap: ")
706 .append(ctx.getRequest().getScheme())
707 .append("://")
708 .append(ctx.getRequest().getServerName())
709 .append(":")
710 .append(ctx.getRequest().getServerPort())
711 .append(ctx.getPortalURI())
712 .append("sitemaps.xml \n");
713 } else {
714 robotsContent.append("Sitemap: ")
715 .append(ctx.getRequest().getScheme())
716 .append("://")
717 .append(ctx.getRequest().getServerName())
718 .append(ctx.getPortalURI())
719 .append("sitemaps.xml \n");
720 }
721 }
722 robotsNode.setProperty("jcr:data", robotsContent.toString());
723 robotsNode.setProperty("jcr:lastModified", new GregorianCalendar());
724 cache.put(getRobotsCacheKey(portalName), robotsContent.toString());
725 }
726 }
727
728 private String getRobotsCacheKey(String portalName) throws Exception {
729 return getHash(portalName + ROBOTS_NAME);
730 }
731
732
733
734
735 public String getSitemap(String portalName) throws Exception {
736 String hash = getSiteMapCacheKey(portalName);
737 String sitemapContent = (String) getCachedEntry(hash, false);
738
739 if (sitemapContent == null || sitemapContent.length() == 0) {
740 SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
741 LivePortalManagerService livePortalManagerService = WCMCoreUtils
742 .getService(LivePortalManagerService.class);
743 Node dummyNode = livePortalManagerService.getLivePortal(sessionProvider,
744 portalName);
745 Session session = dummyNode.getSession();
746 if (dummyNode.hasNode(METADATA_BASE_PATH)
747 && dummyNode.getNode(METADATA_BASE_PATH).hasNode(SITEMAP_NAME)) {
748 Node sitemapFolder = dummyNode.getNode(METADATA_BASE_PATH + "/"
749 + SITEMAP_NAME);
750 Node sitemapNode = sitemapFolder.getNode("jcr:content");
751 DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
752 .newInstance();
753 DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
754 InputStream stream = sitemapNode.getProperty("jcr:data").getStream();
755 Document doc = docBuilder.parse(stream);
756 TransformerFactory transformerFactory = TransformerFactory
757 .newInstance();
758 Transformer transformer = transformerFactory.newTransformer();
759 DOMSource source = new DOMSource(doc);
760 StringWriter writer = new StringWriter();
761 transformer.transform(source, new StreamResult(writer));
762 sitemapContent = writer.toString();
763 } else {
764 DocumentBuilderFactory docFactory = DocumentBuilderFactory
765 .newInstance();
766 DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
767 Document doc = docBuilder.newDocument();
768 Element rootElement = doc.createElement("urlset");
769 doc.appendChild(rootElement);
770 TransformerFactory transformerFactory = TransformerFactory
771 .newInstance();
772 Transformer transformer = transformerFactory.newTransformer();
773 DOMSource source = new DOMSource(doc);
774 StringWriter writer = new StringWriter();
775 transformer.transform(source, new StreamResult(writer));
776 sitemapContent = writer.toString();
777 }
778 session.save();
779 cache.put(hash, sitemapContent);
780 }
781 return sitemapContent;
782 }
783
784 private String getSiteMapCacheKey(String portalName) throws Exception {
785 return getHash(portalName + SITEMAP_NAME);
786 }
787
788
789
790
791 public String getRobots(String portalName) throws Exception {
792 String hash = getRobotsCacheKey(portalName);
793 String robotsCache = (String) getCachedEntry(hash, false);
794
795 if (robotsCache != null && robotsCache.trim().length() > 0) {
796 return robotsCache;
797 }
798
799 StringBuffer robotsContent = null;
800 SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
801 LivePortalManagerService livePortalManagerService = WCMCoreUtils.getService(LivePortalManagerService.class);
802 Node dummyNode = livePortalManagerService.getLivePortal(sessionProvider, portalName);
803 Session session = dummyNode.getSession();
804 if (dummyNode.hasNode(METADATA_BASE_PATH)
805 && dummyNode.getNode(METADATA_BASE_PATH).hasNode(ROBOTS_NAME)) {
806 Node robotsFolder = dummyNode.getNode(METADATA_BASE_PATH + "/" + ROBOTS_NAME);
807 Node robotsNode = robotsFolder.getNode("jcr:content");
808 robotsContent = new StringBuffer(robotsNode.getProperty("jcr:data").getValue().getString());
809 } else {
810 robotsContent = new StringBuffer("# robots.txt \n");
811 robotsContent.append("User-agent: * \n");
812 robotsContent.append("Disallow: \n");
813 }
814 session.save();
815 cache.put(hash, robotsContent.toString());
816 return robotsContent.toString();
817 }
818
819
820
821
822
823
824
825
826 public String getHash(String uri) throws Exception {
827 String key = uri;
828 return MessageDigester.getHash(key);
829 }
830
831 private String getStandardURL(String path) throws Exception {
832 if(path != null) {
833 if (path.substring(path.length() - 1, path.length()).equals("/"))
834 path = path.substring(0, path.length() - 1);
835 }
836 return path;
837 }
838
839 public Node getContentNode(String seoPath) throws Exception {
840 Node seoNode = null;
841 if (seoPath != null && seoPath.length() > 0) {
842 String tmpPath = seoPath.trim();
843 if (tmpPath.startsWith("/"))
844 tmpPath = tmpPath.substring(1, tmpPath.length());
845 String[] arrPath = tmpPath.split("/");
846 if (arrPath != null && arrPath.length > 3) {
847 String repo = arrPath[0];
848 String ws = arrPath[1];
849 if (repo != null && ws != null) {
850 boolean isWs = false;
851 String nodePath = tmpPath.substring(
852 tmpPath.indexOf(ws) + ws.length(), tmpPath.length());
853 if (nodePath != null && nodePath.length() > 0) {
854 ManageableRepository manageRepo = WCMCoreUtils.getRepository();
855 List<WorkspaceEntry> wsList = manageRepo.getConfiguration().getWorkspaceEntries();
856 for (int i = 0; i < wsList.size(); i++) {
857 WorkspaceEntry wsEntry = (WorkspaceEntry) wsList.get(i);
858 if (wsEntry.getName().equals(ws)) {
859 isWs = true;
860 break;
861 }
862 }
863 if (isWs) {
864 Session session = WCMCoreUtils.getUserSessionProvider()
865 .getSession(ws, manageRepo);
866 nodePath = nodePath.replaceAll("//", "/");
867 if (session.getItem(nodePath) != null) {
868 if (session.getItem(nodePath).isNode()) {
869 seoNode = (Node) session.getItem(nodePath);
870 }
871 }
872 }
873 }
874 }
875 }
876 }
877 return seoNode;
878 }
879
880 @Managed
881 @ManagedDescription("Is the cache used ?")
882 public boolean isCached() {
883 return isCached;
884 }
885
886 @Managed
887 @ManagedDescription("How many nodes in the cache ?")
888 public int getCachedEntries() {
889 return this.cache.getCacheSize();
890 }
891
892 @Managed
893 @ManagedDescription("Activate/deactivate the composer cache ?")
894 public void setCached(
895 @ManagedDescription("Enable/Disable the cache ?") @ManagedName("isCached") boolean isCached) {
896 this.isCached = isCached;
897 }
898 }