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 GmbH & Co. KG, 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.repository; 029 030import org.opencms.file.CmsFile; 031import org.opencms.file.CmsResource; 032import org.opencms.file.CmsResourceFilter; 033import org.opencms.file.CmsUser; 034import org.opencms.file.CmsVfsResourceAlreadyExistsException; 035import org.opencms.file.CmsVfsResourceNotFoundException; 036import org.opencms.file.types.CmsResourceTypeFolder; 037import org.opencms.file.wrapper.CmsObjectWrapper; 038import org.opencms.lock.CmsLock; 039import org.opencms.main.CmsException; 040import org.opencms.main.CmsLog; 041import org.opencms.main.OpenCms; 042import org.opencms.security.CmsSecurityException; 043import org.opencms.util.CmsFileUtil; 044 045import java.io.IOException; 046import java.io.InputStream; 047import java.util.ArrayList; 048import java.util.Iterator; 049import java.util.List; 050 051import org.apache.commons.logging.Log; 052 053/** 054 * This is the session class to work with the {@link CmsRepository}.<p> 055 * 056 * You can get an instance of this class by calling 057 * {@link CmsRepository#login(String, String)}.<p> 058 * 059 * This class provides basic file and folder operations on the resources 060 * in the VFS of OpenCms.<p> 061 * 062 * @see A_CmsRepositorySession 063 * @see I_CmsRepositorySession 064 * 065 * @since 6.5.6 066 */ 067public class CmsRepositorySession extends A_CmsRepositorySession { 068 069 /** The log object for this class. */ 070 private static final Log LOG = CmsLog.getLog(CmsRepositorySession.class); 071 072 /** The initialized {@link CmsObjectWrapper}. */ 073 private final CmsObjectWrapper m_cms; 074 075 /** 076 * Constructor with an initialized {@link CmsObjectWrapper} and a 077 * {@link CmsRepositoryFilter} to use.<p> 078 * 079 * @param cms the initialized CmsObject 080 * @param filter the repository filter to use 081 */ 082 public CmsRepositorySession(CmsObjectWrapper cms, CmsRepositoryFilter filter) { 083 084 m_cms = cms; 085 setFilter(filter); 086 } 087 088 /** 089 * @see org.opencms.repository.I_CmsRepositorySession#copy(java.lang.String, java.lang.String, boolean) 090 */ 091 public void copy(String src, String dest, boolean overwrite) throws CmsException { 092 093 src = validatePath(src); 094 dest = validatePath(dest); 095 096 if (LOG.isDebugEnabled()) { 097 LOG.debug(Messages.get().getBundle().key(Messages.LOG_COPY_ITEM_2, src, dest)); 098 } 099 100 // It is only possible in OpenCms to overwrite files. 101 // Folder are not possible to overwrite. 102 if (exists(dest)) { 103 104 if (overwrite) { 105 CmsResource srcRes = m_cms.readResource(src, CmsResourceFilter.DEFAULT); 106 CmsResource destRes = m_cms.readResource(dest, CmsResourceFilter.DEFAULT); 107 108 if ((srcRes.isFile()) && (destRes.isFile())) { 109 110 if (LOG.isDebugEnabled()) { 111 LOG.debug(Messages.get().getBundle().key(Messages.LOG_DELETE_DEST_0)); 112 } 113 114 // delete existing resource 115 delete(dest); 116 } else { 117 118 if (LOG.isDebugEnabled()) { 119 LOG.debug(Messages.get().getBundle().key(Messages.ERR_OVERWRITE_0)); 120 } 121 122 // internal error (not possible) 123 throw new CmsException(Messages.get().container(Messages.ERR_OVERWRITE_0)); 124 } 125 } else { 126 127 if (LOG.isDebugEnabled()) { 128 LOG.debug(Messages.get().getBundle().key(Messages.ERR_DEST_EXISTS_0)); 129 } 130 131 throw new CmsVfsResourceAlreadyExistsException(Messages.get().container(Messages.ERR_DEST_EXISTS_0)); 132 } 133 } 134 135 // copy resource 136 m_cms.copyResource(src, dest, CmsResource.COPY_PRESERVE_SIBLING); 137 138 // unlock destination resource 139 m_cms.unlockResource(dest); 140 } 141 142 /** 143 * @see org.opencms.repository.I_CmsRepositorySession#create(java.lang.String) 144 */ 145 public void create(String path) throws CmsException { 146 147 path = validatePath(path); 148 149 if (LOG.isDebugEnabled()) { 150 LOG.debug(Messages.get().getBundle().key(Messages.LOG_CREATE_ITEM_1, path)); 151 } 152 153 // create the folder 154 CmsResource res = m_cms.createResource(path, CmsResourceTypeFolder.RESOURCE_TYPE_ID); 155 156 // unlock new created folders if lock is not inherited 157 if (!m_cms.getLock(res).isInherited()) { 158 m_cms.unlockResource(path); 159 } 160 } 161 162 /** 163 * @see org.opencms.repository.I_CmsRepositorySession#delete(java.lang.String) 164 */ 165 public void delete(String path) throws CmsException { 166 167 path = validatePath(path); 168 169 if (LOG.isDebugEnabled()) { 170 LOG.debug(Messages.get().getBundle().key(Messages.LOG_DELETE_ITEM_1, path)); 171 } 172 173 CmsRepositoryLockInfo lock = getLock(path); 174 175 // lock resource 176 m_cms.lockResource(path); 177 178 // delete resource 179 m_cms.deleteResource(path, CmsResource.DELETE_PRESERVE_SIBLINGS); 180 181 // if deleting items out of a xml page restore lock state after deleting 182 try { 183 if (lock == null) { 184 m_cms.unlockResource(path); 185 } 186 } catch (CmsException ex) { 187 // noop 188 } 189 } 190 191 /** 192 * @see org.opencms.repository.I_CmsRepositorySession#exists(java.lang.String) 193 */ 194 public boolean exists(String path) { 195 196 try { 197 path = validatePath(path); 198 return m_cms.existsResource(path); 199 } catch (CmsException ex) { 200 return false; 201 } 202 } 203 204 /** 205 * @see org.opencms.repository.I_CmsRepositorySession#getItem(java.lang.String) 206 */ 207 public I_CmsRepositoryItem getItem(String path) throws CmsException { 208 209 path = validatePath(path); 210 211 if (LOG.isDebugEnabled()) { 212 LOG.debug(Messages.get().getBundle().key(Messages.LOG_READ_ITEM_1, path)); 213 } 214 215 CmsResource res = m_cms.readResource(path, CmsResourceFilter.DEFAULT); 216 217 CmsRepositoryItem item = new CmsRepositoryItem(res, m_cms); 218 return item; 219 } 220 221 /** 222 * @see org.opencms.repository.I_CmsRepositorySession#getLock(java.lang.String) 223 */ 224 public CmsRepositoryLockInfo getLock(String path) { 225 226 try { 227 CmsRepositoryLockInfo lockInfo = new CmsRepositoryLockInfo(); 228 229 path = validatePath(path); 230 231 CmsResource res = m_cms.readResource(path, CmsResourceFilter.DEFAULT); 232 233 // check user locks 234 CmsLock cmsLock = m_cms.getLock(res); 235 if (!cmsLock.isUnlocked()) { 236 lockInfo.setPath(path); 237 238 CmsUser owner = m_cms.readUser(cmsLock.getUserId()); 239 if (owner != null) { 240 lockInfo.setUsername(owner.getName()); 241 lockInfo.setOwner(owner.getName() + "||" + owner.getEmail()); 242 } 243 return lockInfo; 244 } 245 246 return null; 247 } catch (CmsException ex) { 248 249 // error occurred while finding locks 250 // return null (no lock found) 251 return null; 252 } 253 } 254 255 /** 256 * @see org.opencms.repository.I_CmsRepositorySession#list(java.lang.String) 257 */ 258 public List<I_CmsRepositoryItem> list(String path) throws CmsException { 259 260 List<I_CmsRepositoryItem> ret = new ArrayList<I_CmsRepositoryItem>(); 261 262 path = validatePath(path); 263 264 if (LOG.isDebugEnabled()) { 265 LOG.debug(Messages.get().getBundle().key(Messages.LOG_LIST_ITEMS_1, path)); 266 } 267 268 List<CmsResource> resources = m_cms.getResourcesInFolder(path, CmsResourceFilter.DEFAULT); 269 Iterator<CmsResource> iter = resources.iterator(); 270 while (iter.hasNext()) { 271 CmsResource res = iter.next(); 272 273 if (!isFiltered(m_cms.getRequestContext().removeSiteRoot(res.getRootPath()))) { 274 275 // open the original resource (for virtual files this is the resource in the VFS 276 // which the virtual resource is based on) 277 // this filters e.g. property files for resources that are filtered out and thus 278 // should not be displayed 279 CmsResource org = m_cms.readResource(res.getStructureId(), CmsResourceFilter.DEFAULT); 280 if (!isFiltered(m_cms.getRequestContext().removeSiteRoot(org.getRootPath()))) { 281 ret.add(new CmsRepositoryItem(res, m_cms)); 282 } 283 } 284 } 285 286 if (LOG.isDebugEnabled()) { 287 LOG.debug(Messages.get().getBundle().key(Messages.LOG_LIST_ITEMS_SUCESS_1, new Integer(ret.size()))); 288 } 289 290 return ret; 291 } 292 293 /** 294 * @see org.opencms.repository.I_CmsRepositorySession#lock(java.lang.String, org.opencms.repository.CmsRepositoryLockInfo) 295 */ 296 public boolean lock(String path, CmsRepositoryLockInfo lock) throws CmsException { 297 298 path = validatePath(path); 299 300 if (LOG.isDebugEnabled()) { 301 LOG.debug(Messages.get().getBundle().key(Messages.LOG_LOCK_ITEM_1, path)); 302 } 303 304 m_cms.lockResource(path); 305 return true; 306 } 307 308 /** 309 * @see org.opencms.repository.I_CmsRepositorySession#move(java.lang.String, java.lang.String, boolean) 310 */ 311 public void move(String src, String dest, boolean overwrite) throws CmsException { 312 313 src = validatePath(src); 314 dest = validatePath(dest); 315 316 if (LOG.isDebugEnabled()) { 317 LOG.debug(Messages.get().getBundle().key(Messages.LOG_MOVE_ITEM_2, src, dest)); 318 } 319 320 // It is only possible in OpenCms to overwrite files. 321 // Folder are not possible to overwrite. 322 if (exists(dest)) { 323 324 if (overwrite) { 325 CmsResource srcRes = m_cms.readResource(src, CmsResourceFilter.DEFAULT); 326 CmsResource destRes = m_cms.readResource(dest, CmsResourceFilter.DEFAULT); 327 328 if ((srcRes.isFile()) && (destRes.isFile())) { 329 330 if (LOG.isDebugEnabled()) { 331 LOG.debug(Messages.get().getBundle().key(Messages.LOG_DELETE_DEST_0)); 332 } 333 334 // delete existing resource 335 delete(dest); 336 } else { 337 338 if (LOG.isDebugEnabled()) { 339 LOG.debug(Messages.get().getBundle().key(Messages.ERR_OVERWRITE_0)); 340 } 341 342 throw new CmsException(Messages.get().container(Messages.ERR_OVERWRITE_0)); 343 } 344 } else { 345 346 if (LOG.isDebugEnabled()) { 347 LOG.debug(Messages.get().getBundle().key(Messages.ERR_DEST_EXISTS_0)); 348 } 349 350 throw new CmsVfsResourceAlreadyExistsException(Messages.get().container(Messages.ERR_DEST_EXISTS_0)); 351 } 352 } 353 354 // lock source resource 355 m_cms.lockResource(src); 356 357 // moving 358 m_cms.moveResource(src, dest); 359 360 // unlock destination resource 361 m_cms.unlockResource(dest); 362 } 363 364 /** 365 * @see org.opencms.repository.I_CmsRepositorySession#save(java.lang.String, java.io.InputStream, boolean) 366 */ 367 public void save(String path, InputStream inputStream, boolean overwrite) throws CmsException, IOException { 368 369 path = validatePath(path); 370 byte[] content = CmsFileUtil.readFully(inputStream); 371 372 try { 373 CmsFile file = m_cms.readFile(path, CmsResourceFilter.DEFAULT); 374 375 if (LOG.isDebugEnabled()) { 376 LOG.debug(Messages.get().getBundle().key(Messages.LOG_UPDATE_ITEM_1, path)); 377 } 378 379 if (overwrite) { 380 381 file.setContents(content); 382 383 CmsLock lock = m_cms.getLock(file); 384 385 // lock resource 386 if (!lock.isInherited()) { 387 m_cms.lockResource(path); 388 } 389 390 // write file 391 m_cms.writeFile(file); 392 393 if (lock.isNullLock()) { 394 m_cms.unlockResource(path); 395 } 396 } else { 397 398 if (LOG.isDebugEnabled()) { 399 LOG.debug(Messages.get().getBundle().key(Messages.ERR_DEST_EXISTS_0)); 400 } 401 402 throw new CmsVfsResourceAlreadyExistsException(Messages.get().container(Messages.ERR_DEST_EXISTS_0)); 403 } 404 } catch (CmsVfsResourceNotFoundException ex) { 405 406 if (LOG.isDebugEnabled()) { 407 LOG.debug(Messages.get().getBundle().key(Messages.LOG_CREATE_ITEM_1, path)); 408 } 409 410 int type = OpenCms.getResourceManager().getDefaultTypeForName(path).getTypeId(); 411 412 // create the file 413 CmsResource res = m_cms.createResource(path, type, content, null); 414 415 // unlock file after creation if lock is not inherited 416 if (!m_cms.getLock(res).isInherited()) { 417 m_cms.unlockResource(path); 418 } 419 } 420 421 } 422 423 /** 424 * @see org.opencms.repository.I_CmsRepositorySession#unlock(java.lang.String) 425 */ 426 public void unlock(String path) { 427 428 try { 429 path = validatePath(path); 430 431 if (LOG.isDebugEnabled()) { 432 LOG.debug(Messages.get().getBundle().key(Messages.LOG_UNLOCK_ITEM_1, path)); 433 } 434 435 m_cms.unlockResource(path); 436 } catch (CmsException ex) { 437 438 if (LOG.isErrorEnabled()) { 439 LOG.error(Messages.get().getBundle().key(Messages.ERR_UNLOCK_FAILED_0), ex); 440 } 441 } 442 } 443 444 /** 445 * Adds the site root to the path name and checks then if the path 446 * is filtered.<p> 447 * 448 * @see org.opencms.repository.A_CmsRepositorySession#isFiltered(java.lang.String) 449 */ 450 @Override 451 protected boolean isFiltered(String name) { 452 453 boolean ret = super.isFiltered(m_cms.getRequestContext().addSiteRoot(name)); 454 if (ret) { 455 456 if (LOG.isDebugEnabled()) { 457 LOG.debug(Messages.get().getBundle().key(Messages.ERR_ITEM_FILTERED_1, name)); 458 } 459 460 } 461 462 return ret; 463 } 464 465 /** 466 * Validates (translates) the given path and checks if it is filtered out.<p> 467 * 468 * @param path the path to validate 469 * 470 * @return the validated path 471 * 472 * @throws CmsSecurityException if the path is filtered out 473 */ 474 private String validatePath(String path) throws CmsSecurityException { 475 476 // Problems with spaces in new folders (default: "Neuer Ordner") 477 // Solution: translate this to a correct name. 478 String ret = m_cms.getRequestContext().getFileTranslator().translateResource(path); 479 480 // add site root only works correct if system folder ends with a slash 481 if (CmsResource.VFS_FOLDER_SYSTEM.equals(ret)) { 482 ret = ret.concat("/"); 483 } 484 485 // filter path 486 if (isFiltered(ret)) { 487 throw new CmsSecurityException(Messages.get().container(Messages.ERR_ITEM_FILTERED_1, path)); 488 } 489 490 return ret; 491 } 492}