diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/library/scala/sys/Prop.scala | 101 | ||||
-rw-r--r-- | src/library/scala/sys/PropImpl.scala | 58 | ||||
-rw-r--r-- | src/library/scala/sys/SystemProperties.scala (renamed from src/library/scala/sys/PropertiesMap.scala) | 28 | ||||
-rw-r--r-- | src/library/scala/sys/package.scala | 6 |
4 files changed, 187 insertions, 6 deletions
diff --git a/src/library/scala/sys/Prop.scala b/src/library/scala/sys/Prop.scala new file mode 100644 index 0000000000..8444976826 --- /dev/null +++ b/src/library/scala/sys/Prop.scala @@ -0,0 +1,101 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.sys + +/** A lightweight interface wrapping a property contained in some + * unspecified map. Generally it'll be the system properties but this + * is not a requirement. + * + * See `scala.sys.SystemProperties` for an example usage. + * + * @author Paul Phillips + * @version 2.9 + * @since 2.9 + */ +trait Prop[T] { + /** The full name of the property, e.g. "java.awt.headless". + */ + def key: String + + /** If the key exists in the properties map, converts the value + * to type `T` using valueFn. As yet no validation is performed: + * it will throw an exception on a failed conversion. + * @return the converted value, or `zero` if not in the map + */ + def value: T + + /** True if the key exists in the properties map. Note that this + * is not sufficient for a Boolean property to be considered true. + * @return whether the map contains the key + */ + def isSet: Boolean + + /** Sets the property. + * + * @param the new string value + * @return the old value, or null if it was unset. + */ + def set(newValue: String): String + + /** Gets the current string value if any. Will not return null: use + * `isSet` to test for existence. + * @return the current string value if any, else the empty string + */ + def get: String + + /** Removes the property from the underlying map. + */ + def clear(): Unit + + /** A value of type `T` for use when the property is unset. + * The default implementation delivers null for reference types + * and 0/0.0/false for non-reference types. + */ + protected def zero: T +} + +/** 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". + * + * @return true if the current String is considered true, false otherwise + */ + def value: Boolean + + /** Alter this property so that `value` will be true. */ + def enable(): Unit + + /** Alter this property so that `value` will be false. */ + def disable(): Unit + + /** Toggle the property between enabled and disabled states. */ + def toggle(): Unit +} + +object Prop extends PropCompanion { + /** 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] { + /** 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 new file mode 100644 index 0000000000..02f00f682b --- /dev/null +++ b/src/library/scala/sys/PropImpl.scala @@ -0,0 +1,58 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.sys + +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] { + def value: T = if (isSet) valueFn(get) else zero + def isSet = underlying contains key + def set(newValue: String): String = { + val old = if (isSet) get else null + underlying(key) = newValue + old + } + def get: String = + if (isSet) underlying(key) + else "" + + def clear() = underlying -= key + + /** The underlying property map, in our case always sys.props */ + protected def underlying: mutable.Map[String, String] = scala.sys.props + protected def zero: T = null.asInstanceOf[T] + private def getString = if (isSet) "currently: " + get else "unset" + 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) + } +} diff --git a/src/library/scala/sys/PropertiesMap.scala b/src/library/scala/sys/SystemProperties.scala index 68f8d10418..cc8131220f 100644 --- a/src/library/scala/sys/PropertiesMap.scala +++ b/src/library/scala/sys/SystemProperties.scala @@ -20,12 +20,34 @@ import scala.collection.JavaConverters._ * @version 2.9 * @since 2.9 */ -class PropertiesMap extends mutable.Map[String, String] { - override def empty = new PropertiesMap +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 } -}
\ No newline at end of file +} + +/** The values in SystemProperties can be used to access and manipulate + * designated system properties. See `scala.sys.Prop` for particulars. + * @example {{{ + * if (!headless.isSet) headless.enable() + * }}} + */ +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 + } + def help(key: String) = propertyHelp.getOrElse(key, "") + + // Todo: bring some sanity to the intersection of system properties aka "mutable + // state shared by everyone and everything" and the reality that there is no other + // mechanism for accomplishing some things on the jvm. + lazy val headless = bool("java.awt.headless", "system should not utilize a display device") + lazy val preferIPv4 = bool("java.net.preferIPv4Stack", "system should prefer IPv4 sockets") +} diff --git a/src/library/scala/sys/package.scala b/src/library/scala/sys/package.scala index e8c17596ff..16faded419 100644 --- a/src/library/scala/sys/package.scala +++ b/src/library/scala/sys/package.scala @@ -49,10 +49,10 @@ package object sys { /** A bidirectional, mutable Map representing the current system Properties. * - * @return a PropertiesMap. - * @see `scala.sys.PropertiesMap` + * @return a SystemProperties. + * @see `scala.sys.SystemProperties` */ - def props: PropertiesMap = new PropertiesMap + def props: SystemProperties = new SystemProperties /** An immutable Map representing the current system environment. * |