-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMainUsing.scala
More file actions
118 lines (93 loc) · 2.61 KB
/
Copy pathMainUsing.scala
File metadata and controls
118 lines (93 loc) · 2.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import java.util.logging.Logger
object arm {
type Resource = AutoCloseable
case class ScopeResource(val x: Resource, val canThrow: Boolean = true, val doLog: Boolean = false)
@annotation.implicitNotFound(msg = "Resource acquisition requires a scope.")
final class Scope {
var resources: List[ScopeResource] = Nil
final def acquire(res: Resource, canThrow:Boolean = true, log:Boolean = false): Unit = {
resources ::= ScopeResource(res,canThrow,log)
}
}
object using {
def apply[T](f: Scope => T): T = {
var innerException : Option[Throwable] = Option.empty
val scope = new Scope
try
return f(scope)
catch {
case e =>
innerException = Some(e)
throw e
}
finally {
scope.resources.foreach { r =>
try {
r.x.close()
}
catch {
case e: Throwable => {
if (r.canThrow) {
if (innerException.isEmpty) innerException = Some(e)
else innerException.get.addSuppressed(e)
}
else {
if( r.doLog ) Logger.getLogger("global").warning(e.getMessage)
}
}
}
}
if (innerException.nonEmpty) throw innerException.get
}
}
}
def acquire[R <: Resource](res: R)(implicit in: Scope): R = {
in.acquire(res)
res
}
implicit class AutoCloseResource[T <: AutoCloseable](val x: T) extends AnyVal {
def autoClose(canThrow:Boolean=true,log:Boolean=false)(implicit in: Scope): T = {
in.acquire(x,canThrow,log)
x
}
def use[R](body: T => R): R = use(canThrow=true,body)
def use[R](canThrow: Boolean = true, body: T => R): R = using { implicit scope =>
autoClose(canThrow = canThrow)
body(x)
}
}
}
import arm._
class TestToClose(val name: String) extends AutoCloseable {
override def close(): Unit = {
println(s"Close $name")
throw new Exception(s"Close Exception $name")
}
def getName() = name
}
object MainUsing extends App {
System.setErr(System.out)
// using - autoClose
try using { implicit scope =>
val t = new TestToClose("test1").autoClose()
val t2 = new TestToClose("test2").autoClose(canThrow = false, log = true)
println(t.name)
}
catch {
case e: Exception =>
e.printStackTrace()
}
// using use - similar to kotlin
try {
new TestToClose("test3").use (canThrow=false, { r =>
println(r.name)
})
new TestToClose("test4").use { r =>
println(r.name)
}
}
catch {
case e: Exception =>
e.printStackTrace()
}
}