001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (C) Alkacon Software (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.postupload; 029 030import org.opencms.ade.configuration.CmsADEConfigData; 031import org.opencms.ade.postupload.shared.CmsPostUploadDialogBean; 032import org.opencms.ade.postupload.shared.CmsPostUploadDialogPanelBean; 033import org.opencms.ade.postupload.shared.I_CmsDialogConstants; 034import org.opencms.ade.postupload.shared.rpc.I_CmsPostUploadDialogService; 035import org.opencms.file.CmsObject; 036import org.opencms.file.CmsProperty; 037import org.opencms.file.CmsPropertyDefinition; 038import org.opencms.file.CmsResource; 039import org.opencms.file.types.I_CmsResourceType; 040import org.opencms.flex.CmsFlexController; 041import org.opencms.gwt.CmsGwtService; 042import org.opencms.gwt.CmsPropertyEditorHelper; 043import org.opencms.gwt.CmsRpcException; 044import org.opencms.gwt.CmsVfsService; 045import org.opencms.gwt.shared.CmsListInfoBean; 046import org.opencms.gwt.shared.property.CmsClientProperty; 047import org.opencms.gwt.shared.property.CmsPropertyModification; 048import org.opencms.main.CmsException; 049import org.opencms.main.CmsLog; 050import org.opencms.main.OpenCms; 051import org.opencms.util.CmsMacroResolver; 052import org.opencms.util.CmsStringUtil; 053import org.opencms.util.CmsUUID; 054import org.opencms.workplace.explorer.CmsExplorerTypeSettings; 055import org.opencms.xml.content.CmsXmlContentProperty; 056import org.opencms.xml.content.CmsXmlContentPropertyHelper; 057 058import java.util.ArrayList; 059import java.util.HashSet; 060import java.util.LinkedHashMap; 061import java.util.LinkedHashSet; 062import java.util.List; 063import java.util.Locale; 064import java.util.Map; 065import java.util.Set; 066import java.util.stream.Collectors; 067 068import javax.servlet.http.HttpServletRequest; 069 070import org.apache.commons.logging.Log; 071 072import com.google.common.collect.Iterables; 073 074/** 075 * The service implementation for the org.opencms.ade.postupload module.<p> 076 */ 077public class CmsPostUploadDialogService extends CmsGwtService implements I_CmsPostUploadDialogService { 078 079 /** Serial version id. */ 080 private static final long serialVersionUID = 1L; 081 082 /** Logger instance for this class. */ 083 private static final Log LOG = CmsLog.getLog(CmsPostUploadDialogService.class); 084 085 /** 086 * Creates a new instance.<p> 087 */ 088 public CmsPostUploadDialogService() { 089 090 super(); 091 } 092 093 /** 094 * Fetches the dialog data.<p> 095 * 096 * @param request the servlet request 097 * 098 * @return the dialog data 099 * @throws CmsRpcException if something goes wrong 100 */ 101 public static CmsPostUploadDialogBean prefetch(HttpServletRequest request) throws CmsRpcException { 102 103 CmsPostUploadDialogService srv = new CmsPostUploadDialogService(); 104 srv.setCms(CmsFlexController.getCmsObject(request)); 105 srv.setRequest(request); 106 CmsPostUploadDialogBean result = null; 107 try { 108 result = srv.prefetch(); 109 } finally { 110 srv.clearThreadStorage(); 111 } 112 return result; 113 } 114 115 /** 116 * @see org.opencms.ade.postupload.shared.rpc.I_CmsPostUploadDialogService#load(org.opencms.util.CmsUUID, boolean,boolean) 117 */ 118 public CmsPostUploadDialogPanelBean load(CmsUUID id, boolean useConfiguration, boolean addBasicProperties) 119 throws CmsRpcException { 120 121 try { 122 CmsResource res = getCmsObject().readResource(id); 123 List<CmsProperty> properties = getCmsObject().readPropertyObjects(res, false); 124 String title = CmsProperty.get(CmsPropertyDefinition.PROPERTY_TITLE, properties).getValue(); 125 if (title == null) { 126 title = res.getName(); 127 } 128 String description = CmsProperty.get(CmsPropertyDefinition.PROPERTY_DESCRIPTION, properties).getValue(); 129 if (description == null) { 130 description = getCmsObject().getSitePath(res); 131 } 132 CmsListInfoBean listInfo = CmsVfsService.getPageInfo(getCmsObject(), res); 133 134 CmsPostUploadDialogPanelBean result = new CmsPostUploadDialogPanelBean(id, listInfo); 135 String warning = OpenCms.getADEManager().getUploadWarningTable().getMessage(res.getStructureId()); 136 if (warning != null) { 137 Locale wpLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(getCmsObject()); 138 CmsMacroResolver resolver = new CmsMacroResolver(); 139 resolver.setMessages(OpenCms.getWorkplaceManager().getMessages(wpLocale)); 140 warning = resolver.resolveMacros(warning); 141 result.setWarning(warning); 142 } 143 144 I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(res.getTypeId()); 145 String typeName = type.getTypeName(); 146 listInfo.setResourceType(typeName); 147 148 CmsExplorerTypeSettings settings = OpenCms.getWorkplaceManager().getExplorerTypeSetting(typeName); 149 150 List<String> defaultProperties = settings.getProperties(); 151 while (properties.isEmpty() && !CmsStringUtil.isEmptyOrWhitespaceOnly(settings.getReference())) { 152 settings = OpenCms.getWorkplaceManager().getExplorerTypeSetting(settings.getReference()); 153 defaultProperties = settings.getProperties(); 154 } 155 156 Map<String, CmsXmlContentProperty> propertyDefinitions = new LinkedHashMap<String, CmsXmlContentProperty>(); 157 Map<String, CmsClientProperty> clientProperties = new LinkedHashMap<String, CmsClientProperty>(); 158 159 // add the file name to the list of properties to allow renaming the uploaded file 160 CmsXmlContentProperty fileNamePropDef = new CmsXmlContentProperty( 161 CmsPropertyModification.FILE_NAME_PROPERTY, 162 "string", 163 "string", 164 "", 165 "", 166 "", 167 "", 168 Messages.get().getBundle(OpenCms.getWorkplaceManager().getWorkplaceLocale(getCmsObject())).key( 169 Messages.GUI_UPLOAD_FILE_NAME_0), 170 "", 171 "", 172 "false"); 173 propertyDefinitions.put(CmsPropertyModification.FILE_NAME_PROPERTY, fileNamePropDef); 174 clientProperties.put( 175 CmsPropertyModification.FILE_NAME_PROPERTY, 176 new CmsClientProperty(CmsPropertyModification.FILE_NAME_PROPERTY, res.getName(), res.getName())); 177 178 CmsADEConfigData configData = OpenCms.getADEManager().lookupConfiguration( 179 getCmsObject(), 180 res.getRootPath()); 181 Map<String, CmsXmlContentProperty> propertyConfiguration = configData.getPropertyConfigurationAsMap(); 182 183 Set<String> propertiesToShow = new LinkedHashSet<String>(); 184 propertiesToShow.addAll(defaultProperties); 185 if (addBasicProperties) { 186 propertiesToShow.addAll(propertyConfiguration.keySet()); 187 } 188 Set<String> requiredProperties = getRequiredProperties(getCmsObject(), res); 189 for (String propertyName : propertiesToShow) { 190 CmsXmlContentProperty propDef = null; 191 if (useConfiguration) { 192 propDef = propertyConfiguration.get(propertyName); 193 } 194 if (propDef == null) { 195 propDef = new CmsXmlContentProperty( 196 propertyName, 197 "string", 198 "string", 199 "", 200 "", 201 "", 202 "", 203 null, 204 "", 205 "", 206 "false"); 207 } 208 if (requiredProperties.contains(propertyName)) { 209 String validationErrorMessage = Messages.get().getBundle( 210 OpenCms.getWorkplaceManager().getWorkplaceLocale(getCmsObject())).key( 211 Messages.GUI_POSTUPLOAD_REQUIRED_PROPERTY_1, 212 propertyName); 213 propDef = propDef.withValidation(".*?[^ ].*", "error", validationErrorMessage); 214 } 215 216 propertyDefinitions.put(propertyName, propDef); 217 CmsProperty property = CmsProperty.get(propertyName, properties); 218 if (property != null) { 219 CmsClientProperty clientProperty = new CmsClientProperty( 220 propertyName, 221 property.getStructureValue(), 222 property.getResourceValue()); 223 clientProperties.put(clientProperty.getName(), clientProperty); 224 } 225 } 226 227 propertyDefinitions = CmsXmlContentPropertyHelper.resolveMacrosInProperties( 228 propertyDefinitions, 229 CmsMacroResolver.newWorkplaceLocaleResolver(getCmsObject())); 230 231 CmsPropertyEditorHelper.updateWysiwygConfig(propertyDefinitions, getCmsObject(), res); 232 233 result.setPropertyDefinitions(propertyDefinitions); 234 result.setProperties(clientProperties); 235 return result; 236 } catch (CmsException e) { 237 error(e); 238 return null; // will never be reached 239 } 240 } 241 242 /** 243 * @see org.opencms.ade.postupload.shared.rpc.I_CmsPostUploadDialogService#prefetch() 244 */ 245 public CmsPostUploadDialogBean prefetch() throws CmsRpcException { 246 247 try { 248 249 List<CmsResource> resources = new ArrayList<>(); 250 251 if ((CmsStringUtil.isNotEmptyOrWhitespaceOnly( 252 getRequest().getParameter(I_CmsDialogConstants.PARAM_RESOURCES)))) { 253 // if the request parameter resources exists and contains a list of UUIDs 254 // this dialog is used as upload hook 255 String resourcesParam = getRequest().getParameter(I_CmsDialogConstants.PARAM_RESOURCES); 256 List<String> resourceUUIDs = CmsStringUtil.splitAsList(resourcesParam, ","); 257 for (String uuidAsString : resourceUUIDs) { 258 CmsUUID uuid = new CmsUUID(uuidAsString); 259 CmsResource res = getCmsObject().readResource(uuid); 260 resources.add(res); 261 } 262 } else if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(getRequest().getParameter("resource"))) { 263 // if there was no parameter "resources" set as request parameter 264 // this dialog is not used as upload hook try to read the resource parameter 265 String resourceParam = getRequest().getParameter("resource"); 266 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(resourceParam)) { 267 CmsResource res = getCmsObject().readResource(resourceParam); 268 resources.add(res); 269 } 270 } 271 return createUploadDialogBean(resources); 272 } catch (CmsException e) { 273 error(e); 274 return null; // will never be reached 275 } 276 } 277 278 /** 279 * Creates the data bean for the dialog from the list of created resources. 280 * 281 * @param resources the resources 282 * @return the data bean for the dialog 283 */ 284 private CmsPostUploadDialogBean createUploadDialogBean(List<CmsResource> resources) { 285 286 Map<CmsUUID, String> result = new LinkedHashMap<>(); 287 CmsObject cms = getCmsObject(); 288 // split resource list into two parts, ones that have required properties and ones that don't, 289 // then iterate over the ones with required properties first. 290 // 291 // this is because the buttons in the upload property dialog only trigger validation for the current tab, 292 // so we want the user to go through all resources which require validation first before they can exit the dialog. 293 Map<Boolean, List<CmsResource>> parts = resources.stream().collect( 294 Collectors.partitioningBy(res -> getRequiredProperties(cms, res).size() > 0)); 295 296 for (CmsResource res : Iterables.concat(parts.get(Boolean.TRUE), parts.get(Boolean.FALSE))) { 297 result.put(res.getStructureId(), cms.getRequestContext().removeSiteRoot(res.getRootPath())); 298 } 299 Set<CmsUUID> reqValIds = parts.get(Boolean.TRUE).stream().map(res -> res.getStructureId()).collect( 300 Collectors.toSet()); 301 return new CmsPostUploadDialogBean(result, reqValIds); 302 } 303 304 /** 305 * Gets the properties required for the given resource (as defined by the requiredOnUpload setting on the corresponding explorertype). 306 * 307 * @param cms the CMS context 308 * @param res a resource 309 * @return the set of required properties 310 */ 311 private Set<String> getRequiredProperties(CmsObject cms, CmsResource res) { 312 313 Set<String> requiredProps = new HashSet<>(); 314 try { 315 String typeName = OpenCms.getResourceManager().getResourceType(res).getTypeName(); 316 CmsExplorerTypeSettings explorerType = OpenCms.getWorkplaceManager().getExplorerTypeSetting(typeName); 317 if (explorerType != null) { 318 for (String prop : explorerType.getProperties()) { 319 if (explorerType.isPropertyRequiredOnUpload(prop)) { 320 requiredProps.add(prop); 321 } 322 } 323 } 324 } catch (Exception e) { 325 LOG.error(e.getLocalizedMessage(), e); 326 return requiredProps; 327 } 328 return requiredProps; 329 } 330 331}