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.ui.apps.logfile; 029 030import org.opencms.main.CmsLog; 031import org.opencms.ui.CmsVaadinUtils; 032import org.opencms.ui.components.CmsBasicDialog; 033import org.opencms.util.CmsStringUtil; 034 035import java.io.File; 036import java.io.FileInputStream; 037import java.io.FileNotFoundException; 038import java.io.FileOutputStream; 039import java.io.IOException; 040import java.io.InputStream; 041import java.io.OutputStream; 042import java.util.ArrayList; 043import java.util.HashSet; 044import java.util.List; 045import java.util.Set; 046import java.util.zip.ZipEntry; 047import java.util.zip.ZipOutputStream; 048 049import org.apache.commons.logging.Log; 050 051import com.vaadin.server.FileDownloader; 052import com.vaadin.server.Resource; 053import com.vaadin.server.StreamResource; 054import com.vaadin.ui.Button; 055import com.vaadin.ui.Button.ClickEvent; 056import com.vaadin.ui.Button.ClickListener; 057import com.vaadin.ui.Window; 058import com.vaadin.v7.data.Property.ValueChangeEvent; 059import com.vaadin.v7.data.Property.ValueChangeListener; 060import com.vaadin.v7.shared.ui.combobox.FilteringMode; 061import com.vaadin.v7.ui.CheckBox; 062import com.vaadin.v7.ui.ComboBox; 063 064/** 065 * Class for the Download dialog.<p> 066 */ 067public class CmsLogDownloadDialog extends CmsBasicDialog { 068 069 /** 070 * Helper class for generating the zip file for the log download.<p> 071 */ 072 class ZipGenerator { 073 074 /** The set of generated parent directories. */ 075 private Set<String> m_directories = new HashSet<>(); 076 077 /** The zip output. */ 078 private ZipOutputStream m_zos; 079 080 /** 081 * Creates a new instance.<p> 082 * 083 * @param output the output stream to write to 084 */ 085 public ZipGenerator(OutputStream output) { 086 087 m_zos = new ZipOutputStream(output); 088 } 089 090 /** 091 * Adds a file to a zip-stream.<p> 092 * 093 * @param directory to be zipped 094 * @param file to be added zo zip 095 * @throws IOException exception 096 */ 097 public void addToZip(File directory, File file) throws IOException { 098 099 FileInputStream fis = new FileInputStream(file); 100 String dirPath = directory.getCanonicalPath(); 101 String filePath = file.getCanonicalPath(); 102 String zipFilePath; 103 if (CmsStringUtil.isPrefixPath(dirPath, filePath)) { 104 zipFilePath = filePath.substring(dirPath.length() + 1, filePath.length()); 105 } else { 106 String parentName = generateParentName(file); 107 if (!m_directories.contains(parentName)) { 108 m_zos.putNextEntry(new ZipEntry(parentName)); 109 } 110 m_directories.add(parentName); 111 zipFilePath = CmsStringUtil.joinPaths(parentName, file.getName()); 112 } 113 ZipEntry zipEntry = new ZipEntry(zipFilePath); 114 m_zos.putNextEntry(zipEntry); 115 116 byte[] bytes = new byte[1024]; 117 int length; 118 while ((length = fis.read(bytes)) >= 0) { 119 m_zos.write(bytes, 0, length); 120 } 121 m_zos.closeEntry(); 122 fis.close(); 123 } 124 125 /** 126 * Closes the zip stream.<p> 127 * 128 * @throws IOException if something goes wrong 129 */ 130 public void close() throws IOException { 131 132 m_zos.close(); 133 } 134 135 /** 136 * Generates the name of the parent directory in the zip file for a non-standard log file location.<p> 137 * 138 * @param file the log file 139 * @return the generated parent directory name 140 */ 141 String generateParentName(File file) { 142 143 // we might be on Windows, so we can't just assume path is /foo/bar/baz 144 List<String> pathComponents = new ArrayList<>(); 145 for (int i = 0; i < (file.toPath().getNameCount() - 1); i++) { 146 pathComponents.add(file.toPath().getName(i).toString()); 147 } 148 // need trailing slash when writing directory entries to ZipOutputStream 149 return CmsStringUtil.listAsString(pathComponents, "_") + "/"; 150 } 151 152 } 153 154 /** Logger.*/ 155 private static Log LOG = CmsLog.getLog(CmsLogDownloadDialog.class.getName()); 156 157 /**vaadin serial id.*/ 158 private static final long serialVersionUID = -7447640082260176245L; 159 160 /** Path to zip file.*/ 161 private static final String ZIP_PATH = CmsLogFileApp.LOG_FOLDER + "logs.zip"; 162 163 /**File downloader. */ 164 protected FileDownloader m_downloader; 165 166 /**Vaadin component.*/ 167 private Button m_cancel; 168 169 /**Vaadin component.**/ 170 private CheckBox m_donwloadAll; 171 172 /**Vaadin component.*/ 173 private ComboBox m_file; 174 175 /**Vaadin component.*/ 176 private Button m_ok; 177 178 /**total size of log files in MB.*/ 179 private double m_totalSize; 180 181 /** 182 * public constructor.<p> 183 * 184 * @param window to hold the dialog 185 * @param filePath path of currently shown file 186 */ 187 public CmsLogDownloadDialog(final Window window, String filePath) { 188 189 CmsVaadinUtils.readAndLocalizeDesign(this, CmsVaadinUtils.getWpMessagesForCurrentLocale(), null); 190 191 m_totalSize = 0; 192 for (File file : CmsLogFileOptionProvider.getLogFiles()) { 193 if (!file.getAbsolutePath().endsWith(".zip")) { 194 m_file.addItem(file.getAbsolutePath()); 195 m_totalSize += file.length() / (1024 * 1024); 196 } 197 } 198 199 m_donwloadAll.setVisible(m_totalSize < 150); 200 201 m_file.setFilteringMode(FilteringMode.CONTAINS); 202 m_file.setNullSelectionAllowed(false); 203 m_file.setNewItemsAllowed(false); 204 205 m_file.select(filePath); 206 207 m_cancel.addClickListener(new ClickListener() { 208 209 private static final long serialVersionUID = 4336654148546091114L; 210 211 public void buttonClick(ClickEvent event) { 212 213 window.close(); 214 215 } 216 217 }); 218 m_downloader = new FileDownloader(getDownloadResource()); 219 m_downloader.extend(m_ok); 220 221 ValueChangeListener listener = new ValueChangeListener() { 222 223 private static final long serialVersionUID = -1127012396158402096L; 224 225 public void valueChange(ValueChangeEvent event) { 226 227 m_downloader.setFileDownloadResource(getDownloadResource()); 228 setComboBoxEnable(); 229 230 } 231 }; 232 233 m_file.addValueChangeListener(listener); 234 m_donwloadAll.addValueChangeListener(listener); 235 236 } 237 238 /** 239 * Creates log-file resource for download.<p> 240 * 241 * @return vaadin resource 242 */ 243 protected Resource getDownloadResource() { 244 245 String pathToDownload = (String)m_file.getValue(); 246 247 if (m_donwloadAll.getValue().booleanValue()) { 248 pathToDownload = ZIP_PATH; 249 writeZipFile(); 250 } 251 252 final File downloadFile = new File(pathToDownload); 253 254 return new StreamResource(new StreamResource.StreamSource() { 255 256 private static final long serialVersionUID = -8868657402793427460L; 257 258 public InputStream getStream() { 259 260 try { 261 return new FileInputStream(downloadFile); 262 } catch (FileNotFoundException e) { 263 return null; 264 } 265 266 } 267 }, downloadFile.getName()); 268 } 269 270 /** 271 * En/ disables the combo box for files.<p> 272 */ 273 protected void setComboBoxEnable() { 274 275 m_file.setEnabled(!m_donwloadAll.getValue().booleanValue()); 276 } 277 278 /** 279 * Writes the zip file with all logs.<p> 280 */ 281 private void writeZipFile() { 282 283 try { 284 FileOutputStream fos = new FileOutputStream(ZIP_PATH); 285 ZipGenerator zipGen = new ZipGenerator(fos); 286 for (File file : CmsLogFileOptionProvider.getLogFiles()) { 287 if (!file.isDirectory() & !ZIP_PATH.equals(file.getAbsolutePath())) { 288 zipGen.addToZip(new File(CmsLogFileApp.LOG_FOLDER), file); 289 } 290 } 291 zipGen.close(); 292 fos.close(); 293 294 } catch (IOException e) { 295 LOG.error("unable to build zip file", e); 296 } 297 } 298}