aboutsummaryrefslogtreecommitdiffstats
path: root/src/com/cyanogenmod/filemanager/commands/shell/CompressCommand.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/cyanogenmod/filemanager/commands/shell/CompressCommand.java')
-rw-r--r--src/com/cyanogenmod/filemanager/commands/shell/CompressCommand.java307
1 files changed, 307 insertions, 0 deletions
diff --git a/src/com/cyanogenmod/filemanager/commands/shell/CompressCommand.java b/src/com/cyanogenmod/filemanager/commands/shell/CompressCommand.java
new file mode 100644
index 00000000..d4dec8d8
--- /dev/null
+++ b/src/com/cyanogenmod/filemanager/commands/shell/CompressCommand.java
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2012 The CyanogenMod Project
+ *
+ * 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 com.cyanogenmod.filemanager.commands.shell;
+
+import com.cyanogenmod.filemanager.commands.AsyncResultListener;
+import com.cyanogenmod.filemanager.commands.CompressExecutable;
+import com.cyanogenmod.filemanager.commands.SIGNAL;
+import com.cyanogenmod.filemanager.console.CommandNotFoundException;
+import com.cyanogenmod.filemanager.console.ExecutionException;
+import com.cyanogenmod.filemanager.console.InsufficientPermissionsException;
+import com.cyanogenmod.filemanager.preferences.CompressionMode;
+import com.cyanogenmod.filemanager.util.FileHelper;
+
+import java.io.File;
+
+/**
+ * A class for compress file system objects
+ *
+ * {@link "http://unixhelp.ed.ac.uk/CGI/man-cgi?tar"}
+ * {@link "http://unixhelp.ed.ac.uk/CGI/man-cgi?gzip"}
+ * {@link "http://unixhelp.ed.ac.uk/CGI/man-cgi?bzip2"}
+ */
+public class CompressCommand extends AsyncResultProgram implements CompressExecutable {
+
+ /**
+ * An enumeration of implemented compression modes.
+ */
+ private enum Mode {
+ /**
+ * Archive using Tar algorithm
+ */
+ A_TAR(TAR_ID, "", CompressionMode.A_TAR), //$NON-NLS-1$
+ /**
+ * Archive and compress using Gzip algorithm
+ */
+ AC_GZIP(TAR_ID, "z", CompressionMode.AC_GZIP), //$NON-NLS-1$
+ /**
+ * Archive and compress using Gzip algorithm
+ */
+ AC_GZIP2(TAR_ID, "z", CompressionMode.AC_GZIP2), //$NON-NLS-1$
+ /**
+ * Archive and compress using Bzip algorithm
+ */
+ AC_BZIP(TAR_ID, "j", CompressionMode.AC_BZIP), //$NON-NLS-1$
+ /**
+ * Compress using Gzip algorithm
+ */
+ C_GZIP(GZIP_ID, "z", CompressionMode.C_GZIP), //$NON-NLS-1$
+ /**
+ * Compress using Bzip algorithm
+ */
+ C_BZIP(BZIP_ID, "j", CompressionMode.C_BZIP); //$NON-NLS-1$
+
+ final String mId;
+ final String mFlag;
+ final CompressionMode mMode;
+
+ /**
+ * Constructor of <code>Mode</code>
+ *
+ * @param id The command identifier
+ * @param flag The tar compression flag
+ * @param mode The compression mode
+ */
+ private Mode(String id, String flag, CompressionMode mode) {
+ this.mId = id;
+ this.mFlag = flag;
+ this.mMode = mode;
+ }
+
+ /**
+ * Method that return the mode from his compression mode
+ *
+ * @param mode The compression mode
+ * @return Mode The mode
+ */
+ public static Mode fromCompressionMode(CompressionMode mode) {
+ Mode[] modes = Mode.values();
+ int cc = modes.length;
+ for (int i = 0; i < cc; i++) {
+ if (modes[i].mMode.compareTo(mode) == 0) {
+ return modes[i];
+ }
+ }
+ return null;
+ }
+ }
+
+ private static final String TAR_ID = "tar"; //$NON-NLS-1$
+ private static final String GZIP_ID = "gzip"; //$NON-NLS-1$
+ private static final String BZIP_ID = "bzip"; //$NON-NLS-1$
+
+ private Boolean mResult;
+ private String mPartial;
+
+ private final String mOutFile;
+
+ /**
+ * Constructor of <code>CompressCommand</code>. This method creates an archive-compressed
+ * file from one or various file system objects.
+ *
+ * @param mode The compression mode
+ * @param dst The absolute path of the new compress file
+ * @param src An array of file system objects to compress
+ * @param asyncResultListener The partial result listener
+ * @throws InvalidCommandDefinitionException If the command has an invalid definition
+ */
+ public CompressCommand(
+ CompressionMode mode, String dst, String[] src, AsyncResultListener asyncResultListener)
+ throws InvalidCommandDefinitionException {
+ super(TAR_ID, asyncResultListener,
+ new String[]{Mode.fromCompressionMode(mode).mFlag, dst});
+
+ //Convert the arguments from absolute to relative
+ addExpandedArguments(
+ convertAbsolutePathsToRelativePaths(dst, src), true);
+
+ // Create the output file
+ this.mOutFile = dst;
+ }
+
+ /**
+ * Constructor of <code>CompressCommand</code>. This method creates a compressed
+ * file from one file.
+ *
+ * @param mode The compression mode
+ * @param src The file to compress
+ * @param asyncResultListener The partial result listener
+ * @throws InvalidCommandDefinitionException If the command has an invalid definition
+ */
+ public CompressCommand(
+ CompressionMode mode, String src, AsyncResultListener asyncResultListener)
+ throws InvalidCommandDefinitionException {
+ super(Mode.fromCompressionMode(mode).mId, asyncResultListener, resolveArguments(mode, src));
+ if (Mode.fromCompressionMode(mode).mMode.mArchive) {
+ throw new InvalidCommandDefinitionException(
+ "Unsupported compression mode"); //$NON-NLS-1$
+ }
+
+ // Create the output file
+ this.mOutFile = resolveOutputFile(mode, src);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onStartParsePartialResult() {
+ this.mResult = Boolean.FALSE;
+ this.mPartial = ""; //$NON-NLS-1$
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onEndParsePartialResult(boolean cancelled) {
+ // Send the last partial data
+ if (this.mPartial != null && this.mPartial.length() > 0) {
+ if (getAsyncResultListener() != null) {
+ getAsyncResultListener().onPartialResult(this.mPartial);
+ }
+ }
+ this.mPartial = ""; //$NON-NLS-1$
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onParsePartialResult(final String partialIn) {
+ if (partialIn == null || partialIn.length() ==0) return;
+ boolean endsWithNewLine = partialIn.endsWith("\n"); //$NON-NLS-1$
+ String[] lines = partialIn.split("\n"); //$NON-NLS-1$
+
+ // Append the pending data to the first line
+ lines[0] = this.mPartial + lines[0];
+
+ // Return all the lines, except the last
+ int cc = lines.length;
+ for (int i = 0; i < cc-1; i++) {
+ if (getAsyncResultListener() != null) {
+ getAsyncResultListener().onPartialResult(lines[i]);
+ }
+ }
+
+ // Return the last line?
+ if (endsWithNewLine) {
+ if (getAsyncResultListener() != null) {
+ getAsyncResultListener().onPartialResult(lines[lines.length-1]);
+ }
+ this.mPartial = ""; //$NON-NLS-1$
+ } else {
+ // Save the partial for next calls
+ this.mPartial = lines[lines.length-1];
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onParseErrorPartialResult(String partialErr) {/**NON BLOCK**/}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SIGNAL onRequestEnd() {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Boolean getResult() {
+ return this.mResult;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void checkExitCode(int exitCode)
+ throws InsufficientPermissionsException, CommandNotFoundException, ExecutionException {
+
+ //Ignore exit code 143 (cancelled)
+ //Ignore exit code 137 (kill -9)
+ if (exitCode != 0 && exitCode != 1 && exitCode != 143 && exitCode != 137) {
+ throw new ExecutionException(
+ "exitcode != 0 && != 143 && != 137"); //$NON-NLS-1$
+ }
+
+ // Correct
+ this.mResult = Boolean.TRUE;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getOutCompressedFile() {
+ return this.mOutFile;
+ }
+
+ /**
+ * Method that resolves the arguments for the compression
+ *
+ * @return String[] The arguments
+ */
+ private static String[] resolveArguments(CompressionMode mode, String src) {
+ switch (mode) {
+ case C_GZIP:
+ case C_BZIP:
+ return new String[]{src};
+ default:
+ return new String[]{};
+ }
+ }
+
+ /**
+ * Method that resolves the output path of the compressed file
+ *
+ * @return String The output path of the compressed file
+ */
+ private static String resolveOutputFile(CompressionMode mode, String src) {
+ return String.format("%s.%s", src, mode.mExtension); //$NON-NLS-1$
+ }
+
+ /**
+ * Method that converts the absolute paths of the source files to relative paths
+ *
+ * @param dst The destination compressed file
+ * @param src The source uncompressed files
+ * @return String[] The array of relative paths
+ */
+ private static String[] convertAbsolutePathsToRelativePaths(String dst, String[] src) {
+ File parent = new File(dst).getParentFile();
+ String p = File.separator;
+ if (parent != null) {
+ p = parent.getAbsolutePath();
+ }
+
+ // Converts every path
+ String[] out = new String[src.length];
+ int cc = src.length;
+ for (int i = 0; i < cc; i++) {
+ out[i] = FileHelper.toRelativePath(src[i], p);
+ }
+ return out;
+ }
+}