summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/library/scala/sys/BooleanProp.scala40
-rw-r--r--src/library/scala/sys/Prop.scala8
-rw-r--r--src/library/scala/sys/PropImpl.scala31
-rw-r--r--src/library/scala/sys/SystemProperties.scala29
-rw-r--r--src/partest/scala/tools/partest/SecurityTest.scala32
-rw-r--r--test/files/run/applet-prop.scala40
-rw-r--r--test/files/run/sysprops.scala2
-rw-r--r--test/files/specialized/test.scala11
8 files changed, 146 insertions, 47 deletions
diff --git a/src/library/scala/sys/BooleanProp.scala b/src/library/scala/sys/BooleanProp.scala
index 0f04d1f45e..e598d81307 100644
--- a/src/library/scala/sys/BooleanProp.scala
+++ b/src/library/scala/sys/BooleanProp.scala
@@ -11,9 +11,8 @@ package scala.sys
/** A few additional conveniences for Boolean properties.
*/
trait BooleanProp extends Prop[Boolean] {
- /** The default implementation of `value` adheres to java's definition
- * of truth, which means it is true only if there is a value in the map and
- * that value, once converted to all lower case, is equal to "true".
+ /** The semantics of value are determined at Prop creation. See methods
+ * `valueIsTrue` and `keyExists` in object BooleanProp for examples.
*
* @return true if the current String is considered true, false otherwise
*/
@@ -30,5 +29,40 @@ trait BooleanProp extends Prop[Boolean] {
}
object BooleanProp {
+ private[sys]
+ class BooleanPropImpl(key: String, valueFn: String => Boolean) extends PropImpl(key, valueFn) with BooleanProp {
+ def enable() = this set "true"
+ def disable() = this.clear()
+ def toggle() = if (value) disable() else enable()
+ }
+ private[sys]
+ class ConstantImpl(val key: String, val value: Boolean) extends BooleanProp {
+ val isSet = value
+ def set(newValue: String) = "" + value
+ def get: String = "" + value
+ val clear, enable, disable, toggle = ()
+ protected def zero = false
+ }
+
+ /** The java definition of property truth is that the key be in the map and
+ * the value be equal to the String "true", case insensitively. This method
+ * creates a BooleanProp instance which adheres to that definition.
+ *
+ * @return A BooleanProp which acts like java's Boolean.getBoolean
+ */
+ def valueIsTrue[T](key: String): BooleanProp = new BooleanPropImpl(key, _.toLowerCase == "true")
+
+ /** As an alternative, this method creates a BooleanProp which is true
+ * if the key exists in the map. This way -Dfoo.bar is enough to be
+ * considered true.
+ *
+ * @return A BooleanProp with a liberal truth policy
+ */
+ def keyExists[T](key: String): BooleanProp = new BooleanPropImpl(key, _ => true)
+
+ /** A constant true or false property which ignores all method calls.
+ */
+ def constant(key: String, isOn: Boolean): BooleanProp = new ConstantImpl(key, isOn)
+
implicit def booleanPropAsBoolean(b: BooleanProp): Boolean = b.value
}
diff --git a/src/library/scala/sys/Prop.scala b/src/library/scala/sys/Prop.scala
index 1ac63ebc71..e3cbd4e515 100644
--- a/src/library/scala/sys/Prop.scala
+++ b/src/library/scala/sys/Prop.scala
@@ -18,7 +18,7 @@ package scala.sys
* @version 2.9
* @since 2.9
*/
-trait Prop[T] {
+trait Prop[+T] {
/** The full name of the property, e.g. "java.awt.headless".
*/
def key: String
@@ -60,21 +60,19 @@ trait Prop[T] {
protected def zero: T
}
-object Prop extends PropCompanion {
+object Prop {
/** A creator of property instances. For any type `T`, if an implicit
* parameter of type Creator[T] is in scope, a Prop[T] can be created
* via this object's apply method.
*/
- trait Creator[T] {
+ trait Creator[+T] {
/** Creates a Prop[T] of this type based on the given key. */
def apply(key: String): Prop[T]
}
- implicit object BooleanProp extends BooleanCreatorImpl
implicit object StringProp extends CreatorImpl[String](s => s)
implicit object IntProp extends CreatorImpl[Int](_.toInt)
implicit object DoubleProp extends CreatorImpl[Double](_.toDouble)
- def bool[T](key: String): BooleanProp = BooleanProp(key)
def apply[T: Creator](key: String): Prop[T] = implicitly[Creator[T]] apply key
}
diff --git a/src/library/scala/sys/PropImpl.scala b/src/library/scala/sys/PropImpl.scala
index 02f00f682b..55073c35d3 100644
--- a/src/library/scala/sys/PropImpl.scala
+++ b/src/library/scala/sys/PropImpl.scala
@@ -12,7 +12,7 @@ import scala.collection.mutable
/** The internal implementation of scala.sys.Prop.
*/
-private[sys] class PropImpl[T](val key: String, valueFn: String => T) extends Prop[T] {
+private[sys] class PropImpl[+T](val key: String, valueFn: String => T) extends Prop[T] {
def value: T = if (isSet) valueFn(get) else zero
def isSet = underlying contains key
def set(newValue: String): String = {
@@ -21,10 +21,10 @@ private[sys] class PropImpl[T](val key: String, valueFn: String => T) extends Pr
old
}
def get: String =
- if (isSet) underlying(key)
+ if (isSet) underlying.getOrElse(key, "")
else ""
- def clear() = underlying -= key
+ def clear(): Unit = underlying -= key
/** The underlying property map, in our case always sys.props */
protected def underlying: mutable.Map[String, String] = scala.sys.props
@@ -33,26 +33,7 @@ private[sys] class PropImpl[T](val key: String, valueFn: String => T) extends Pr
override def toString = "%s (%s)".format(key, getString)
}
-trait PropCompanion {
- self: Prop.type =>
-
- private[sys] class BooleanPropImpl(key: String, valueFn: String => Boolean) extends PropImpl[Boolean](key, valueFn) with BooleanProp {
- def enable() = this set "true"
- def disable() = this.clear()
- def toggle() = if (value) disable() else enable()
- }
- private[sys] abstract class CreatorImpl[T](f: String => T) extends Creator[T] {
- def apply(key: String): Prop[T] = new PropImpl[T](key, f)
- }
- /** Implicit objects for the standard types. Custom ones can also be
- * created by implementing Creator[T].
- */
- private[sys] trait BooleanCreatorImpl extends Creator[Boolean] {
- self: BooleanProp.type =>
-
- /** As implemented in java.lang.Boolean.getBoolean. */
- private def javaStyleTruth(s: String) = s.toLowerCase == "true"
-
- def apply(key: String): BooleanProp = new BooleanPropImpl(key, javaStyleTruth)
- }
+private[sys] abstract class CreatorImpl[+T](f: String => T) extends Prop.Creator[T] {
+ def apply(key: String): Prop[T] = new PropImpl[T](key, f)
}
+
diff --git a/src/library/scala/sys/SystemProperties.scala b/src/library/scala/sys/SystemProperties.scala
index de3f9598f0..7c6286516b 100644
--- a/src/library/scala/sys/SystemProperties.scala
+++ b/src/library/scala/sys/SystemProperties.scala
@@ -10,11 +10,14 @@ package scala.sys
import scala.collection.mutable
import scala.collection.JavaConverters._
+import java.security.AccessControlException
/** A bidirectional map wrapping the java System properties.
* Changes to System properties will be immediately visible in the map,
* and modifications made to the map will be immediately applied to the
- * System properties.
+ * System properties. If a security manager is in place which prevents
+ * the properties from being read or written, the AccessControlException
+ * will be caught and discarded.
*
* @author Paul Phillips
* @version 2.9
@@ -23,11 +26,19 @@ import scala.collection.JavaConverters._
class SystemProperties extends mutable.Map[String, String] {
override def empty = new SystemProperties
override def default(key: String): String = null
- def iterator: Iterator[(String, String)] = System.getProperties().asScala.iterator
- def get(key: String) = Option(System.getProperty(key))
- def -= (key: String): this.type = { System.clearProperty(key) ; this }
- def += (kv: (String, String)): this.type = { System.setProperty(kv._1, kv._2) ; this }
+ def iterator: Iterator[(String, String)] =
+ wrapAccess(System.getProperties().asScala.iterator) getOrElse Iterator.empty
+ def get(key: String) =
+ wrapAccess(Option(System.getProperty(key))) flatMap (x => x)
+ override def contains(key: String) =
+ wrapAccess(super.contains(key)) exists (x => x)
+
+ def -= (key: String): this.type = { wrapAccess(System.clearProperty(key)) ; this }
+ def += (kv: (String, String)): this.type = { wrapAccess(System.setProperty(kv._1, kv._2)) ; this }
+
+ def wrapAccess[T](body: => T): Option[T] =
+ try Some(body) catch { case _: AccessControlException => None }
}
/** The values in SystemProperties can be used to access and manipulate
@@ -40,8 +51,12 @@ object SystemProperties {
implicit def systemPropertiesToCompanion(p: SystemProperties): SystemProperties.type = this
private lazy val propertyHelp = mutable.Map[String, String]()
private def bool(key: String, helpText: String) = {
- try Prop.bool(key)
- finally propertyHelp(key) = helpText
+ val prop = (
+ if (key startsWith "java.") BooleanProp.valueIsTrue(key)
+ else BooleanProp.keyExists(key)
+ )
+ propertyHelp(key) = helpText
+ prop
}
def help(key: String) = propertyHelp.getOrElse(key, "")
diff --git a/src/partest/scala/tools/partest/SecurityTest.scala b/src/partest/scala/tools/partest/SecurityTest.scala
new file mode 100644
index 0000000000..54aad5a625
--- /dev/null
+++ b/src/partest/scala/tools/partest/SecurityTest.scala
@@ -0,0 +1,32 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools.partest
+
+import java.security._
+import java.util._
+
+abstract class SecurityTest extends App {
+ def throwIt(x: Any) = throw new AccessControlException("" + x)
+
+ def readPerm(p: PropertyPermission) = p.getActions contains "read"
+ def writePerm(p: PropertyPermission) = p.getActions contains "write"
+ def propertyCheck(p: PropertyPermission): Unit = throwIt(p)
+
+ def check(perm: Permission): Unit = perm match {
+ case p: PropertyPermission => propertyCheck(p)
+ case _ => ()
+ }
+
+ lazy val sm = new SecurityManager {
+ // these two are the choke points for all permissions checks
+ override def checkPermission(perm: Permission): Unit = check(perm)
+ override def checkPermission(perm: Permission, context: Object): Unit = check(perm)
+ }
+ def securityOn(): Boolean = {
+ try { System.setSecurityManager(sm) ; true }
+ catch { case _: SecurityException => false }
+ }
+}
diff --git a/test/files/run/applet-prop.scala b/test/files/run/applet-prop.scala
new file mode 100644
index 0000000000..fb112bf7d5
--- /dev/null
+++ b/test/files/run/applet-prop.scala
@@ -0,0 +1,40 @@
+import scala.tools.partest._
+import java.util.PropertyPermission
+import java.security.AccessControlException
+
+class S extends javax.swing.JApplet {
+ scala.collection.Traversable
+}
+
+object Test extends SecurityTest {
+ val s = new S
+ // lazy val TestKey = sys.SystemProperties.noTraceSupression.key
+ // def hitPerm() = new Throwable with scala.util.control.ControlThrowable { }
+ //
+ // var throwing = false
+ // override def propertyCheck(p: PropertyPermission): Unit = {
+ // if (p.getName == TestKey) {
+ // println("I see " + p.getName)
+ // if (throwing)
+ // throwIt(p)
+ // }
+ // }
+ //
+ // hitPerm()
+ // securityOn()
+ // hitPerm()
+ //
+ // throwing = true
+ //
+ // val caught =
+ // try { hitPerm() ; false }
+ // catch { case _: AccessControlException => true }
+ //
+ // assert(caught, "Should have incurred exception.")
+ // throwing = false
+ // hitPerm()
+ //
+ // val xs = new Traversable[Int] { def foreach[U](f: Int => U) = 1 to 3 foreach f }
+ // xs foreach println
+}
+
diff --git a/test/files/run/sysprops.scala b/test/files/run/sysprops.scala
index d3df22d634..bdad677221 100644
--- a/test/files/run/sysprops.scala
+++ b/test/files/run/sysprops.scala
@@ -5,7 +5,7 @@ object Test {
val key = "ding.dong.doobie"
def bool() = {
- val prop = Prop.bool(key)
+ val prop = BooleanProp.valueIsTrue(key)
assert(prop.key == key)
prop.clear()
diff --git a/test/files/specialized/test.scala b/test/files/specialized/test.scala
index 54ef28d68a..bccc6f0f93 100644
--- a/test/files/specialized/test.scala
+++ b/test/files/specialized/test.scala
@@ -1,10 +1,9 @@
-
-
-
object Test {
-
+ // not sure exactly what this is enforcing, but it was failing on
+ // me due to some early boxing happening with the check for a
+ // stack trace suppression system property, so I boosted the count.
def main(args: Array[String]) {
- assert(runtime.BoxesRunTime.booleanBoxCount == 0)
+ assert(runtime.BoxesRunTime.booleanBoxCount < 10,
+ "Expected no more than 10 boolean boxings, found " + runtime.BoxesRunTime.booleanBoxCount)
}
-
}