001: /*
002: * File : $Source: /usr/local/cvs/opencms/src-modules/org/opencms/workplace/tools/content/CmsTagReplaceThread.java,v $
003: * Date : $Date: 2008-02-27 12:05:37 $
004: * Version: $Revision: 1.6 $
005: *
006: * This library is part of OpenCms -
007: * the Open Source Content Management System
008: *
009: * Copyright (c) 2002 - 2008 Alkacon Software GmbH (http://www.alkacon.com)
010: *
011: * This library is free software; you can redistribute it and/or
012: * modify it under the terms of the GNU Lesser General Public
013: * License as published by the Free Software Foundation; either
014: * version 2.1 of the License, or (at your option) any later version.
015: *
016: * This library is distributed in the hope that it will be useful,
017: * but WITHOUT ANY WARRANTY; without even the implied warranty of
018: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: * Lesser General Public License for more details.
020: *
021: * For further information about Alkacon Software GmbH, please see the
022: * company website: http://www.alkacon.com
023: *
024: * For further information about OpenCms, please see the
025: * project website: http://www.opencms.org
026: *
027: * You should have received a copy of the GNU Lesser General Public
028: * License along with this library; if not, write to the Free Software
029: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
030: */
031:
032: package org.opencms.workplace.tools.content;
033:
034: import org.opencms.file.CmsFile;
035: import org.opencms.file.CmsObject;
036: import org.opencms.file.CmsProperty;
037: import org.opencms.file.CmsResource;
038: import org.opencms.file.CmsResourceFilter;
039: import org.opencms.file.CmsUser;
040: import org.opencms.i18n.CmsMessageContainer;
041: import org.opencms.lock.CmsLock;
042: import org.opencms.main.CmsException;
043: import org.opencms.main.CmsLog;
044: import org.opencms.main.OpenCms;
045: import org.opencms.report.A_CmsReportThread;
046: import org.opencms.report.I_CmsReport;
047: import org.opencms.util.CmsStringUtil;
048: import org.opencms.xml.CmsXmlException;
049: import org.opencms.xml.content.CmsXmlContent;
050: import org.opencms.xml.content.CmsXmlContentFactory;
051: import org.opencms.xml.types.I_CmsXmlContentValue;
052:
053: import java.util.Iterator;
054: import java.util.List;
055: import java.util.Locale;
056:
057: import org.apache.commons.logging.Log;
058:
059: import org.htmlparser.util.ParserException;
060:
061: /**
062: * Replaces HTML tags of xmlpage resources using the corresponding settings object.
063: * <p>
064: *
065: * @author Achim Westermann
066: *
067: * @version $Revision: 1.6 $
068: *
069: * @since 6.1.8
070: */
071: public class CmsTagReplaceThread extends A_CmsReportThread {
072:
073: /** The log object for this class. */
074: private static final Log LOG = CmsLog
075: .getLog(CmsTagReplaceThread.class);
076:
077: private CmsProperty m_markerProperty;
078:
079: private CmsTagReplaceSettings m_settings;
080:
081: /**
082: * Creates a replace html tag Thread.<p>
083: *
084: * @param cms the current cms context.
085: *
086: * @param settings the settings needed to perform the operation.
087: */
088: public CmsTagReplaceThread(CmsObject cms,
089: CmsTagReplaceSettings settings) {
090:
091: super (cms, Messages.get().getBundle().key(
092: Messages.GUI_TAGREPLACE_THREAD_NAME_0));
093: initHtmlReport(cms.getRequestContext().getLocale());
094: m_settings = settings;
095: m_markerProperty = new CmsProperty(
096: CmsTagReplaceSettings.PROPERTY_CONTENTOOLS_TAGREPLACE,
097: null, m_settings.getPropertyValueTagReplaceID(), true);
098: }
099:
100: /**
101: * @see org.opencms.report.A_CmsReportThread#getReportUpdate()
102: */
103: public String getReportUpdate() {
104:
105: return getReport().getReportUpdate();
106: }
107:
108: /**
109: * @see java.lang.Runnable#run()
110: */
111: public void run() {
112:
113: getReport().println(
114: Messages.get().container(
115: Messages.RPT_TAGREPLACE_BEGIN_1,
116: m_settings.getWorkPath()),
117: I_CmsReport.FORMAT_HEADLINE);
118: try {
119: // change the element locales
120: replaceTags();
121: } catch (CmsException e) {
122: getReport().println(
123: org.opencms.report.Messages.get().container(
124: org.opencms.report.Messages.RPT_FAILED_0),
125: I_CmsReport.FORMAT_ERROR);
126: getReport().println(e.getMessageContainer(),
127: I_CmsReport.FORMAT_ERROR);
128: if (LOG.isErrorEnabled()) {
129: LOG.error(e.getMessageContainer(), e);
130: }
131: } catch (Throwable f) {
132: getReport().println(
133: org.opencms.report.Messages.get().container(
134: org.opencms.report.Messages.RPT_FAILED_0),
135: I_CmsReport.FORMAT_ERROR);
136: getReport().println(f);
137: if (LOG.isErrorEnabled()) {
138: LOG.error(f);
139: }
140: }
141:
142: // append runtime statistics to report
143: getReport().print(
144: org.opencms.report.Messages.get().container(
145: org.opencms.report.Messages.RPT_STAT_0));
146: getReport()
147: .println(
148: org.opencms.report.Messages
149: .get()
150: .container(
151: org.opencms.report.Messages.RPT_STAT_DURATION_1,
152: getReport().formatRuntime()));
153: getReport()
154: .println(
155: Messages.get().container(
156: Messages.RPT_TAGREPLACE_END_0),
157: I_CmsReport.FORMAT_HEADLINE);
158: }
159:
160: /**
161: * Checks the shared property {@link CmsTagReplaceSettings#PROPERTY_CONTENTOOLS_TAGREPLACE} if
162: * it has the value of this configuration ({@link CmsTagReplaceSettings#getPropertyValueTagReplaceID()}).<p>
163: *
164: * @param resource the resource to test.
165: *
166: * @return true if the property with the value was found.
167: *
168: * @throws CmsException if reading a property fails.
169: */
170: private boolean isProcessedBefore(CmsResource resource)
171: throws CmsException {
172:
173: CmsProperty testProp = getCms().readPropertyObject(resource,
174: CmsTagReplaceSettings.PROPERTY_CONTENTOOLS_TAGREPLACE,
175: false);
176: if (testProp.isNullProperty()) {
177: return false;
178: } else {
179: String testValue = testProp.getResourceValue();
180: if (CmsStringUtil.isEmptyOrWhitespaceOnly(testValue)) {
181: return false;
182: } else {
183: return testValue.equals(m_settings
184: .getPropertyValueTagReplaceID());
185: }
186: }
187: }
188:
189: private void replaceTags() throws CmsException {
190:
191: I_CmsReport report = getReport();
192: report.print(Messages.get().container(
193: Messages.RPT_TAGREPLACE_READ_RESOURCES_1,
194: m_settings.getWorkPath()));
195: report.print(org.opencms.report.Messages.get().container(
196: org.opencms.report.Messages.RPT_DOTS_0));
197: if (LOG.isDebugEnabled()) {
198: LOG.debug(Messages.get().getBundle().key(
199: Messages.RPT_TAGREPLACE_READ_RESOURCES_1,
200: m_settings.getWorkPath()));
201: }
202: CmsResourceFilter filter = CmsResourceFilter.ALL
203: .addRequireType(OpenCms.getResourceManager()
204: .getResourceType("xmlpage").getTypeId());
205: List resources = getCms().readResources(
206: m_settings.getWorkPath(), filter, true);
207: if (LOG.isDebugEnabled()) {
208: LOG.debug(Messages.get().getBundle().key(
209: Messages.LOG_TAGREPLACE_READ_RESOURCES_OK_1,
210: m_settings.getWorkPath()));
211: }
212: report.println(org.opencms.report.Messages.get().container(
213: org.opencms.report.Messages.RPT_OK_0),
214: I_CmsReport.FORMAT_OK);
215: Integer size = new Integer(resources.size());
216: Iterator itResources = resources.iterator();
217: CmsResource resource;
218: int count = 1;
219: while (itResources.hasNext()) {
220: resource = (CmsResource) itResources.next();
221: replaceTags(resource, size, new Integer(count));
222: count++;
223: }
224: }
225:
226: /**
227: * Replaces all replacement mappings configured in the internal {@link CmsTagReplaceSettings}
228: * instance in the content of the given resource.<p>
229: *
230: * No modifications will be done:
231: * <ol>
232: * <li>the resource is locked by another user.</li>
233: * <li>the special marker property with the value that stands for the replacement configuration
234: * is set on the resource (shared).</li>
235: * <li>locking of the non-locked resource fails.</li>
236: * <li>Loading of the content fails.</li>
237: * <li>Unmarshalling fails.</li>
238: * <li>Unexpected exception while replacing occur.</li>
239: * <li>Marshalling of XML fails.</li>
240: * <li>Writing of the marker property fails.</li>
241: * <li>Writing of the file fails.</li>
242: * </ol>
243: * <p>
244: *
245: * @param resource denotes the content to process.
246: *
247: * @param totalJobCount for fancy report writing.
248: *
249: * @param actualJobCount for even fancier report writing.
250: *
251: * @throws CmsException if sth. goes wrong.
252: */
253: private void replaceTags(CmsResource resource,
254: Integer totalJobCount, Integer actualJobCount)
255: throws CmsException {
256:
257: I_CmsReport report = getReport();
258: report.print(org.opencms.report.Messages.get().container(
259: org.opencms.report.Messages.RPT_SUCCESSION_2,
260: actualJobCount, totalJobCount));
261: report.print(Messages.get().container(
262: Messages.RPT_TAGREPLACE_PROCESS_FILE_1,
263: getCms().getRequestContext().removeSiteRoot(
264: resource.getRootPath())));
265: report.print(org.opencms.report.Messages.get().container(
266: org.opencms.report.Messages.RPT_DOTS_0));
267:
268: if (isProcessedBefore(resource)) {
269: report.print(org.opencms.report.Messages.get().container(
270: org.opencms.report.Messages.RPT_SKIPPED_0),
271: I_CmsReport.FORMAT_OK);
272: report.println(Messages.get().container(
273: Messages.RPT_TAGREPLACE_SKIP_REASON_PROPERTY_0),
274: I_CmsReport.FORMAT_OK);
275: return;
276: }
277:
278: if (LOG.isDebugEnabled()) {
279: LOG.debug(Messages.get().getBundle().key(
280: Messages.LOG_DEBUG_TAGREPLACE_LOCK_RESOURCE_1,
281: resource.getRootPath()));
282: }
283: try {
284: // checking the lock:
285: if (LOG.isDebugEnabled()) {
286: LOG.debug(Messages.get().getBundle().key(
287: Messages.LOG_DEBUG_TAGREPLACE_LOCK_READ_1,
288: resource.getRootPath()));
289: }
290:
291: CmsLock lock = getCms().getLock(resource);
292:
293: if (LOG.isDebugEnabled()) {
294: LOG.debug(Messages.get().getBundle().key(
295: Messages.LOG_DEBUG_TAGREPLACE_LOCK_READ_1,
296: resource.getRootPath()));
297: }
298:
299: boolean myLock = !lock.isNullLock()
300: && lock.isOwnedBy(getCms().getRequestContext()
301: .currentUser());
302: if (lock.isNullLock() || myLock) {
303: if (!myLock) {
304: if (LOG.isDebugEnabled()) {
305: LOG
306: .debug(Messages
307: .get()
308: .getBundle()
309: .key(
310: Messages.LOG_DEBUG_TAGREPLACE_LOCK_RESOURCE_1,
311: resource.getRootPath()));
312: }
313: // obtaining the lock:
314: getCms().lockResource(
315: getCms().getRequestContext()
316: .removeSiteRoot(
317: resource.getRootPath()));
318: if (LOG.isDebugEnabled()) {
319: LOG
320: .debug(Messages
321: .get()
322: .getBundle()
323: .key(
324: Messages.LOG_DEBUG_TAGREPLACE_LOCK_RESOURCE_OK_1,
325: resource.getRootPath()));
326: }
327: }
328: } else {
329: // locked by another user:
330: if (LOG.isDebugEnabled()) {
331: LOG
332: .debug(Messages
333: .get()
334: .getBundle()
335: .key(
336: Messages.LOG_DEBUG_TAGREPLACE_RESOURCE_SKIPPED_1,
337: resource.getRootPath()));
338: LOG
339: .debug(Messages
340: .get()
341: .getBundle()
342: .key(
343: Messages.RPT_TAGREPLACE_SKIP_REASON_LOCKED_0));
344: }
345: report
346: .print(
347: org.opencms.report.Messages
348: .get()
349: .container(
350: org.opencms.report.Messages.RPT_SKIPPED_0),
351: I_CmsReport.FORMAT_WARNING);
352: try {
353: CmsUser locker = getCms()
354: .readUser(lock.getUserId());
355: report
356: .println(
357: Messages
358: .get()
359: .container(
360: Messages.RPT_TAGREPLACE_SKIP_REASON_LOCKED_1,
361: locker.getName()),
362: I_CmsReport.FORMAT_WARNING);
363: } catch (Throwable f) {
364: report
365: .println(
366: Messages
367: .get()
368: .container(
369: Messages.RPT_TAGREPLACE_SKIP_REASON_ERR_LOCK_0),
370: I_CmsReport.FORMAT_WARNING);
371: if (LOG.isDebugEnabled()) {
372: LOG
373: .debug(Messages
374: .get()
375: .getBundle()
376: .key(
377: Messages.LOG_DEBUG_TAGREPLACE_RESOURCE_SKIPPED_1,
378: resource.getRootPath()));
379: LOG
380: .debug(Messages
381: .get()
382: .getBundle()
383: .key(
384: Messages.RPT_TAGREPLACE_SKIP_REASON_ERR_LOCK_0));
385: }
386: }
387: return;
388: }
389: } catch (CmsException e) {
390: if (LOG.isErrorEnabled()) {
391: LOG
392: .error(
393: Messages
394: .get()
395: .getBundle()
396: .key(
397: Messages.LOG_WARN_TAGREPLACE_LOCK_RESOURCE_FAILED_1,
398: resource.getRootPath()),
399: e);
400: }
401: report.print(org.opencms.report.Messages.get().container(
402: org.opencms.report.Messages.RPT_SKIPPED_0),
403: I_CmsReport.FORMAT_WARNING);
404: report.println(Messages.get().container(
405: Messages.RPT_TAGREPLACE_SKIP_REASON_LOCKED_0),
406: I_CmsReport.FORMAT_WARNING);
407: return;
408: }
409:
410: if (LOG.isDebugEnabled()) {
411: LOG.debug(Messages.get().getBundle().key(
412: Messages.LOG_DEBUG_TAGREPLACE_LOAD_FILE_1,
413: resource.getRootPath()));
414: }
415:
416: CmsFile file = getCms().readFile(resource);
417:
418: if (LOG.isDebugEnabled()) {
419: LOG.debug(Messages.get().getBundle().key(
420: Messages.LOG_DEBUG_TAGREPLACE_LOAD_FILE_OK_1,
421: resource.getRootPath()));
422: LOG.debug(Messages.get().getBundle().key(
423: Messages.LOG_DEBUG_TAGREPLACE_UNMARSHAL_1,
424: resource.getRootPath()));
425: }
426:
427: CmsXmlContent xmlcontent = CmsXmlContentFactory.unmarshal(
428: getCms(), file);
429:
430: if (LOG.isDebugEnabled()) {
431: LOG.debug(Messages.get().getBundle().key(
432: Messages.LOG_DEBUG_TAGREPLACE_UNMARSHAL_OK_1,
433: resource.getRootPath()));
434: }
435:
436: List locales = xmlcontent.getLocales();
437: Iterator itLocales = locales.iterator();
438: List elements;
439: Iterator itElements;
440: Locale locale;
441: CmsTagReplaceParser parser = new CmsTagReplaceParser(m_settings);
442: I_CmsXmlContentValue value;
443: int count = 1;
444: while (itLocales.hasNext()) {
445: locale = (Locale) itLocales.next();
446: if (LOG.isDebugEnabled()) {
447: LOG.debug(Messages.get().getBundle().key(
448: Messages.LOG_DEBUG_TAGREPLACE_LOCALE_1,
449: locale.getLanguage()));
450: }
451:
452: elements = xmlcontent.getValues(locale);
453: itElements = elements.iterator();
454: while (itElements.hasNext()) {
455: value = (I_CmsXmlContentValue) itElements.next();
456: String content = value.getStringValue(getCms());
457: if (LOG.isDebugEnabled()) {
458: LOG.debug(Messages.get().getBundle().key(
459: Messages.LOG_DEBUG_TAGREPLACE_ELEMENT_2,
460: value.getPath(), content));
461: }
462: try {
463:
464: parser.process(content, xmlcontent.getEncoding());
465: value.setStringValue(getCms(), parser.getResult());
466: } catch (ParserException e) {
467: CmsMessageContainer container = Messages
468: .get()
469: .container(
470: Messages.ERR_TAGREPLACE_PARSE_4,
471: new Object[] {
472: getCms()
473: .getRequestContext()
474: .removeSiteRoot(
475: resource
476: .getRootPath()),
477: locale.getLanguage(),
478: value.getPath(),
479: parser.getResult() });
480: throw new CmsXmlException(container, e);
481: }
482: }
483: count++;
484: }
485:
486: if (parser.isChangedContent()) {
487:
488: if (LOG.isDebugEnabled()) {
489: LOG.debug(Messages.get().getBundle().key(
490: Messages.LOG_DEBUG_TAGREPLACE_MARSHAL_1,
491: resource.getRootPath()));
492: }
493: byte[] content = xmlcontent.marshal();
494: if (LOG.isDebugEnabled()) {
495: LOG.debug(Messages.get().getBundle().key(
496: Messages.LOG_DEBUG_TAGREPLACE_MARSHAL_OK_1,
497: resource.getRootPath()));
498: }
499:
500: // write back the modified xmlcontent:
501: file.setContents(content);
502:
503: if (LOG.isDebugEnabled()) {
504: LOG.debug(Messages.get().getBundle().key(
505: Messages.LOG_DEBUG_TAGREPLACE_WRITE_1,
506: resource.getRootPath()));
507: }
508:
509: getCms().writeFile(file);
510:
511: if (LOG.isDebugEnabled()) {
512: LOG.debug(Messages.get().getBundle().key(
513: Messages.LOG_DEBUG_TAGREPLACE_WRITE_OK_1,
514: resource.getRootPath()));
515: }
516:
517: try {
518: // set the marker property:
519:
520: if (LOG.isDebugEnabled()) {
521: LOG
522: .debug(Messages
523: .get()
524: .getBundle()
525: .key(
526: Messages.LOG_DEBUG_TAGREPLACE_PROPERTY_WRITE_3,
527: new Object[] {
528: m_markerProperty
529: .getName(),
530: m_markerProperty
531: .getResourceValue(),
532: resource
533: .getRootPath() }));
534: }
535: getCms().writePropertyObject(
536: getCms().getRequestContext().removeSiteRoot(
537: resource.getRootPath()),
538: m_markerProperty);
539: if (LOG.isDebugEnabled()) {
540: LOG
541: .debug(Messages
542: .get()
543: .getBundle()
544: .key(
545: Messages.LOG_DEBUG_TAGREPLACE_PROPERTY_WRITE_OK_0));
546: }
547: report.println(
548: org.opencms.report.Messages.get().container(
549: org.opencms.report.Messages.RPT_OK_0),
550: I_CmsReport.FORMAT_OK);
551: } catch (CmsException e) {
552: CmsMessageContainer container = Messages
553: .get()
554: .container(
555: Messages.LOG_ERROR_TAGREPLACE_PROPERTY_WRITE_3,
556: new Object[] {
557: m_markerProperty.getName(),
558: m_markerProperty
559: .getResourceValue(),
560: resource.getRootPath() });
561: throw new CmsXmlException(container, e);
562: }
563:
564: } else {
565: if (LOG.isDebugEnabled()) {
566: LOG.debug(Messages.get().container(
567: Messages.LOG_DEBUG_TAGREPLACE_UNLOCK_FILE_1,
568: resource.getRootPath()));
569: }
570: getCms().unlockResource(
571: getCms().getRequestContext().removeSiteRoot(
572: resource.getRootPath()));
573: if (LOG.isDebugEnabled()) {
574: LOG
575: .debug(Messages
576: .get()
577: .container(
578: Messages.LOG_DEBUG_TAGREPLACE_UNLOCK_FILE_OK_0));
579: }
580: report.print(org.opencms.report.Messages.get().container(
581: org.opencms.report.Messages.RPT_SKIPPED_0),
582: I_CmsReport.FORMAT_OK);
583: report.println(Messages.get().container(
584: Messages.RPT_TAGREPLACE_SKIP_REASON_UNMODIFIED_0),
585: I_CmsReport.FORMAT_OK);
586:
587: }
588: }
589: }
|