You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@ant.apache.org by bo...@apache.org on 2016/04/17 11:59:06 UTC
ant git commit: helper class for dealing with file permissions
Repository: ant
Updated Branches:
refs/heads/master f6e6c20a8 -> 97a0b26c7
helper class for dealing with file permissions
Project: http://git-wip-us.apache.org/repos/asf/ant/repo
Commit: http://git-wip-us.apache.org/repos/asf/ant/commit/97a0b26c
Tree: http://git-wip-us.apache.org/repos/asf/ant/tree/97a0b26c
Diff: http://git-wip-us.apache.org/repos/asf/ant/diff/97a0b26c
Branch: refs/heads/master
Commit: 97a0b26c7e3aa1df286f2c318d6433f7b3d2023f
Parents: f6e6c20
Author: Stefan Bodewig <bo...@apache.org>
Authored: Sun Apr 17 11:58:40 2016 +0200
Committer: Stefan Bodewig <bo...@apache.org>
Committed: Sun Apr 17 11:58:40 2016 +0200
----------------------------------------------------------------------
.../apache/tools/ant/util/PermissionUtils.java | 207 +++++++++++++++++++
.../tools/ant/util/PermissionUtilsTest.java | 155 ++++++++++++++
2 files changed, 362 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ant/blob/97a0b26c/src/main/org/apache/tools/ant/util/PermissionUtils.java
----------------------------------------------------------------------
diff --git a/src/main/org/apache/tools/ant/util/PermissionUtils.java b/src/main/org/apache/tools/ant/util/PermissionUtils.java
new file mode 100644
index 0000000..6fbf163
--- /dev/null
+++ b/src/main/org/apache/tools/ant/util/PermissionUtils.java
@@ -0,0 +1,207 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.tools.ant.util;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.PosixFilePermission;
+import java.util.EnumSet;
+import java.util.Set;
+
+import org.apache.tools.ant.types.Resource;
+import org.apache.tools.ant.types.resources.ArchiveResource;
+import org.apache.tools.ant.types.resources.FileProvider;
+
+/**
+ * Contains helper methods for dealing with {@link
+ * PosixFilePermission} or the traditional Unix mode representation of
+ * permissions.
+ *
+ * @since Ant 1.10.0
+ */
+public class PermissionUtils {
+
+ private PermissionUtils() { }
+
+ /**
+ * Translates a set of permissons into a Unix stat(2) {@code
+ * st_mode} result.
+ * @param permissions the permissions
+ * @param type the file type
+ * @return the "mode"
+ */
+ public static int modeFromPermissions(Set<PosixFilePermission> permissions,
+ FileType type) {
+ int mode;
+ switch (type) {
+ case SYMLINK:
+ mode = 012;
+ break;
+ case REGULAR_FILE:
+ mode = 010;
+ break;
+ case DIR:
+ mode = 004;
+ break;
+ default:
+ // OTHER could be a character or block device, a socket or a FIFO - so don't set anything
+ mode = 0;
+ break;
+ }
+ mode <<= 3;
+ mode <<= 3; // we don't support sticky, setuid, setgid
+ mode |= modeFromPermissions(permissions, "OWNER");
+ mode <<= 3;
+ mode |= modeFromPermissions(permissions, "GROUP");
+ mode <<= 3;
+ mode |= modeFromPermissions(permissions, "OTHERS");
+ return mode;
+ }
+
+ /**
+ * Translates a Unix stat(2) {@code st_mode} compatible value into
+ * a set of permissions.
+ * @param mode the "mode"
+ * @return set of permissions
+ */
+ public static Set<PosixFilePermission> permissionsFromMode(int mode) {
+ Set<PosixFilePermission> permissions = EnumSet.noneOf(PosixFilePermission.class);
+ addPermissions(permissions, "OTHERS", mode);
+ addPermissions(permissions, "GROUP", mode >> 3);
+ addPermissions(permissions, "OWNER", mode >> 6);
+ return permissions;
+ }
+
+ /**
+ * Sets permissions on a {@link Resource} - doesn't do anything
+ * for unsupported resource types.
+ *
+ * <p>Supported types are:</p>
+ * <ul>
+ * <li>any {@link FileProvider}</li>
+ * <li>{@link ArchiveResource}</li>
+ * </ul>
+ *
+ * @param resource the resource to set permissions for
+ * @param permissions the permissions
+ */
+ public static void setPermissions(Resource r, Set<PosixFilePermission> permissions)
+ throws IOException {
+ FileProvider f = r.as(FileProvider.class);
+ if (f != null) {
+ Files.setPosixFilePermissions(f.getFile().toPath(), permissions);
+ } else if (r instanceof ArchiveResource) {
+ ((ArchiveResource) r).setMode(modeFromPermissions(permissions,
+ FileType.of(r)));
+ }
+ }
+
+ /**
+ * Sets permissions of a {@link Resource} - doesn't returns an
+ * empty set for unsupported resource types.
+ *
+ * <p>Supported types are:</p>
+ * <ul>
+ * <li>any {@link FileProvider}</li>
+ * <li>{@link ArchiveResource}</li>
+ * </ul>
+ *
+ * @param resource the resource to read permissions from
+ * @return the permissions
+ */
+ public static Set<PosixFilePermission> getPermissions(Resource r) throws IOException {
+ FileProvider f = r.as(FileProvider.class);
+ if (f != null) {
+ return Files.getPosixFilePermissions(f.getFile().toPath());
+ } else if (r instanceof ArchiveResource) {
+ return permissionsFromMode(((ArchiveResource) r).getMode());
+ }
+ return EnumSet.noneOf(PosixFilePermission.class);
+ }
+
+ private static long modeFromPermissions(Set<PosixFilePermission> permissions,
+ String prefix) {
+ long mode = 0;
+ if (permissions.contains(PosixFilePermission.valueOf(prefix + "_READ"))) {
+ mode |= 4;
+ }
+ if (permissions.contains(PosixFilePermission.valueOf(prefix + "_WRITE"))) {
+ mode |= 2;
+ }
+ if (permissions.contains(PosixFilePermission.valueOf(prefix + "_EXECUTE"))) {
+ mode |= 1;
+ }
+ return mode;
+ }
+
+ private static void addPermissions(Set<PosixFilePermission> permissions,
+ String prefix, long mode) {
+ if ((mode & 1) == 1) {
+ permissions.add(PosixFilePermission.valueOf(prefix + "_EXECUTE"));
+ }
+ if ((mode & 2) == 2) {
+ permissions.add(PosixFilePermission.valueOf(prefix + "_WRITE"));
+ }
+ if ((mode & 4) == 4) {
+ permissions.add(PosixFilePermission.valueOf(prefix + "_READ"));
+ }
+ }
+
+ /**
+ * The supported types of files, maps to the {@code isFoo} methods
+ * in {@link java.nio.file.attribute.BasicFileAttributes}.
+ */
+ public enum FileType {
+ /** A regular file. */
+ REGULAR_FILE,
+ /** A directory. */
+ DIR,
+ /** A symbolic link. */
+ SYMLINK,
+ /** Something that is neither a regular file nor a directory nor a symbolic link. */
+ OTHER;
+
+ /**
+ * Determines the file type of a {@link Path}.
+ */
+ public static FileType of(Path p) throws IOException {
+ BasicFileAttributes attrs =
+ Files.readAttributes(p, BasicFileAttributes.class);
+ if (attrs.isRegularFile()) {
+ return FileType.REGULAR_FILE;
+ } else if (attrs.isDirectory()) {
+ return FileType.DIR;
+ } else if (attrs.isSymbolicLink()) {
+ return FileType.SYMLINK;
+ }
+ return FileType.OTHER;
+ }
+
+ /**
+ * Determines the file type of a {@link Resource}.
+ */
+ public static FileType of(Resource r) {
+ if (r.isDirectory()) {
+ return FileType.DIR;
+ }
+ return FileType.REGULAR_FILE;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ant/blob/97a0b26c/src/tests/junit/org/apache/tools/ant/util/PermissionUtilsTest.java
----------------------------------------------------------------------
diff --git a/src/tests/junit/org/apache/tools/ant/util/PermissionUtilsTest.java b/src/tests/junit/org/apache/tools/ant/util/PermissionUtilsTest.java
new file mode 100644
index 0000000..eed265d
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/util/PermissionUtilsTest.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.tools.ant.util;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.attribute.PosixFilePermission;
+import java.util.EnumSet;
+import java.util.Set;
+
+import org.apache.tools.ant.types.resources.FileResource;
+import org.apache.tools.ant.types.resources.TarResource;
+import org.apache.tools.ant.types.resources.ZipResource;
+import org.apache.tools.tar.TarEntry;
+import org.apache.tools.tar.TarOutputStream;
+import org.apache.tools.zip.ZipEntry;
+import org.apache.tools.zip.ZipOutputStream;
+import org.junit.Test;
+
+public class PermissionUtilsTest {
+
+ @Test
+ public void modeFromPermissionsReturnsExpectedResult() {
+ int mode = PermissionUtils.modeFromPermissions(EnumSet.of(PosixFilePermission.OWNER_READ,
+ PosixFilePermission.OWNER_WRITE,
+ PosixFilePermission.OWNER_EXECUTE),
+ PermissionUtils.FileType.REGULAR_FILE);
+ assertEquals("100700", Integer.toString(mode, 8));
+ }
+
+ @Test
+ public void permissionsFromModeReturnsExpectedResult() {
+ Set<PosixFilePermission> s = PermissionUtils.permissionsFromMode(0100753);
+ assertEquals(EnumSet.of(PosixFilePermission.OWNER_READ,
+ PosixFilePermission.OWNER_WRITE,
+ PosixFilePermission.OWNER_EXECUTE,
+ PosixFilePermission.GROUP_READ,
+ PosixFilePermission.GROUP_EXECUTE,
+ PosixFilePermission.OTHERS_WRITE,
+ PosixFilePermission.OTHERS_EXECUTE),
+ s);
+ }
+
+ @Test
+ public void detectsFileTypeOfRegularFileFromPath() throws IOException {
+ File f = File.createTempFile("ant", ".tst");
+ f.deleteOnExit();
+ assertEquals(PermissionUtils.FileType.REGULAR_FILE,
+ PermissionUtils.FileType.of(f.toPath()));
+ }
+
+ @Test
+ public void detectsFileTypeOfRegularFileFromResource() throws IOException {
+ File f = File.createTempFile("ant", ".tst");
+ f.deleteOnExit();
+ assertEquals(PermissionUtils.FileType.REGULAR_FILE,
+ PermissionUtils.FileType.of(new FileResource(f)));
+ }
+
+ @Test
+ public void detectsFileTypeOfDirectoryFromPath() throws IOException {
+ File f = File.createTempFile("ant", ".dir");
+ f.delete();
+ f.mkdirs();
+ f.deleteOnExit();
+ assertEquals(PermissionUtils.FileType.DIR,
+ PermissionUtils.FileType.of(f.toPath()));
+ }
+
+ @Test
+ public void detectsFileTypeOfDirectoryFromResource() throws IOException {
+ File f = File.createTempFile("ant", ".tst");
+ f.delete();
+ f.mkdirs();
+ f.deleteOnExit();
+ assertEquals(PermissionUtils.FileType.DIR,
+ PermissionUtils.FileType.of(new FileResource(f)));
+ }
+
+ @Test
+ public void getSetPermissionsWorksForFiles() throws IOException {
+ File f = File.createTempFile("ant", ".tst");
+ f.deleteOnExit();
+ Set<PosixFilePermission> s =
+ EnumSet.of(PosixFilePermission.OWNER_READ,
+ PosixFilePermission.OWNER_WRITE,
+ PosixFilePermission.OWNER_EXECUTE,
+ PosixFilePermission.GROUP_READ);
+ PermissionUtils.setPermissions(new FileResource(f), s);
+ assertEquals(s, PermissionUtils.getPermissions(new FileResource(f)));
+ }
+
+ @Test
+ public void getSetPermissionsWorksForZipResources() throws IOException {
+ File f = File.createTempFile("ant", ".zip");
+ f.deleteOnExit();
+ try (ZipOutputStream os = new ZipOutputStream(f)) {
+ ZipEntry e = new ZipEntry("foo");
+ os.putNextEntry(e);
+ os.closeEntry();
+ }
+
+ ZipResource r = new ZipResource();
+ r.setName("foo");
+ r.setArchive(f);
+ Set<PosixFilePermission> s =
+ EnumSet.of(PosixFilePermission.OWNER_READ,
+ PosixFilePermission.OWNER_WRITE,
+ PosixFilePermission.OWNER_EXECUTE,
+ PosixFilePermission.GROUP_READ);
+ PermissionUtils.setPermissions(r, s);
+ assertEquals(s, PermissionUtils.getPermissions(r));
+ }
+
+ @Test
+ public void getSetPermissionsWorksForTarResources() throws IOException {
+ File f = File.createTempFile("ant", ".zip");
+ f.deleteOnExit();
+ try (TarOutputStream os = new TarOutputStream(new FileOutputStream(f))) {
+ TarEntry e = new TarEntry("foo");
+ os.putNextEntry(e);
+ os.closeEntry();
+ }
+
+ TarResource r = new TarResource();
+ r.setName("foo");
+ r.setArchive(f);
+ Set<PosixFilePermission> s =
+ EnumSet.of(PosixFilePermission.OWNER_READ,
+ PosixFilePermission.OWNER_WRITE,
+ PosixFilePermission.OWNER_EXECUTE,
+ PosixFilePermission.GROUP_READ);
+ PermissionUtils.setPermissions(r, s);
+ assertEquals(s, PermissionUtils.getPermissions(r));
+ }
+}