/*******************************************************************************
* Copyright (c) 2010 the CHISEL group and contributors.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Del Myers - initial API and implementation
*******************************************************************************/
package ca.uvic.chisel.logging.eclipse.internal;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import ca.uvic.chisel.logging.eclipse.WorkbenchLoggingPlugin;
/**
* Simple class for logging events.
* @author Del Myers
*
*/
public class Log {
private LoggingCategory category;
private PrintStream fStream;
public Log(LoggingCategory category) {
this.category = category;
}
/**
* @return the category
*/
public LoggingCategory getCategory() {
return category;
}
public synchronized void logLine(String info) {
if (!WorkbenchLoggingPlugin.isEnabled()) return;
if (getCategory().isEnabled()) {
PrintStream stream = getStream();
stream.println(info);
}
}
private synchronized PrintStream getStream() {
if (fStream == null) {
fStream = newStream();
}
return fStream;
}
private PrintStream newStream() {
File logFile = getLogFile();
boolean insertHeader = !logFile.exists();
try {
FileOutputStream os = new FileOutputStream(logFile, true);
PrintStream stream = new PrintStream(os, true);
if (insertHeader) {
stream.println("#Eclipse UI Log");
stream.println("#User ID:" + WorkbenchLoggingPlugin.getDefault().getLocalUser());
}
return stream;
} catch (FileNotFoundException e) {
WorkbenchLoggingPlugin.getDefault().log(e);
return null;
}
}
public synchronized File getLogFile() {
File categoryLocation = category.getLogLocation();
if (!categoryLocation.exists()){
if (!categoryLocation.mkdirs()) {
WorkbenchLoggingPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, WorkbenchLoggingPlugin.PLUGIN_ID, "Could not create log location"));
}
} else if (!categoryLocation.isDirectory()) {
WorkbenchLoggingPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, WorkbenchLoggingPlugin.PLUGIN_ID, "Could not create log location"));
}
File logFile = new File(categoryLocation, "eclipse.log");
return logFile;
}
/**
* Copies the log to a backup file, and resets the log.
* @return the file backed-up.
*/
public File[] archiveLog(IProgressMonitor monitor) {
File logFile = getLogFile();
File[] backup = backupLog(monitor);
if (!monitor.isCanceled()) {
if (fStream != null) {
fStream.close();
}
logFile.delete();
fStream = null;
}
return backup;
}
/**
* Returns all the files that are used as backup.
* @return
*/
public File[] getBackupFiles() {
File[] children = category.getLogLocation().listFiles(new FileFilter(){
public boolean accept(File pathname) {
String fileName = pathname.getName();
return fileName.endsWith(".zip");
}});
return children;
}
/**
* Copies the current log to a backup file. The backup has a size limit of
* approximately 1 megabyte. If a file exceeds 1 megabyte, it will be split
* across multiple files. The file name of subsequent files will have
* "-1", "-2", etc. appended to their name. The zip files will simply contain
* a continuation of the text represented in the log. All lines of text in
* the output file will be complete.
* @return an array of files of size less than 1.5 megabytes that represent the
* backup.
*/
public File[] backupLog(IProgressMonitor monitor) {
long time = System.currentTimeMillis();
File logFile = getLogFile();
File tempFile = new File(logFile.getAbsolutePath() + ".tmp");
synchronized (this){
if (!logFile.exists()) {
return null;
}
//copy to a temporary file.
FileInputStream copyIn = null;
FileOutputStream copyOut = null;
try {
copyIn = new FileInputStream(logFile);
copyOut = new FileOutputStream(tempFile);
int length = -1;
byte[] buff = new byte[2048];
while ((length = copyIn.read(buff)) != -1) {
copyOut.write(buff, 0, length);
}
} catch (IOException e) {
return null;
} finally {
if (copyIn != null) {
try {
copyIn.close();
} catch (IOException e) {}
}
if (copyOut != null) {
try {
copyOut.close();
} catch (IOException e) {}
}
}
}
ArrayList<File> files = new ArrayList<File>();
File outputFile = new File(tempFile.getParentFile(), time + ".zip");
float scale = 1;
if (tempFile.length() > Integer.MAX_VALUE){
scale = ((float)Integer.MAX_VALUE)/tempFile.length();
}
String separator = System.getProperty("line.separator");
if (separator == null) {
separator = "\n";
}
int sbl = separator.getBytes().length;
monitor.beginTask("Backing up log", (int)(tempFile.length()*scale));
int fileCount = 0;
try {
ZipOutputStream zo = new ZipOutputStream(new FileOutputStream(outputFile));
PrintStream ps = new PrintStream(zo);
ZipEntry entry = new ZipEntry(time + ".log");
zo.putNextEntry(entry);
long linesRead = 0;
BufferedReader reader = new BufferedReader(new FileReader(tempFile));
String line = null;
while ((line = reader.readLine()) != null) {
if (monitor.isCanceled()) break;
if (outputFile.length() >= 1024*1024) {
files.add(outputFile);
linesRead = 0;
//create a new file.
zo.closeEntry();
ps.close();
fileCount++;
outputFile = new File(tempFile.getParentFile(), time + "-" + fileCount + ".zip");
zo = new ZipOutputStream(new FileOutputStream(outputFile));
ps = new PrintStream(zo);
entry = new ZipEntry(time + "-" + fileCount + ".log");
zo.putNextEntry(entry);
}
int bytesRead = line.getBytes().length + sbl;
monitor.worked((int)(bytesRead*scale));
linesRead++;
ps.println(line);
if ((linesRead % 100) ==0) {
ps.flush();
}
}
zo.closeEntry();
reader.close();
ps.close();
if (linesRead > 0){
files.add(outputFile);
}
tempFile.delete();
} catch (IOException e) {
WorkbenchLoggingPlugin.getDefault().log(e);
return null;
}
return files.toArray(new File[files.size()]);
}
}