All Downloads are FREE. Search and download functionalities are using the official Maven repository.

resource.AbstractManagedResource.scala Maven / Gradle / Ivy

The newest version!
// -----------------------------------------------------------------------------
//
//  scala.arm - The Scala Incubator Project
//  Copyright (c) 2009 The Scala Incubator Project. All rights reserved.
//
//  The primary distribution site is http://jsuereth.github.com/scala-arm
//
//  This software is released under the terms of the Revised BSD License.
//  There is NO WARRANTY.  See the file LICENSE for the full text.
//
// -----------------------------------------------------------------------------


package resource

import _root_.scala.collection.Seq
import _root_.scala.util.control.Exception


/**
 * An implementation of an ExtractableManagedResource that defers all processing until the user pulls out information using
 * either or opt functions.
 */
private[resource] class DeferredExtractableManagedResource[+A,R](val resource : ManagedResource[R], val translate : R => A) extends 
  ExtractableManagedResource[A] with ManagedResourceOperations[A] { self =>

  override def acquireFor[B](f : A => B) : Either[List[Throwable], B] = resource acquireFor translate.andThen(f)

  override def either = resource acquireFor translate

  override def opt = either.right.toOption

  override def equals(that : Any) = that match {
    case x : DeferredExtractableManagedResource[A,R] => (x.resource == resource) && (x.translate == translate)
    case _ => false
  }
  override def hashCode() : Int = (resource.hashCode << 7) + translate.hashCode + 13

  override def toString = "DeferredExtractableManagedResource(" + resource + ", " + translate + ")"
}


/**
 * Abstract class implementing most of the managed resource features in terms of an open and close method.   This
 * is a refinement over ManagedResourceOperations as it defines the acquireForMethod generically using the
 * scala.util.control.Exception API.
 */
trait AbstractManagedResource[R] extends ManagedResource[R] with ManagedResourceOperations[R] {

  /** 
   * Opens a given resource, returning a handle to execute against during the "session" of the resource being open.
   */
  protected def open : R

  /**
   * Closes a resource using the handle.  This method will throw any exceptions normally occuring during the close of
   * a resource.
   */
  protected def unsafeClose(handle : R, errors: Option[Throwable]) : Unit

  /**
   * The list of exceptions that get caught during ARM and will always be rethrown (considered 'fatal')
   */
  protected def rethrownExceptions : Seq[Class[_]] = List(classOf[java.lang.RuntimeException],
                                                          classOf[java.lang.VirtualMachineError],
                                                          classOf[java.lang.InterruptedException],
                                                          classOf[scala.util.control.ControlThrowable])
  /** Throws an exception if it is in the rethrow list. */
  private def rethrowIfBad(t: Throwable)  : Throwable =
    if (rethrownExceptions.exists(_.isInstance(t))) {
      throw t
    } else t

  override def acquireFor[B](f : R => B) : Either[List[Throwable], B] = {
    import Exception._
    val handle = open
    val result  = catchingPromiscuously(classOf[java.lang.Throwable]) either (f(handle))
    val close = catchingPromiscuously(classOf[java.lang.Throwable]) either unsafeClose(handle, result.left.toOption)
    // Combine resulting exceptions as necessary.   Finally, throw any exceptions
    // That we can't hold onto (like ControlThrowable).
    result.left.map[List[Throwable]]( _ :: close.left.toOption.toList).left.map {
      exceptions => exceptions.map(rethrowIfBad)
    }
  }
}

/**
 * This is the default implementation of a ManagedResource that makes use of the Resource type trait.
 */
final class DefaultManagedResource[R : Resource : Manifest](r : => R) extends AbstractManagedResource[R] { self =>
  /** Stable reference to the Resource type trait.*/
  protected val typeTrait = implicitly[Resource[R]]
  /**
   * Opens a given resource, returning a handle to execute against during the "session" of the resource being open.
   */
  override protected def open: R = {
    val resource = r
    typeTrait.open(resource)
    resource
  }

  /**
   * Closes a resource using the handle.  This method will throw any exceptions normally occurring during the close of
   * a resource.
   */
  override protected def unsafeClose(r: R, error: Option[Throwable]): Unit = error match {
    case None    => typeTrait.close(r)
    case Some(t) => typeTrait.closeAfterException(r, t)
  }

  /**
   * The list of exceptions that get caught during ARM and will not prevent a call to close.
   */
  override protected def rethrownExceptions: Seq[Class[_]] = typeTrait.fatalExceptions
  /* You cannot serialize resource and send them, so referential equality should be sufficient. */
  /** Add the type trait to help disperse resources */
  override def hashCode(): Int = (typeTrait.hashCode << 7) + super.hashCode + 13
  // That's right, we use manifest solely for nicer toStrings!
  override def toString = "Default[" + implicitly[Manifest[R]] + " : " + typeTrait + "](...)"
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy