Submitted by: J.M. (Martijn) Kruithof (ant at kruithof dot xs4all dot nl) git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@275149 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -574,6 +574,10 @@ Other changes: | |||||
| * <junit>'s XML formatter adds a new classname attribute to the <testcase> | * <junit>'s XML formatter adds a new classname attribute to the <testcase> | ||||
| elements. | elements. | ||||
| * new <permissions> type add permission handling to the code | |||||
| this type can be nested in the <java> and <junit> tasks. | |||||
| Bugzilla Report 22533. | |||||
| Changes from Ant 1.5.3 to Ant 1.5.4 | Changes from Ant 1.5.3 to Ant 1.5.4 | ||||
| =================================== | =================================== | ||||
| @@ -212,6 +212,18 @@ support it (i.e. Java 1.1).</p> | |||||
| forked VM via nested <i>env</i> elements. See the description in the | forked VM via nested <i>env</i> elements. See the description in the | ||||
| section about <a href="exec.html#env">exec</a></p> | section about <a href="exec.html#env">exec</a></p> | ||||
| <p>Settings will be ignored if fork is disabled.</p> | <p>Settings will be ignored if fork is disabled.</p> | ||||
| <h4>permissions</h4> | |||||
| <p>Security permissions can be revoked and granted during the execution of the | |||||
| class via a nested <i>permissions</i> element. For more information please | |||||
| see <a href="../CoreTypes/permissions.html">permissions</a></p> | |||||
| <p>When the permission RuntimePermission exitVM has not been granted (or has | |||||
| been revoked) the System.exit() call will be intercepted | |||||
| and treated like indicated in <i>failonerror</i>.</p> | |||||
| <p>Settings will be ignored if fork is enabled.</p> | |||||
| <p><em>since Ant 1.6</em>.</p> | |||||
| <h3>Errors and return codes</h3> | <h3>Errors and return codes</h3> | ||||
| By default the return code of a <java> is ignored. Alternatively, you can set <code>resultproperty</code> to the name | By default the return code of a <java> is ignored. Alternatively, you can set <code>resultproperty</code> to the name | ||||
| @@ -0,0 +1,148 @@ | |||||
| <html> | |||||
| <head> | |||||
| <meta http-equiv="Content-Language" content="en-us"> | |||||
| <title>Permissions type</title> | |||||
| </head> | |||||
| <body> | |||||
| <h2><a name="permissions">Permissions</a></h2> | |||||
| <p> | |||||
| Permissions represents a set of security permissions granted or revoked to | |||||
| a specific part code executed in the JVM where ant is running in. | |||||
| The actual Permissions are specified via a set of nested permission items either | |||||
| <code><grant></code>ed or <code><revoke></code>d.</p> | |||||
| <p> | |||||
| In the base situation a <a href="#baseset">base set</a> of permissions granted. | |||||
| Extra permissions can be | |||||
| granted. A granted permission can be overruled by revoking a permission. | |||||
| The security manager installed by the permissions will throw an | |||||
| <code>SecurityException</code> if | |||||
| the code subject to these permissions try to use an permission that has not been | |||||
| granted or that has been revoked.</p> | |||||
| <h3>Nested elements</h3> | |||||
| <h4>grant</h4> | |||||
| <p> | |||||
| Indicates a specific permission is always granted. Its attributes indicate which | |||||
| permissions are granted.</p> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">class</td> | |||||
| <td valign="top">The fully qualified name of the Permission class.</td> | |||||
| <td valign="top" align="center">Yes</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">name</td> | |||||
| <td valign="top">The name of the Permission. The actual contents depends on the | |||||
| Permission class.</td> | |||||
| <td valign="top" align="center">No</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">actions</td> | |||||
| <td valign="top">The actions allowed. The actual contents depend on the | |||||
| Permission class and name.</td> | |||||
| <td valign="top" align="center">No</td> | |||||
| </tr> | |||||
| </table> | |||||
| <p> | |||||
| Implied permissions are granted. | |||||
| </p> | |||||
| <p> | |||||
| Please note that some Permission classes may actually need a name and / or actions in order to function properly. The name and actions are parsed by the actual | |||||
| Permission class. | |||||
| </p> | |||||
| <h4>revoke</h4> | |||||
| <p> | |||||
| Indicates a specific permission is revoked.</p> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">class</td> | |||||
| <td valign="top">The fully qualified name of the Permission class.</td> | |||||
| <td valign="top" align="center">Yes</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">name</td> | |||||
| <td valign="top">The name of the Permission. The actual contents depends on the | |||||
| Permission class.</td> | |||||
| <td valign="top" align="center">No</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">actions</td> | |||||
| <td valign="top">The actions allowed. The actual contents depend on the | |||||
| Permission class and name.</td> | |||||
| <td valign="top" align="center">No</td> | |||||
| </tr> | |||||
| </table> | |||||
| <p> | |||||
| Implied permissions are not resolved and therefore also not revoked. | |||||
| </p> | |||||
| <p> | |||||
| The name can handle the * wildcard at the end of the name, in which case all | |||||
| permissions of the specified class of which the name starts with the specified name | |||||
| (excluding the *) are revoked. Note that the - wildcard often supported by the | |||||
| granted properties is not supported. | |||||
| If the name is left empty all names match, and are revoked. | |||||
| If the actions are left empty all actions match, and are revoked. | |||||
| </p> | |||||
| <h3><a name="baseset">Base set</a></h3> | |||||
| A permissions set implictly contains the following permissions: | |||||
| <blockquote><pre> | |||||
| <grant class="java.net.SocketPermission" name=localhost:1024-" actions="listen"> | |||||
| <grant class="java.util.PropertyPermission" name=java.version" actions="read"> | |||||
| <grant class="java.util.PropertyPermission" name=java.vendor" actions="read"> | |||||
| <grant class="java.util.PropertyPermission" name=java.vendor.url" actions="read"> | |||||
| <grant class="java.util.PropertyPermission" name=java.class.version" actions="read"> | |||||
| <grant class="java.util.PropertyPermission" name=os.name" actions="read"> | |||||
| <grant class="java.util.PropertyPermission" name=os.version" actions="read"> | |||||
| <grant class="java.util.PropertyPermission" name=os.arch" actions="read"> | |||||
| <grant class="java.util.PropertyPermission" name=file.separator" actions="read"> | |||||
| <grant class="java.util.PropertyPermission" name=path.separator" actions="read"> | |||||
| <grant class="java.util.PropertyPermission" name=line.separator" actions="read"> | |||||
| <grant class="java.util.PropertyPermission" name=java.specification.version" actions="read"> | |||||
| <grant class="java.util.PropertyPermission" name=java.specification.vendor" actions="read"> | |||||
| <grant class="java.util.PropertyPermission" name=java.specification.name" actions="read"> | |||||
| <grant class="java.util.PropertyPermission" name=java.vm.specification.version" actions="read"> | |||||
| <grant class="java.util.PropertyPermission" name=java.vm.specification.vendor" actions="read"> | |||||
| <grant class="java.util.PropertyPermission" name=java.vm.specification.name" actions="read"> | |||||
| <grant class="java.util.PropertyPermission" name=java.vm.version" actions="read"> | |||||
| <grant class="java.util.PropertyPermission" name=java.vm.vendor" actions="read"> | |||||
| <grant class="java.util.PropertyPermission" name=java.vm.name" actions="read"> | |||||
| </blockquote></pre> | |||||
| These permissions can be revoked via <revoke> elements if necessary. | |||||
| <h3>Examples</h3> | |||||
| <blockquote><pre> | |||||
| <permissions> | |||||
| <grant class="java.security.AllPermission"/> | |||||
| <revoke class="java.util.PropertyPermission"/> | |||||
| </permissions> | |||||
| </pre></blockquote> | |||||
| <p> | |||||
| Grants all permissions to the code except for those handling Properties. | |||||
| </p> | |||||
| <blockquote><pre> | |||||
| <permissions> | |||||
| <grant class="java.net.SocketPermission" name="foo.bar.com" action="connect"/> | |||||
| <grant class="java.util.PropertyPermission" name="user.home" action="read,write"/> | |||||
| </permissions> | |||||
| </pre></blockquote> | |||||
| <p> | |||||
| Grants the base set of permissions with the addition of a SocketPermission to connect | |||||
| to foo.bar.com and the permission to read and write the user.home system property. | |||||
| </p> | |||||
| <hr> | |||||
| <p align="center">Copyright © 2003 Apache Software Foundation. | |||||
| All rights Reserved.</p> | |||||
| </body> | |||||
| </html> | |||||
| @@ -244,6 +244,15 @@ support it (i.e. Java 1.1).</p> | |||||
| <p><em>since Ant 1.6</em>.</p> | <p><em>since Ant 1.6</em>.</p> | ||||
| <h4>permissions</h4> | |||||
| <p>Security permissions can be revoked and granted during the execution of the | |||||
| class via a nested <i>permissions</i> element. For more information please | |||||
| see <a href="../CoreTypes/permissions.html">permissions</a></p> | |||||
| <p>Settings will be ignored if fork is enabled.</p> | |||||
| <p><em>since Ant 1.6</em>.</p> | |||||
| <h4>formatter</h4> | <h4>formatter</h4> | ||||
| <p>The results of the tests can be printed in different | <p>The results of the tests can be printed in different | ||||
| @@ -25,6 +25,7 @@ | |||||
| <a href="CoreTypes/filterset.html">FilterSet</a><br> | <a href="CoreTypes/filterset.html">FilterSet</a><br> | ||||
| <a href="CoreTypes/patternset.html">PatternSet</a><br> | <a href="CoreTypes/patternset.html">PatternSet</a><br> | ||||
| <a href="using.html#path">Path-like Structures</a><br> | <a href="using.html#path">Path-like Structures</a><br> | ||||
| <a href="CoreTypes/permissions.html">Permissions</a><br> | |||||
| <a href="CoreTypes/propertyset.html">PropertySet</a><br> | <a href="CoreTypes/propertyset.html">PropertySet</a><br> | ||||
| <a href="CoreTypes/selectors.html">Selectors</a><br> | <a href="CoreTypes/selectors.html">Selectors</a><br> | ||||
| <a href="CoreTypes/xmlcatalog.html">XMLCatalog</a><br> | <a href="CoreTypes/xmlcatalog.html">XMLCatalog</a><br> | ||||
| @@ -99,6 +99,7 @@ | |||||
| <java classname="${app}" | <java classname="${app}" | ||||
| classpath="${tests-classpath.value}" | classpath="${tests-classpath.value}" | ||||
| resultproperty="exitcode" | resultproperty="exitcode" | ||||
| fork="true" | |||||
| > | > | ||||
| </java> | </java> | ||||
| <echo message="exitcode = ${exitcode}"/> | <echo message="exitcode = ${exitcode}"/> | ||||
| @@ -116,12 +117,40 @@ | |||||
| <echo message="exitcode = ${exitcode}"/> | <echo message="exitcode = ${exitcode}"/> | ||||
| </target> | </target> | ||||
| <target name="testResultPropertyZeroNoFork"> | |||||
| <java classname="${app}" | |||||
| classpath="${tests-classpath.value}" | |||||
| resultproperty="exitcode" | |||||
| fork="false" | |||||
| > | |||||
| <permissions/> | |||||
| </java> | |||||
| <echo message="exitcode = ${exitcode}"/> | |||||
| </target> | |||||
| <target name="testResultPropertyNonZeroNoFork"> | |||||
| <java classname="${app}" | |||||
| classpath="${tests-classpath.value}" | |||||
| resultproperty="exitcode" | |||||
| failonerror="false" | |||||
| fork="false" | |||||
| > | |||||
| <arg value="-1"/> | |||||
| <permissions/> | |||||
| </java> | |||||
| <echo message="exitcode = ${exitcode}"/> | |||||
| </target> | |||||
| <target name="testSpawn"> | <target name="testSpawn"> | ||||
| <java classname="${spawnapp}" fork="true" spawn="true" classpath="${tests-classpath.value}"> | <java classname="${spawnapp}" fork="true" spawn="true" classpath="${tests-classpath.value}"> | ||||
| <arg value="${timeToWait}"/> | <arg value="${timeToWait}"/> | ||||
| <arg value="${logFile}" /> | <arg value="${logFile}" /> | ||||
| </java> | </java> | ||||
| </target> | </target> | ||||
| <target name="cleanup"> | <target name="cleanup"> | ||||
| <delete file="${logFile}"/> | <delete file="${logFile}"/> | ||||
| </target> | </target> | ||||
| @@ -1,7 +1,7 @@ | |||||
| /* | /* | ||||
| * The Apache Software License, Version 1.1 | * The Apache Software License, Version 1.1 | ||||
| * | * | ||||
| * Copyright (c) 2001-2002 The Apache Software Foundation. All rights | |||||
| * Copyright (c) 2001-2003 The Apache Software Foundation. All rights | |||||
| * reserved. | * reserved. | ||||
| * | * | ||||
| * Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
| @@ -57,8 +57,10 @@ package org.apache.tools.ant; | |||||
| * Used to report exit status of classes which call System.exit(). | * Used to report exit status of classes which call System.exit(). | ||||
| * | * | ||||
| * @see org.apache.tools.ant.util.optional.NoExitSecurityManager | * @see org.apache.tools.ant.util.optional.NoExitSecurityManager | ||||
| * @see org.apache.tools.ant.types.Permissions | |||||
| * | * | ||||
| * @author Conor MacNeill | * @author Conor MacNeill | ||||
| * @author <a href="mailto:martijn@kruithof.xs4all.nl">Martijn Kruithof</a> | |||||
| */ | */ | ||||
| public class ExitException extends SecurityException { | public class ExitException extends SecurityException { | ||||
| @@ -74,6 +76,16 @@ public class ExitException extends SecurityException { | |||||
| this.status = status; | this.status = status; | ||||
| } | } | ||||
| /** | |||||
| * Constructs an exit exception. | |||||
| * @param msg the messge to be displayed. | |||||
| * @param status the status code returned via System.exit() | |||||
| */ | |||||
| public ExitException(String msg, int status) { | |||||
| super(msg); | |||||
| this.status = status; | |||||
| } | |||||
| /** | /** | ||||
| * The status code returned by System.exit() | * The status code returned by System.exit() | ||||
| * | * | ||||
| @@ -65,6 +65,7 @@ import org.apache.tools.ant.Task; | |||||
| import org.apache.tools.ant.types.Commandline; | import org.apache.tools.ant.types.Commandline; | ||||
| import org.apache.tools.ant.types.CommandlineJava; | import org.apache.tools.ant.types.CommandlineJava; | ||||
| import org.apache.tools.ant.types.Path; | import org.apache.tools.ant.types.Path; | ||||
| import org.apache.tools.ant.types.Permissions; | |||||
| import org.apache.tools.ant.util.TimeoutObserver; | import org.apache.tools.ant.util.TimeoutObserver; | ||||
| import org.apache.tools.ant.util.Watchdog; | import org.apache.tools.ant.util.Watchdog; | ||||
| @@ -72,6 +73,7 @@ import org.apache.tools.ant.util.Watchdog; | |||||
| * | * | ||||
| * @author thomas.haas@softwired-inc.com | * @author thomas.haas@softwired-inc.com | ||||
| * @author Stefan Bodewig | * @author Stefan Bodewig | ||||
| * @author <a href="mailto:martijn@kruithof.xs4all.nl">Martijn Kruithof</a> | |||||
| * @since Ant 1.2 | * @since Ant 1.2 | ||||
| */ | */ | ||||
| public class ExecuteJava implements Runnable, TimeoutObserver { | public class ExecuteJava implements Runnable, TimeoutObserver { | ||||
| @@ -79,6 +81,7 @@ public class ExecuteJava implements Runnable, TimeoutObserver { | |||||
| private Commandline javaCommand = null; | private Commandline javaCommand = null; | ||||
| private Path classpath = null; | private Path classpath = null; | ||||
| private CommandlineJava.SysProperties sysProperties = null; | private CommandlineJava.SysProperties sysProperties = null; | ||||
| private Permissions perm = null; | |||||
| private Method main = null; | private Method main = null; | ||||
| private Long timeout = null; | private Long timeout = null; | ||||
| private Throwable caught = null; | private Throwable caught = null; | ||||
| @@ -101,6 +104,15 @@ public class ExecuteJava implements Runnable, TimeoutObserver { | |||||
| public void setSystemProperties(CommandlineJava.SysProperties s) { | public void setSystemProperties(CommandlineJava.SysProperties s) { | ||||
| sysProperties = s; | sysProperties = s; | ||||
| } | } | ||||
| /** | |||||
| * Permissions for the application run. | |||||
| * @since Ant 1.6 | |||||
| * @param permissions | |||||
| */ | |||||
| public void setPermissions(Permissions permissions) { | |||||
| perm = permissions; | |||||
| } | |||||
| /** | /** | ||||
| * All output (System.out as well as System.err) will be written | * All output (System.out as well as System.err) will be written | ||||
| @@ -208,6 +220,9 @@ public class ExecuteJava implements Runnable, TimeoutObserver { | |||||
| public void run() { | public void run() { | ||||
| final Object[] argument = {javaCommand.getArguments()}; | final Object[] argument = {javaCommand.getArguments()}; | ||||
| try { | try { | ||||
| if(perm != null) { | |||||
| perm.setSecurityManager(); | |||||
| } | |||||
| main.invoke(null, argument); | main.invoke(null, argument); | ||||
| } catch (InvocationTargetException e) { | } catch (InvocationTargetException e) { | ||||
| Throwable t = e.getTargetException(); | Throwable t = e.getTargetException(); | ||||
| @@ -217,6 +232,9 @@ public class ExecuteJava implements Runnable, TimeoutObserver { | |||||
| } catch (Throwable t) { | } catch (Throwable t) { | ||||
| caught = t; | caught = t; | ||||
| } finally { | } finally { | ||||
| if(perm != null) { | |||||
| perm.restoreSecurityManager(); | |||||
| } | |||||
| synchronized (this) { | synchronized (this) { | ||||
| notifyAll(); | notifyAll(); | ||||
| } | } | ||||
| @@ -68,6 +68,7 @@ import org.apache.tools.ant.types.Path; | |||||
| import org.apache.tools.ant.types.PropertySet; | import org.apache.tools.ant.types.PropertySet; | ||||
| import org.apache.tools.ant.types.Reference; | import org.apache.tools.ant.types.Reference; | ||||
| import org.apache.tools.ant.types.Assertions; | import org.apache.tools.ant.types.Assertions; | ||||
| import org.apache.tools.ant.types.Permissions; | |||||
| /** | /** | ||||
| * Launcher for Java applications. Allows use of | * Launcher for Java applications. Allows use of | ||||
| @@ -78,6 +79,7 @@ import org.apache.tools.ant.types.Assertions; | |||||
| * <a href="mailto:stefano@apache.org">stefano@apache.org</a> | * <a href="mailto:stefano@apache.org">stefano@apache.org</a> | ||||
| * @author Stefan Bodewig | * @author Stefan Bodewig | ||||
| * @author <a href="mailto:donal@savvion.com">Donal Quinlan</a> | * @author <a href="mailto:donal@savvion.com">Donal Quinlan</a> | ||||
| * @author <a href="mailto:martijn@kruithof.xs4all.nl">Martijn Kruithof</a> | |||||
| * | * | ||||
| * @since Ant 1.1 | * @since Ant 1.1 | ||||
| * | * | ||||
| @@ -95,7 +97,8 @@ public class Java extends Task { | |||||
| private Long timeout = null; | private Long timeout = null; | ||||
| private Redirector redirector = new Redirector(this); | private Redirector redirector = new Redirector(this); | ||||
| private String resultProperty; | private String resultProperty; | ||||
| private Permissions perm; | |||||
| private boolean spawn = false; | private boolean spawn = false; | ||||
| private boolean incompatibleWithSpawn = false; | private boolean incompatibleWithSpawn = false; | ||||
| /** | /** | ||||
| @@ -109,7 +112,7 @@ public class Java extends Task { | |||||
| int err = -1; | int err = -1; | ||||
| try { | try { | ||||
| err = executeJava(); | err = executeJava(); | ||||
| if (fork && err != 0) { | |||||
| if (err != 0) { | |||||
| if (failOnError) { | if (failOnError) { | ||||
| throw new BuildException("Java returned: " + err, getLocation()); | throw new BuildException("Java returned: " + err, getLocation()); | ||||
| } else { | } else { | ||||
| @@ -152,6 +155,9 @@ public class Java extends Task { | |||||
| + "not compatible with spawn"); | + "not compatible with spawn"); | ||||
| } | } | ||||
| if (fork) { | if (fork) { | ||||
| if(perm != null) { | |||||
| log("Permissions can not be set this way in forked mode.",Project.MSG_WARN); | |||||
| } | |||||
| log(cmdl.describeCommand(), Project.MSG_VERBOSE); | log(cmdl.describeCommand(), Project.MSG_VERBOSE); | ||||
| } else { | } else { | ||||
| if (cmdl.getVmCommand().size() > 1) { | if (cmdl.getVmCommand().size() > 1) { | ||||
| @@ -180,7 +186,7 @@ public class Java extends Task { | |||||
| try { | try { | ||||
| if (fork) { | if (fork) { | ||||
| if (!spawn) { | if (!spawn) { | ||||
| return run(cmdl.getCommandline()); | |||||
| return fork(cmdl.getCommandline()); | |||||
| } else { | } else { | ||||
| spawn(cmdl.getCommandline()); | spawn(cmdl.getCommandline()); | ||||
| return 0; | return 0; | ||||
| @@ -248,6 +254,18 @@ public class Java extends Task { | |||||
| return cmdl.createBootclasspath(getProject()).createPath(); | return cmdl.createBootclasspath(getProject()).createPath(); | ||||
| } | } | ||||
| /** | |||||
| * Sets the permissions for the application run inside the same JVM. | |||||
| * @since Ant 1.6 | |||||
| * @return . | |||||
| */ | |||||
| public Permissions createPermissions() { | |||||
| if (perm == null) { | |||||
| perm = new Permissions(); | |||||
| } | |||||
| return perm; | |||||
| } | |||||
| /** | /** | ||||
| * Classpath to use, by reference. | * Classpath to use, by reference. | ||||
| * | * | ||||
| @@ -662,6 +680,7 @@ public class Java extends Task { | |||||
| exe.setJavaCommand(command.getJavaCommand()); | exe.setJavaCommand(command.getJavaCommand()); | ||||
| exe.setClasspath(command.getClasspath()); | exe.setClasspath(command.getClasspath()); | ||||
| exe.setSystemProperties(command.getSystemProperties()); | exe.setSystemProperties(command.getSystemProperties()); | ||||
| exe.setPermissions(perm); | |||||
| exe.setTimeout(timeout); | exe.setTimeout(timeout); | ||||
| redirector.createStreams(); | redirector.createStreams(); | ||||
| exe.execute(getProject()); | exe.execute(getProject()); | ||||
| @@ -674,7 +693,7 @@ public class Java extends Task { | |||||
| /** | /** | ||||
| * Executes the given classname with the given arguments in a separate VM. | * Executes the given classname with the given arguments in a separate VM. | ||||
| */ | */ | ||||
| private int run(String[] command) throws BuildException { | |||||
| private int fork(String[] command) throws BuildException { | |||||
| Execute exe | Execute exe | ||||
| = new Execute(redirector.createHandler(), createWatchdog()); | = new Execute(redirector.createHandler(), createWatchdog()); | ||||
| @@ -76,6 +76,7 @@ import org.apache.tools.ant.types.CommandlineJava; | |||||
| import org.apache.tools.ant.types.EnumeratedAttribute; | import org.apache.tools.ant.types.EnumeratedAttribute; | ||||
| import org.apache.tools.ant.types.Environment; | import org.apache.tools.ant.types.Environment; | ||||
| import org.apache.tools.ant.types.Path; | import org.apache.tools.ant.types.Path; | ||||
| import org.apache.tools.ant.types.Permissions; | |||||
| import org.apache.tools.ant.types.PropertySet; | import org.apache.tools.ant.types.PropertySet; | ||||
| import org.apache.tools.ant.util.FileUtils; | import org.apache.tools.ant.util.FileUtils; | ||||
| import org.apache.tools.ant.util.LoaderUtils; | import org.apache.tools.ant.util.LoaderUtils; | ||||
| @@ -180,6 +181,7 @@ public class JUnitTask extends Task { | |||||
| private boolean showOutput = false; | private boolean showOutput = false; | ||||
| private File tmpDir; | private File tmpDir; | ||||
| private AntClassLoader classLoader = null; | private AntClassLoader classLoader = null; | ||||
| private Permissions perm = null; | |||||
| private static final int STRING_BUFFER_SIZE = 128; | private static final int STRING_BUFFER_SIZE = 128; | ||||
| /** | /** | ||||
| @@ -570,6 +572,18 @@ public class JUnitTask extends Task { | |||||
| commandline.setAssertions(asserts); | commandline.setAssertions(asserts); | ||||
| } | } | ||||
| /** | |||||
| * Sets the permissions for the application run inside the same JVM. | |||||
| * @since Ant 1.6 | |||||
| * @return . | |||||
| */ | |||||
| public Permissions createPermissions() { | |||||
| if (perm == null) { | |||||
| perm = new Permissions(); | |||||
| } | |||||
| return perm; | |||||
| } | |||||
| /** | /** | ||||
| * Creates a new JUnitRunner and enables fork of a new Java VM. | * Creates a new JUnitRunner and enables fork of a new Java VM. | ||||
| * | * | ||||
| @@ -688,6 +702,10 @@ public class JUnitTask extends Task { | |||||
| private int executeAsForked(JUnitTest test, ExecuteWatchdog watchdog) | private int executeAsForked(JUnitTest test, ExecuteWatchdog watchdog) | ||||
| throws BuildException { | throws BuildException { | ||||
| if(perm != null) { | |||||
| log("Permissions ignored when running in forked mode!", Project.MSG_WARN); | |||||
| } | |||||
| CommandlineJava cmd = (CommandlineJava) commandline.clone(); | CommandlineJava cmd = (CommandlineJava) commandline.clone(); | ||||
| cmd.setClassname("org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner"); | cmd.setClassname("org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner"); | ||||
| @@ -935,6 +953,8 @@ public class JUnitTask extends Task { | |||||
| f.setOutput(getDefaultOutput()); | f.setOutput(getDefaultOutput()); | ||||
| runner.addFormatter(f); | runner.addFormatter(f); | ||||
| } | } | ||||
| runner.setPermissions(perm); | |||||
| final FormatterElement[] feArray = mergeFormatters(test); | final FormatterElement[] feArray = mergeFormatters(test); | ||||
| for (int i = 0; i < feArray.length; i++) { | for (int i = 0; i < feArray.length; i++) { | ||||
| @@ -75,6 +75,7 @@ import junit.framework.TestResult; | |||||
| import junit.framework.TestSuite; | import junit.framework.TestSuite; | ||||
| import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
| import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
| import org.apache.tools.ant.types.Permissions; | |||||
| import org.apache.tools.ant.util.StringUtils; | import org.apache.tools.ant.util.StringUtils; | ||||
| import org.apache.tools.ant.util.TeeOutputStream; | import org.apache.tools.ant.util.TeeOutputStream; | ||||
| @@ -95,6 +96,7 @@ import org.apache.tools.ant.util.TeeOutputStream; | |||||
| * | * | ||||
| * @author Stefan Bodewig | * @author Stefan Bodewig | ||||
| * @author <a href="mailto:ehatcher@apache.org">Erik Hatcher</a> | * @author <a href="mailto:ehatcher@apache.org">Erik Hatcher</a> | ||||
| * @author <a href="mailto:martijn@kruithof.xs4all.nl">Martijn Kruithof</a> | |||||
| * | * | ||||
| * @since Ant 1.2 | * @since Ant 1.2 | ||||
| */ | */ | ||||
| @@ -136,6 +138,11 @@ public class JUnitTestRunner implements TestListener { | |||||
| */ | */ | ||||
| private boolean showOutput = false; | private boolean showOutput = false; | ||||
| /** | |||||
| * The permissions set for the test to run. | |||||
| */ | |||||
| private Permissions perm = null; | |||||
| private static final String[] DEFAULT_TRACE_FILTERS = new String[] { | private static final String[] DEFAULT_TRACE_FILTERS = new String[] { | ||||
| "junit.framework.TestCase", | "junit.framework.TestCase", | ||||
| "junit.framework.TestResult", | "junit.framework.TestResult", | ||||
| @@ -309,12 +316,20 @@ public class JUnitTestRunner implements TestListener { | |||||
| ) | ) | ||||
| ); | ); | ||||
| } | } | ||||
| perm = null; | |||||
| } else { | |||||
| if(perm != null) { | |||||
| perm.setSecurityManager(); | |||||
| } | |||||
| } | } | ||||
| try { | try { | ||||
| suite.run(res); | suite.run(res); | ||||
| } finally { | } finally { | ||||
| if(perm != null) { | |||||
| perm.restoreSecurityManager(); | |||||
| } | |||||
| if (savedOut != null) { | if (savedOut != null) { | ||||
| System.setOut(savedOut); | System.setOut(savedOut); | ||||
| } | } | ||||
| @@ -398,6 +413,15 @@ public class JUnitTestRunner implements TestListener { | |||||
| res.stop(); | res.stop(); | ||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Permissions for the test run. | |||||
| * @since Ant 1.6 | |||||
| * @param permissions | |||||
| */ | |||||
| public void setPermissions(Permissions permissions) { | |||||
| perm = permissions; | |||||
| } | |||||
| protected void handleOutput(String output) { | protected void handleOutput(String output) { | ||||
| if (systemOut != null) { | if (systemOut != null) { | ||||
| @@ -0,0 +1,324 @@ | |||||
| /* | |||||
| * The Apache Software License, Version 1.1 | |||||
| * | |||||
| * Copyright (c) 2003 The Apache Software Foundation. All rights | |||||
| * reserved. | |||||
| * | |||||
| * Redistribution and use in source and binary forms, with or without | |||||
| * modification, are permitted provided that the following conditions | |||||
| * are met: | |||||
| * | |||||
| * 1. Redistributions of source code must retain the above copyright | |||||
| * notice, this list of conditions and the following disclaimer. | |||||
| * | |||||
| * 2. Redistributions in binary form must reproduce the above copyright | |||||
| * notice, this list of conditions and the following disclaimer in | |||||
| * the documentation and/or other materials provided with the | |||||
| * distribution. | |||||
| * | |||||
| * 3. The end-user documentation included with the redistribution, if | |||||
| * any, must include the following acknowlegement: | |||||
| * "This product includes software developed by the | |||||
| * Apache Software Foundation (http://www.apache.org/)." | |||||
| * Alternately, this acknowlegement may appear in the software itself, | |||||
| * if and wherever such third-party acknowlegements normally appear. | |||||
| * | |||||
| * 4. The names "Ant" and "Apache Software | |||||
| * Foundation" must not be used to endorse or promote products derived | |||||
| * from this software without prior written permission. For written | |||||
| * permission, please contact apache@apache.org. | |||||
| * | |||||
| * 5. Products derived from this software may not be called "Apache" | |||||
| * nor may "Apache" appear in their names without prior written | |||||
| * permission of the Apache Group. | |||||
| * | |||||
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||||
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||||
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||||
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||||
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||||
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||||
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||||
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||||
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||||
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||
| * SUCH DAMAGE. | |||||
| * ==================================================================== | |||||
| * | |||||
| * This software consists of voluntary contributions made by many | |||||
| * individuals on behalf of the Apache Software Foundation. For more | |||||
| * information on the Apache Software Foundation, please see | |||||
| * <http://www.apache.org/>. | |||||
| */ | |||||
| package org.apache.tools.ant.types; | |||||
| import java.security.UnresolvedPermission; | |||||
| import java.util.HashSet; | |||||
| import java.util.Iterator; | |||||
| import java.util.LinkedList; | |||||
| import java.util.List; | |||||
| import java.util.Set; | |||||
| import java.util.StringTokenizer; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.ExitException; | |||||
| /** | |||||
| * This class implements a security manager meant for useage by tasks that run inside the | |||||
| * ant VM. An examples are the Java Task and JUnitTask. | |||||
| * | |||||
| * The basic functionality is that nothing (except for a base set of permissions) is allowed, unless | |||||
| * the permission is granted either explicitly or implicitly. | |||||
| * If an permission is granted this can be overruled by explicitly revoking the permission. | |||||
| * | |||||
| * It is not permissible to add permissions (either granted or revoked) while the Security Manager | |||||
| * is active (after calling setSecurityManager() but before calling restoreSecurityManager()). | |||||
| * | |||||
| * @since Ant 1.6 | |||||
| * @author <a href="mailto:martijn@kruithof.xs4all.nl">Martijn Kruithof</a> | |||||
| */ | |||||
| public class Permissions { | |||||
| private List grantedPermissions = new LinkedList(); | |||||
| private List revokedPermissions = new LinkedList(); | |||||
| private java.security.Permissions granted = null; | |||||
| private SecurityManager origSm = null; | |||||
| private boolean active = false; | |||||
| /** | |||||
| * Adds a permission to be granted. | |||||
| * @param perm The Permissions.Permission to be granted. | |||||
| */ | |||||
| public void addConfiguredGrant(Permissions.Permission perm) { | |||||
| grantedPermissions.add(perm); | |||||
| } | |||||
| /** | |||||
| * Adds a permission to be revoked. | |||||
| * @param perm The Permissions.Permission to be revoked | |||||
| */ | |||||
| public void addConfiguredRevoke(Permissions.Permission perm) { | |||||
| revokedPermissions.add(perm); | |||||
| } | |||||
| /** | |||||
| * To be used by tasks wishing to use this security model before executing the part to be | |||||
| * subject to these Permissions. Note that setting the SecurityManager too early may | |||||
| * prevent your part from starting, as for instance changing classloaders may be prohibited. | |||||
| * The classloader for the new situation is supposed to be present. | |||||
| */ | |||||
| public void setSecurityManager() throws BuildException{ | |||||
| origSm = System.getSecurityManager(); | |||||
| init(); | |||||
| System.setSecurityManager(new MySM()); | |||||
| active = true; | |||||
| } | |||||
| /** | |||||
| * Initializes the list of granted permissions, checks the list of revoked permissions. | |||||
| */ | |||||
| private void init() throws BuildException { | |||||
| granted = new java.security.Permissions(); | |||||
| for (Iterator i = revokedPermissions.listIterator(); i.hasNext();) { | |||||
| Permissions.Permission p = (Permissions.Permission) i.next(); | |||||
| if (p.getClassName() == null) { | |||||
| throw new BuildException("Revoked permission " + p + " does not contain a class."); | |||||
| } | |||||
| } | |||||
| for (Iterator i = grantedPermissions.listIterator(); i.hasNext();) { | |||||
| Permissions.Permission p = (Permissions.Permission) i.next(); | |||||
| if (p.getClassName() == null) { | |||||
| throw new BuildException("Granted permission " + p + " does not contain a class."); | |||||
| } else { | |||||
| java.security.Permission perm = new UnresolvedPermission(p.getClassName(),p.getName(),p.getActions(),null); | |||||
| granted.add(perm); | |||||
| } | |||||
| } | |||||
| // Add base set of permissions | |||||
| granted.add(new java.net.SocketPermission("localhost:1024-", "listen")); | |||||
| granted.add(new java.util.PropertyPermission("java.version", "read")); | |||||
| granted.add(new java.util.PropertyPermission("java.vendor", "read")); | |||||
| granted.add(new java.util.PropertyPermission("java.vendor.url", "read")); | |||||
| granted.add(new java.util.PropertyPermission("java.class.version", "read")); | |||||
| granted.add(new java.util.PropertyPermission("os.name", "read")); | |||||
| granted.add(new java.util.PropertyPermission("os.version", "read")); | |||||
| granted.add(new java.util.PropertyPermission("os.arch", "read")); | |||||
| granted.add(new java.util.PropertyPermission("file.separator", "read")); | |||||
| granted.add(new java.util.PropertyPermission("path.separator", "read")); | |||||
| granted.add(new java.util.PropertyPermission("line.separator", "read")); | |||||
| granted.add(new java.util.PropertyPermission("java.specification.version", "read")); | |||||
| granted.add(new java.util.PropertyPermission("java.specification.vendor", "read")); | |||||
| granted.add(new java.util.PropertyPermission("java.specification.name", "read")); | |||||
| granted.add(new java.util.PropertyPermission("java.vm.specification.version", "read")); | |||||
| granted.add(new java.util.PropertyPermission("java.vm.specification.vendor", "read")); | |||||
| granted.add(new java.util.PropertyPermission("java.vm.specification.name", "read")); | |||||
| granted.add(new java.util.PropertyPermission("java.vm.version", "read")); | |||||
| granted.add(new java.util.PropertyPermission("java.vm.vendor", "read")); | |||||
| granted.add(new java.util.PropertyPermission("java.vm.name", "read")); | |||||
| } | |||||
| /** | |||||
| * To be used by tasks that just finished executing the parts subject to these permissions. | |||||
| */ | |||||
| public void restoreSecurityManager() { | |||||
| active = false; | |||||
| System.setSecurityManager(origSm); | |||||
| } | |||||
| /** | |||||
| * This inner class implements the actual SecurityManager that can be used by tasks | |||||
| * supporting Permissions. | |||||
| */ | |||||
| private class MySM extends SecurityManager { | |||||
| /** | |||||
| * Exit is treated in a special way in order to be able to return the exit code towards tasks. | |||||
| * An ExitException is thrown instead of a simple SecurityException to indicate the exit | |||||
| * code. | |||||
| * Overridden from java.lang.SecurityManager | |||||
| * @param status The exit status requested. | |||||
| */ | |||||
| public void checkExit(int status) { | |||||
| java.security.Permission perm = new java.lang.RuntimePermission("exitVM",null); | |||||
| try { | |||||
| checkPermission(perm); | |||||
| } catch (SecurityException e) { | |||||
| throw new ExitException(e.getMessage(), status); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * The central point in checking permissions. | |||||
| * Overridden from java.lang.SecurityManager | |||||
| * | |||||
| * @parem perm The permission requested. | |||||
| */ | |||||
| public void checkPermission(java.security.Permission perm) { | |||||
| if (active) { | |||||
| if (!granted.implies(perm)) { | |||||
| throw new SecurityException("Permission " + perm +" was not granted."); | |||||
| } | |||||
| for (Iterator i = revokedPermissions.listIterator(); i.hasNext();) { | |||||
| if (((Permissions.Permission)i.next()).matches(perm)) { | |||||
| throw new SecurityException("Permission " + perm +" was revoked."); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| /** Represents a permission. */ | |||||
| public static class Permission { | |||||
| private String className; | |||||
| private String name; | |||||
| private String actionString; | |||||
| private Set actions; | |||||
| /** | |||||
| * Sets the class, mandatory. | |||||
| * @param aClass The class name of the permission. | |||||
| */ | |||||
| public void setClass(String aClass) { | |||||
| className = aClass.trim(); | |||||
| } | |||||
| /** Get the class of the permission | |||||
| * @return The class name of the permission. | |||||
| */ | |||||
| public String getClassName() { | |||||
| return className; | |||||
| } | |||||
| /** | |||||
| * Sets the name of the permission. | |||||
| * @param aName The name of the permission. | |||||
| */ | |||||
| public void setName(String aName) { | |||||
| name = aName.trim(); | |||||
| } | |||||
| /** | |||||
| * Get the name of the permission. | |||||
| * @return The name of the permission. | |||||
| */ | |||||
| public String getName() { | |||||
| return name; | |||||
| } | |||||
| /** | |||||
| * Sets the actions. | |||||
| * @param actions The actions of the permission. | |||||
| */ | |||||
| public void setActions(String actions) { | |||||
| actionString = actions; | |||||
| if (actions.length() > 0) { | |||||
| this.actions = parseActions(actions); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Gets the actions. | |||||
| * @return The actions of the permission. | |||||
| */ | |||||
| public String getActions() { | |||||
| return actionString; | |||||
| } | |||||
| /** | |||||
| * Checks if the permission matches in case of a revoked permission. | |||||
| * @param perm The permission to check against. | |||||
| */ | |||||
| boolean matches(java.security.Permission perm) { | |||||
| if (!className.equals(perm.getClass().getName())) { | |||||
| return false; | |||||
| } | |||||
| if (name != null) { | |||||
| if (name.endsWith("*")) { | |||||
| if (!perm.getName().startsWith(name.substring(0,name.length()-1))) { | |||||
| return false; | |||||
| } | |||||
| } else { | |||||
| if (!name.equals(perm.getName())) { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| } | |||||
| if (actions != null) { | |||||
| Set as = parseActions(perm.getActions()); | |||||
| int size = as.size(); | |||||
| as.removeAll(actions); | |||||
| if (as.size() == size) { | |||||
| // None of the actions revoked, so all allowed. | |||||
| return false; | |||||
| } | |||||
| } | |||||
| return true; | |||||
| } | |||||
| /** | |||||
| * Parses the actions into a set of separate strings. | |||||
| * @param action The actions to be parsed. | |||||
| */ | |||||
| private Set parseActions(String actions) { | |||||
| Set result = new HashSet(); | |||||
| StringTokenizer tk = new StringTokenizer(actions, ","); | |||||
| while (tk.hasMoreTokens()) { | |||||
| String item = tk.nextToken().trim(); | |||||
| if (!item.equals("")) { | |||||
| result.add(item); | |||||
| } | |||||
| } | |||||
| return result; | |||||
| } | |||||
| public String toString() { | |||||
| return ("Permission: " + className + " (\""+name+"\", \""+actions+"\")"); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -64,6 +64,7 @@ import org.apache.tools.ant.util.FileUtils; | |||||
| * @author steve loughran | * @author steve loughran | ||||
| * @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a> | * @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a> | ||||
| * @author <a href="mailto:donal@savvion.com">Donal Quinlan</a> | * @author <a href="mailto:donal@savvion.com">Donal Quinlan</a> | ||||
| * @author <a href="mailto:martijn@kruithof.xs4all.nl">Martijn Kruithof</a> | |||||
| * */ | * */ | ||||
| public class JavaTest extends BuildFileTest { | public class JavaTest extends BuildFileTest { | ||||
| @@ -185,6 +186,16 @@ public class JavaTest extends BuildFileTest { | |||||
| assertEquals("2",project.getProperty("exitcode")); | assertEquals("2",project.getProperty("exitcode")); | ||||
| } | } | ||||
| public void testResultPropertyZeroNoFork() { | |||||
| executeTarget("testResultPropertyZeroNoFork"); | |||||
| assertEquals("0",project.getProperty("exitcode")); | |||||
| } | |||||
| public void testResultPropertyNonZeroNoFork() { | |||||
| executeTarget("testResultPropertyNonZeroNoFork"); | |||||
| assertEquals("-1",project.getProperty("exitcode")); | |||||
| } | |||||
| public void testSpawn() { | public void testSpawn() { | ||||
| FileUtils fileutils = FileUtils.newFileUtils(); | FileUtils fileutils = FileUtils.newFileUtils(); | ||||
| File logFile = fileutils.createTempFile("spawn","log", project.getBaseDir()); | File logFile = fileutils.createTempFile("spawn","log", project.getBaseDir()); | ||||
| @@ -0,0 +1,187 @@ | |||||
| /* | |||||
| * The Apache Software License, Version 1.1 | |||||
| * | |||||
| * Copyright (c) 2003 The Apache Software Foundation. All rights | |||||
| * reserved. | |||||
| * | |||||
| * Redistribution and use in source and binary forms, with or without | |||||
| * modification, are permitted provided that the following conditions | |||||
| * are met: | |||||
| * | |||||
| * 1. Redistributions of source code must retain the above copyright | |||||
| * notice, this list of conditions and the following disclaimer. | |||||
| * | |||||
| * 2. Redistributions in binary form must reproduce the above copyright | |||||
| * notice, this list of conditions and the following disclaimer in | |||||
| * the documentation and/or other materials provided with the | |||||
| * distribution. | |||||
| * | |||||
| * 3. The end-user documentation included with the redistribution, if | |||||
| * any, must include the following acknowlegement: | |||||
| * "This product includes software developed by the | |||||
| * Apache Software Foundation (http://www.apache.org/)." | |||||
| * Alternately, this acknowlegement may appear in the software itself, | |||||
| * if and wherever such third-party acknowlegements normally appear. | |||||
| * | |||||
| * 4. The names "Ant" and "Apache Software | |||||
| * Foundation" must not be used to endorse or promote products derived | |||||
| * from this software without prior written permission. For written | |||||
| * permission, please contact apache@apache.org. | |||||
| * | |||||
| * 5. Products derived from this software may not be called "Apache" | |||||
| * nor may "Apache" appear in their names without prior written | |||||
| * permission of the Apache Group. | |||||
| * | |||||
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||||
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||||
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||||
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||||
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||||
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||||
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||||
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||||
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||||
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||
| * SUCH DAMAGE. | |||||
| * ==================================================================== | |||||
| * | |||||
| * This software consists of voluntary contributions made by many | |||||
| * individuals on behalf of the Apache Software Foundation. For more | |||||
| * information on the Apache Software Foundation, please see | |||||
| * <http://www.apache.org/>. | |||||
| */ | |||||
| package org.apache.tools.ant.types; | |||||
| import junit.framework.TestCase; | |||||
| import org.apache.tools.ant.ExitException; | |||||
| /** | |||||
| * JUnit 3 testcases for org.apache.tools.ant.types.Permissions. | |||||
| * | |||||
| * @author <a href="mailto:martijn@kruithof.xs4all.nl>Martijn Kruithof</a> | |||||
| */ | |||||
| public class PermissionsTest extends TestCase { | |||||
| Permissions perms; | |||||
| public PermissionsTest(String name) { | |||||
| super(name); | |||||
| } | |||||
| public void setUp() { | |||||
| perms = new Permissions(); | |||||
| Permissions.Permission perm = new Permissions.Permission(); | |||||
| // Grant extra permissions to read and write the user.* properties and read to the | |||||
| // java.home property | |||||
| perm.setActions("read, write"); | |||||
| perm.setName("user.*"); | |||||
| perm.setClass("java.util.PropertyPermission"); | |||||
| perms.addConfiguredGrant(perm); | |||||
| perm = new Permissions.Permission(); | |||||
| perm.setActions("read"); | |||||
| perm.setName("java.home"); | |||||
| perm.setClass("java.util.PropertyPermission"); | |||||
| perms.addConfiguredGrant(perm); | |||||
| // Revoke permission to write user.home (granted above via user.*), still able to read though. | |||||
| // and the default granted permission to read os.name. | |||||
| perm = new Permissions.Permission(); | |||||
| perm.setActions("write"); | |||||
| perm.setName("user.home"); | |||||
| perm.setClass("java.util.PropertyPermission"); | |||||
| perms.addConfiguredRevoke(perm); | |||||
| perm = new Permissions.Permission(); | |||||
| perm.setActions("read"); | |||||
| perm.setName("os.*"); | |||||
| perm.setClass("java.util.PropertyPermission"); | |||||
| perms.addConfiguredRevoke(perm); | |||||
| } | |||||
| /** Tests a permission that is granted per default. */ | |||||
| public void testDefaultGranted() { | |||||
| perms.setSecurityManager(); | |||||
| try { | |||||
| String s = System.getProperty("line.separator"); | |||||
| } finally { | |||||
| perms.restoreSecurityManager(); | |||||
| } | |||||
| } | |||||
| /** Tests a permission that has been granted later via wildcard. */ | |||||
| public void testGranted() { | |||||
| perms.setSecurityManager(); | |||||
| try { | |||||
| String s = System.getProperty("user.name"); | |||||
| System.setProperty("user.name", s); | |||||
| } finally { | |||||
| perms.restoreSecurityManager(); | |||||
| } | |||||
| } | |||||
| /** Tests a permission that has been granted and revoked later. */ | |||||
| public void testGrantedAndRevoked() { | |||||
| perms.setSecurityManager(); | |||||
| try { | |||||
| String s = System.getProperty("user.home"); | |||||
| System.setProperty("user.home", s); | |||||
| fail("Could perform an action that should have been forbidden."); | |||||
| } catch (SecurityException e){ | |||||
| // Was expected, test passes | |||||
| } finally { | |||||
| perms.restoreSecurityManager(); | |||||
| } | |||||
| } | |||||
| /** Tests a permission that is granted as per default but revoked later via wildcard. */ | |||||
| public void testDefaultRevoked() { | |||||
| perms.setSecurityManager(); | |||||
| try { | |||||
| System.getProperty("os.name"); | |||||
| fail("Could perform an action that should have been forbidden."); | |||||
| } catch (SecurityException e){ | |||||
| // Was expected, test passes | |||||
| } finally { | |||||
| perms.restoreSecurityManager(); | |||||
| } | |||||
| } | |||||
| /** Tests a permission that has not been granted or revoked. */ | |||||
| public void testOther() { | |||||
| String ls = System.getProperty("line.separator"); | |||||
| perms.setSecurityManager(); | |||||
| try { | |||||
| String s = System.setProperty("line.separator",ls); | |||||
| fail("Could perform an action that should have been forbidden."); | |||||
| } catch (SecurityException e){ | |||||
| // Was expected, test passes | |||||
| } finally { | |||||
| perms.restoreSecurityManager(); | |||||
| } | |||||
| } | |||||
| /** Tests an exit condition. */ | |||||
| public void testExit() { | |||||
| perms.setSecurityManager(); | |||||
| try { | |||||
| System.out.println("If this is the last line on standard out the testExit f.a.i.l.e.d"); | |||||
| System.exit(3); | |||||
| fail("Totaly impossible that this fail is ever executed. Please let me know if it is!"); | |||||
| } catch (ExitException e) { | |||||
| if (e.getStatus() != 3) { | |||||
| fail("Received wrong exit status in Exit Exception."); | |||||
| } | |||||
| System.out.println("testExit successfull."); | |||||
| } finally { | |||||
| perms.restoreSecurityManager(); | |||||
| } | |||||
| } | |||||
| public void tearDown() { | |||||
| } | |||||
| } | |||||