Java tutorial
/* * File : $Source$ * Date : $Date$ * Version: $Revision$ * * This library is part of OpenCms - * the Open Source Content Management System * * Copyright (C) 2002 - 2011 Alkacon Software (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, 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.ade.containerpage.inherited; import static org.opencms.ade.containerpage.inherited.CmsContainerConfiguration.N_CONFIGURATION; import static org.opencms.ade.containerpage.inherited.CmsContainerConfiguration.N_ELEMENT; import static org.opencms.ade.containerpage.inherited.CmsContainerConfiguration.N_HIDDEN; import static org.opencms.ade.containerpage.inherited.CmsContainerConfiguration.N_KEY; import static org.opencms.ade.containerpage.inherited.CmsContainerConfiguration.N_NAME; import static org.opencms.ade.containerpage.inherited.CmsContainerConfiguration.N_NEWELEMENT; import static org.opencms.ade.containerpage.inherited.CmsContainerConfiguration.N_ORDERKEY; import static org.opencms.ade.containerpage.inherited.CmsContainerConfiguration.N_URI; import static org.opencms.ade.containerpage.inherited.CmsContainerConfiguration.N_VISIBLE; import org.opencms.ade.containerpage.shared.CmsInheritanceInfo; import org.opencms.file.CmsFile; import org.opencms.file.CmsObject; import org.opencms.file.CmsResource; import org.opencms.file.types.CmsResourceTypeXmlContainerPage; import org.opencms.file.types.CmsResourceTypeXmlContent; import org.opencms.lock.CmsLock; import org.opencms.main.CmsException; import org.opencms.main.CmsLog; import org.opencms.main.OpenCms; import org.opencms.relations.CmsRelationType; import org.opencms.util.CmsStringUtil; import org.opencms.util.CmsUUID; import org.opencms.xml.CmsXmlUtils; import org.opencms.xml.containerpage.CmsContainerElementBean; import org.opencms.xml.content.CmsXmlContent; import org.opencms.xml.content.CmsXmlContentFactory; import org.opencms.xml.content.CmsXmlContentProperty; import org.opencms.xml.content.CmsXmlContentPropertyHelper; import org.opencms.xml.types.CmsXmlVfsFileValue; import org.opencms.xml.types.I_CmsXmlContentValue; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import org.apache.commons.logging.Log; import org.dom4j.Element; /** * A helper class for writing inherited container configuration back to a VFS file.<p> */ public class CmsContainerConfigurationWriter { /** The logger instance for this class. */ @SuppressWarnings("unused") private static final Log LOG = CmsLog.getLog(CmsContainerConfigurationWriter.class); /** * Saves a list of container element beans to a file in the VFS.<p> * * @param cms the current CMS context * @param name the name of the configuration to save * @param newOrdering true if a new ordering needs to be saved * @param pageResource a container page or folder * @param elements the elements whose data should be saved * * @throws CmsException if something goes wrong */ public void save(CmsObject cms, String name, boolean newOrdering, CmsResource pageResource, List<CmsContainerElementBean> elements) throws CmsException { cms = OpenCms.initCmsObject(cms); cms.getRequestContext().setSiteRoot(""); String configPath; if (pageResource.isFolder()) { configPath = CmsStringUtil.joinPaths(pageResource.getRootPath(), CmsContainerConfigurationCache.INHERITANCE_CONFIG_FILE_NAME); } else { configPath = CmsStringUtil.joinPaths(CmsResource.getParentFolder(pageResource.getRootPath()), CmsContainerConfigurationCache.INHERITANCE_CONFIG_FILE_NAME); } CmsInheritedContainerState state = OpenCms.getADEManager().getInheritedContainerState(cms, CmsResource.getParentFolder(CmsResource.getParentFolder(configPath)), name); Set<String> keys = state.getNewElementKeys(); CmsResource configRes = null; boolean needToUnlock = false; if (!cms.existsResource(configPath)) { // create it configRes = cms.createResource(configPath, OpenCms.getResourceManager() .getResourceType(CmsResourceTypeXmlContainerPage.INHERIT_CONTAINER_CONFIG_TYPE_NAME)); needToUnlock = true; } if (configRes == null) { configRes = cms.readResource(configPath); } CmsFile configFile = cms.readFile(configRes); // make sure the internal flag is set configFile.setFlags(configFile.getFlags() | CmsResource.FLAG_INTERNAL); CmsXmlContent content = CmsXmlContentFactory.unmarshal(cms, configFile); for (Locale localeToRemoveEntryFrom : content.getLocales()) { removeExistingEntry(cms, content, localeToRemoveEntryFrom, name); } CmsContainerConfiguration configuration = createConfigurationBean(newOrdering, elements, keys); Locale saveLocale = Locale.ENGLISH; for (Locale locale : content.getLocales()) { if (!saveLocale.equals(locale)) { content.removeLocale(locale); } } if (!content.hasLocale(saveLocale)) { content.addLocale(cms, saveLocale); } Element parentElement = content.getLocaleNode(saveLocale); serializeSingleConfiguration(cms, name, configuration, parentElement); byte[] contentBytes = content.marshal(); configFile.setContents(contentBytes); CmsLock prevLock = cms.getLock(configRes); boolean alreadyLocked = prevLock.isOwnedBy(cms.getRequestContext().getCurrentUser()); if (!alreadyLocked) { cms.lockResourceTemporary(configRes); needToUnlock = true; } try { cms.writeFile(configFile); } finally { if (needToUnlock) { cms.unlockResource(configRes); } } } /** * Serializes a single container configuration into an XML element.<p> * * @param cms the current CMS context * @param name the configuration name * @param config the configuration bean * @param parentElement the parent element to which the new element should be attached * @return the created XML element * * @throws CmsException if something goes wrong */ public Element serializeSingleConfiguration(CmsObject cms, String name, CmsContainerConfiguration config, Element parentElement) throws CmsException { List<String> visibles = new ArrayList<String>(); List<String> invisibles = new ArrayList<String>(); for (String key : config.getVisibility().keySet()) { Boolean value = config.getVisibility().get(key); if (value.booleanValue()) { visibles.add(key); } else { invisibles.add(key); } } if (config.getOrdering().isEmpty() && visibles.isEmpty() && invisibles.isEmpty() && config.getNewElements().isEmpty()) { // don't add empty inheritance configurations return null; } Element root = parentElement.addElement(N_CONFIGURATION); root.addElement(N_NAME).addCDATA(name); for (String orderKey : config.getOrdering()) { root.addElement(N_ORDERKEY).addCDATA(orderKey); } for (String visible : visibles) { root.addElement(N_VISIBLE).addCDATA(visible); } for (String invisible : invisibles) { root.addElement(N_HIDDEN).addCDATA(invisible); } for (Map.Entry<String, CmsContainerElementBean> entry : config.getNewElements().entrySet()) { String key = entry.getKey(); CmsContainerElementBean elementBean = entry.getValue(); elementBean.initResource(cms); Map<String, CmsXmlContentProperty> settingConfiguration = getSettingConfiguration(cms, elementBean.getResource()); CmsUUID structureId = elementBean.getId(); Map<String, String> settings = elementBean.getIndividualSettings(); Element newElementElement = root.addElement(N_NEWELEMENT); newElementElement.addElement(N_KEY).addCDATA(key); Element elementElement = newElementElement.addElement(N_ELEMENT); Element uriElement = elementElement.addElement(N_URI); CmsXmlVfsFileValue.fillEntry(uriElement, structureId, "", CmsRelationType.XML_STRONG); CmsXmlContentPropertyHelper.saveProperties(cms, elementElement, settings, settingConfiguration); } return root; } /** * Converts a list of container elements into a bean which should be saved to the inherited container configuration.<p> * * @param newOrdering if true, save a new ordering * @param elements the elements which should be converted * @param parentKeys the keys for new elements defined in the parent configurations * * @return the bean containing the information from the container elements which should be saved */ protected CmsContainerConfiguration createConfigurationBean(boolean newOrdering, List<CmsContainerElementBean> elements, Set<String> parentKeys) { Map<String, CmsContainerElementBean> newElements = new HashMap<String, CmsContainerElementBean>(); List<String> ordering = new ArrayList<String>(); Map<String, Boolean> visibility = new HashMap<String, Boolean>(); for (CmsContainerElementBean elementBean : elements) { CmsInheritanceInfo info = elementBean.getInheritanceInfo(); if (info.isNew()) { newElements.put(info.getKey(), elementBean); } } if (newOrdering) { for (CmsContainerElementBean elementBean : elements) { CmsInheritanceInfo info = elementBean.getInheritanceInfo(); // remove dangling element references if (parentKeys.contains(info.getKey()) || newElements.containsKey(info.getKey())) { ordering.add(info.getKey()); } } } for (CmsContainerElementBean elementBean : elements) { CmsInheritanceInfo info = elementBean.getInheritanceInfo(); if (info.isVisible() != info.isParentVisible()) { visibility.put(info.getKey(), new Boolean(info.isVisible())); } } CmsContainerConfiguration configuration = new CmsContainerConfiguration(ordering, visibility, newElements); return configuration; } /** * Gets the setting configuration of an element.<p> * * @param cms the current CMS context * @param resource the resource for which the setting configuration should be returned * @return the setting configuration for that element * * @throws CmsException if something goes wrong */ protected Map<String, CmsXmlContentProperty> getSettingConfiguration(CmsObject cms, CmsResource resource) throws CmsException { return OpenCms.getADEManager().getElementSettings(cms, resource); } /** * Removes an existing inheritance container entry with a given name from the configuration file.<p> * * This does nothing if no such entry actually exists.<p> * * @param cms the current CMS context * @param content the XML content * @param locale the locale from which to remove the entry * @param name the name of the entry * */ protected void removeExistingEntry(CmsObject cms, CmsXmlContent content, Locale locale, String name) { if (!content.hasLocale(locale)) { return; } String entriesXpath = N_CONFIGURATION; List<I_CmsXmlContentValue> values = content.getValues(entriesXpath, locale); int valueIndex = 0; for (I_CmsXmlContentValue value : values) { String valueXpath = value.getPath(); I_CmsXmlContentValue nameValue = content.getValue(CmsXmlUtils.concatXpath(valueXpath, N_NAME), locale); String currentName = nameValue.getStringValue(cms); if (currentName.equals(name)) { content.removeValue(valueXpath, locale, valueIndex); break; } valueIndex += 1; } } /** * Saves a single container configuration in an XML content object, but doesn't write it to the VFS.<p> * * If the XML content passed as a parameter is null, a new XML content object will be created * * @param cms the current CMS context * @param content the XML content * @param locale the locale in which the configuration should be written * @param name the name of the configuration * @param configuration the configuration to write * * @return the modified or new XML content * * @throws CmsException if something goes wrong */ protected CmsXmlContent saveInContentObject(CmsObject cms, CmsXmlContent content, Locale locale, String name, CmsContainerConfiguration configuration) throws CmsException { if (content == null) { content = CmsXmlContentFactory.createDocument(cms, locale, (CmsResourceTypeXmlContent) OpenCms.getResourceManager() .getResourceType(CmsResourceTypeXmlContainerPage.INHERIT_CONTAINER_CONFIG_TYPE_NAME)); } if (!content.hasLocale(locale)) { content.addLocale(cms, locale); } Element parentElement = content.getLocaleNode(locale); serializeSingleConfiguration(cms, name, configuration, parentElement); return content; } }