Issue #2225 Changes for make tar compressed files.

Change-Id: I154683fec10b57d548944dd9037d4ca61cbe1b1b

Former-commit-id: 477719a069 [formerly 3456f395e845457b1add41ca8d736a65b6fbb1c7]
Former-commit-id: d4eeceb020
This commit is contained in:
Roger Ferrel 2013-08-26 09:54:21 -05:00
parent 4ea2999847
commit b606e2b075
24 changed files with 1118 additions and 177 deletions

View file

@ -42,6 +42,13 @@
install-size="0"
version="0.0.0"/>
<plugin
id="org.apache.commons.compress"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.core.runtime"
download-size="0"

View file

@ -8,6 +8,7 @@ Bundle-Vendor: RAYTHEON
Require-Bundle: org.eclipse.ui;bundle-version="3.8.2",
org.eclipse.core.runtime,
org.apache.commons.lang;bundle-version="2.3.0",
org.apache.commons.io;bundle-version="2.4.0",
com.raytheon.viz.ui;bundle-version="1.12.1174",
com.raytheon.uf.common.serialization;bundle-version="1.12.1174",
com.raytheon.uf.common.localization;bundle-version="1.12.1174",
@ -18,3 +19,5 @@ Require-Bundle: org.eclipse.ui;bundle-version="3.8.2",
com.raytheon.uf.common.units;bundle-version="1.0.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Import-Package: org.apache.commons.compress.archivers,
org.apache.commons.compress.archivers.tar

View file

@ -52,6 +52,7 @@ import com.raytheon.uf.common.archive.config.DisplayData;
* Jun 10, 2013 #1966 rferrel Implemented hooks to get display and save to work.
* Jul 24, 2013 #2220 rferrel Add recompute size button.
* Jul 24, 2013 #2221 rferrel Changes for select configuration.
* Aug 26, 2013 #2225 rferrel Make dialog perspective independent.
*
* </pre>
*
@ -80,7 +81,8 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg {
*/
public ArchiveRetentionDlg(Shell parentShell) {
super(parentShell, SWT.DIALOG_TRIM | SWT.MIN, CAVE.DO_NOT_BLOCK
| CAVE.MODE_INDEPENDENT | CAVE.INDEPENDENT_SHELL);
| CAVE.MODE_INDEPENDENT | CAVE.INDEPENDENT_SHELL
| CAVE.PERSPECTIVE_INDEPENDENT);
this.type = Type.Retention;
}

View file

@ -62,6 +62,7 @@ import com.raytheon.uf.viz.archive.data.SizeJob;
* Jul 24, 2013 #2221 rferrel Changes for select configuration.
* Aug 06, 2013 #2222 rferrel Changes to display all selected data.
* Aug 14, 2013 #2220 rferrel Add refresh method.
* Aug 26, 2013 #2225 rferrel Add missing updates.
*
* </pre>
*
@ -493,6 +494,7 @@ public class ArchiveTableComp extends Composite {
table.setSortColumn(table.getColumn(LABEL_COL_INDEX));
table.setSortDirection(SWT.UP);
table.clearAll();
updateSelectionLabels();
}
/**
@ -500,6 +502,7 @@ public class ArchiveTableComp extends Composite {
*/
public void refresh() {
table.clearAll();
updateSelectionLabels();
}
/**

View file

@ -0,0 +1,82 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.archive.ui;
/**
* Exception to use when problem creating a case.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 22, 2013 2225 rferrel Initial creation
*
* </pre>
*
* @author rferrel
* @version 1.0
*/
public class CaseCreateException extends Exception {
static final long serialVersionUID = 0L;
/**
*
*/
public CaseCreateException() {
}
/**
* @param message
*/
public CaseCreateException(String message) {
super(message);
}
/**
* @param cause
*/
public CaseCreateException(Throwable cause) {
super(cause);
}
/**
* @param message
* @param cause
*/
public CaseCreateException(String message, Throwable cause) {
super(message, cause);
}
/**
* @param message
* @param cause
* @param enableSuppression
* @param writableStackTrace
*/
public CaseCreateException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
}

View file

@ -25,6 +25,7 @@ import java.util.Calendar;
import java.util.Date;
import java.util.List;
import org.apache.commons.io.FileUtils;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.dialogs.MessageDialog;
@ -71,6 +72,7 @@ import com.raytheon.viz.ui.dialogs.ICloseCallback;
* Jul 24, 2013 #2220 rferrel Add recompute size button.
* Jul 24, 2013 #2221 rferrel Changes for select configuration.
* Aug 06, 2013 #2222 rferrel Changes to display all selected data.
* Aug 26, 2013 #2225 rferrel Make perspective independent and no longer modal.
*
* </pre>
*
@ -152,6 +154,12 @@ public class CaseCreationDlg extends AbstractArchiveDlg {
/** Dialog to delete a select case. */
private CaseLoadSaveDeleteDlg deleteDlg;
/** Allow only single instance of dialog. */
private CaseNameDialog caseNameDlg;
/** Allow only single instance of dialog. */
private GenerateCaseDlg generateCaseDlg;
/**
* Constructor.
*
@ -160,7 +168,8 @@ public class CaseCreationDlg extends AbstractArchiveDlg {
*/
public CaseCreationDlg(Shell parentShell) {
super(parentShell, SWT.DIALOG_TRIM | SWT.MIN, CAVE.DO_NOT_BLOCK
| CAVE.MODE_INDEPENDENT | CAVE.INDEPENDENT_SHELL);
| CAVE.PERSPECTIVE_INDEPENDENT | CAVE.MODE_INDEPENDENT
| CAVE.INDEPENDENT_SHELL);
this.type = Type.Case;
this.setSelect = false;
this.type = Type.Case;
@ -623,7 +632,7 @@ public class CaseCreationDlg extends AbstractArchiveDlg {
}
/**
* Display modal dialog that performs the Generation of the case.
* Display dialog that performs the Generation of the case.
*/
private void generateCase() {
setCursorBusy(true);
@ -638,30 +647,44 @@ public class CaseCreationDlg extends AbstractArchiveDlg {
int compressSize = fileSizeSpnr.getSelection();
String sizeType = fileSizeCbo.getItem(fileSizeCbo.getSelectionIndex());
// Assume Model dialog.
GenerateCaseDlg dialog = new GenerateCaseDlg(shell, targetDir, caseDir,
startCal, endCal, displayDatas, doCompress, doMultiFiles,
compressSize, sizeType);
dialog.addJobChangeListener(new JobChangeAdapter() {
@Override
public void done(IJobChangeEvent event) {
VizApp.runAsync(new Runnable() {
@Override
public void run() {
updateLocationState();
}
});
setCursorBusy(true);
if (generateCaseDlg == null || generateCaseDlg.isDisposed()) {
long splitSize = 0L;
if (doCompress && doMultiFiles) {
if (sizeType.equals("MB")) {
splitSize = compressSize * FileUtils.ONE_MB;
} else {
splitSize = compressSize * FileUtils.ONE_GB;
}
}
});
dialog.setCloseCallback(new ICloseCallback() {
generateCaseDlg = new GenerateCaseDlg(shell, targetDir, caseDir,
startCal, endCal, displayDatas, doCompress, doMultiFiles,
splitSize);
generateCaseDlg.addJobChangeListener(new JobChangeAdapter() {
@Override
public void dialogClosed(Object returnValue) {
setCursorBusy(false);
}
});
dialog.open();
@Override
public void done(IJobChangeEvent event) {
VizApp.runAsync(new Runnable() {
@Override
public void run() {
updateLocationState();
setCursorBusy(false);
generateCaseDlg = null;
}
});
}
});
generateCaseDlg.setCloseCallback(new ICloseCallback() {
@Override
public void dialogClosed(Object returnValue) {
setCursorBusy(false);
}
});
generateCaseDlg.open();
} else {
generateCaseDlg.bringToTop();
}
}
@ -690,22 +713,29 @@ public class CaseCreationDlg extends AbstractArchiveDlg {
}
File targetDir = (File) o;
// Assume modal dialog.
CaseNameDialog dialog = new CaseNameDialog(shell, targetDir);
dialog.setCloseCallback(new ICloseCallback() {
@Override
public void dialogClosed(Object returnValue) {
if (returnValue instanceof File) {
File caseDir = (File) returnValue;
String caseName = caseDir.getAbsolutePath();
caseNameLbl.setText(caseName);
caseNameLbl.setData(caseDir);
checkGenerateButton();
setCursorBusy(true);
if (caseNameDlg == null || caseNameDlg.isDisposed()) {
caseNameDlg = new CaseNameDialog(shell, targetDir);
caseNameDlg.setCloseCallback(new ICloseCallback() {
@Override
public void dialogClosed(Object returnValue) {
if (returnValue instanceof File) {
File caseDir = (File) returnValue;
String caseName = caseDir.getAbsolutePath();
caseNameLbl.setText(caseName);
caseNameLbl.setData(caseDir);
checkGenerateButton();
}
caseNameDlg = null;
setCursorBusy(false);
}
}
});
dialog.open();
});
caseNameDlg.open();
} else {
caseNameDlg.bringToTop();
}
}
/**
@ -783,6 +813,9 @@ public class CaseCreationDlg extends AbstractArchiveDlg {
* Update location's state.
*/
private void updateLocationState() {
if (isDisposed()) {
return;
}
File dir = (File) locationLbl.getData();
long totSpace = dir.getTotalSpace();
long freeSpace = dir.getUsableSpace();
@ -824,51 +857,57 @@ public class CaseCreationDlg extends AbstractArchiveDlg {
* True for start time, false for end time.
*/
private void displayDateTimeControls(boolean startTimeFlag) {
setCursorBusy(true);
try {
Date acDate = startTimeFlag ? startDate : endDate;
AwipsCalendar ac = new AwipsCalendar(shell, acDate, 1);
ac.setTimeZone(TimeUtil.newCalendar().getTimeZone());
ac.setText((startTimeFlag ? "Start" : "End") + " Time Calendar");
Date acDate = startTimeFlag ? startDate : endDate;
AwipsCalendar ac = new AwipsCalendar(shell, acDate, 1);
ac.setTimeZone(TimeUtil.newCalendar().getTimeZone());
Date date = (Date) ac.open();
Date date = (Date) ac.open();
if (date == null) {
return;
}
if (startTimeFlag) {
if (date.after(endDate)) {
MessageBox mb = new MessageBox(shell, SWT.ICON_QUESTION
| SWT.OK);
mb.setText("Date Error");
mb.setMessage("The selected start date is after the end date. Resetting.");
mb.open();
if (date == null) {
return;
}
if (!startDate.equals(date)) {
startDate = date;
sizeJob.resetTime(getStart(), getEnd());
modified();
}
} else {
if (date.before(startDate)) {
MessageBox mb = new MessageBox(shell, SWT.ICON_QUESTION
| SWT.OK);
mb.setText("Date Error");
mb.setMessage("The selected end date is before the start date. Resetting.");
mb.open();
return;
}
if (!endDate.equals(date)) {
endDate = date;
sizeJob.resetTime(getStart(), getEnd());
modified();
}
}
if (startTimeFlag) {
if (date.after(endDate)) {
MessageBox mb = new MessageBox(shell, SWT.ICON_QUESTION
| SWT.OK);
mb.setText("Date Error");
mb.setMessage("The selected start date is after the end date. Resetting.");
mb.open();
return;
}
if (startTimeFlag) {
startTimeLbl.setText(dateFmt.format(date));
} else {
endTimeLbl.setText(dateFmt.format(date));
if (!startDate.equals(date)) {
startDate = date;
sizeJob.resetTime(getStart(), getEnd());
modified();
}
} else {
if (date.before(startDate)) {
MessageBox mb = new MessageBox(shell, SWT.ICON_QUESTION
| SWT.OK);
mb.setText("Date Error");
mb.setMessage("The selected end date is before the start date. Resetting.");
mb.open();
return;
}
if (!endDate.equals(date)) {
endDate = date;
sizeJob.resetTime(getStart(), getEnd());
modified();
}
}
if (startTimeFlag) {
startTimeLbl.setText(dateFmt.format(date));
} else {
endTimeLbl.setText(dateFmt.format(date));
}
} finally {
setCursorBusy(false);
}
}

View file

@ -45,6 +45,7 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 31, 2013 2221 rferrel Initial creation
* Aug 26, 2013 2225 rferrel Make perspective independent.
*
* </pre>
*
@ -85,7 +86,8 @@ public class CaseLoadSaveDeleteDlg extends CaveSWTDialog {
private Button cancelBtn;
protected CaseLoadSaveDeleteDlg(Shell parentShell, Type type) {
super(parentShell, SWT.DIALOG_TRIM | SWT.RESIZE, CAVE.DO_NOT_BLOCK);
super(parentShell, SWT.DIALOG_TRIM | SWT.RESIZE, CAVE.DO_NOT_BLOCK
| CAVE.PERSPECTIVE_INDEPENDENT);
this.type = type;
}

View file

@ -47,6 +47,7 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 5, 2013 1966 rferrel Initial creation
* Aug 26, 2013 2225 rferrel Make perspective independent.
*
* </pre>
*
@ -65,7 +66,7 @@ public class CaseNameDialog extends CaveSWTDialog {
/** Non-blocking modal constructor. */
protected CaseNameDialog(Shell parent, File locationDir) {
super(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL,
CAVE.DO_NOT_BLOCK);
CAVE.DO_NOT_BLOCK | CAVE.PERSPECTIVE_INDEPENDENT);
this.locationDir = locationDir;
}

View file

@ -19,12 +19,24 @@
**/
package com.raytheon.uf.viz.archive.ui;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.zip.GZIPOutputStream;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.io.FileUtils;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
@ -45,6 +57,7 @@ import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Shell;
import com.raytheon.uf.common.archive.config.ArchiveConfigManager;
import com.raytheon.uf.common.archive.config.ArchiveConstants;
import com.raytheon.uf.common.archive.config.DisplayData;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
@ -54,7 +67,8 @@ import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
/**
* Class to show progress of creating a case.
* This class performs the desired type of case creation and display a
* progress/status message dialog.
*
* <pre>
*
@ -63,10 +77,13 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 3, 2013 1966 rferrel Initial creation
* Aug 16, 2013 2225 rferrel Change structure of copy to include
* archive and category directory and
* implementation of compression.
*
* </pre>
*
* @author rferrelGenerateJob
* @author rferrel
* @version 1.0
*/
@ -86,9 +103,6 @@ public class GenerateCaseDlg extends CaveSWTDialog {
/** Active have generation is finish or has an error. */
private Button closeBtn;
/** The main destination directory. */
private final File targetDir;
/**
* The case's destination directory. Assumed to be a sub-directory of
* targetDir.
@ -102,7 +116,7 @@ public class GenerateCaseDlg extends CaveSWTDialog {
private final Calendar endCal;
/** Data list for the case. */
private final List<DisplayData> sourceDataList;
private final DisplayData[] sourceDataList;
/** When true compress the case directory. */
private final boolean doCompress;
@ -110,11 +124,9 @@ public class GenerateCaseDlg extends CaveSWTDialog {
/** When true break the compress file into multiple files. */
private final boolean doMultiFiles;
/** The compress size for muliple files. */
private final int compressSize;
/** Assumed to be MG or GB to indicate scaling factor for compressSize. */
private final String sizeType;
// Needed when compress and split implemented
// /** The compress size for multiple files. */
// private final long splitSize;
/** Job to perform the case generation off of the UI thread. */
private GenerateJob generateJob;
@ -140,24 +152,24 @@ public class GenerateCaseDlg extends CaveSWTDialog {
* @param sourceList
* @param doCompress
* @param doMultiFiles
* @param compressSize
* @param sizeType
* @param splitSize
*/
protected GenerateCaseDlg(Shell parentShell, File targetDir, File caseDir,
Calendar startCal, Calendar endCal, List<DisplayData> sourceList,
boolean doCompress, boolean doMultiFiles, int compressSize,
String sizeType) {
super(parentShell, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL,
CAVE.DO_NOT_BLOCK);
this.targetDir = targetDir;
boolean doCompress, boolean doMultiFiles, long splitSize) {
super(parentShell, SWT.DIALOG_TRIM, CAVE.DO_NOT_BLOCK
| CAVE.PERSPECTIVE_INDEPENDENT);
this.caseDir = caseDir;
this.startCal = startCal;
this.endCal = endCal;
this.sourceDataList = new ArrayList<DisplayData>(sourceList);
this.sourceDataList = sourceList.toArray(new DisplayData[sourceList
.size()]);
Arrays.sort(this.sourceDataList, DisplayData.LABEL_ORDER);
this.doCompress = doCompress;
this.doMultiFiles = doMultiFiles;
this.compressSize = compressSize;
this.sizeType = sizeType;
// Needed when compress and split implemented.
// this.splitSize = splitSize;
this.caseName = caseDir.getAbsolutePath().substring(
targetDir.getAbsolutePath().length() + 1);
setText("Generating - " + caseName);
@ -173,7 +185,7 @@ public class GenerateCaseDlg extends CaveSWTDialog {
}
/**
* Remve a job listener.
* Remove a job listener.
*
* @param listener
*/
@ -357,10 +369,10 @@ public class GenerateCaseDlg extends CaveSWTDialog {
* The performs the work of generating the case on a non-UI thread.
*/
private class GenerateJob extends Job {
boolean shutdown = false;
private final AtomicBoolean shutdown = new AtomicBoolean(false);
public GenerateJob() {
super("Generate Job");
super("Generate Case");
}
@Override
@ -371,81 +383,100 @@ public class GenerateCaseDlg extends CaveSWTDialog {
setStateLbl("Creating: " + caseDir.getName(),
caseDir.getAbsolutePath());
ICaseCopy caseCopy = null;
String errorMessage = null;
if (caseDir.exists()) {
setStateLbl("Case exists: " + caseName,
caseDir.getAbsolutePath());
errorMessage = "Case exists: " + caseDir.getName();
} else if (!caseDir.mkdirs()) {
errorMessage = "Unable to create case: " + caseDir.getName();
}
if (errorMessage != null) {
setStateLbl(errorMessage, caseDir.getAbsolutePath());
setProgressBar(100, SWT.ERROR);
return Status.OK_STATUS;
}
if (!caseDir.mkdirs()) {
setStateLbl("Unable to create case: " + caseName,
caseDir.getAbsolutePath());
setProgressBar(100, SWT.ERROR);
if (shutdown.get()) {
return Status.OK_STATUS;
}
if (shutdown) {
return Status.OK_STATUS;
}
String currentArchive = null;
String currentCategory = null;
boolean updateDestDir = false;
for (DisplayData displayData : sourceDataList) {
if (shutdown) {
return Status.OK_STATUS;
}
setStateLbl(
"Copying \"" + displayData.getDisplayLabel() + "\"",
null);
String rootDir = displayData.getRootDir();
int beginIndex = rootDir.length();
List<File> files = archiveManager.getDisplayFiles(displayData,
startCal, endCal);
for (File source : files) {
if (shutdown) {
try {
for (DisplayData displayData : sourceDataList) {
if (shutdown.get()) {
return Status.OK_STATUS;
}
String name = source.getAbsolutePath();
String relativePath = name.substring(beginIndex);
if (!displayData.getArchiveName().equals(currentArchive)) {
updateDestDir = true;
currentArchive = displayData.getArchiveName();
currentCategory = displayData.getCategoryName();
} else if (!displayData.getCategoryName().equals(
currentCategory)) {
updateDestDir = true;
currentCategory = displayData.getCategoryName();
}
setStateLbl("Copy: " + relativePath, name);
File destination = new File(caseDir, relativePath);
try {
if (source.isDirectory()) {
destination.mkdirs();
FileUtil.copyDirectory(source, destination);
if (updateDestDir) {
updateDestDir = false;
if (caseCopy != null) {
caseCopy.finishCase();
} else {
File destParent = destination.getParentFile();
destParent.mkdirs();
FileUtil.copyFile(source, destination);
if (!doCompress) {
caseCopy = new CopyMove();
} else if (doMultiFiles) {
caseCopy = new CompressAndSplitCopy();
} else {
caseCopy = new CompressCopy();
}
}
} catch (IOException e) {
statusHandler.handle(Priority.PROBLEM,
e.getLocalizedMessage(), e);
caseCopy.startCase(caseDir, displayData, shutdown);
setStateLbl(currentArchive + " | " + currentCategory,
caseDir.getAbsolutePath() + "\n"
+ currentArchive + "\n"
+ currentCategory);
}
List<File> files = archiveManager.getDisplayFiles(
displayData, startCal, endCal);
for (File source : files) {
if (shutdown.get()) {
return Status.OK_STATUS;
}
caseCopy.copy(source);
}
}
}
if (caseCopy != null) {
caseCopy.finishCase();
}
caseCopy = null;
if (!doCompress) {
setProgressBar(100, SWT.NORMAL);
setStateLbl("Created: " + caseName, caseDir.getAbsolutePath());
return Status.OK_STATUS;
}
if (shutdown) {
return Status.OK_STATUS;
}
if (doMultiFiles) {
setProgressBar(100, SWT.NORMAL);
String message = "Compress into multifiles NYI.";
setStateLbl(message, null);
} else {
setProgressBar(100, SWT.NORMAL);
String message = "Compress into one file NYI";
setStateLbl(message, null);
} catch (CaseCreateException e) {
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
e);
setStateLbl(
"Failed to Create: " + caseName,
caseDir.getAbsolutePath() + "\n"
+ e.getLocalizedMessage());
setProgressBar(100, SWT.ERROR);
} finally {
if (caseCopy != null) {
try {
caseCopy.finishCase();
} catch (CaseCreateException ex) {
// Ignore
}
caseCopy = null;
}
}
return Status.OK_STATUS;
@ -458,8 +489,602 @@ public class GenerateCaseDlg extends CaveSWTDialog {
*/
@Override
protected void canceling() {
shutdown = true;
shutdown.set(true);
generateJob = null;
}
}
/**
* This class copies selected files/directories to a
* case-directory/archive/category.
*/
private static class CopyMove implements ICaseCopy {
/**
* Flag to indicate user canceled the case generation.
*/
private AtomicBoolean shutdown;
/**
* Top destination directory to move files/dirctories to.
*/
private File destDir;
/**
* Index on source Files where relative path starts.
*/
private int startRelativePath;
/**
* Copy source File to desired destination.
*
* @param source
* @param destination
* @throws IOException
*/
private void copyFile(File source, File destination) throws IOException {
if (shutdown.get()) {
return;
}
if (source.isDirectory()) {
if (!destination.exists()) {
destination.mkdir();
}
String[] files = source.list();
for (String file : files) {
copyFile(new File(source, file),
new File(destination, file));
}
} else {
FileUtil.copyFile(source, destination);
destination.setLastModified(source.lastModified());
}
}
@Override
public void copy(File source) throws CaseCreateException {
String relativePath = source.getAbsolutePath().substring(
startRelativePath);
File destination = new File(destDir, relativePath);
try {
destination.getParentFile().mkdirs();
copyFile(source, destination);
} catch (IOException ex) {
throw new CaseCreateException("CopyMove.copy: ", ex);
}
}
@Override
public void startCase(File caseDir, DisplayData displayData,
AtomicBoolean shutdown) {
this.shutdown = shutdown;
String archiveDirName = ArchiveConstants
.convertToFileName(displayData.getArchiveName());
String catgegoryDirName = ArchiveConstants
.convertToFileName(displayData.getCategoryName());
destDir = new File(caseDir, archiveDirName + File.separator
+ catgegoryDirName);
destDir.mkdirs();
startRelativePath = displayData.getRootDir().length();
}
@Override
public void finishCase() {
// Nothing to do.
}
}
/**
* This class takes selected directories/files to
* case-directory/archive/compress-category-file. The compress-category-file
* is a tar gzip file containing the categorie's data.
*/
private static class CompressCopy implements ICaseCopy {
/**
* Flag to indicate user canceled case geneation.
*/
private AtomicBoolean shutdown;
/**
* Top Level destination directory.
*/
private File destDir;
/**
* Stream to the file being created.
*/
private FileOutputStream fileStream;
/**
* Stream to perform the compression.
*/
private GZIPOutputStream zipStream;
/**
* Stream to create the tar image.
*/
private ArchiveOutputStream tarStream;
/**
* Index to start of relative path in source File.
*/
private int startRelativePath;
/**
* Directories already created in the tar image.
*/
private final HashSet<File> tarDirFile = new HashSet<File>();
/**
* Category directory name; may be different from the category name.
*/
private String categoryDirName;
/**
* Buffer to use for reading in a file.
*/
private final byte[] buffer = new byte[(int) (32 * FileUtils.ONE_KB)];
@Override
public void copy(File source) throws CaseCreateException {
try {
addParentDir(source);
addTarFiles(new File[] { source });
} catch (IOException e) {
throw new CaseCreateException("Compress Copy failed: ", e);
}
}
/**
* Add list of Files to the tar image.
*
* @param files
* @throws IOException
*/
private void addTarFiles(File[] files) throws IOException {
for (File file : files) {
if (shutdown.get()) {
return;
}
String name = categoryDirName + File.separator
+ file.getAbsolutePath().substring(startRelativePath);
if (file.isDirectory()) {
if (!tarDirFile.contains(file)) {
TarArchiveEntry entry = new TarArchiveEntry(file, name);
tarStream.putArchiveEntry(entry);
tarStream.closeArchiveEntry();
tarDirFile.add(file);
addTarFiles(file.listFiles());
}
} else {
TarArchiveEntry entry = new TarArchiveEntry(file, name);
entry.setSize(file.length());
FileInputStream fileStream = null;
tarStream.putArchiveEntry(entry);
try {
fileStream = new FileInputStream(file);
int len;
while ((len = fileStream.read(buffer)) != -1) {
tarStream.write(buffer, 0, len);
}
} finally {
if (fileStream != null) {
closeStream(fileStream);
}
}
tarStream.closeArchiveEntry();
}
}
}
/**
* Convince method to close a steam and ignore any IOException.
*
* @param stream
*/
private void closeStream(Closeable stream) {
try {
stream.close();
} catch (IOException ex) {
// Ignore
}
}
/**
* If needed add parent directories to the tar image.
*
* @param file
* @throws IOException
*/
private void addParentDir(File file) throws IOException {
File parent = file.getParentFile();
if (parent != null && !tarDirFile.contains(parent)) {
addParentDir(parent);
String name = categoryDirName + File.separator
+ parent.getAbsolutePath().substring(startRelativePath);
TarArchiveEntry entry = new TarArchiveEntry(parent, name);
tarStream.putArchiveEntry(entry);
tarStream.closeArchiveEntry();
tarDirFile.add(parent);
}
}
@Override
public void startCase(File caseDir, DisplayData displayData,
AtomicBoolean shutdown) throws CaseCreateException {
try {
this.shutdown = shutdown;
String archiveDirName = ArchiveConstants
.convertToFileName(displayData.getArchiveName());
categoryDirName = ArchiveConstants
.convertToFileName(displayData.getCategoryName());
destDir = new File(caseDir, archiveDirName);
destDir.mkdirs();
tarDirFile.clear();
startRelativePath = displayData.getRootDir().length();
File sourceRootDir = new File(displayData.getRootDir());
File tarFile = new File(destDir, categoryDirName
+ ArchiveConstants.TAR_EXTENSION);
fileStream = new FileOutputStream(tarFile);
zipStream = new GZIPOutputStream(fileStream);
ArchiveStreamFactory factory = new ArchiveStreamFactory();
tarStream = factory.createArchiveOutputStream(
ArchiveStreamFactory.TAR, zipStream);
if (tarStream instanceof TarArchiveOutputStream) {
((TarArchiveOutputStream) tarStream)
.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
}
TarArchiveEntry entry = new TarArchiveEntry(sourceRootDir,
categoryDirName);
tarStream.putArchiveEntry(entry);
tarStream.closeArchiveEntry();
tarDirFile.add(sourceRootDir);
} catch (Exception e) {
throw new CaseCreateException("CompressCopy.startCase: ", e);
}
}
@Override
public void finishCase() throws CaseCreateException {
try {
if (tarStream != null) {
tarStream.finish();
}
if (zipStream != null) {
zipStream.finish();
}
} catch (IOException e) {
throw new CaseCreateException("CaseCopy.finish: ", e);
} finally {
if (tarStream != null) {
closeStream(tarStream);
} else if (zipStream != null) {
closeStream(zipStream);
} else if (fileStream != null) {
closeStream(fileStream);
}
tarStream = null;
zipStream = null;
fileStream = null;
}
}
}
/*
* This class intended for making "image" files read for burning to a CD or
* DVD. Need to resolve issues on how this should be done.
*/
private static class CompressAndSplitCopy implements ICaseCopy {
public void startCase(File caseDir, DisplayData displayData,
AtomicBoolean shutdown) throws CaseCreateException {
throw new CaseCreateException(
"Compress and split not yet implemented.");
}
@Override
public void copy(File source) throws CaseCreateException {
// TODO Auto-generated method stub
}
@Override
public void finishCase() {
// TODO Auto-generated method stub
}
// TODO Example code for future implementation of this class.
// Will need to break up into the starCase, copy and finishCase will
// need close and join.
// private void compressAndSplitCase() {
// ArchiveOutputStream tarStream = null;
// GZIPOutputStream zipStream = null;
// try {
// Pipe pipe = Pipe.open();
// OutputStream poStream = Channels.newOutputStream(pipe.sink());
// zipStream = new GZIPOutputStream(poStream);
// ArchiveStreamFactory factory = new ArchiveStreamFactory();
//
// tarStream = factory.createArchiveOutputStream(
// ArchiveStreamFactory.TAR, zipStream);
//
// if (tarStream instanceof TarArchiveOutputStream) {
// ((TarArchiveOutputStream) tarStream)
// .setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
// }
//
// final InputStream piStream = Channels.newInputStream(pipe
// .source());
// splitDone.set(false);
//
// Job splitJob = new Job("Split") {
//
// @Override
// protected IStatus run(IProgressMonitor monitor) {
// OutputStream splitStream = null;
// long totSize = 0;
// try {
// byte[] buffer = new byte[12 * 1024];
//
// int bufCnt = 0;
// long splitCnt = 0L;
// while ((bufCnt = piStream.read(buffer)) != -1) {
// totSize += bufCnt;
// if (splitStream == null) {
// splitStream = openSplitFile(++numSplitFiles);
// }
// long fileSize = splitCnt + bufCnt;
// if (fileSize < splitSize) {
// splitStream.write(buffer, 0, bufCnt);
// splitCnt = fileSize;
// } else if (fileSize == splitSize) {
// splitStream.write(buffer, 0, bufCnt);
// splitStream.close();
// splitStream = null;
// splitCnt = 0L;
// } else {
// int cnt = (int) (splitSize - splitCnt);
// splitStream.write(buffer, 0, cnt);
// splitStream.close();
// splitStream = openSplitFile(++numSplitFiles);
// int remainder = bufCnt - cnt;
// splitStream.write(buffer, cnt, remainder);
// splitCnt = remainder;
// }
// }
// } catch (IOException e) {
// statusHandler.handle(Priority.PROBLEM,
// e.getLocalizedMessage(), e);
// } finally {
// if (splitStream != null) {
// try {
// splitStream.close();
// } catch (IOException e) {
// // Ignore
// }
// }
// splitDone.set(true);
// System.out.println("totalSize: " + totSize
// + ", splitSize: " + splitSize
// + ", numSplitFiles: " + numSplitFiles);
// }
//
// return Status.OK_STATUS;
// }
// };
// splitJob.schedule();
//
// createTarFile(tarStream, caseDir.listFiles());
// tarStream.finish();
// zipStream.finish();
// try {
// tarStream.close();
// } catch (IOException ex) {
// // Ignore
// }
// tarStream = null;
//
// try {
// zipStream.close();
// } catch (IOException ex) {
// // Ignore
// }
// zipStream = null;
//
// while (!splitDone.get()) {
// if (splitJob.getState() == Job.RUNNING) {
// try {
// System.out.println("splitJob.join()");
// splitJob.join();
// } catch (InterruptedException e) {
// statusHandler.handle(Priority.INFO,
// e.getLocalizedMessage(), e);
// }
// } else {
// try {
// private void compressAndSplitCase() {
// ArchiveOutputStream tarStream = null;
// GZIPOutputStream zipStream = null;
// try {
// Pipe pipe = Pipe.open();
// OutputStream poStream = Channels.newOutputStream(pipe.sink());
// zipStream = new GZIPOutputStream(poStream);
// ArchiveStreamFactory factory = new ArchiveStreamFactory();
//
// tarStream = factory.createArchiveOutputStream(
// ArchiveStreamFactory.TAR, zipStream);
//
// if (tarStream instanceof TarArchiveOutputStream) {
// ((TarArchiveOutputStream) tarStream)
// .setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
// }
//
// final InputStream piStream = Channels.newInputStream(pipe
// .source());
// splitDone.set(false);
//
// Job splitJob = new Job("Split") {
//
// @Override
// protected IStatus run(IProgressMonitor monitor) {
// OutputStream splitStream = null;
// long totSize = 0;
// try {
// byte[] buffer = new byte[12 * 1024];
//
// int bufCnt = 0;
// long splitCnt = 0L;
// while ((bufCnt = piStream.read(buffer)) != -1) {
// totSize += bufCnt;
// if (splitStream == null) {
// splitStream = openSplitFile(++numSplitFiles);
// }
// long fileSize = splitCnt + bufCnt;
// if (fileSize < splitSize) {
// splitStream.write(buffer, 0, bufCnt);
// splitCnt = fileSize;
// } else if (fileSize == splitSize) {
// splitStream.write(buffer, 0, bufCnt);
// splitStream.close();
// splitStream = null;
// splitCnt = 0L;
// } else {
// int cnt = (int) (splitSize - splitCnt);
// splitStream.write(buffer, 0, cnt);
// splitStream.close();
// splitStream = openSplitFile(++numSplitFiles);
// int remainder = bufCnt - cnt;
// splitStream.write(buffer, cnt, remainder);
// splitCnt = remainder;
// }
// }
// } catch (IOException e) {
// statusHandler.handle(Priority.PROBLEM,
// e.getLocalizedMessage(), e);
// } finally {
// if (splitStream != null) {
// try {
// splitStream.close();
// } catch (IOException e) {
// // Ignore
// }
// }
// splitDone.set(true);
// System.out.println("totalSize: " + totSize
// + ", splitSize: " + splitSize
// + ", numSplitFiles: " + numSplitFiles);
// }
//
// return Status.OK_STATUS;
// }
// };
// splitJob.schedule();
//
// createTarFile(tarStream, caseDir.listFiles());
// tarStream.finish();
// zipStream.finish();
// try {
// tarStream.close();
// } catch (IOException ex) {
// // Ignore
// }
// tarStream = null;
//
// try {
// zipStream.close();
// } catch (IOException ex) {
// // Ignore
// }
// zipStream = null;
//
// while (!splitDone.get()) {
// if (splitJob.getState() == Job.RUNNING) {
// try {
// System.out.println("splitJob.join()");
// splitJob.join();
// } catch (InterruptedException e) {
// statusHandler.handle(Priority.INFO,
// e.getLocalizedMessage(), e);
// }
// } else {
// try {
// Thread.sleep(200L);
// } catch (InterruptedException e) {
// statusHandler.handle(Priority.INFO,
// e.getLocalizedMessage(), e);
// }
// }
// }
// } catch (IOException e) {
// statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
// e);
// } catch (ArchiveException e1) {
// statusHandler.handle(Priority.PROBLEM,
// e1.getLocalizedMessage(), e1);
// } finally {
// if (tarStream != null) {
// try {
// tarStream.close();
// } catch (IOException e) {
// // Ignore
// }
// }
//
// if (zipStream != null) {
// try {
// zipStream.close();
// } catch (IOException e) {
// // Ignore
// }
// }
// }
// setProgressBar(100, SWT.NORMAL);
// deleteCaseDir();
// String message = caseDir.getName() + "split into " + numSplitFiles
// + " file(s).";
// setStateLbl(message, null);
// }
// Thread.sleep(200L);
// } catch (InterruptedException e) {
// statusHandler.handle(Priority.INFO,
// e.getLocalizedMessage(), e);
// }
// }
// }
// } catch (IOException e) {
// statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
// e);
// } catch (ArchiveException e1) {
// statusHandler.handle(Priority.PROBLEM,
// e1.getLocalizedMessage(), e1);
// } finally {
// if (tarStream != null) {
// try {
// tarStream.close();
// } catch (IOException e) {
// // Ignore
// }
// }
//
// if (zipStream != null) {
// try {
// zipStream.close();
// } catch (IOException e) {
// // Ignore
// }
// }
// }
// setProgressBar(100, SWT.NORMAL);
// deleteCaseDir();
// String message = caseDir.getName() + "split into " + numSplitFiles
// + " file(s).";
// setStateLbl(message, null);
// }
}
}

View file

@ -0,0 +1,76 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.archive.ui;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import com.raytheon.uf.common.archive.config.DisplayData;
/**
* Interface for copying source files/directories to the desired type of
* destination.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 21, 2013 2225 rferrel Initial creation
*
* </pre>
*
* @author rferrel
* @version 1.0
*/
public interface ICaseCopy {
/**
* Prepare copier for sending display data's archive and category
* selections.
*
* @param caseDir
* - top level case directory file
* @param displayData
* - data preparing to move
* @param shutdown
* - Flag to check for orderly shudown
* @throws CaseCreateException
*/
public void startCase(File caseDir, DisplayData displayData,
AtomicBoolean shutdown) throws CaseCreateException;
/**
* A source to copy.
*
* @param source
* @throws IOException
*/
public void copy(File source) throws CaseCreateException;
/**
* Finish the move process for the current archive and category.
*
*/
public void finishCase() throws CaseCreateException;
}

View file

@ -0,0 +1,47 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.archive.ui;
/**
* Interface to adjusting values based on the retention hour value found in a
* selection configuration.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 13, 2013 2220 rferrel Initial creation
*
* </pre>
*
* @author rferrel
* @version 1.0
*/
public interface IRetentionHour {
/**
* Adjust start/end based on the value found in selection configuration.
*
* @param startRetentionHours
*/
public void setRetentionTimes(long startRetentionHours);
}

View file

@ -4,7 +4,6 @@
<classpathentry exported="true" kind="lib" path="apache-mime4j-dom-0.7.jar"/>
<classpathentry exported="true" kind="lib" path="asm-3.1.jar"/>
<classpathentry exported="true" kind="lib" path="boilerpipe-1.1.0.jar"/>
<classpathentry exported="true" kind="lib" path="commons-compress-1.3.jar"/>
<classpathentry exported="true" kind="lib" path="je-4.0.92.jar"/>
<classpathentry exported="true" kind="lib" path="metadata-extractor-2.4.0-beta-1.jar"/>
<classpathentry exported="true" kind="lib" path="tagsoup-1.2.1.jar"/>

View file

@ -9,7 +9,6 @@ Bundle-ClassPath: apache-mime4j-core-0.7.jar,
apache-mime4j-dom-0.7.jar,
asm-3.1.jar,
boilerpipe-1.1.0.jar,
commons-compress-1.3.jar,
je-4.0.92.jar,
metadata-extractor-2.4.0-beta-1.jar,
tagsoup-1.2.1.jar,
@ -17,7 +16,8 @@ Bundle-ClassPath: apache-mime4j-core-0.7.jar,
tika-parsers-1.0.jar,
.
Require-Bundle: org.apache.commons.codec;bundle-version="1.4.0",
org.apache.http;bundle-version="4.1.2"
org.apache.http;bundle-version="4.1.2",
org.apache.commons.compress;bundle-version="1.5.0"
Export-Package: com.drew.imaging,
com.drew.imaging.jpeg,
com.drew.imaging.tiff,
@ -87,19 +87,6 @@ Export-Package: com.drew.imaging,
edu.uci.ics.crawler4j.robotstxt,
edu.uci.ics.crawler4j.url,
edu.uci.ics.crawler4j.util,
org.apache.commons.compress.archivers,
org.apache.commons.compress.archivers.ar,
org.apache.commons.compress.archivers.cpio,
org.apache.commons.compress.archivers.dump,
org.apache.commons.compress.archivers.jar,
org.apache.commons.compress.archivers.tar,
org.apache.commons.compress.archivers.zip,
org.apache.commons.compress.changes,
org.apache.commons.compress.compressors,
org.apache.commons.compress.compressors.bzip2,
org.apache.commons.compress.compressors.gzip,
org.apache.commons.compress.compressors.pack200,
org.apache.commons.compress.utils,
org.apache.james.mime4j,
org.apache.james.mime4j.codec,
org.apache.james.mime4j.dom,

View file

@ -6,7 +6,6 @@ bin.includes = META-INF/,\
apache-mime4j-dom-0.7.jar,\
asm-3.1.jar,\
boilerpipe-1.1.0.jar,\
commons-compress-1.3.jar,\
je-4.0.92.jar,\
metadata-extractor-2.4.0-beta-1.jar,\
tagsoup-1.2.1.jar,\

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry exported="true" kind="lib" path="commons-compress-1.5.jar" sourcepath="commons-compress-1.5-sources.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.apache.commons.compress</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,7 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

View file

@ -0,0 +1,21 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Compress
Bundle-SymbolicName: org.apache.commons.compress
Bundle-Version: 1.5
Bundle-Vendor: Apache
Export-Package: org.apache.commons.compress.archivers,
org.apache.commons.compress.archivers.ar,
org.apache.commons.compress.archivers.cpio,
org.apache.commons.compress.archivers.dump,
org.apache.commons.compress.archivers.jar,
org.apache.commons.compress.archivers.tar,
org.apache.commons.compress.archivers.zip,
org.apache.commons.compress.changes,
org.apache.commons.compress.compressors,
org.apache.commons.compress.compressors.bzip2,
org.apache.commons.compress.compressors.gzip,
org.apache.commons.compress.compressors.pack200,
org.apache.commons.compress.compressors.xz,
org.apache.commons.compress.utils
Bundle-ClassPath: commons-compress-1.5.jar

View file

@ -0,0 +1,2 @@
bin.includes = META-INF/,\
commons-compress-1.5.jar

View file

@ -33,6 +33,7 @@ import com.raytheon.uf.common.localization.IPathManager;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 23, 2013 #2221 rferrel Initial creation
* Aug 26, 2013 #2225 rferrel Added tar extension.
*
* </pre>
*
@ -66,6 +67,9 @@ public class ArchiveConstants {
}
}
/** Extension for compressed tar files. */
public final static String TAR_EXTENSION = ".tgz";
/**
* Do not allow an instance of this class.
*/