Skip to content

Commit

Permalink
Merge branch 'bugfix/spine-from-jar'
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielSWolf committed Mar 29, 2018
2 parents 5169e3e + e4a6615 commit a3a64d8
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 9 deletions.
6 changes: 6 additions & 0 deletions VERSION.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Version history

## Unreleased

* Fixed [issue #34](https://github.com/DanielSWolf/rhubarb-lip-sync/issues/34): Generic error message in Rhubarb for Spine
* More helpful error dialogs for internal errors in Rhubarb Lip Sync for Spine
* Internal errors in Rhubarb Lip Sync for Spine are logged to stderr

## Version 1.7.0

* Integration with Spine animation software
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,16 @@ class AudioFileModel(
}
} catch (e: InterruptedException) {
} catch (e: Exception) {
e.printStackTrace(System.err);

Platform.runLater {
Alert(Alert.AlertType.ERROR).apply {
headerText = "Error performing lip sync for event '$eventName'."
contentText = e.message
contentText = if (e.message.isNullOrEmpty())
// Some exceptions don't have a message
"An internal error of type ${e.javaClass.name} occurred."
else
e.message
show()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import java.io.*
import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.time.Duration
import java.util.concurrent.Callable

class RhubarbTask(
Expand Down Expand Up @@ -106,12 +104,8 @@ class RhubarbTask(
}

private val guiBinDirectory: Path by lazy {
var path: String = ClassLoader.getSystemClassLoader().getResource(".")!!.path
if (path.length >= 3 && path[2] == ':') {
// Workaround for https://stackoverflow.com/questions/9834776/java-nio-file-path-issue
path = path.substring(1)
}
return@lazy Paths.get(path)
val path = urlToPath(getLocation(RhubarbTask::class.java))
return@lazy if (Files.isDirectory(path)) path.parent else path
}

private val rhubarbBinFilePath: Path by lazy {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package com.rhubarb_lip_sync.rhubarb_for_spine

import java.io.FileInputStream
import java.net.MalformedURLException
import java.net.URISyntaxException
import java.net.URL
import org.apache.commons.lang3.SystemUtils.IS_OS_WINDOWS
import java.nio.file.Path
import java.nio.file.Paths

// The following code is adapted from https://stackoverflow.com/a/12733172/52041

/**
* Gets the base location of the given class.
*
* If the class is directly on the file system (e.g.,
* "/path/to/my/package/MyClass.class") then it will return the base directory
* (e.g., "file:/path/to").
*
* If the class is within a JAR file (e.g.,
* "/path/to/my-jar.jar!/my/package/MyClass.class") then it will return the
* path to the JAR (e.g., "file:/path/to/my-jar.jar").
*
* @param c The class whose location is desired.
*/
fun getLocation(c: Class<*>): URL {
// Try the easy way first
try {
val codeSourceLocation = c.protectionDomain.codeSource.location
if (codeSourceLocation != null) return codeSourceLocation
} catch (e: SecurityException) {
// Cannot access protection domain
} catch (e: NullPointerException) {
// Protection domain or code source is null
}

// The easy way failed, so we try the hard way. We ask for the class
// itself as a resource, then strip the class's path from the URL string,
// leaving the base path.

// Get the class's raw resource path
val classResource = c.getResource(c.simpleName + ".class")
?: throw Exception("Cannot find class resource.")

val url = classResource.toString()
val suffix = c.canonicalName.replace('.', '/') + ".class"
if (!url.endsWith(suffix)) throw Exception("Malformed URL.")

// strip the class's path from the URL string
val base = url.substring(0, url.length - suffix.length)

var path = base

// remove the "jar:" prefix and "!/" suffix, if present
if (path.startsWith("jar:")) path = path.substring(4, path.length - 2)

return URL(path)
}

/**
* Converts the given URL to its corresponding [Path].
*
* @param url The URL to convert.
* @return A file path suitable for use with e.g. [FileInputStream]
*/
fun urlToPath(url: URL): Path {
var pathString = url.toString()

if (pathString.startsWith("jar:")) {
// Remove "jar:" prefix and "!/" suffix
val index = pathString.indexOf("!/")
pathString = pathString.substring(4, index)
}

try {
if (IS_OS_WINDOWS && pathString.matches("file:[A-Za-z]:.*".toRegex())) {
pathString = "file:/" + pathString.substring(5)
}
return Paths.get(URL(pathString).toURI())
} catch (e: MalformedURLException) {
// URL is not completely well-formed.
} catch (e: URISyntaxException) {
// URL is not completely well-formed.
}

if (pathString.startsWith("file:")) {
// Pass through the URL as-is, minus "file:" prefix
pathString = pathString.substring(5)
return Paths.get(pathString)
}
throw IllegalArgumentException("Invalid URL: $url")
}

0 comments on commit a3a64d8

Please sign in to comment.