Skip to content

Commit e2ebf59

Browse files
committed
add withResources pattern
1 parent 9f7dcfa commit e2ebf59

File tree

5 files changed

+60
-18
lines changed

5 files changed

+60
-18
lines changed

build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ ThisBuild / organization := "app.softnetwork"
3030

3131
name := "generic-persistence-api"
3232

33-
ThisBuild / version := "0.3.5.1"
33+
ThisBuild / version := "0.3.5.2"
3434

3535
ThisBuild / scalaVersion := "2.12.11"
3636

common/src/main/scala/app/softnetwork/io/package.scala

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,36 @@ package app.softnetwork
33
import java.io.InputStream
44
import scala.io.Source
55
import scala.language.implicitConversions
6+
import scala.util.control.NonFatal
67

78
package object io {
89
implicit def inputStreamToString(is: InputStream): String = Source.fromInputStream(is).mkString
10+
11+
def withResources[T <: AutoCloseable, V](r: => T)(f: T => V): V = {
12+
val resource: T = r
13+
require(resource != null, "resource is null")
14+
var exception: Throwable = null
15+
try {
16+
f(resource)
17+
} catch {
18+
case NonFatal(e) =>
19+
exception = e
20+
throw e
21+
} finally {
22+
closeAndAddSuppressed(exception, resource)
23+
}
24+
}
25+
26+
private def closeAndAddSuppressed(e: Throwable, resource: AutoCloseable): Unit = {
27+
if (e != null) {
28+
try {
29+
resource.close()
30+
} catch {
31+
case NonFatal(suppressed) =>
32+
e.addSuppressed(suppressed)
33+
}
34+
} else {
35+
resource.close()
36+
}
37+
}
938
}

common/src/main/scala/app/softnetwork/utils/Base64Tools.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ object Base64Tools {
1313
def encodeBase64(bytes: Array[Byte], mimeType: Option[String] = None): String = {
1414
val encoded = Base64.encodeBase64String(bytes)
1515
mimeType match {
16-
case Some(_) => s"data:$mimeType;base64,$encoded"
17-
case _ => encoded
16+
case Some(value) => s"data:$value;base64,$encoded"
17+
case _ => encoded
1818
}
1919
}
2020

common/src/main/scala/app/softnetwork/utils/ImageTools.scala

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package app.softnetwork.utils
22

3+
import app.softnetwork.io.withResources
34
import com.typesafe.scalalogging.StrictLogging
45

56
import java.awt.Color
@@ -43,19 +44,18 @@ object ImageTools extends StrictLogging {
4344
def encodeImageBase64(path: Path, encodeAsURI: Boolean = false): Option[String] = {
4445
if (Option(path).isDefined) {
4546
import Base64Tools._
46-
val bos = new ByteArrayOutputStream()
4747
Try {
4848
val mimeType = detectMimeType(path)
4949
val format = toFormat(mimeType)
50-
ImageIO.write(ImageIO.read(Files.newInputStream(path)), format.getOrElse("jpeg"), bos)
51-
val encoded = encodeBase64(bos.toByteArray, if (encodeAsURI) mimeType else None)
52-
bos.close()
53-
encoded
50+
withResources(new ByteArrayOutputStream()) { bos =>
51+
withResources(Files.newInputStream(path)) { inputStream =>
52+
ImageIO.write(ImageIO.read(inputStream), format.getOrElse("jpeg"), bos)
53+
encodeBase64(bos.toByteArray, if (encodeAsURI) mimeType else None)
54+
}
55+
}
5456
} match {
5557
case Success(s) => Some(s)
56-
case Failure(_) =>
57-
bos.close()
58-
None
58+
case Failure(_) => None
5959
}
6060
} else {
6161
None
@@ -79,9 +79,11 @@ object ImageTools extends StrictLogging {
7979
|${sizes.map(s => s"${s.width}x${s.height}").mkString(",")}""".stripMargin
8080
)
8181
Try(
82-
Option(
83-
ImageIO.read(Files.newInputStream(originalPath))
84-
)
82+
withResources(Files.newInputStream(originalPath)) { inputStream =>
83+
Option(
84+
ImageIO.read(inputStream)
85+
)
86+
}
8587
) match {
8688
case Success(value) =>
8789
value match {
@@ -140,9 +142,11 @@ object ImageTools extends StrictLogging {
140142
!Files.exists(out) || originalPath.toFile.lastModified() > out.toFile.lastModified()
141143
) {
142144
Try(
143-
Option(
144-
ImageIO.read(Files.newInputStream(originalPath))
145-
)
145+
withResources(Files.newInputStream(originalPath)) { inputStream =>
146+
Option(
147+
ImageIO.read(inputStream)
148+
)
149+
}
146150
) match {
147151
case Success(value) =>
148152
value match {
@@ -203,7 +207,11 @@ object ImageTools extends StrictLogging {
203207

204208
val dest = Scalr.resize(src, Scalr.Method.ULTRA_QUALITY, imgWidth, imgHeight)
205209
val dest2 = Scalr.move(dest, leftMargin, topMargin, width, height, Color.WHITE)
206-
Try(ImageIO.write(dest2, format, Files.newOutputStream(out))) match {
210+
Try(
211+
withResources(Files.newOutputStream(out)) { outputStream =>
212+
ImageIO.write(dest2, format, outputStream)
213+
}
214+
) match {
207215
case Success(_) =>
208216
case Failure(f) =>
209217
logger.error(

common/src/test/scala/app/softnetwork/utils/ImageToolsSpec.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ class ImageToolsSpec extends AnyWordSpecLike {
1717
"check if it is an image" in {
1818
assert(ImageTools.isAnImage(path))
1919
}
20+
"encode an image as Base64" in {
21+
val encoded = ImageTools.encodeImageBase64(path, encodeAsURI = true)
22+
assert(encoded.nonEmpty)
23+
assert(encoded.exists(_.startsWith("data:image/jpeg;base64,/")))
24+
}
2025
"resize an image" in {
2126
val sizes = Seq(Icon)
2227
assert(ImageTools.generateImages(path, sizes))

0 commit comments

Comments
 (0)