001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.ade.configuration.formatters; 029 030import org.opencms.main.OpenCms; 031import org.opencms.util.CmsStringUtil; 032import org.opencms.util.CmsUUID; 033import org.opencms.xml.containerpage.I_CmsFormatterBean; 034 035import java.util.Collection; 036import java.util.HashMap; 037import java.util.Iterator; 038import java.util.Map; 039import java.util.Map.Entry; 040import java.util.Set; 041import java.util.regex.Pattern; 042 043/** 044 * This class represents the changes which can be made to formatters in a sitemap configuration file.<p> 045 */ 046public class CmsFormatterChangeSet { 047 048 /** The prefix used for types in the Add/RemoveFormatter fields in the configuration. */ 049 public static final String PREFIX_TYPE = "type_"; 050 051 /** The path pattern to match formatters accessible from the current site. */ 052 private Pattern m_pathPattern; 053 054 /** A map which indicates whether schema formatters for a type (which is the key) should be added (value=true) or removed (value=False). */ 055 private Map<String, Boolean> m_typeUpdateSet = new HashMap<String, Boolean>(); 056 057 /** A map which indicates whether a formatter (whose id is the key) should be added (value=true) or removed (value= false). */ 058 private Map<CmsUUID, Boolean> m_updateSet = new HashMap<CmsUUID, Boolean>(); 059 060 /** A flag, indicating if all formatters that are not explicitly added should be removed. */ 061 private boolean m_removeAllNonExplicitlyAdded; 062 063 /** 064 * Creates an empty formatter change set.<p> 065 */ 066 public CmsFormatterChangeSet() { 067 068 // do nothing 069 } 070 071 /** 072 * Creates a new formatter change set.<p> 073 * 074 * @param toRemove the formatter keys to remove 075 * @param toAdd the formatter keys to add 076 * @param siteRoot the site root of the current config 077 * @param removeAllNonExplicitlyAdded flag, indicating if all formatters that are not explicitly added should be removed 078 */ 079 public CmsFormatterChangeSet( 080 Collection<String> toRemove, 081 Collection<String> toAdd, 082 String siteRoot, 083 boolean removeAllNonExplicitlyAdded) { 084 085 this(); 086 initialize(toRemove, toAdd, siteRoot, removeAllNonExplicitlyAdded); 087 } 088 089 /** 090 * Produces the key for a given resource type.<p> 091 * 092 * @param typeName the resource type name 093 * @return the key to use 094 */ 095 public static String keyForType(String typeName) { 096 097 return "type_" + typeName; 098 } 099 100 /** 101 * Applies this change set to a list of external (non schema-based) formatters.<p> 102 * 103 * @param formatters the map of formatters to which the changes should be applied 104 * @param externalFormatters the formatter collection which should be used to add formatters which are not already present in 'formatters' 105 */ 106 public void applyToFormatters( 107 Map<CmsUUID, I_CmsFormatterBean> formatters, 108 CmsFormatterConfigurationCacheState externalFormatters) { 109 110 if (m_removeAllNonExplicitlyAdded) { 111 formatters.clear(); 112 } 113 for (Map.Entry<CmsUUID, Boolean> updateEntry : m_updateSet.entrySet()) { 114 CmsUUID key = updateEntry.getKey(); 115 Boolean value = updateEntry.getValue(); 116 if (value.booleanValue()) { 117 I_CmsFormatterBean addedFormatter = externalFormatters.getFormatters().get(key); 118 if (addedFormatter != null) { 119 formatters.put(key, addedFormatter); 120 } 121 } else { 122 formatters.remove(key); 123 } 124 } 125 if (m_pathPattern != null) { 126 // remove all formatters where the location path does not match the path pattern, this prevents cross site formatter use 127 Iterator<Entry<CmsUUID, I_CmsFormatterBean>> formattersIt = formatters.entrySet().iterator(); 128 while (formattersIt.hasNext()) { 129 Entry<CmsUUID, I_CmsFormatterBean> entry = formattersIt.next(); 130 if ((entry.getValue().getLocation() != null) 131 && !m_pathPattern.matcher(entry.getValue().getLocation()).matches()) { 132 formattersIt.remove(); 133 } 134 } 135 } 136 } 137 138 /** 139 * Applies the changes (addition or removal of schema formatters) to a set of resource type names, 140 * adding resource types for which schema formatters should be added and removing those for which 141 * schema formatters should be removed.<p> 142 * 143 * @param types the set of types to apply the changes to 144 */ 145 public void applyToTypes(Set<String> types) { 146 147 if (m_removeAllNonExplicitlyAdded) { 148 types.clear(); 149 } 150 for (Map.Entry<String, Boolean> typeUpdateEntry : m_typeUpdateSet.entrySet()) { 151 String typeName = typeUpdateEntry.getKey(); 152 Boolean add = typeUpdateEntry.getValue(); 153 if (add.booleanValue()) { 154 types.add(typeName); 155 } else { 156 types.remove(typeName); 157 } 158 } 159 } 160 161 /** 162 * Initializes this formatter change set with the values from the sitemap configuration.<p> 163 * 164 * @param toRemove the keys for the formatters to remove 165 * @param toAdd the keys for the formatters to add 166 * @param siteRoot the site root of the current config 167 * @param removeAllNonExplicitlyAdded flag, indicating if all formatters that are not explicitly added should be removed 168 */ 169 private void initialize( 170 Collection<String> toRemove, 171 Collection<String> toAdd, 172 String siteRoot, 173 boolean removeAllNonExplicitlyAdded) { 174 175 m_removeAllNonExplicitlyAdded = removeAllNonExplicitlyAdded; 176 177 for (String removeKey : toRemove) { 178 if (CmsUUID.isValidUUID(removeKey)) { 179 m_updateSet.put(new CmsUUID(removeKey), Boolean.FALSE); 180 } else if (removeKey.startsWith(PREFIX_TYPE)) { 181 m_typeUpdateSet.put(removePrefix(removeKey), Boolean.FALSE); 182 } 183 } 184 for (String addKey : toAdd) { 185 if (CmsUUID.isValidUUID(addKey)) { 186 m_updateSet.put(new CmsUUID(addKey), Boolean.TRUE); 187 } else if (addKey.startsWith(PREFIX_TYPE)) { 188 m_typeUpdateSet.put(removePrefix(addKey), Boolean.TRUE); 189 } 190 } 191 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(siteRoot)) { 192 if (!siteRoot.endsWith("/")) { 193 siteRoot += "/"; 194 } 195 String regex = "^(/system/|" + OpenCms.getSiteManager().getSharedFolder() + "|" + siteRoot + ").*"; 196 197 m_pathPattern = Pattern.compile(regex); 198 } 199 } 200 201 /** 202 * Removes a prefix from the given key.<p> 203 * 204 * @param key the key 205 * 206 * @return the key with the prefix removed 207 */ 208 private String removePrefix(String key) { 209 210 if (key.startsWith(PREFIX_TYPE)) { 211 return key.substring(PREFIX_TYPE.length()); 212 } 213 return key; 214 } 215 216}