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

com.rojoma.simplearm.Resource.scala Maven / Gradle / Ivy

The newest version!
package com.rojoma
package simplearm

// Most of this file is copied verbatim from jsuereth's scala-arm

import java.io.Closeable

trait Resource[A] {
  def open(a: A) {}
  def close(a: A)
  def closeAbnormally(a: A, cause: Throwable) { close(a) }
  // On java pre-7, this throws the secondary exception; on java post-7,
  // it adds the secondary to the primary's list of suppressed exceptions.
  def handleSecondaryException(primary: Throwable, secondary: Exception) =
    SecondaryExceptionHandler.defaultHandler(primary, secondary)
}

object SecondaryExceptionHandler {
  val defaultHandler: (Throwable, Exception) => Nothing =
    try {
      Class.forName("com.rojoma.simplearm.Suppresser").newInstance().asInstanceOf[(Throwable, Exception) => Nothing]
    } catch {
      case _: ClassNotFoundException =>
        new SecondaryThrower
    }
}

class SecondaryThrower extends ((Throwable, Exception) => Nothing) {
  def apply(primary: Throwable, secondary: Exception) = throw secondary
}

class Suppresser extends ((Throwable, Exception) => Nothing) {
  def apply(primary: Throwable, secondary: Exception) = {
    primary.addSuppressed(secondary)
    throw primary
  }
}

sealed trait LowPriorityResourceImplicits {
  /** Structural type for disposable resources */
  type ReflectiveCloseable = { def close() }

  /**
   * This is the type class implementation for reflectively assuming a class with a close method is
   * a resource.
   */
  implicit def reflectiveCloseableResource[A <: ReflectiveCloseable] = new Resource[A] {
    def close(r: A) = r.close()
    override def toString = "Resource[{ def close() : Unit }]"
  }

  /** Structural type for disposable resources */
  type ReflectiveDisposable = { def dispose() }

  /**
   * This is the type class implementation for reflectively assuming a class with a dispose method is
   * a resource.
   */
  implicit def reflectiveDisposableResource[A <: ReflectiveDisposable] = new Resource[A] {
    def close(r: A) = r.dispose()
    override def toString = "Resource[{ def dispose() : Unit }]"
  }
}

sealed trait SecondarilyMediumPriorityResourceImplicits extends LowPriorityResourceImplicits {
  implicit def autoCloseableResource[A <: AutoCloseable] = new Resource[A] {
    def close(r: A) = r.close()
    override def toString = "Resource[java.lang.AutoCloseable]"
  }
}

sealed trait MediumPriorityResourceImplicits extends SecondarilyMediumPriorityResourceImplicits {
  implicit def closeableResource[A <: Closeable] = new Resource[A] {
    def close(r: A) = r.close()
    override def toString = "Resource[java.io.Closeable]"
  }
  
  //Add All JDBC related handlers.
  implicit def connectionResource[A <: java.sql.Connection] = new Resource[A] {
    def close(r: A) = r.close()
    override def toString = "Resource[java.sql.Connection]"
  }

  // This will work for Statements, PreparedStatements and CallableStatements.
  implicit def statementResource[A <: java.sql.Statement] = new Resource[A] {
    def close(r: A) = r.close()
    override def toString = "Resource[java.sql.Statement]"
  }

  // Also handles RowSet
  implicit def resultSetResource[A <: java.sql.ResultSet] = new Resource[A] {
    def close(r: A) = r.close()
    override def toString = "Resource[java.sql.ResultSet]"
  }

  implicit def pooledConnectionResource[A <: javax.sql.PooledConnection] = new Resource[A] {
    def close(r: A) = r.close()
    override def toString = "Resource[javax.sql.PooledConnection]"
  }
}

/**
 * Companion object to the Resource type trait. This contains all the default implicits in appropriate priority order.
 */
object Resource extends MediumPriorityResourceImplicits




© 2015 - 2025 Weber Informatics LLC | Privacy Policy