/* * This library is part of OpenCms - * the Open Source Content Management System * * Copyright (c) Alkacon Software GmbH (http://www.alkacon.com) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * For further information about Alkacon Software GmbH, please see the * company website: http://www.alkacon.com * * For further information about OpenCms, please see the * project website: http://www.opencms.org * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.opencms.workplace.tools.content.languagecopy; import org.opencms.file.CmsFile; import org.opencms.file.CmsObject; import org.opencms.i18n.CmsLocaleManager; import org.opencms.i18n.CmsMessageContainer; import org.opencms.lock.CmsLock; import org.opencms.main.CmsException; import org.opencms.main.CmsLog; import org.opencms.main.OpenCms; import org.opencms.report.A_CmsReportThread; import org.opencms.report.CmsHtmlReport; import org.opencms.report.CmsLogReport; import org.opencms.report.I_CmsReport; import org.opencms.xml.content.CmsXmlContent; import org.opencms.xml.content.CmsXmlContentFactory; import java.util.Iterator; import java.util.List; import java.util.Locale; import org.apache.commons.logging.Log; /** * Copies language nodes in XML contents.<p> * * @since 7.5.1 */ public class CmsLanguageCopyThread extends A_CmsReportThread { /** The log object for this class. */ private static final Log LOG = CmsLog.getLog(CmsLanguageCopyThread.class); /** The resources to copy. */ private String[] m_copyresources; /** The special multiplex report. */ private I_CmsReport m_report; /** The source language. */ private String m_sourceLanguage; /** The source language. */ private String m_targetLanguage; /** * Copies language nodes in XML contents.<p> * * @param cms the current cms context * @param copyResources the resources to copy * @param sourceLanguage the source language * @param targetLanguage the target language */ public CmsLanguageCopyThread( final CmsObject cms, String[] copyResources, String sourceLanguage, String targetLanguage) { super(cms, Messages.get().getBundle().key(Messages.GUI_REPORT_LANGUAGECOPY_NAME_0)); m_copyresources = copyResources; m_sourceLanguage = sourceLanguage; m_targetLanguage = targetLanguage; initHtmlReport(cms.getRequestContext().getLocale()); CmsMultiplexReport report = new CmsMultiplexReport(); Locale locale = cms.getRequestContext().getLocale(); report.addReport(new CmsHtmlReport(locale, cms.getRequestContext().getSiteRoot())); report.addReport(new CmsLogReport(locale, CmsLanguageCopyThread.class)); this.m_report = report; } /** * @see org.opencms.report.A_CmsReportThread#getReportUpdate() */ @Override public String getReportUpdate() { return this.getReport().getReportUpdate(); } /** * @see java.lang.Runnable#run() */ @Override public void run() { CmsMultiplexReport report = (CmsMultiplexReport)this.getReport(); int totalFiles = this.m_copyresources.length; Locale sourceLocale = CmsLocaleManager.getLocale(this.m_sourceLanguage); Locale targetLocale = CmsLocaleManager.getLocale(this.m_targetLanguage); report.println( Messages.get().container( Messages.GUI_REPORT_LANGUAGEC0PY_START_3, new Object[] {new Integer(totalFiles), sourceLocale, targetLocale}), I_CmsReport.FORMAT_HEADLINE); try { this.copyLanguageNodes(); } catch (Throwable e) { report.println(e); if (LOG.isErrorEnabled()) { LOG.error(Messages.get().getBundle().key(Messages.ERR_REPORT_LANGUAGEC0PY_0), e); } } // List the errors: List<Object> errors = report.getErrors(); List<Object> warnings = report.getWarnings(); report.println( Messages.get().container( Messages.GUI_REPORT_LANGUAGEC0PY_END_2, new Object[] {new Integer(warnings.size()), new Integer(errors.size())}), I_CmsReport.FORMAT_HEADLINE); for (Object f : warnings) { if (f instanceof CmsMessageContainer) { report.println((CmsMessageContainer)f, I_CmsReport.FORMAT_WARNING); } } for (Object f : errors) { if (f instanceof CmsMessageContainer) { report.println((CmsMessageContainer)f, I_CmsReport.FORMAT_ERROR); } } } /** * @see org.opencms.report.A_CmsReportThread#getReport() */ @Override protected I_CmsReport getReport() { return m_report; } /** * Does the job.<p> */ private void copyLanguageNodes() { CmsObject cms = this.getCms(); CmsMultiplexReport report = (CmsMultiplexReport)this.getReport(); CmsFile file; CmsXmlContent content; int totalFiles = this.m_copyresources.length; int processedFiles = 0; Locale sourceLocale = CmsLocaleManager.getLocale(this.m_sourceLanguage); Locale targetLocale = CmsLocaleManager.getLocale(this.m_targetLanguage); for (int i = 0; i < this.m_copyresources.length; i++) { processedFiles++; report.print( org.opencms.report.Messages.get().container( org.opencms.report.Messages.RPT_SUCCESSION_2, new Object[] {String.valueOf(processedFiles), String.valueOf(totalFiles)}), I_CmsReport.FORMAT_NOTE); report.print(Messages.get().container( Messages.RPT_LOCALIZATION_BYPASS_1, new Object[] {this.m_copyresources[i]})); report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0)); try { file = cms.readFile(this.m_copyresources[i]); content = CmsXmlContentFactory.unmarshal(cms, file); if (!content.hasLocale(sourceLocale)) { report.println( Messages.get().container( Messages.GUI_REPORT_LANGUAGEC0PY_WARN_SOURCELOCALE_MISSING_1, new Object[] {sourceLocale}), I_CmsReport.FORMAT_WARNING); CmsMessageContainer container = Messages.get().container( Messages.GUI_REPORT_LANGUAGEC0PY_WARN_SOURCELOCALE_MISSING_2, new Object[] {this.m_copyresources[i], sourceLocale}); report.addWarning(container); } else if (content.hasLocale(targetLocale)) { report.println( Messages.get().container( Messages.GUI_REPORT_LANGUAGEC0PY_WARN_TARGETLOCALE_EXISTS_1, new Object[] {targetLocale}), I_CmsReport.FORMAT_WARNING); CmsMessageContainer container = Messages.get().container( Messages.GUI_REPORT_LANGUAGEC0PY_WARN_TARGETLOCALE_EXISTS_2, new Object[] {this.m_copyresources[i], targetLocale}); report.addWarning(container); } else { content.copyLocale(sourceLocale, targetLocale); file.setContents(content.marshal()); CmsLock lock = cms.getLock(file); if (lock.isInherited()) { this.unlockInherited(file.getRootPath()); cms.lockResource(this.m_copyresources[i]); } else { if (lock.isNullLock()) { cms.lockResource(this.m_copyresources[i]); } else { if (!lock.isLockableBy(cms.getRequestContext().getCurrentUser())) { cms.changeLock(this.m_copyresources[i]); } } } cms.writeFile(file); cms.unlockResource(this.m_copyresources[i]); report.println( org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0), I_CmsReport.FORMAT_OK); } } catch (Throwable f) { CmsMessageContainer error = Messages.get().container( Messages.GUI_REPORT_LANGUAGEC0PY_ERROR_2, new String[] {this.m_copyresources[i], CmsException.getStackTraceAsString(f)}); report.println( org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_FAILED_0), I_CmsReport.FORMAT_ERROR); // report.println(f); report.addError(error); } } } /** * Returns the lock of a possible locked parent folder of a resource, system locks are ignored.<p> * * @param absoluteResourceName the name of the resource * * @return the lock of a parent folder, or {@link CmsLock#getNullLock()} * if no parent folders are locked by a non system lock */ private CmsLock getParentFolderLock(final String absoluteResourceName) { Iterator<CmsLock> itLocks = OpenCms.getMemoryMonitor().getAllCachedLocks().iterator(); while (itLocks.hasNext()) { CmsLock lock = itLocks.next(); if (lock.getResourceName().endsWith("/") && absoluteResourceName.startsWith(lock.getResourceName()) && !absoluteResourceName.equals(lock.getResourceName())) { // system locks does not get inherited lock = lock.getEditionLock(); // check the lock if (!lock.isUnlocked()) { return lock; } } } return CmsLock.getNullLock(); } /** * Returns the inherited lock of a resource.<p> * * @param absoluteResourcename the absolute path of the resource * * @return the inherited lock or the null lock */ private CmsLock getParentLock(final String absoluteResourcename) { CmsLock parentFolderLock = getParentFolderLock(absoluteResourcename); if (!parentFolderLock.isNullLock()) { return parentFolderLock; } return CmsLock.getNullLock(); } /** * Recursively steps up to the resource that is the originator of the given * resource which has an inherited lock.<p> * * @param absoluteResourcename the absolute resource with the inherited lock * * @throws CmsException if something goes wrong */ private void unlockInherited(final String absoluteResourcename) throws CmsException { CmsObject cms = getCms(); CmsLock parentLock = getParentLock(absoluteResourcename); if (!parentLock.isNullLock()) { if (parentLock.isInherited()) { unlockInherited(parentLock.getResourceName()); } else { if (!parentLock.isLockableBy(cms.getRequestContext().getCurrentUser())) { cms.changeLock(cms.getRequestContext().removeSiteRoot(parentLock.getResourceName())); } cms.unlockResource(cms.getRequestContext().removeSiteRoot(parentLock.getResourceName())); } } } }