diff --git a/.jvmopts b/.jvmopts index dc0787730..d2ce8b88e 100644 --- a/.jvmopts +++ b/.jvmopts @@ -1,3 +1 @@ -Xmx12g --XX:+CMSClassUnloadingEnabled --XX:+UseConcMarkSweepGC diff --git a/compile.sbt b/compile.sbt index de5e70e0e..153ca5e1c 100644 --- a/compile.sbt +++ b/compile.sbt @@ -1,4 +1,4 @@ -import org.clulab.sbt.Versioner +//import org.clulab.sbt.Versioner // This setting adversely affects logLevel during tests, so needs counterweight. // ThisBuild / Compile / logLevel := Level.Error @@ -6,7 +6,7 @@ import org.clulab.sbt.Versioner ThisBuild / Compile / scalacOptions ++= Seq("-feature", "-unchecked", "-deprecation") Compile / sourceGenerators += Def.task { import java.io.File - import Versioner._ + //import Versioner._ // These values need to be collected in a task in order have them forwarded to Scala functions. val versioner = Versioner(git.runner.value, git.gitCurrentBranch.value, baseDirectory.value, (Compile / sourceManaged).value) diff --git a/eidoscommon/build.sbt b/eidoscommon/build.sbt index 4bf9a167d..cd29c50e3 100644 --- a/eidoscommon/build.sbt +++ b/eidoscommon/build.sbt @@ -10,8 +10,8 @@ resolvers ++= Seq( libraryDependencies ++= { // Versions were last checked 2021 Mar 12. - val procVer = "8.5.0" - val luceneVer = "6.6.6" + val procVer = "8.5.2-SNAPSHOT" + val luceneVer = "7.5.0" // Match processors! // Run dependencyTree, dependencyList, and dependencyStats on eidos and // see what kinds of duplicates with different version numbers show up. @@ -21,6 +21,7 @@ libraryDependencies ++= { // It is possible then that something using eidoscommons and something using // eidos would get different answers. "org.apache.lucene" % "lucene-analyzers-common" % luceneVer, + "org.apache.lucene" % "lucene-backward-codecs" % luceneVer, "org.apache.lucene" % "lucene-core" % luceneVer, "org.apache.lucene" % "lucene-queries" % luceneVer, "org.apache.lucene" % "lucene-queryparser" % luceneVer, diff --git a/eidoscommon/src/main/scala/org/clulab/wm/eidoscommon/utils/Closer.scala b/eidoscommon/src/main/scala/org/clulab/wm/eidoscommon/utils/Closer.scala index 94dc57942..89c817a41 100644 --- a/eidoscommon/src/main/scala/org/clulab/wm/eidoscommon/utils/Closer.scala +++ b/eidoscommon/src/main/scala/org/clulab/wm/eidoscommon/utils/Closer.scala @@ -1,20 +1,41 @@ package org.clulab.wm.eidoscommon.utils -import scala.language.reflectiveCalls +import scala.io.Source +import scala.language.implicitConversions import scala.util.control.NonFatal object Closer { - protected type Closeable = {def close() : Unit} + trait Releasable[Resource] { + def release(resource: Resource): Unit + } + + object Releasable { + + implicit def releasableAutoCloseable[Resource <: AutoCloseable]: Releasable[Resource] = { + new Releasable[Resource] { + def release(resource: Resource): Unit = resource.close() + } + } - def close[Resource <: Closeable](resource: => Resource): Unit = resource.close() + // In Scala 2.11, Source does not inherit from Closeable, so one has to tell Closer how to close() it. + implicit def releasableSource[Resource <: Source]: Releasable[Resource] = { + new Releasable[Resource] { + def release(resource: Resource): Unit = resource.close() + } + } + } + + def close[Resource: Releasable](resource: => Resource): Unit = + implicitly[Releasable[Resource]].release(resource) // This is so that exceptions caused during close are caught, but don't // prevent the registration of any previous exception. // See also https://medium.com/@dkomanov/scala-try-with-resources-735baad0fd7d. // Others have resource: => Closeable, but I want the resource evaluated beforehand // so that it doesn't throw an exception before there is anything to close. - def autoClose[Resource <: Closeable, Result](resource: Resource)(function: Resource => Result): Result = { + // 3 here is for the number of arguments. Operator overloading doesn't handle it. + protected def autoClose3[Resource, Result](resource: Resource)(closer: () => Unit)(function: Resource => Result): Result = { val (result: Option[Result], exception: Option[Throwable]) = try { (Some(function(resource)), None) @@ -23,9 +44,9 @@ object Closer { case exception: Throwable => (None, Some(exception)) } - val closeException: Option[Throwable] = Option(resource).flatMap { resource => + val closeException: Option[Throwable] = Option(resource).flatMap { _ => try { - resource.close() + closer() None } catch { @@ -54,9 +75,12 @@ object Closer { } } - // Allow for alternative syntax closeable.autoClose { closeable => ... } - implicit class AutoCloser[Resource <: Closer.Closeable](resource: Resource) { + def autoClose[Resource: Releasable, Result](resource: Resource)(function: Resource => Result): Result = + autoClose3(resource)(() => implicitly[Releasable[Resource]].release(resource))(function) + + implicit class AutoCloser[Resource: Releasable](resource: Resource) { - def autoClose[Result](function: Resource => Result): Result = Closer.autoClose(resource)(function) + def autoClose[Result](function: Resource => Result): Result = + Closer.autoClose(resource)(function) } } diff --git a/eidoscommon/src/main/scala/org/clulab/wm/eidoscommon/utils/XsvUtils.scala b/eidoscommon/src/main/scala/org/clulab/wm/eidoscommon/utils/XsvUtils.scala index f3c84929e..7e8c17bbf 100644 --- a/eidoscommon/src/main/scala/org/clulab/wm/eidoscommon/utils/XsvUtils.scala +++ b/eidoscommon/src/main/scala/org/clulab/wm/eidoscommon/utils/XsvUtils.scala @@ -1,6 +1,6 @@ package org.clulab.wm.eidoscommon.utils -import java.io.PrintWriter +import java.io.{Closeable, PrintWriter} class EscapePair(char: Char, escaped: Char) { val unescapedString: String = char.toString @@ -74,7 +74,7 @@ class CsvReader() extends XsvReader(XsvUtils.commaChar) { // TODO It is more complicated because of the multiple lines per string } -abstract class XsvWriter(val printWriter: PrintWriter, separatorChar: Char) { +abstract class XsvWriter(val printWriter: PrintWriter, separatorChar: Char) extends Closeable { protected val separatorString: String = separatorChar.toString def quote(text: String): String = "\"" + text.replace("\"", "\"\"") + "\"" diff --git a/eidoscommon/src/test/scala/org/clulab/wm/eidoscommon/utils/TestAutoClosing.scala b/eidoscommon/src/test/scala/org/clulab/wm/eidoscommon/utils/TestAutoClosing.scala index 37bc26369..578f7f4c9 100644 --- a/eidoscommon/src/test/scala/org/clulab/wm/eidoscommon/utils/TestAutoClosing.scala +++ b/eidoscommon/src/test/scala/org/clulab/wm/eidoscommon/utils/TestAutoClosing.scala @@ -2,9 +2,12 @@ package org.clulab.wm.eidoscommon.utils import org.clulab.wm.eidoscommon.utils.Closer.AutoCloser +import java.io.Closeable +import scala.io.Source + class TestAutoClosing extends Test { - class Closing(exception: Option[Throwable] = None) { + class Closing(exception: Option[Throwable] = None) extends Closeable { var closed: Boolean = false // test def close(): Unit = { @@ -137,4 +140,9 @@ class TestAutoClosing extends Test { } closing.closed should be (false) } + + it should "work with a plain Source, even in Scala 2.11" in { + val source = Source.fromString("foo\nbar\n") + Closer.close(source) + } } diff --git a/eidoscommon/src/test/scala/org/clulab/wm/eidoscommon/utils/TestCloser.scala b/eidoscommon/src/test/scala/org/clulab/wm/eidoscommon/utils/TestCloser.scala index e685926cd..16e46b2e7 100644 --- a/eidoscommon/src/test/scala/org/clulab/wm/eidoscommon/utils/TestCloser.scala +++ b/eidoscommon/src/test/scala/org/clulab/wm/eidoscommon/utils/TestCloser.scala @@ -1,8 +1,14 @@ package org.clulab.wm.eidoscommon.utils + +import org.clulab.utils.Closer.AutoCloser + +import java.io.Closeable +import scala.io.Source + class TestCloser extends Test { - class Closing(exception: Option[Throwable] = None) { + class Closing(exception: Option[Throwable] = None) extends Closeable { var closed: Boolean = false // test def close(): Unit = { @@ -135,4 +141,10 @@ class TestCloser extends Test { } closing.closed should be (false) } + + it should "work with a plain Source, even in Scala 2.11" in { + Source.fromString("foo\nbar\n").autoClose { source => + source.getLines.toList + } + } } diff --git a/project/build.properties b/project/build.properties index 495c3b551..507badd1e 100644 --- a/project/build.properties +++ b/project/build.properties @@ -4,4 +4,4 @@ # Avoid "java.lang.OutOfMemoryError: Required array size too large" of 1.4+. # Versions in the 1.3+ range seem to break the sbt-dependency-graph plugin and ivy-related things. # Processors is at 1.2.8, the highest available 1.2. -sbt.version = 1.4.5 +sbt.version = 1.6.2 diff --git a/src/test/scala/org/clulab/wm/eidos/text/englishGrounding/TestGrounding.scala b/src/test/scala/org/clulab/wm/eidos/text/englishGrounding/TestGrounding.scala index 5020cb2cf..8d4131734 100644 --- a/src/test/scala/org/clulab/wm/eidos/text/englishGrounding/TestGrounding.scala +++ b/src/test/scala/org/clulab/wm/eidos/text/englishGrounding/TestGrounding.scala @@ -9,6 +9,8 @@ import org.clulab.wm.eidos.mentions.EidosMention import org.clulab.wm.eidos.test.EnglishGroundingTest import org.clulab.wm.eidos.test.TestUtils._ +import scala.language.reflectiveCalls + class TestGrounding extends EnglishGroundingTest { // Grounding needs to be activated in englishTest.conf for these tests to be active. // Update: Grounding is now activated in EnglishTests by default. diff --git a/wmexchanger/src/main/scala/org/clulab/wm/wmexchanger/utils/RestExchanger.scala b/wmexchanger/src/main/scala/org/clulab/wm/wmexchanger/utils/RestExchanger.scala index 5d4ac8f26..4c7be5c9c 100644 --- a/wmexchanger/src/main/scala/org/clulab/wm/wmexchanger/utils/RestExchanger.scala +++ b/wmexchanger/src/main/scala/org/clulab/wm/wmexchanger/utils/RestExchanger.scala @@ -8,12 +8,13 @@ import org.apache.http.impl.client.BasicCredentialsProvider import org.apache.http.impl.client.CloseableHttpClient import org.apache.http.impl.client.HttpClientBuilder +import java.io.Closeable import java.net.URL // See https://hc.apache.org/httpcomponents-client-ga/tutorial/html/authentication.html // and https://mkyong.com/java/apache-httpclient-basic-authentication-examples/ // and https://stackoverflow.com/questions/2304663/apache-httpclient-making-multipart-form-post -class RestExchanger(service: String, username: String, password: String) { +class RestExchanger(service: String, username: String, password: String) extends Closeable { protected val url = new URL(service) protected val httpHost: HttpHost = newHttpHost(url)