-
Notifications
You must be signed in to change notification settings - Fork 236
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'bugfix/spine-from-jar'
- Loading branch information
Showing
4 changed files
with
107 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
92 changes: 92 additions & 0 deletions
92
...ericSoftwareSpine/src/main/kotlin/com/rhubarb_lip_sync/rhubarb_for_spine/classLocation.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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") | ||
} |