@@ -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())); | |||
} | |||
} | |||
} |