Skip to content

Commit 8355734

Browse files
committed
JavaMain: added "application home" import search path detection
1 parent b89bf40 commit 8355734

File tree

1 file changed

+67
-3
lines changed

1 file changed

+67
-3
lines changed

jvm/src/main/scala/io/kaitai/struct/JavaMain.scala

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.kaitai.struct
22

33
import java.io.{File, FileWriter}
4+
import java.net.URLDecoder
45

56
import io.kaitai.struct.CompileLog._
67
import io.kaitai.struct.JavaMain.CLIConfig
@@ -111,14 +112,79 @@ object JavaMain {
111112
parser.parse(args, CLIConfig())
112113
}
113114

115+
/**
116+
* Insanely hacky method that relies on some JVM black magic to get
117+
* application "home". From that, we can check if it has a "formats" subdir,
118+
* and if it does, consider that an additional default ksy imports path.
119+
* @return additional import search path ("default", platform-specific one),
120+
* if it's found
121+
*/
122+
private def homePath: Option[String] = {
123+
// fStr is mysterious and probably unreliable, but that's the best I've
124+
// came up with. It uses java.security API, in which CodeSource is used
125+
// to have indicative "code location", but AFAIK, in Sun/Oracle applications
126+
// it is only used as URL for comparison purposes. It is URL-encoded, so
127+
// we need to decode it as well.
128+
//
129+
// Linux, from IDE:
130+
// $HOME/git/kaitai_struct/compiler/jvm/target/scala-2.11/classes/
131+
//
132+
// Linux, from stage:
133+
// $HOME/git/kaitai_struct/compiler/jvm/target/universal/stage/lib/io.kaitai.kaitai-struct-compiler-0.7-SNAPSHOT.jar
134+
//
135+
// Linux, from "sbt compilerJVM/run"
136+
// $HOME/git/kaitai_struct/compiler/jvm/target/scala-2.11/classes/
137+
//
138+
// Linux, from universal, custom install path:
139+
// /tmp/a%20b/kaitai-struct-compiler-0.7-SNAPSHOT/lib/io.kaitai.kaitai-struct-compiler-0.7-SNAPSHOT.jar
140+
//
141+
// Linux, from Debian install:
142+
// /usr/share/kaitai-struct-compiler/lib/io.kaitai.kaitai-struct-compiler-0.7-SNAPSHOT.jar
143+
//
144+
// Windows, default install path:
145+
// /C:/Program%20Files/kaitai-struct-compiler/lib/io.kaitai.kaitai-struct-compiler-0.7-SNAPSHOT.jar
146+
//
147+
// Windows, custom install path with spaces and non-latin chars:
148+
// /G:/%d0%b3%d0%b4%d0%b5-%d1%82%d0%be%20%d1%82%d0%b0%d0%bc/lib/io.kaitai.kaitai-struct-compiler-0.7-SNAPSHOT.jar
149+
150+
val fStr = classOf[JavaMain].getProtectionDomain.getCodeSource.getLocation.getPath
151+
Log.importOps.info(() => s"home path: location = $fStr")
152+
153+
if (fStr.endsWith(".jar")) {
154+
val fDec = URLDecoder.decode(fStr, "UTF-8")
155+
Log.importOps.info(() => s"... URL-decoded = $fDec")
156+
157+
val homeFile = new File(fDec).getParentFile.getParentFile
158+
Log.importOps.info(() => s"... home = $homeFile")
159+
160+
if (homeFile.exists) {
161+
val homeFormat = new File(homeFile, "formats")
162+
Log.importOps.info(() => s"... formats = $homeFormat")
163+
if (homeFormat.exists) {
164+
Some(homeFormat.toString)
165+
} else {
166+
Log.importOps.info(() => "... home formats dir doesn't exist => fail")
167+
None
168+
}
169+
} else {
170+
Log.importOps.info(() => s"... home doesn't exist => no home import paths")
171+
None
172+
}
173+
} else {
174+
Log.importOps.info(() => s"... not a jar, we're not running a packaged app => no home")
175+
None
176+
}
177+
}
178+
114179
private def envPaths: List[String] =
115180
sys.env.get("KSPATH").toList.flatMap((x) => x.split(File.pathSeparatorChar))
116181

117182
def main(args: Array[String]): Unit = {
118183
parseCommandLine(args) match {
119184
case None => System.exit(1)
120185
case Some(config0) =>
121-
val config = config0.copy(importPaths = config0.importPaths ++ envPaths)
186+
Log.initFromVerboseFlag(config0.verbose)
187+
val config = config0.copy(importPaths = config0.importPaths ++ envPaths ++ homePath)
122188
new JavaMain(config).run()
123189
}
124190
}
@@ -127,8 +193,6 @@ object JavaMain {
127193
class JavaMain(config: CLIConfig) {
128194
import JavaMain._
129195

130-
Log.initFromVerboseFlag(config.verbose)
131-
132196
def run(): Unit = {
133197
val logs: Map[String, InputEntry] = config.srcFiles.map { srcFile =>
134198
val log = if (config.throwExceptions) {

0 commit comments

Comments
 (0)