| @@ -84,6 +84,10 @@ | |||
| symlinks.</li> | |||
| <li><a href="#ownedBy"><code><ownedBy></code></a>—Select files if they are owned | |||
| by a given user.</li> | |||
| <li><a href="#posixGroup"><code><posixGroup></code>—Select | |||
| files if they have a given POSIX group.</li> | |||
| <li><a href="#posixPermissions"><code><posixPermissions></code>—Select | |||
| files if they have given POSIX permissions.</li> | |||
| </ul> | |||
| <h4 id="containsselect">Contains Selector</h4> | |||
| @@ -923,6 +927,50 @@ | |||
| </tr> | |||
| </table> | |||
| <h4 id="posixGroup">PosixGroup Selector</h4> | |||
| <p>The <code><posixGroup></code> selector selects only files that are owned by the given | |||
| POSIX group. Ant only invokes <code class="code">java.nio.file.Files#readAttributes</code> so | |||
| if a file system doesn't support the operation or POSIX attributes this selector will not | |||
| select the file.</p> | |||
| <p><em>Since Ant 1.10.4</em></p> | |||
| <table class="attr"> | |||
| <tr> | |||
| <th scope="col">Attribute</th> | |||
| <th scope="col">Description</th> | |||
| <th scope="col">Required</th> | |||
| </tr> | |||
| <tr> | |||
| <td>group</td> | |||
| <td>POSIX group name</td> | |||
| <td>Yes</td> | |||
| </tr> | |||
| </table> | |||
| <h4 id="posixPermissions">PosixPermissions Selector</h4> | |||
| <p>The <code><posixPermissions></code> selector selects only files that have the given | |||
| POSIX permissions. Ant only | |||
| invokes <code class="code">java.nio.file.Files#getPosixFilePermissions</code> so if a file | |||
| system doesn't support the operation this selector will not select the file.</p> | |||
| <p><em>Since Ant 1.10.4</em></p> | |||
| <table class="attr"> | |||
| <tr> | |||
| <th scope="col">Attribute</th> | |||
| <th scope="col">Description</th> | |||
| <th scope="col">Required</th> | |||
| </tr> | |||
| <tr> | |||
| <td>permissions</td> | |||
| <td>POSIX permissions in string (<q>rwxrwxrwx</q>) or octal (<q>777</q>) format</td> | |||
| <td>Yes</td> | |||
| </tr> | |||
| </table> | |||
| <h4 id="scriptselector">Script Selector</h4> | |||
| <p>The <code><scriptselector></code> element enables you to write a complex selection | |||
| @@ -46,6 +46,8 @@ import org.apache.tools.ant.types.selectors.NoneSelector; | |||
| import org.apache.tools.ant.types.selectors.NotSelector; | |||
| import org.apache.tools.ant.types.selectors.OrSelector; | |||
| import org.apache.tools.ant.types.selectors.OwnedBySelector; | |||
| import org.apache.tools.ant.types.selectors.PosixGroupSelector; | |||
| import org.apache.tools.ant.types.selectors.PosixPermissionsSelector; | |||
| import org.apache.tools.ant.types.selectors.PresentSelector; | |||
| import org.apache.tools.ant.types.selectors.ReadableSelector; | |||
| import org.apache.tools.ant.types.selectors.SelectSelector; | |||
| @@ -824,7 +826,7 @@ public abstract class AbstractFileSet extends DataType | |||
| /** | |||
| * Add the modified selector. | |||
| * @param selector the <code>ModifiedSelector</code> to add. | |||
| * @since ant 1.6 | |||
| * @since Ant 1.6 | |||
| */ | |||
| @Override | |||
| public void addModified(ModifiedSelector selector) { | |||
| @@ -863,6 +865,22 @@ public abstract class AbstractFileSet extends DataType | |||
| appendSelector(o); | |||
| } | |||
| /** | |||
| * @param o PosixGroupSelector | |||
| * @since 1.10.4 | |||
| */ | |||
| public void addPosixGroup(PosixGroupSelector o) { | |||
| appendSelector(o); | |||
| } | |||
| /** | |||
| * @param o PosixPermissionsSelector | |||
| * @since 1.10.4 | |||
| */ | |||
| public void addPosixPermissions(PosixPermissionsSelector o) { | |||
| appendSelector(o); | |||
| } | |||
| /** | |||
| * Add an arbitrary selector. | |||
| * @param selector the <code>FileSelector</code> to add. | |||
| @@ -324,6 +324,22 @@ public abstract class AbstractSelectorContainer extends DataType | |||
| appendSelector(o); | |||
| } | |||
| /** | |||
| * @param o PosixGroupSelector | |||
| * @since 1.10.4 | |||
| */ | |||
| public void addPosixGroup(PosixGroupSelector o) { | |||
| appendSelector(o); | |||
| } | |||
| /** | |||
| * @param o PosixPermissionsSelector | |||
| * @since 1.10.4 | |||
| */ | |||
| public void addPosixPermissions(PosixPermissionsSelector o) { | |||
| appendSelector(o); | |||
| } | |||
| /** | |||
| * add an arbitrary selector | |||
| * @param selector the selector to add | |||
| @@ -320,6 +320,22 @@ public abstract class BaseSelectorContainer extends BaseSelector | |||
| appendSelector(o); | |||
| } | |||
| /** | |||
| * @param o PosixGroupSelector | |||
| * @since 1.10.4 | |||
| */ | |||
| public void addPosixGroup(PosixGroupSelector o) { | |||
| appendSelector(o); | |||
| } | |||
| /** | |||
| * @param o PosixPermissionsSelector | |||
| * @since 1.10.4 | |||
| */ | |||
| public void addPosixPermissions(PosixPermissionsSelector o) { | |||
| appendSelector(o); | |||
| } | |||
| /** | |||
| * add an arbitrary selector | |||
| * @param selector the selector to add | |||
| @@ -0,0 +1,66 @@ | |||
| /* | |||
| * 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.types.selectors; | |||
| import org.apache.tools.ant.BuildException; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.nio.file.Files; | |||
| import java.nio.file.LinkOption; | |||
| import java.nio.file.attribute.GroupPrincipal; | |||
| import java.nio.file.attribute.PosixFileAttributes; | |||
| /** | |||
| * A selector that selects files based on their POSIX group. | |||
| * | |||
| * <p>Group is defined in terms of {@link java.nio.file.Files#readAttributes} | |||
| * group attribute as provided by {@link java.nio.file.attribute.PosixFileAttributes}, | |||
| * this means the selector will accept any file that exists and has the given | |||
| * group attribute.</p> | |||
| * | |||
| * @since Ant 1.10.4 | |||
| */ | |||
| public class PosixGroupSelector implements FileSelector { | |||
| private String group; | |||
| /** | |||
| * Sets the group name to look for. | |||
| * @param group the group name | |||
| */ | |||
| public void setGroup(String group) { | |||
| this.group = group; | |||
| } | |||
| @Override | |||
| public boolean isSelected(File basedir, String filename, File file) { | |||
| if (group == null) { | |||
| throw new BuildException("the group attribute is required"); | |||
| } | |||
| try { | |||
| GroupPrincipal actualGroup = Files.readAttributes(file.toPath(), | |||
| PosixFileAttributes.class, LinkOption.NOFOLLOW_LINKS).group(); | |||
| return actualGroup != null && actualGroup.getName().equals(group); | |||
| } catch (IOException e) { | |||
| // => not the expected group | |||
| } | |||
| return false; | |||
| } | |||
| } | |||
| @@ -0,0 +1,76 @@ | |||
| /* | |||
| * 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.types.selectors; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.util.PermissionUtils; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.nio.file.Files; | |||
| import java.nio.file.LinkOption; | |||
| import java.nio.file.attribute.PosixFilePermissions; | |||
| /** | |||
| * A selector that selects files based on their POSIX permissions. | |||
| * | |||
| * <p>Permissions are defined in terms of {@link | |||
| * java.nio.file.Files#getPosixFilePermissions}, this means the selector will accept | |||
| * any file that exists and has given POSIX permissions.</p> | |||
| * | |||
| * @since Ant 1.10.4 | |||
| */ | |||
| public class PosixPermissionsSelector implements FileSelector { | |||
| private String permissions; | |||
| /** | |||
| * Sets the permissions to look for. | |||
| * @param permissions the permissions string (rwxrwxrwx or octal) | |||
| */ | |||
| public void setPermissions(String permissions) { | |||
| if (permissions.length() == 3 && permissions.matches("^[0-7]+$")) { | |||
| this.permissions = PosixFilePermissions.toString( | |||
| PermissionUtils.permissionsFromMode(Integer.parseInt(permissions, 8))); | |||
| return; | |||
| } | |||
| try { | |||
| this.permissions = PosixFilePermissions.toString(PosixFilePermissions.fromString(permissions)); | |||
| } catch (IllegalArgumentException ex) { | |||
| throw new BuildException("the permissions attribute " + permissions | |||
| + " is invalid", ex); | |||
| } | |||
| } | |||
| @Override | |||
| public boolean isSelected(File basedir, String filename, File file) { | |||
| if (permissions == null) { | |||
| throw new BuildException("the permissions attribute is required"); | |||
| } | |||
| try { | |||
| return PosixFilePermissions.toString( | |||
| Files.getPosixFilePermissions(file.toPath(), LinkOption.NOFOLLOW_LINKS)) | |||
| .equals(permissions); | |||
| } catch (IOException e) { | |||
| // => not the expected permissions | |||
| } | |||
| return false; | |||
| } | |||
| } | |||
| @@ -0,0 +1,64 @@ | |||
| package org.apache.tools.ant.types.selectors; | |||
| import org.apache.tools.ant.taskdefs.condition.Os; | |||
| import org.junit.Before; | |||
| import org.junit.Rule; | |||
| import org.junit.Test; | |||
| import org.junit.rules.TemporaryFolder; | |||
| import java.io.File; | |||
| import java.nio.file.Files; | |||
| import java.nio.file.LinkOption; | |||
| import java.nio.file.attribute.GroupPrincipal; | |||
| import java.util.Map; | |||
| import static org.junit.Assert.assertEquals; | |||
| import static org.junit.Assert.assertTrue; | |||
| import static org.junit.Assume.assumeNoException; | |||
| import static org.junit.Assume.assumeTrue; | |||
| public class PosixGroupSelectorTest { | |||
| @Rule | |||
| public TemporaryFolder folder = new TemporaryFolder(); | |||
| private final String GROUP_GETTER = "getGid"; | |||
| private Class<?> jaasProviderClass; | |||
| private PosixGroupSelector s; | |||
| @Before | |||
| public void setUp() { | |||
| assumeTrue(Os.isFamily("unix")); | |||
| String osName = System.getProperty("os.name", "unknown").toLowerCase(); | |||
| String jaasProviderClassName = osName.contains("sunos") | |||
| ? "com.sun.security.auth.module.SolarisSystem" | |||
| : "com.sun.security.auth.module.UnixSystem"; | |||
| try { | |||
| jaasProviderClass = Class.forName(jaasProviderClassName); | |||
| } catch (Throwable e) { | |||
| assumeNoException("Cannot obtain OS-specific JAAS information", e); | |||
| } | |||
| s = new PosixGroupSelector(); | |||
| } | |||
| @Test | |||
| public void PosixGroupIsTrueForSelf() throws Exception { | |||
| long gid = (long) jaasProviderClass.getMethod(GROUP_GETTER) | |||
| .invoke(jaasProviderClass.newInstance()); | |||
| File file = folder.newFile("f.txt"); | |||
| Map<String, Object> fileAttributes = Files.readAttributes(file.toPath(), | |||
| "unix:group,gid", LinkOption.NOFOLLOW_LINKS); | |||
| long actualGid = (int) fileAttributes.get("gid"); | |||
| assertEquals("Different GIDs", gid, actualGid); | |||
| GroupPrincipal actualGroup = (GroupPrincipal) fileAttributes.get("group"); | |||
| s.setGroup(actualGroup.getName()); | |||
| assertTrue(s.isSelected(null, null, file)); | |||
| } | |||
| } | |||
| @@ -0,0 +1,78 @@ | |||
| package org.apache.tools.ant.types.selectors; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.taskdefs.condition.Os; | |||
| import org.junit.Before; | |||
| import org.junit.Rule; | |||
| import org.junit.Test; | |||
| import org.junit.experimental.runners.Enclosed; | |||
| import org.junit.rules.TemporaryFolder; | |||
| import org.junit.runner.RunWith; | |||
| import org.junit.runners.Parameterized; | |||
| import java.util.Arrays; | |||
| import java.util.Collection; | |||
| import static org.junit.Assert.assertTrue; | |||
| import static org.junit.Assume.assumeTrue; | |||
| @RunWith(Enclosed.class) | |||
| public class PosixPermissionsSelectorTest { | |||
| @RunWith(Parameterized.class) | |||
| public static class IllegalArgumentTest { | |||
| private PosixPermissionsSelector s; | |||
| // requires JUnit 4.12 | |||
| @Parameterized.Parameters(name = "illegal argument: |{0}|") | |||
| public static Collection<String> data() { | |||
| return Arrays.asList("855", "4555", "-rwxr-xr-x", "xrwr-xr-x"); | |||
| } | |||
| @Parameterized.Parameter | |||
| public String argument; | |||
| @Before | |||
| public void setUp() { | |||
| assumeTrue("no POSIX", Os.isFamily("unix")); | |||
| s = new PosixPermissionsSelector(); | |||
| } | |||
| @Test(expected = BuildException.class) | |||
| public void test() { | |||
| s.setPermissions(argument); | |||
| } | |||
| } | |||
| @RunWith(Parameterized.class) | |||
| public static class LegalArgumentTest { | |||
| private PosixPermissionsSelector s; | |||
| @Rule | |||
| public TemporaryFolder folder = new TemporaryFolder(); | |||
| // requires JUnit 4.12 | |||
| @Parameterized.Parameters(name = "legal argument: |{0}|") | |||
| public static Collection<String> data() { | |||
| return Arrays.asList("755", "rwxr-xr-x"); | |||
| } | |||
| @Parameterized.Parameter | |||
| public String argument; | |||
| @Before | |||
| public void setUp() { | |||
| assumeTrue("No POSIX", Os.isFamily("unix")); | |||
| s = new PosixPermissionsSelector(); | |||
| } | |||
| @Test | |||
| public void PosixPermissionsIsTrueForSelf() throws Exception { | |||
| s.setPermissions(argument); | |||
| assertTrue(s.isSelected(null, null, folder.newFolder())); | |||
| } | |||
| } | |||
| } | |||