From: jruesga Date: Thu, 11 Oct 2012 23:27:12 +0000 (+0200) Subject: New command: LinkCommand (for create symlinks) X-Git-Tag: android-x86-6.0-r1~764 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=c0a0acd87d57de98f6f342698c55ce5d45a45b07;p=android-x86%2Fpackages-apps-CMFileManager.git New command: LinkCommand (for create symlinks) --- diff --git a/res/xml/command_list.xml b/res/xml/command_list.xml index 9246c65..8161115 100644 --- a/res/xml/command_list.xml +++ b/res/xml/command_list.xml @@ -49,6 +49,7 @@ + diff --git a/src/com/cyanogenmod/explorer/commands/ExecutableCreator.java b/src/com/cyanogenmod/explorer/commands/ExecutableCreator.java index 2f6703f..5a4f2f3 100644 --- a/src/com/cyanogenmod/explorer/commands/ExecutableCreator.java +++ b/src/com/cyanogenmod/explorer/commands/ExecutableCreator.java @@ -201,6 +201,17 @@ public interface ExecutableCreator { IdentityExecutable createIdentityExecutable() throws CommandNotFoundException; /** + * Method that creates a symlink of an other file system object. + * + * @param src The absolute path to the source fso + * @param link The absolute path to the link fso + * @return LinkExecutable A {@link LinkExecutable} executable implementation reference + * @throws CommandNotFoundException If the executable can't be created + */ + LinkExecutable createLinkExecutable( + String src, String link) throws CommandNotFoundException; + + /** * Method that creates an executable for list files of a directory. * * @param src The directory where to do the listing diff --git a/src/com/cyanogenmod/explorer/commands/LinkExecutable.java b/src/com/cyanogenmod/explorer/commands/LinkExecutable.java new file mode 100644 index 0000000..1064dfa --- /dev/null +++ b/src/com/cyanogenmod/explorer/commands/LinkExecutable.java @@ -0,0 +1,29 @@ +/* + * 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.explorer.commands; + +/** + * An interface that represents an executable for create symlinks to other file system objects. + */ +public interface LinkExecutable extends WritableExecutable { + + /** + * {@inheritDoc} + */ + @Override + Boolean getResult(); +} diff --git a/src/com/cyanogenmod/explorer/commands/shell/LinkCommand.java b/src/com/cyanogenmod/explorer/commands/shell/LinkCommand.java new file mode 100644 index 0000000..09b29a0 --- /dev/null +++ b/src/com/cyanogenmod/explorer/commands/shell/LinkCommand.java @@ -0,0 +1,88 @@ +/* + * 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.explorer.commands.shell; + +import com.cyanogenmod.explorer.commands.LinkExecutable; +import com.cyanogenmod.explorer.console.CommandNotFoundException; +import com.cyanogenmod.explorer.console.ExecutionException; +import com.cyanogenmod.explorer.console.InsufficientPermissionsException; +import com.cyanogenmod.explorer.model.MountPoint; +import com.cyanogenmod.explorer.util.MountPointHelper; + +import java.text.ParseException; + + +/** + * A class for create a symlink of an other file system object. + * + * {@link "http://unixhelp.ed.ac.uk/CGI/man-cgi?ln"} + */ +public class LinkCommand extends SyncResultProgram implements LinkExecutable { + + private static final String ID = "link"; //$NON-NLS-1$ + private Boolean mRet; + private final String mLink; + + /** + * Constructor of LinkCommand. + * + * @param src The path of the source file + * @param link The path of the link file + * @throws InvalidCommandDefinitionException If the command has an invalid definition + */ + public LinkCommand(String src, String link) throws InvalidCommandDefinitionException { + super(ID, src, link); + this.mLink = link; + } + + /** + * {@inheritDoc} + */ + @Override + public void parse(String in, String err) throws ParseException { + //Release the return object + this.mRet = Boolean.TRUE; + } + + /** + * {@inheritDoc} + */ + @Override + public Boolean getResult() { + return this.mRet; + } + + /** + * {@inheritDoc} + */ + @Override + public void checkExitCode(int exitCode) + throws InsufficientPermissionsException, CommandNotFoundException, ExecutionException { + // Not raise insufficient permissions if the link is in + if (exitCode != 0) { + throw new ExecutionException("exitcode != 0"); //$NON-NLS-1$ + } + } + + /** + * {@inheritDoc} + */ + @Override + public MountPoint getWritableMountPoint() { + return MountPointHelper.getMountPointFromDirectory(this.mLink); + } +} diff --git a/src/com/cyanogenmod/explorer/commands/shell/ShellExecutableCreator.java b/src/com/cyanogenmod/explorer/commands/shell/ShellExecutableCreator.java index 3d455ec..8e308e8 100644 --- a/src/com/cyanogenmod/explorer/commands/shell/ShellExecutableCreator.java +++ b/src/com/cyanogenmod/explorer/commands/shell/ShellExecutableCreator.java @@ -33,6 +33,7 @@ import com.cyanogenmod.explorer.commands.FindExecutable; import com.cyanogenmod.explorer.commands.FolderUsageExecutable; import com.cyanogenmod.explorer.commands.GroupsExecutable; import com.cyanogenmod.explorer.commands.IdentityExecutable; +import com.cyanogenmod.explorer.commands.LinkExecutable; import com.cyanogenmod.explorer.commands.ListExecutable; import com.cyanogenmod.explorer.commands.MountExecutable; import com.cyanogenmod.explorer.commands.MountPointInfoExecutable; @@ -275,6 +276,20 @@ public class ShellExecutableCreator implements ExecutableCreator { * {@inheritDoc} */ @Override + public LinkExecutable createLinkExecutable(String src, String link) + throws CommandNotFoundException { + try { + return new LinkCommand(src, link); + } catch (InvalidCommandDefinitionException icdEx) { + throw new CommandNotFoundException("LinkCommand", icdEx); //$NON-NLS-1$ + } + } + + + /** + * {@inheritDoc} + */ + @Override public ListExecutable createListExecutable(String src) throws CommandNotFoundException { try { diff --git a/src/com/cyanogenmod/explorer/util/CommandHelper.java b/src/com/cyanogenmod/explorer/util/CommandHelper.java index f79eb19..f9793b8 100644 --- a/src/com/cyanogenmod/explorer/util/CommandHelper.java +++ b/src/com/cyanogenmod/explorer/util/CommandHelper.java @@ -36,6 +36,7 @@ import com.cyanogenmod.explorer.commands.FindExecutable; import com.cyanogenmod.explorer.commands.FolderUsageExecutable; import com.cyanogenmod.explorer.commands.GroupsExecutable; import com.cyanogenmod.explorer.commands.IdentityExecutable; +import com.cyanogenmod.explorer.commands.LinkExecutable; import com.cyanogenmod.explorer.commands.ListExecutable; import com.cyanogenmod.explorer.commands.MountExecutable; import com.cyanogenmod.explorer.commands.MountPointInfoExecutable; @@ -535,6 +536,39 @@ public final class CommandHelper { return executable.getResult(); } + /** + * Method that creates a symlink of an other file system object. + * + * @param context The current context (needed if console == null) + * @param src The absolute path to the source fso + * @param link The absolute path to the link fso + * @param console The console in which execute the program. null + * to attach to the default console + * @return boolean The operation result + * @throws FileNotFoundException If the initial directory not exists + * @throws IOException If initial directory can't not be checked + * @throws InvalidCommandDefinitionException If the command has an invalid definition + * @throws NoSuchFileOrDirectory If the file or directory was not found + * @throws ConsoleAllocException If the console can't be allocated + * @throws InsufficientPermissionsException If an operation requires elevated permissions + * @throws CommandNotFoundException If the command was not found + * @throws OperationTimeoutException If the operation exceeded the maximum time of wait + * @throws ExecutionException If the operation returns a invalid exit code + * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem + * @see LinkExecutable + */ + public static boolean createLink(Context context, String src, String link, Console console) + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, + ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException { + Console c = ensureConsole(context, console); + LinkExecutable executable = + c.getExecutableFactory().newCreator().createLinkExecutable(src, link); + writableExecute(context, executable, c); + return executable.getResult().booleanValue(); + } + /** * Method that retrieves the parent directory of a file system object. * diff --git a/src/com/cyanogenmod/explorer/util/StorageHelper.java b/src/com/cyanogenmod/explorer/util/StorageHelper.java index 9a0abff..b15203e 100644 --- a/src/com/cyanogenmod/explorer/util/StorageHelper.java +++ b/src/com/cyanogenmod/explorer/util/StorageHelper.java @@ -20,6 +20,7 @@ import android.os.Environment; import android.os.storage.StorageManager; import android.os.storage.StorageVolume; +import com.cyanogenmod.explorer.ExplorerApplication; import com.cyanogenmod.explorer.R; import java.io.File; @@ -96,4 +97,22 @@ public final class StorageHelper { } } + /** + * Method that returns if the path is in a volume storage + * + * @param path The path + * @return boolean If the path is in a volume storage + */ + public static boolean isPathInStorageVolume(String path) { + StorageVolume[] volumes = + getStorageVolumes(ExplorerApplication.getInstance().getApplicationContext()); + for (int i=0; i < volumes.length; i++) { + StorageVolume vol = volumes[i]; + if (path.startsWith(vol.getPath())) { + return true; + } + } + return false; + } + } diff --git a/tests/src/com/cyanogenmod/explorer/commands/shell/LinkCommandTest.java b/tests/src/com/cyanogenmod/explorer/commands/shell/LinkCommandTest.java new file mode 100644 index 0000000..318475f --- /dev/null +++ b/tests/src/com/cyanogenmod/explorer/commands/shell/LinkCommandTest.java @@ -0,0 +1,98 @@ +/* + * 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.explorer.commands.shell; + +import com.cyanogenmod.explorer.console.InsufficientPermissionsException; +import com.cyanogenmod.explorer.model.FileSystemObject; +import com.cyanogenmod.explorer.model.Symlink; +import com.cyanogenmod.explorer.util.CommandHelper; + +/** + * A class for testing the {@link LinkCommandTest} command. + * + * @see DeleteFileCommand + */ +public class LinkCommandTest extends AbstractConsoleTest { + + private static final String PATH_SOURCE_OK = "/data/source.txt"; //$NON-NLS-1$ + private static final String PATH_LINK_OK = "/data/source-link"; //$NON-NLS-1$ + private static final String PATH_SOURCE_ERROR = "/sdcard/source.txt"; //$NON-NLS-1$ + private static final String PATH_LINK_ERROR = "/sdcard/source-link"; //$NON-NLS-1$ + + /** + * {@inheritDoc} + */ + @Override + public boolean isRootConsoleNeeded() { + return true; + } + + /** + * Method that performs a test to delete a file. + * + * @throws Exception If test failed + */ + public void testCreateSymlinkOk() throws Exception { + try { + CommandHelper.createFile(getContext(), PATH_SOURCE_OK, getConsole()); + boolean ret = CommandHelper.createLink( + getContext(), PATH_SOURCE_OK, PATH_LINK_OK, getConsole()); + FileSystemObject fso = + CommandHelper.getFileInfo(getContext(), PATH_LINK_OK, false, getConsole()); + assertTrue("response==false", ret); //$NON-NLS-1$ + assertTrue("fso not is Symlink", fso instanceof Symlink); //$NON-NLS-1$ + } finally { + try { + CommandHelper.deleteFile(getContext(), PATH_SOURCE_OK, getConsole()); + } catch (Exception e) {/**NON BLOCK**/} + try { + CommandHelper.deleteFile(getContext(), PATH_LINK_OK, getConsole()); + } catch (Exception e) {/**NON BLOCK**/} + } + } + + /** + * Method that performs a test to delete an invalid file. + * + * @throws Exception If test failed + */ + public void testCreateSymlinkFail() throws Exception { + try { + CommandHelper.createFile(getContext(), PATH_SOURCE_ERROR, getConsole()); + boolean ret = CommandHelper.createLink( + getContext(), PATH_SOURCE_ERROR, PATH_LINK_ERROR, getConsole()); + assertTrue("response==false", ret); //$NON-NLS-1$ + try { + FileSystemObject fso = + CommandHelper.getFileInfo(getContext(), PATH_LINK_ERROR, getConsole()); + assertTrue("fso != null", fso == null); //$NON-NLS-1$ + } catch (Exception e) { + //OK. getFileInfo throws an exception because the symlink couldn't be created + } + } catch (InsufficientPermissionsException eex) { + // This the expected behaviour because the symlink couldn't be created + } finally { + try { + CommandHelper.deleteFile(getContext(), PATH_SOURCE_ERROR, getConsole()); + } catch (Exception e) {/**NON BLOCK**/} + try { + CommandHelper.deleteFile(getContext(), PATH_LINK_ERROR, getConsole()); + } catch (Exception e) {/**NON BLOCK**/} + } + } + +}