de.schlichtherle.io.samples.CommandLineUtility Maven / Gradle / Ivy
Show all versions of truezip Show documentation
/*
* Copyright (C) 2007-2010 Schlichtherle IT Services
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.schlichtherle.io.samples;
import de.schlichtherle.io.*;
import de.schlichtherle.io.File;
import java.io.*;
import java.text.*;
/**
* Abstract base class for command line utilities.
*
* @author Christian Schlichtherle
* @version $Id: CommandLineUtility.java,v 1.5 2010/09/21 14:06:45 christian_schlichtherle Exp $
* @since TrueZIP 6.5
*/
abstract class CommandLineUtility {
/** The print stream for standard output. */
protected final PrintStream out;
/** The print stream for error output. */
protected final PrintStream err;
/** The command line progress monitor. */
protected final ProgressMonitor progressMonitor;
/**
* Equivalent to
* {@link #CommandLineUtility(OutputStream, OutputStream, boolean)
* CommandLineUtility(System.out, System.err, true)}.
*/
protected CommandLineUtility() {
this(System.out, System.err, true);
}
/**
* Constructs a new command line utility instance.
*
* Warning: This constructor has side effects:
* If Swing based prompting is used, the Hurling Window Feedback is set for
* feedback on wrong key entry unless the respective system properties
* have been explicitly set.
*
* @param out The standard output stream.
* @param err The error output stream.
* @param autoFlush If the output streams are not {@link PrintStream}s,
* then they are wrapped in a new {@code PrintStream} with
* this as the additional constructor parameter.
* @see de.schlichtherle.key.passwd.swing.PromptingKeyManager
*/
protected CommandLineUtility(
final OutputStream out,
final OutputStream err,
final boolean autoFlush) {
if (out == null || err == null)
throw new NullPointerException();
this.out = out instanceof PrintStream
? (PrintStream) out
: new PrintStream(out, autoFlush);
this.err = err instanceof PrintStream
? (PrintStream) err
: new PrintStream(err, autoFlush);
this.progressMonitor = new ProgressMonitor(this.err);
configKeyManager();
}
/**
* Configure the key manager to use when prompting the user for keys for
* RAES encrypted ZIP files.
*/
private static void configKeyManager() {
String feedback;
feedback = "de.schlichtherle.key.passwd.swing.InvalidOpenKeyFeedback";
System.setProperty(feedback,
System.getProperty(feedback,
"de.schlichtherle.key.passwd.swing.HurlingWindowFeedback"));
feedback = "de.schlichtherle.key.passwd.swing.InvalidCreateKeyFeedback";
System.setProperty(feedback,
System.getProperty(feedback,
"de.schlichtherle.key.passwd.swing.HurlingWindowFeedback"));
}
/**
* Runs this command line utility.
* Prints a user readable error message to the error output stream
* which was provided to the constructor if an error occurs.
*
* @param args A non-empty array of Unix-like commands and optional
* parameters.
* @return {@code 1} iff the command fails,
* {@code 0} otherwise.
*/
public final int run(final String[] args) {
try {
try {
return runWithException(args) ? 0 : 1;
} finally {
try {
File.umount();
} finally {
progressMonitor.shutdown();
}
}
} catch (IllegalUsageException ex) {
err.println(ex.getLocalizedMessage());
return 1;
} catch (IOException ex) {
err.println(ex.getLocalizedMessage());
return 1;
}
}
/**
* Runs this command line utility.
* Throws an exception if an error occurs.
*
* @param args A non-empty array of Unix-like commands and optional
* parameters.
* @return {@code false} iff the command is a test which fails,
* {@code true} otherwise.
* @throws IllegalUsageException If {@code args} does not contain
* correct commands or parameters.
* @throws IOException On any I/O related exception.
*/
public abstract boolean runWithException(String[] args)
throws IllegalUsageException, IOException;
protected static abstract class IllegalUsageException extends IllegalArgumentException {
IllegalUsageException(String msg) {
super(msg);
}
} // class IllegalUsageException
protected static class ProgressMonitor extends Thread {
private final PrintStream err;
private final Long[] args = new Long[2];
private final ArchiveStatistics liveStats = File.getLiveArchiveStatistics();
ProgressMonitor(final PrintStream err) {
setDaemon(true);
setPriority(Thread.MAX_PRIORITY);
this.err = err;
}
public void start() {
if (err == System.err || err == System.out)
super.start();
}
public void run() {
boolean run = false;
for (long sleep = 2000; ; sleep = 200, run = true) {
try {
Thread.sleep(sleep);
} catch (InterruptedException shutdown) {
break;
}
showProgress();
}
if (run) {
showProgress();
err.println();
}
}
/**
* Prints statistics about the amount of data read and written by
* {@link File#update()} or {@link File#umount()} on standard output.
*/
private void showProgress() {
// Round up to kilobytes.
args[0] = new Long(
(liveStats.getUpdateTotalByteCountRead() + 1023) / 1024);
args[1] = new Long(
(liveStats.getUpdateTotalByteCountWritten() + 1023) / 1024);
err.print(MessageFormat.format(
"Top level archive I/O: {0} / {1} KB \r", args));
err.flush();
}
private void shutdown() {
/*if (err != System.err && err != System.out)
return;*/
interrupt();
try {
join();
} catch (InterruptedException interrupted) {
interrupted.printStackTrace();
}
}
} // class ProgressMonitor
}