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.importexport; 029 030import org.opencms.i18n.CmsEncoder; 031import org.opencms.i18n.CmsMessageContainer; 032import org.opencms.main.CmsLog; 033import org.opencms.main.OpenCms; 034import org.opencms.util.CmsFileUtil; 035import org.opencms.xml.CmsXmlEntityResolver; 036 037import java.io.File; 038import java.io.FileInputStream; 039import java.io.FileNotFoundException; 040import java.io.IOException; 041import java.io.InputStream; 042import java.util.zip.ZipEntry; 043import java.util.zip.ZipException; 044import java.util.zip.ZipFile; 045 046import org.apache.commons.logging.Log; 047 048/** 049 * Import helper.<p> 050 * 051 * @since 7.0.4 052 */ 053public class CmsImportHelper { 054 055 /** The log object for this class. */ 056 private static final Log LOG = CmsLog.getLog(CmsImport.class); 057 058 /** The folder, or <code>null</code> if a zip file.*/ 059 private File m_folder; 060 061 /** The import parameters to use. */ 062 private CmsImportParameters m_params; 063 064 /** The zip file, or <code>null</code> if a folder.*/ 065 private ZipFile m_zipFile; 066 067 /** 068 * Constructor.<p> 069 * 070 * @param parameters the import parameters to use 071 */ 072 public CmsImportHelper(CmsImportParameters parameters) { 073 074 m_params = parameters; 075 } 076 077 /** 078 * Adds a new DTD system id prefix mapping for internal resolution 079 * of external URLs.<p> 080 * 081 * @param dtdSystemLocation the internal system location of the DTD file, e.g. <code>org/opencms/configuration/</code> 082 * @param dtdFilename the name of the DTD file, e.g. <code>opencms-configuration.dtd</code> 083 * @param dtdUrlPrefix the external system id prefix of the DTD file, e.g. <code>http://www.opencms.org/dtd/6.0/</code> 084 * 085 * @see org.opencms.configuration.I_CmsXmlConfiguration 086 */ 087 public void cacheDtdSystemId(String dtdSystemLocation, String dtdFilename, String dtdUrlPrefix) { 088 089 if (dtdSystemLocation != null) { 090 try { 091 String file = CmsFileUtil.readFile(dtdSystemLocation + dtdFilename, CmsEncoder.ENCODING_UTF_8); 092 CmsXmlEntityResolver.cacheSystemId( 093 dtdUrlPrefix + dtdFilename, 094 file.getBytes(CmsEncoder.ENCODING_UTF_8)); 095 if (LOG.isDebugEnabled()) { 096 LOG.debug( 097 org.opencms.configuration.Messages.get().getBundle().key( 098 org.opencms.configuration.Messages.LOG_CACHE_DTD_SYSTEM_ID_1, 099 new Object[] {dtdUrlPrefix + dtdFilename + " --> " + dtdSystemLocation + dtdFilename})); 100 } 101 } catch (IOException e) { 102 LOG.error( 103 org.opencms.configuration.Messages.get().getBundle().key( 104 org.opencms.configuration.Messages.LOG_CACHE_DTD_SYSTEM_ID_FAILURE_1, 105 new Object[] {dtdSystemLocation + dtdFilename}), 106 e); 107 } 108 } 109 } 110 111 /** 112 * Closes the zip file.<p> 113 */ 114 public void closeFile() { 115 116 if (getZipFile() != null) { 117 try { 118 getZipFile().close(); 119 } catch (IOException e) { 120 CmsMessageContainer message = Messages.get().container( 121 Messages.ERR_IMPORTEXPORT_ERROR_CLOSING_ZIP_ARCHIVE_1, 122 getZipFile().getName()); 123 if (LOG.isDebugEnabled()) { 124 LOG.debug(message.key(), e); 125 } 126 } 127 } 128 } 129 130 /** 131 * Returns a byte array containing the content of the file.<p> 132 * 133 * @param filename the name of the file to read, relative to the folder or zip file 134 * 135 * @return a byte array containing the content of the file 136 * 137 * @throws CmsImportExportException if something goes wrong 138 */ 139 public byte[] getFileBytes(String filename) throws CmsImportExportException { 140 141 try { 142 // is this a zip-file? 143 if (getZipFile() != null) { 144 145 ZipEntry entry = getZipEntry(filename); 146 InputStream stream = getZipFile().getInputStream(entry); 147 int size = Long.valueOf(entry.getSize()).intValue(); 148 return CmsFileUtil.readFully(stream, size); 149 } else { 150 // no - use directory 151 File file = getFile(filename); 152 return CmsFileUtil.readFile(file); 153 } 154 } catch (FileNotFoundException fnfe) { 155 CmsMessageContainer msg = Messages.get().container(Messages.ERR_IMPORTEXPORT_FILE_NOT_FOUND_1, filename); 156 if (LOG.isErrorEnabled()) { 157 LOG.error(msg.key(), fnfe); 158 } 159 throw new CmsImportExportException(msg, fnfe); 160 } catch (IOException ioe) { 161 CmsMessageContainer msg = Messages.get().container( 162 Messages.ERR_IMPORTEXPORT_ERROR_READING_FILE_1, 163 filename); 164 if (LOG.isErrorEnabled()) { 165 LOG.error(msg.key(), ioe); 166 } 167 throw new CmsImportExportException(msg, ioe); 168 } 169 } 170 171 public long getFileModification(String filename) throws CmsImportExportException { 172 173 long modificationTime = 0; 174 175 try { 176 // is this a zip-file? 177 if (getZipFile() != null) { 178 // yes 179 ZipEntry entry = getZipEntry(filename); 180 modificationTime = entry.getTime(); 181 } else { 182 // no - use directory 183 File file = getFile(filename); 184 modificationTime = file.lastModified(); 185 } 186 if (modificationTime < 0) { 187 return 0; 188 } else { 189 return modificationTime; 190 } 191 } catch (IOException ioe) { 192 CmsMessageContainer msg = Messages.get().container( 193 Messages.ERR_IMPORTEXPORT_ERROR_READING_FILE_1, 194 filename); 195 if (LOG.isErrorEnabled()) { 196 LOG.error(msg.key(), ioe); 197 } 198 throw new CmsImportExportException(msg, ioe); 199 } 200 } 201 202 /** 203 * Returns the name of the import file, without zip extension.<p> 204 * 205 * @return the name of the import file, without zip extension 206 */ 207 public String getFileName() { 208 209 String fileName = m_params.getPath().replace('\\', '/'); 210 String zipName = fileName.substring(fileName.lastIndexOf('/') + 1); 211 String result; 212 213 if (zipName.toLowerCase().endsWith(".zip")) { 214 result = zipName.substring(0, zipName.lastIndexOf('.')); 215 int pos = result.lastIndexOf('_'); 216 if (pos > 0) { 217 result = result.substring(0, pos); 218 } 219 } else { 220 result = zipName; 221 } 222 return result; 223 } 224 225 /** 226 * Returns a stream for the content of the file.<p> 227 * 228 * @param fileName the name of the file to stream, relative to the folder or zip file 229 * 230 * @return an input stream for the content of the file, remember to close it after using 231 * 232 * @throws CmsImportExportException if something goes wrong 233 */ 234 public InputStream getFileStream(String fileName) throws CmsImportExportException { 235 236 try { 237 InputStream stream = null; 238 // is this a zip-file? 239 if (getZipFile() != null) { 240 // yes 241 ZipEntry entry = getZipFile().getEntry(fileName); 242 // path to file might be relative, too 243 if ((entry == null) && fileName.startsWith("/")) { 244 entry = getZipFile().getEntry(fileName.substring(1)); 245 } 246 if (entry == null) { 247 throw new ZipException( 248 Messages.get().getBundle().key(Messages.LOG_IMPORTEXPORT_FILE_NOT_FOUND_IN_ZIP_1, fileName)); 249 } 250 251 stream = getZipFile().getInputStream(entry); 252 } else { 253 // no - use directory 254 File file = new File(getFolder(), CmsImportExportManager.EXPORT_MANIFEST); 255 stream = new FileInputStream(file); 256 } 257 return stream; 258 } catch (Exception ioe) { 259 CmsMessageContainer msg = Messages.get().container( 260 Messages.ERR_IMPORTEXPORT_ERROR_READING_FILE_1, 261 fileName); 262 if (LOG.isErrorEnabled()) { 263 LOG.error(msg.key(), ioe); 264 } 265 throw new CmsImportExportException(msg, ioe); 266 } 267 } 268 269 /** 270 * Returns the RFS folder to import from.<p> 271 * 272 * @return the RFS folder to import from 273 */ 274 public File getFolder() { 275 276 return m_folder; 277 } 278 279 /** 280 * Returns the class system location.<p> 281 * 282 * i.e: <code>org/opencms/importexport</code><p> 283 * 284 * @param clazz the class to get the location for 285 * 286 * @return the class system location 287 */ 288 public String getLocation(Class<?> clazz) { 289 290 String filename = clazz.getName().replace('.', '/'); 291 int pos = filename.lastIndexOf('/') + 1; 292 return (pos > 0 ? filename.substring(0, pos) : ""); 293 } 294 295 /** 296 * Returns the RFS zip file to import from.<p> 297 * 298 * @return the RFS zip file to import from 299 */ 300 public ZipFile getZipFile() { 301 302 return m_zipFile; 303 } 304 305 /** 306 * Opens the import file.<p> 307 * 308 * @throws IOException if the file could not be opened 309 */ 310 public void openFile() throws IOException { 311 312 // get the import resource 313 m_folder = new File(OpenCms.getSystemInfo().getAbsoluteRfsPathRelativeToWebInf(m_params.getPath())); 314 315 // if it is a file it must be a zip-file 316 if (m_folder.isFile()) { 317 m_zipFile = new ZipFile(m_params.getPath()); 318 m_folder = null; 319 } 320 } 321 322 /** Returns the file for the provided filename. 323 * @param filename name of the file 324 * @return the file. 325 */ 326 protected File getFile(String filename) { 327 328 return new File(getFolder(), filename); 329 } 330 331 /** Returns the zip entry for a file in the archive. 332 * @param filename the file name 333 * @return the zip entry for the file with the provided name 334 * @throws ZipException thrown if the file is not in the zip archive 335 */ 336 protected ZipEntry getZipEntry(String filename) throws ZipException { 337 338 // yes 339 ZipEntry entry = getZipFile().getEntry(filename); 340 // path to file might be relative, too 341 if ((entry == null) && filename.startsWith("/")) { 342 entry = m_zipFile.getEntry(filename.substring(1)); 343 } 344 if (entry == null) { 345 throw new ZipException( 346 Messages.get().getBundle().key(Messages.LOG_IMPORTEXPORT_FILE_NOT_FOUND_IN_ZIP_1, filename)); 347 } 348 return entry; 349 } 350}