/* * This library is part of OpenCms - * the Open Source Content Management System * * Copyright (c) Alkacon Software GmbH (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 GmbH, 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.file; import org.opencms.db.CmsResourceState; import org.opencms.util.CmsStringUtil; /** * Client side implementation of {@link org.opencms.file.CmsResource}.<p> * * @since 8.0.0 */ public class CmsResource { /** Indicates if a resource has been changed in the offline version when compared to the online version. */ public static final CmsResourceState STATE_CHANGED = CmsResourceState.STATE_CHANGED; /** Indicates if a resource has been deleted in the offline version when compared to the online version. */ public static final CmsResourceState STATE_DELETED = CmsResourceState.STATE_DELETED; /** * Special state value that indicates the current state must be kept on a resource, * this value must never be written to the database. */ public static final CmsResourceState STATE_KEEP = CmsResourceState.STATE_KEEP; /** Indicates if a resource is new in the offline version when compared to the online version. */ public static final CmsResourceState STATE_NEW = CmsResourceState.STATE_NEW; /** Indicates if a resource is unchanged in the offline version when compared to the online version. */ public static final CmsResourceState STATE_UNCHANGED = CmsResourceState.STATE_UNCHANGED; /** * Prefix for temporary files in the VFS. * * @see #isTemporaryFileName(String) */ public static final String TEMP_FILE_PREFIX = "~"; /** * Returns the folder path of the resource with the given name.<p> * * If the resource name denotes a folder (that is ends with a "/"), the complete path of the folder * is returned (not the parent folder path).<p> * * This is achieved by just cutting of everything behind the last occurrence of a "/" character * in the String, no check if performed if the resource exists or not in the VFS, * only resources that end with a "/" are considered to be folders. * * Example: Returns <code>/system/def/</code> for the * resource <code>/system/def/file.html</code> and * <code>/system/def/</code> for the (folder) resource <code>/system/def/</code>. * * @param resource the name of a resource * @return the folder of the given resource */ public static String getFolderPath(String resource) { return resource.substring(0, resource.lastIndexOf('/') + 1); } /** * Returns the name of a resource without the path information.<p> * * The resource name of a file is the name of the file. * The resource name of a folder is the folder name with trailing "/". * The resource name of the root folder is <code>/</code>.<p> * * Example: <code>/system/workplace/</code> has the resource name <code>workplace/</code>. * * @param resource the resource to get the name for * @return the name of a resource without the path information */ public static String getName(String resource) { if ("/".equals(resource)) { return "/"; } // remove the last char, for a folder this will be "/", for a file it does not matter String parent = (resource.substring(0, resource.length() - 1)); // now as the name does not end with "/", check for the last "/" which is the parent folder name return resource.substring(parent.lastIndexOf('/') + 1); } /** * Returns the absolute parent folder name of a resource.<p> * * The parent resource of a file is the folder of the file. * The parent resource of a folder is the parent folder. * The parent resource of the root folder is <code>null</code>.<p> * * Example: <code>/system/workplace/</code> has the parent <code>/system/</code>. * * @param resource the resource to find the parent folder for * @return the calculated parent absolute folder path, or <code>null</code> for the root folder */ public static String getParentFolder(String resource) { if (CmsStringUtil.isEmptyOrWhitespaceOnly(resource) || "/".equals(resource)) { return null; } // remove the last char, for a folder this will be "/", for a file it does not matter String parent = (resource.substring(0, resource.length() - 1)); // now as the name does not end with "/", check for the last "/" which is the parent folder name return parent.substring(0, parent.lastIndexOf('/') + 1); } /** * Returns the directory level of a resource.<p> * * The root folder "/" has level 0, * a folder "/foo/" would have level 1, * a folfer "/foo/bar/" level 2 etc.<p> * * @param resource the resource to determine the directory level for * @return the directory level of a resource */ public static int getPathLevel(String resource) { int level = -1; int pos = 0; while (resource.indexOf('/', pos) >= 0) { pos = resource.indexOf('/', pos) + 1; level++; } return level; } /** * Returns the name of a parent folder of the given resource, * that is either minus levels up * from the current folder, or that is plus levels down from the * root folder.<p> * * @param resource the name of a resource * @param level of levels to walk up or down * @return the name of a parent folder of the given resource */ public static String getPathPart(String resource, int level) { resource = getFolderPath(resource); String result = null; int pos = 0, count = 0; if (level >= 0) { // Walk down from the root folder / while ((count < level) && (pos > -1)) { count++; pos = resource.indexOf('/', pos + 1); } } else { // Walk up from the current folder pos = resource.length(); while ((count > level) && (pos > -1)) { count--; pos = resource.lastIndexOf('/', pos - 1); } } if (pos > -1) { // To many levels walked result = resource.substring(0, pos + 1); } else { // Add trailing slash result = (level < 0) ? "/" : resource; } return result; } /** * Returns true if the resource name certainly denotes a folder, that is ends with a "/".<p> * * @param resource the resource to check * @return true if the resource name certainly denotes a folder, that is ends with a "/" */ public static boolean isFolder(String resource) { return CmsStringUtil.isNotEmpty(resource) && (resource.charAt(resource.length() - 1) == '/'); } /** * Returns <code>true</code> if the given resource path points to a temporary file name.<p> * * A resource name is considered a temporary file name if the name of the file * (without parent folders) starts with the prefix char <code>'~'</code> (tilde). * Existing parent folder elements are removed from the path before the file name is checked.<p> * * @param path the resource path to check * * @return <code>true</code> if the given resource name is a temporary file name */ public static boolean isTemporaryFileName(String path) { return (path != null) && getName(path).startsWith(TEMP_FILE_PREFIX); } }