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.workplace.tools.modules; 029 030import org.opencms.ade.configuration.CmsADEManager; 031import org.opencms.ade.configuration.CmsConfigurationReader; 032import org.opencms.ade.configuration.formatters.CmsFormatterBeanParser; 033import org.opencms.ade.configuration.formatters.CmsFormatterConfigurationCache; 034import org.opencms.file.CmsFile; 035import org.opencms.file.CmsObject; 036import org.opencms.file.CmsProject; 037import org.opencms.file.CmsResource; 038import org.opencms.file.CmsUser; 039import org.opencms.file.types.CmsResourceTypeFolder; 040import org.opencms.file.types.CmsResourceTypeXmlContent; 041import org.opencms.file.types.I_CmsResourceType; 042import org.opencms.i18n.CmsLocaleManager; 043import org.opencms.i18n.CmsVfsBundleManager; 044import org.opencms.lock.CmsLock; 045import org.opencms.main.CmsEvent; 046import org.opencms.main.CmsException; 047import org.opencms.main.CmsIllegalArgumentException; 048import org.opencms.main.CmsLog; 049import org.opencms.main.I_CmsEventListener; 050import org.opencms.main.OpenCms; 051import org.opencms.module.CmsModule; 052import org.opencms.module.Messages; 053import org.opencms.report.A_CmsReportThread; 054import org.opencms.report.I_CmsReport; 055import org.opencms.util.CmsFileUtil; 056import org.opencms.util.CmsStringUtil; 057import org.opencms.workplace.explorer.CmsExplorerTypeSettings; 058import org.opencms.xml.content.CmsVfsBundleLoaderXml; 059import org.opencms.xml.content.CmsXmlContent; 060import org.opencms.xml.content.CmsXmlContentFactory; 061import org.opencms.xml.types.I_CmsXmlContentValue; 062 063import java.io.UnsupportedEncodingException; 064import java.util.ArrayList; 065import java.util.Collections; 066import java.util.HashMap; 067import java.util.List; 068import java.util.Locale; 069import java.util.Map; 070import java.util.Map.Entry; 071 072import org.apache.commons.logging.Log; 073 074import org.dom4j.Element; 075 076/** 077 * The report thread to add a new resource type to a module and publish all related resources.<p> 078 */ 079public class CmsModuleAddResourceTypeThread extends A_CmsReportThread { 080 081 /** Message key prefix. */ 082 private static final String KEY_PREFIX_DESCRIPTION = "desc."; 083 084 /** Message key prefix. */ 085 private static final String KEY_PREFIX_NAME = "fileicon."; 086 087 /** Message key prefix. */ 088 private static final String KEY_PREFIX_TITLE = "title."; 089 090 /** The log object for this class. */ 091 private static final Log LOG = CmsLog.getLog(CmsModuleAddResourceTypeThread.class); 092 093 /** Message bundle folder name. */ 094 private static final String PATH_I18N = "i18n"; 095 096 /** Message properties file encoding. */ 097 private static final String PROPERTIES_ENCODING = "ISO-8859-1"; 098 099 /** Message properties file name. */ 100 private static final String PROPERTIES_FILE_NAME = "workplace.properties"; 101 102 /** Sample file. */ 103 private static final String SAMPLE_FORMATTER = "/system/modules/org.opencms.workplace.tools.modules/samples/sample-formatter.jsp"; 104 105 /** Sample file. */ 106 private static final String SAMPLE_ICON_BIG = "/system/modules/org.opencms.workplace.tools.modules/samples/sample-icon_big.png"; 107 108 /** Sample file. */ 109 private static final String SAMPLE_ICON_SMALL = "/system/modules/org.opencms.workplace.tools.modules/samples/sample-icon.png"; 110 111 /** Sample file. */ 112 private static final String SAMPLE_SCHEMA = "/system/modules/org.opencms.workplace.tools.modules/samples/sample-schema.xsd"; 113 114 /** The sample schema type name. */ 115 private static final String SAMPLE_SCHEMA_TYPE_NAME = "SampleType"; 116 117 /** Message bundle file name suffix. */ 118 private static final String SUFFIX_BUNDLE_FILE = ".workplace"; 119 120 /** The resource type information. */ 121 private CmsResourceTypeInfoBean m_resInfo; 122 123 /** 124 * Constructor.<p> 125 * 126 * @param cms the cms context 127 * @param resInfo the resource type information 128 */ 129 protected CmsModuleAddResourceTypeThread(CmsObject cms, CmsResourceTypeInfoBean resInfo) { 130 131 super(cms, resInfo.getName()); 132 m_resInfo = resInfo; 133 initHtmlReport(cms.getRequestContext().getLocale()); 134 } 135 136 /** 137 * @see org.opencms.report.A_CmsReportThread#getReportUpdate() 138 */ 139 @Override 140 public String getReportUpdate() { 141 142 return getReport().getReportUpdate(); 143 } 144 145 /** 146 * @see java.lang.Thread#run() 147 */ 148 @Override 149 public void run() { 150 151 CmsObject cms = getCms(); 152 CmsProject currentProject = cms.getRequestContext().getCurrentProject(); 153 try { 154 CmsProject workProject = cms.createProject( 155 "Add_resource_type_project", 156 "Add resource type project", 157 OpenCms.getDefaultUsers().getGroupAdministrators(), 158 OpenCms.getDefaultUsers().getGroupAdministrators(), 159 CmsProject.PROJECT_TYPE_TEMPORARY); 160 cms.getRequestContext().setCurrentProject(workProject); 161 CmsModule module = OpenCms.getModuleManager().getModule(m_resInfo.getModuleName()).clone(); 162 String moduleFolder = CmsStringUtil.joinPaths("/system/modules/", m_resInfo.getModuleName()); 163 copySampleFiles(module, moduleFolder); 164 List<I_CmsResourceType> types = new ArrayList<I_CmsResourceType>(module.getResourceTypes()); 165 // create the new resource type 166 CmsResourceTypeXmlContent type = new CmsResourceTypeXmlContent(); 167 type.addConfigurationParameter(CmsResourceTypeXmlContent.CONFIGURATION_SCHEMA, m_resInfo.getSchema()); 168 type.setAdditionalModuleResourceType(true); 169 type.setModuleName(m_resInfo.getModuleName()); 170 type.initConfiguration( 171 m_resInfo.getName(), 172 String.valueOf(m_resInfo.getId()), 173 CmsResourceTypeXmlContent.class.getName()); 174 types.add(type); 175 module.setResourceTypes(types); 176 177 List<CmsExplorerTypeSettings> settings = new ArrayList<CmsExplorerTypeSettings>(module.getExplorerTypes()); 178 // create the matching explorer type 179 CmsExplorerTypeSettings setting = new CmsExplorerTypeSettings(); 180 setting.setTypeAttributes( 181 m_resInfo.getName(), 182 m_resInfo.getNiceName(), 183 m_resInfo.getSmallIcon(), 184 m_resInfo.getBigIcon(), 185 null, 186 null, 187 "xmlcontent", 188 null, 189 "false", 190 null, 191 null); 192 setting.setAutoSetNavigation("false"); 193 setting.setAutoSetTitle("false"); 194 setting.setNewResourceOrder("10"); 195 setting.setAddititionalModuleExplorerType(true); 196 addTypeMessages(setting, moduleFolder); 197 settings.add(setting); 198 module.setExplorerTypes(settings); 199 createSampleFormatter(moduleFolder); 200 // now unlock and publish the project 201 getReport().println( 202 Messages.get().container(Messages.RPT_PUBLISH_PROJECT_BEGIN_0), 203 I_CmsReport.FORMAT_HEADLINE); 204 cms.unlockProject(workProject.getUuid()); 205 OpenCms.getPublishManager().publishProject(cms, getReport()); 206 OpenCms.getPublishManager().waitWhileRunning(); 207 208 getReport().println( 209 Messages.get().container(Messages.RPT_PUBLISH_PROJECT_END_0), 210 I_CmsReport.FORMAT_HEADLINE); 211 212 // write the module configuration, init resource types, explorer types and clear OpenCms caches 213 OpenCms.getModuleManager().updateModule(cms, module); 214 OpenCms.getResourceManager().initialize(cms); 215 OpenCms.getWorkplaceManager().addExplorerTypeSettings(module); 216 OpenCms.fireCmsEvent( 217 new CmsEvent(I_CmsEventListener.EVENT_CLEAR_CACHES, Collections.<String, Object> emptyMap())); 218 // re-initialize the workplace 219 OpenCms.getWorkplaceManager().initialize(getCms()); 220 } catch (Exception e) { 221 LOG.error(e.getLocalizedMessage(), e); 222 getReport().addError(e); 223 } finally { 224 cms.getRequestContext().setCurrentProject(currentProject); 225 } 226 } 227 228 /** 229 * Adds the given messages to the workplace properties file.<p> 230 * 231 * @param messages the messages 232 * @param propertiesFile the properties file 233 * @param forcePropertyFileEncoding flag, indicating if encoding {@link #PROPERTIES_ENCODING} should be forced 234 * 235 * @throws CmsException if writing the properties fails 236 * @throws UnsupportedEncodingException in case of encoding issues 237 */ 238 private void addMessagesToPropertiesFile( 239 Map<String, String> messages, 240 CmsFile propertiesFile, 241 boolean forcePropertyFileEncoding) 242 throws CmsException, UnsupportedEncodingException { 243 244 lockTemporary(propertiesFile); 245 String encoding = forcePropertyFileEncoding 246 ? PROPERTIES_ENCODING 247 : CmsFileUtil.getEncoding(getCms(), propertiesFile); 248 StringBuffer contentBuffer = new StringBuffer(); 249 contentBuffer.append(new String(propertiesFile.getContents(), encoding)); 250 for (Entry<String, String> entry : messages.entrySet()) { 251 contentBuffer.append("\n"); 252 contentBuffer.append(entry.getKey()); 253 contentBuffer.append("="); 254 contentBuffer.append(entry.getValue()); 255 } 256 contentBuffer.append("\n"); 257 propertiesFile.setContents(contentBuffer.toString().getBytes(encoding)); 258 getCms().writeFile(propertiesFile); 259 } 260 261 /** 262 * Adds the given messages to the vfs message bundle.<p> 263 * 264 * @param messages the messages 265 * @param vfsBundleFile the bundle file 266 * 267 * @throws CmsException if something goes wrong writing the file 268 */ 269 private void addMessagesToVfsBundle(Map<String, String> messages, CmsFile vfsBundleFile) throws CmsException { 270 271 lockTemporary(vfsBundleFile); 272 CmsObject cms = getCms(); 273 CmsXmlContent content = CmsXmlContentFactory.unmarshal(cms, vfsBundleFile); 274 Locale locale = CmsLocaleManager.getDefaultLocale(); 275 if (!content.hasLocale(locale)) { 276 content.addLocale(cms, locale); 277 } 278 Element root = content.getLocaleNode(locale); 279 for (Entry<String, String> entry : messages.entrySet()) { 280 Element message = root.addElement(CmsVfsBundleLoaderXml.N_MESSAGE); 281 Element key = message.addElement(CmsVfsBundleLoaderXml.N_KEY); 282 key.setText(entry.getKey()); 283 Element value = message.addElement(CmsVfsBundleLoaderXml.N_VALUE); 284 value.setText(entry.getValue()); 285 } 286 content.initDocument(); 287 vfsBundleFile.setContents(content.marshal()); 288 cms.writeFile(vfsBundleFile); 289 } 290 291 /** 292 * Adds the explorer type messages to the modules workplace bundle.<p> 293 * 294 * @param setting the explorer type settings 295 * @param moduleFolder the module folder name 296 * 297 * @throws CmsException if writing the bundle fails 298 * @throws UnsupportedEncodingException in case of encoding issues 299 */ 300 private void addTypeMessages(CmsExplorerTypeSettings setting, String moduleFolder) 301 throws CmsException, UnsupportedEncodingException { 302 303 Map<String, String> messages = new HashMap<String, String>(); 304 CmsObject cms = getCms(); 305 // check if any messages to set 306 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_resInfo.getNiceName())) { 307 String key = KEY_PREFIX_NAME + m_resInfo.getName(); 308 messages.put(key, m_resInfo.getNiceName()); 309 setting.setKey(key); 310 } 311 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_resInfo.getDescription())) { 312 String key = KEY_PREFIX_DESCRIPTION + m_resInfo.getName(); 313 messages.put(key, m_resInfo.getDescription()); 314 setting.setInfo(key); 315 } 316 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_resInfo.getTitle())) { 317 String key = KEY_PREFIX_TITLE + m_resInfo.getName(); 318 messages.put(key, m_resInfo.getTitle()); 319 setting.setTitleKey(key); 320 } 321 if (!messages.isEmpty()) { 322 // add the messages to the module's workplace bundle 323 324 //1. check if the bundle exists as raw Java bundle 325 String workplacePropertiesFile = CmsStringUtil.joinPaths( 326 moduleFolder, 327 CmsModulesEditBase.PATH_CLASSES, 328 m_resInfo.getModuleName().replace(".", "/"), 329 PROPERTIES_FILE_NAME); 330 if (cms.existsResource(workplacePropertiesFile)) { 331 addMessagesToPropertiesFile(messages, cms.readFile(workplacePropertiesFile), true); 332 } else { 333 //2. check if the bundle exists as XML bundle 334 String vfsBundleFileName = CmsStringUtil.joinPaths( 335 moduleFolder, 336 PATH_I18N, 337 m_resInfo.getModuleName() + SUFFIX_BUNDLE_FILE); 338 OpenCms.getLocaleManager(); 339 if (cms.existsResource(vfsBundleFileName)) { 340 addMessagesToVfsBundle(messages, cms.readFile(vfsBundleFileName)); 341 } else { 342 //3. check if the bundle exists as property bundle 343 // we always write to the default locale 344 String propertyBundleFileName = vfsBundleFileName + "_" + CmsLocaleManager.getDefaultLocale(); 345 if (!cms.existsResource(propertyBundleFileName)) { 346 //if non of the checked bundles exist, create one. 347 String bundleFolder = CmsStringUtil.joinPaths(moduleFolder, PATH_I18N); 348 if (!cms.existsResource(bundleFolder)) { 349 cms.createResource( 350 bundleFolder, 351 OpenCms.getResourceManager().getResourceType( 352 CmsResourceTypeFolder.getStaticTypeName())); 353 } 354 CmsResource res = cms.createResource( 355 propertyBundleFileName, 356 OpenCms.getResourceManager().getResourceType(CmsVfsBundleManager.TYPE_PROPERTIES_BUNDLE), 357 null, 358 null); 359 cms.writeResource(res); 360 } 361 addMessagesToPropertiesFile(messages, cms.readFile(propertyBundleFileName), false); 362 } 363 364 } 365 } 366 } 367 368 /** 369 * Copies sample schema and resource type icons and adds the resources to the module.<p> 370 * 371 * @param module the module 372 * @param moduleFolder the module folder name 373 * 374 * @throws CmsIllegalArgumentException in case something goes wrong copying the resources 375 * @throws CmsException in case something goes wrong copying the resources 376 */ 377 private void copySampleFiles(CmsModule module, String moduleFolder) 378 throws CmsIllegalArgumentException, CmsException { 379 380 CmsObject cms = getCms(); 381 List<String> moduleResource = new ArrayList<String>(module.getResources()); 382 if (!cms.existsResource(moduleFolder)) { 383 cms.createResource(moduleFolder, CmsResourceTypeFolder.getStaticTypeId()); 384 moduleResource.add(moduleFolder); 385 } 386 String schemaFolder = CmsStringUtil.joinPaths(moduleFolder, "schemas"); 387 if (!cms.existsResource(schemaFolder)) { 388 cms.createResource(schemaFolder, CmsResourceTypeFolder.getStaticTypeId()); 389 } 390 String schemaFile = CmsStringUtil.joinPaths(schemaFolder, m_resInfo.getName() + ".xsd"); 391 if (!cms.existsResource(schemaFile)) { 392 cms.copyResource(SAMPLE_SCHEMA, schemaFile, CmsResource.COPY_AS_NEW); 393 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_resInfo.getSchemaTypeName())) { 394 // replace the sample schema type name with the provided name 395 try { 396 CmsFile schema = cms.readFile(schemaFile); 397 OpenCms.getLocaleManager(); 398 String schemaContent = new String( 399 schema.getContents(), 400 CmsLocaleManager.getResourceEncoding(cms, schema)); 401 schemaContent = schemaContent.replaceAll(SAMPLE_SCHEMA_TYPE_NAME, m_resInfo.getSchemaTypeName()); 402 schema.setContents(schemaContent.getBytes()); 403 cms.writeFile(schema); 404 } catch (Exception e) { 405 LOG.error(e.getLocalizedMessage(), e); 406 getReport().addError(e); 407 } 408 } 409 410 } 411 m_resInfo.setSchema(schemaFile); 412 String filetypesFolder = "/system/workplace/resources/filetypes/"; 413 String smallIcon = CmsStringUtil.joinPaths(filetypesFolder, m_resInfo.getName() + ".png"); 414 if (!cms.existsResource(smallIcon)) { 415 cms.copyResource(SAMPLE_ICON_SMALL, smallIcon, CmsResource.COPY_AS_NEW); 416 moduleResource.add(smallIcon); 417 } 418 m_resInfo.setSmallIcon(m_resInfo.getName() + ".png"); 419 String bigIcon = CmsStringUtil.joinPaths(filetypesFolder, m_resInfo.getName() + "_big.png"); 420 if (!cms.existsResource(bigIcon)) { 421 cms.copyResource(SAMPLE_ICON_BIG, bigIcon, CmsResource.COPY_AS_NEW); 422 moduleResource.add(bigIcon); 423 } 424 m_resInfo.setBigIcon(m_resInfo.getName() + "_big.png"); 425 module.setResources(moduleResource); 426 } 427 428 /** 429 * Copies the sample formatter JSP, creates the associated formatter and module configuration.<p> 430 * 431 * @param moduleFolder the module folder name 432 * 433 * @throws CmsIllegalArgumentException in case something goes wrong copying the resources 434 * @throws CmsException in case something goes wrong copying the resources 435 */ 436 private void createSampleFormatter(String moduleFolder) throws CmsIllegalArgumentException, CmsException { 437 438 CmsObject cms = getCms(); 439 String formatterFolder = CmsStringUtil.joinPaths(moduleFolder, CmsModulesEditBase.PATH_FORMATTERS); 440 if (!cms.existsResource(formatterFolder)) { 441 cms.createResource(formatterFolder, CmsResourceTypeFolder.getStaticTypeId()); 442 } 443 String formatterJSP = CmsStringUtil.joinPaths(formatterFolder, m_resInfo.getName() + "-formatter.jsp"); 444 if (!cms.existsResource(formatterJSP)) { 445 cms.copyResource(SAMPLE_FORMATTER, formatterJSP, CmsResource.COPY_AS_NEW); 446 } 447 String formatterConfig = CmsStringUtil.joinPaths( 448 formatterFolder, 449 m_resInfo.getName() + "-formatter-config.xml"); 450 if (!cms.existsResource(formatterConfig)) { 451 452 cms.createResource( 453 formatterConfig, 454 OpenCms.getResourceManager().getResourceType( 455 CmsFormatterConfigurationCache.TYPE_FORMATTER_CONFIG).getTypeId()); 456 CmsFile configFile = cms.readFile(formatterConfig); 457 CmsXmlContent configContent = CmsXmlContentFactory.unmarshal(cms, configFile); 458 if (!configContent.hasLocale(CmsConfigurationReader.DEFAULT_LOCALE)) { 459 configContent.addLocale(cms, CmsConfigurationReader.DEFAULT_LOCALE); 460 } 461 I_CmsXmlContentValue typeValue = configContent.getValue( 462 CmsFormatterBeanParser.N_TYPE, 463 CmsConfigurationReader.DEFAULT_LOCALE); 464 typeValue.setStringValue(cms, m_resInfo.getName()); 465 I_CmsXmlContentValue formatterValue = configContent.getValue( 466 CmsFormatterBeanParser.N_JSP, 467 CmsConfigurationReader.DEFAULT_LOCALE); 468 formatterValue.setStringValue(cms, formatterJSP); 469 I_CmsXmlContentValue formatterNameValue = configContent.getValue( 470 CmsFormatterBeanParser.N_NICE_NAME, 471 CmsConfigurationReader.DEFAULT_LOCALE); 472 formatterNameValue.setStringValue( 473 cms, 474 "Sample formatter for " 475 + (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_resInfo.getNiceName()) 476 ? m_resInfo.getNiceName() 477 : m_resInfo.getName())); 478 // set matching container width to '-1' to fit everywhere 479 configContent.addValue(cms, CmsFormatterBeanParser.N_MATCH, CmsConfigurationReader.DEFAULT_LOCALE, 0); 480 configContent.addValue( 481 cms, 482 CmsFormatterBeanParser.N_MATCH + "/" + CmsFormatterBeanParser.N_WIDTH, 483 CmsConfigurationReader.DEFAULT_LOCALE, 484 0); 485 I_CmsXmlContentValue widthValue = configContent.getValue( 486 CmsFormatterBeanParser.N_MATCH 487 + "/" 488 + CmsFormatterBeanParser.N_WIDTH 489 + "/" 490 + CmsFormatterBeanParser.N_WIDTH, 491 CmsConfigurationReader.DEFAULT_LOCALE); 492 widthValue.setStringValue(cms, "-1"); 493 494 // enable the formatter 495 I_CmsXmlContentValue enabledValue = configContent.getValue( 496 CmsFormatterBeanParser.N_AUTO_ENABLED, 497 CmsConfigurationReader.DEFAULT_LOCALE); 498 enabledValue.setStringValue(cms, Boolean.TRUE.toString()); 499 configFile.setContents(configContent.marshal()); 500 cms.writeFile(configFile); 501 } 502 String moduleConfig = CmsStringUtil.joinPaths(moduleFolder, ".config"); 503 if (!cms.existsResource(moduleConfig)) { 504 cms.createResource( 505 moduleConfig, 506 OpenCms.getResourceManager().getResourceType(CmsADEManager.MODULE_CONFIG_TYPE).getTypeId()); 507 } 508 CmsFile moduleConfigFile = cms.readFile(moduleConfig); 509 lockTemporary(moduleConfigFile); 510 CmsXmlContent moduleConfigContent = CmsXmlContentFactory.unmarshal(cms, moduleConfigFile); 511 I_CmsXmlContentValue resourceTypeValue = moduleConfigContent.addValue( 512 cms, 513 CmsConfigurationReader.N_RESOURCE_TYPE, 514 CmsConfigurationReader.DEFAULT_LOCALE, 515 0); 516 I_CmsXmlContentValue typeValue = moduleConfigContent.getValue( 517 resourceTypeValue.getPath() + "/" + CmsConfigurationReader.N_TYPE_NAME, 518 CmsConfigurationReader.DEFAULT_LOCALE); 519 typeValue.setStringValue(cms, m_resInfo.getName()); 520 moduleConfigFile.setContents(moduleConfigContent.marshal()); 521 cms.writeFile(moduleConfigFile); 522 } 523 524 /** 525 * Locks the given resource temporarily.<p> 526 * 527 * @param resource the resource to lock 528 * 529 * @throws CmsException if locking fails 530 */ 531 private void lockTemporary(CmsResource resource) throws CmsException { 532 533 CmsObject cms = getCms(); 534 CmsUser user = cms.getRequestContext().getCurrentUser(); 535 CmsLock lock = cms.getLock(resource); 536 if (!lock.isOwnedBy(user)) { 537 cms.lockResourceTemporary(resource); 538 } else if (!lock.isOwnedInProjectBy(user, cms.getRequestContext().getCurrentProject())) { 539 cms.changeLock(resource); 540 } 541 } 542}