mirror of
https://github.com/corda/corda.git
synced 2025-04-27 06:19:54 +00:00
AttachmentsClassLoader fails when calling setURLStreamHandlerFactory (#4512)
This commit is contained in:
parent
8e61d11a49
commit
2acb3d37cb
@ -19,6 +19,8 @@ import java.io.ByteArrayOutputStream
|
|||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.net.*
|
import java.net.*
|
||||||
|
import java.lang.reflect.AccessibleObject.setAccessible
|
||||||
|
import java.net.URLStreamHandlerFactory
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A custom ClassLoader that knows how to load classes from a set of attachments. The attachments themselves only
|
* A custom ClassLoader that knows how to load classes from a set of attachments. The attachments themselves only
|
||||||
@ -41,10 +43,11 @@ class AttachmentsClassLoader(attachments: List<Attachment>, parent: ClassLoader
|
|||||||
private val log = contextLogger()
|
private val log = contextLogger()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// This is required to register the AttachmentURLStreamHandlerFactory.
|
// Apply our own URLStreamHandlerFactory to resolve attachments
|
||||||
URL.setURLStreamHandlerFactory(AttachmentURLStreamHandlerFactory)
|
setOrDecorateURLStreamHandlerFactory()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Jolokia and Json-simple are dependencies that were bundled by mistake within contract jars.
|
// Jolokia and Json-simple are dependencies that were bundled by mistake within contract jars.
|
||||||
// In the AttachmentsClassLoader we just ignore any class in those 2 packages.
|
// In the AttachmentsClassLoader we just ignore any class in those 2 packages.
|
||||||
private val ignoreDirectories = listOf("org/jolokia/", "org/json/simple/")
|
private val ignoreDirectories = listOf("org/jolokia/", "org/json/simple/")
|
||||||
@ -115,6 +118,50 @@ class AttachmentsClassLoader(attachments: List<Attachment>, parent: ClassLoader
|
|||||||
return it.toByteArray()
|
return it.toByteArray()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply our custom factory either directly, if `URL.setURLStreamHandlerFactory` has not been called yet,
|
||||||
|
* or use a decorator and reflection to bypass the single-call-per-JVM restriction otherwise.
|
||||||
|
*/
|
||||||
|
private fun setOrDecorateURLStreamHandlerFactory() {
|
||||||
|
// Retrieve the `URL.factory` field
|
||||||
|
val factoryField = URL::class.java.getDeclaredField("factory")
|
||||||
|
// Make it accessible
|
||||||
|
factoryField.isAccessible = true
|
||||||
|
|
||||||
|
// Check for preset factory, set directly if missing
|
||||||
|
val existingFactory: URLStreamHandlerFactory? = factoryField.get(null) as URLStreamHandlerFactory?
|
||||||
|
if (existingFactory == null) {
|
||||||
|
URL.setURLStreamHandlerFactory(AttachmentURLStreamHandlerFactory)
|
||||||
|
}
|
||||||
|
// Otherwise, decorate the existing and replace via reflection
|
||||||
|
// as calling `URL.setURLStreamHandlerFactory` again will throw an error
|
||||||
|
else {
|
||||||
|
log.warn("The URLStreamHandlerFactory was already set in the JVM. Please be aware that this is not recommended.")
|
||||||
|
// Retrieve the field "streamHandlerLock" of the class URL that
|
||||||
|
// is the lock used to synchronize access to the protocol handlers
|
||||||
|
val lockField = URL::class.java.getDeclaredField("streamHandlerLock")
|
||||||
|
// It is a private field so we need to make it accessible
|
||||||
|
// Note: this will only work as-is in JDK8.
|
||||||
|
lockField.isAccessible = true
|
||||||
|
// Use the same lock to reset the factory
|
||||||
|
synchronized(lockField.get(null)) {
|
||||||
|
// Reset the value to prevent Error due to a factory already defined
|
||||||
|
factoryField.set(null, null)
|
||||||
|
// Set our custom factory and wrap the current one into it
|
||||||
|
URL.setURLStreamHandlerFactory(
|
||||||
|
// Set the factory to a decorator
|
||||||
|
object : URLStreamHandlerFactory {
|
||||||
|
// route between our own and the pre-existing factory
|
||||||
|
override fun createURLStreamHandler(protocol: String): URLStreamHandler? {
|
||||||
|
return AttachmentURLStreamHandlerFactory.createURLStreamHandler(protocol)
|
||||||
|
?: existingFactory.createURLStreamHandler(protocol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -200,3 +247,4 @@ object AttachmentURLStreamHandlerFactory : URLStreamHandlerFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user