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.cache; 029 030import org.opencms.util.CmsFileUtil; 031import org.opencms.util.CmsStringUtil; 032 033import java.io.File; 034import java.io.FileOutputStream; 035import java.io.IOException; 036 037/** 038 * Implements a RFS file based disk cache, that handles parameter based versions of VFS files, 039 * providing a cache for the "online" and another for the "offline" project.<p> 040 * 041 * @since 6.2.0 042 */ 043public class CmsVfsDiskCache { 044 045 /** The name of the cache base repository folder in the RFS. */ 046 private String m_rfsRepository; 047 048 /** 049 * Creates a new disk cache.<p> 050 * 051 * @param basepath the base path for the cache in the RFS 052 * @param foldername the folder name for this cache, to be used a subfolder for the base folder 053 */ 054 public CmsVfsDiskCache(String basepath, String foldername) { 055 056 // normalize the given folder name 057 m_rfsRepository = CmsFileUtil.normalizePath(basepath + foldername + File.separatorChar); 058 } 059 060 /** 061 * Saves the given file content to a RFS file of the given name (full path).<p> 062 * 063 * If the required parent folders do not exists, they are also created.<p> 064 * 065 * @param rfsName the RFS name of the file to save the content in 066 * @param content the content of the file to save 067 * 068 * @return a reference to the File that was saved 069 * 070 * @throws IOException in case of disk access errors 071 */ 072 public static File saveFile(String rfsName, byte[] content) throws IOException { 073 074 File f = new File(rfsName); 075 File p = f.getParentFile(); 076 if (!p.exists()) { 077 // create parent folders 078 p.mkdirs(); 079 } 080 // write file contents 081 FileOutputStream fs = new FileOutputStream(f); 082 fs.write(content); 083 fs.close(); 084 return f; 085 } 086 087 /** 088 * Returns the content of the requested file in the disk cache, or <code>null</code> if the 089 * file is not found in the cache, or is found but outdated.<p> 090 * 091 * @param rfsName the file RFS name to look up in the cache 092 * @param dateLastModified the date of last modification for the cache 093 * 094 * @return the content of the requested file in the VFS disk cache, or <code>null</code> 095 */ 096 public byte[] getCacheContent(String rfsName, long dateLastModified) { 097 098 dateLastModified = simplifyDateLastModified(dateLastModified); 099 try { 100 File f = new File(rfsName); 101 if (f.exists()) { 102 if (f.lastModified() != dateLastModified) { 103 // last modification time different, remove cached file in RFS 104 f.delete(); 105 } else { 106 return CmsFileUtil.readFile(f); 107 } 108 } 109 } catch (IOException e) { 110 // unable to read content 111 } 112 return null; 113 } 114 115 /** 116 * Returns the RFS name to use for caching the given VFS resource with parameters in the disk cache.<p> 117 * 118 * @param online if true, the online disk cache is used, the offline disk cache otherwise 119 * @param rootPath the VFS resource root path to get the RFS cache name for 120 * @param parameters the parameters of the request to the VFS resource 121 * 122 * @return the RFS name to use for caching the given VFS resource with parameters 123 */ 124 public String getCacheName(boolean online, String rootPath, String parameters) { 125 126 String rfsName = CmsFileUtil.getRepositoryName(m_rfsRepository, rootPath, online); 127 if (CmsStringUtil.isNotEmpty(parameters)) { 128 String extension = CmsFileUtil.getExtension(rfsName); 129 // build the RFS name for the VFS name with parameters 130 rfsName = CmsFileUtil.getRfsPath(rfsName, extension, parameters); 131 } 132 133 return rfsName; 134 } 135 136 /** 137 * Returns the absolute path of the cache repository in the RFS.<p> 138 * 139 * @return the absolute path of the cache repository in the RFS 140 */ 141 public String getRepositoryPath() { 142 143 return m_rfsRepository; 144 } 145 146 /** 147 * Saves the given file content in the disk cache.<p> 148 * 149 * @param rfsName the RFS name of the file to save the content in 150 * @param content the content of the file to save 151 * @param dateLastModified the date of last modification to set for the save file 152 * 153 * @throws IOException in case of disk access errors 154 */ 155 public void saveCacheFile(String rfsName, byte[] content, long dateLastModified) throws IOException { 156 157 dateLastModified = simplifyDateLastModified(dateLastModified); 158 File f = saveFile(rfsName, content); 159 // set last modification date 160 f.setLastModified(dateLastModified); 161 } 162 163 /** 164 * Simplifies the "date last modified" from the OpenCms VFS based milliseconds 165 * to just seconds, to support file systems that don't use milliseconds.<p> 166 * 167 * @param dateLastModified the date to simplify 168 * 169 * @return the simplified date last modified 170 */ 171 private long simplifyDateLastModified(long dateLastModified) { 172 173 return dateLastModified / 1000L; 174 } 175}