Как обмануть на Java API-интерфейс поставщика услуг (как jaxp)


У меня есть апплет, который должен вызвать JAXP, в частностиSAXParserFactory . Теперь, как вы можете видеть из Javadoc, это внутренне использует механизм поставщика услуг, как описано здесь:

В частности, если он не найдет файл ни в одной из моих банок приложений с именем META-INF/services/javax.xml.parsers.SAXParserFactory, он попытается извлечь его из моей кодовой базы приложения. Если мой апплет развернут следующим образом:

<applet code="com.example.applets.MyApplet" 
 codebase="http://www.example.com/myapp/" archive="myapp.jar, dom4j.jar">

Затем он попытается сделать HTTP-запрос к http://www.example.com/myapp/META-INF/services/javax.xml.parsers.SAXParserFactory

Я бы предпочел этого не делать, особенно потому, что мой апплет подписан, и этот дополнительный вызов HTTP вызывает предупреждение о неподписанном коде.

Теперь очевидное решение - просто поместить файл META-INF / services в мой JAR-файл приложения, как он говорит, но как это сделать, чтобы он все еще использовал пользовательскую реализацию JRE по умолчанию JAXP? С другой стороны, есть ли способ, чтобы убедить среду выполнения апплета искать только в моих файлах JAR, а не в codebase для этого файла?

Примечание: Я знаю, что могу также развернуть свою собственную копию JAXP-RI, но это довольно тяжелый вес для апплета.
1 4

1 ответ:

Отключите поиск по кодовой базе:

<applet ...>
 <param name="codebase_lookup" value="false">
</applet>

AppletClassLoader проверяет наличие булева свойства sun.applet.AppletClassLoader.codebaseLookup, на которое можно повлиять, задав указанный выше параметр. Метод sun.applet.AppletPanel.init() прочитает параметр и установит его в AppletClassLoader. После отключения AppletClassLoader перестанет выполнять удаленный поиск классов и ресурсов в кодовой базе, то есть URL, заданный codebase="http://www.example.com/myapp/", и будет искать только в архивах и системных путях к классам.

Примечание: Я не проверял это сам, но в соответствии с обзором кода в разобранном коде я искренне верю, что это может сработать.

Это также описано в JavaSE-технические заметки-руководство разработчика плагинов-специальные атрибуты :

Codebase_lookup

Когда апплету classloader нужно загрузить класс или ресурс (например, конфигурационные файлы для подключаемых поставщиков услуг в каталоге META-INF/services), он сначала ищет необходимые файлы в файлах JAR апплета, а затем из кодовая база апплета. Обычно апплеты развертываются со всеми необходимыми классами и ресурсами, хранящимися в файлах JAR апплетов. В этом случае поиск по кодовой базе не требуется.

Если класс или ресурс недоступны из файлов JAR апплета, возможно, будет лучше, если загрузчик классов завершится ошибкой, а не попытается выполнить поиск по кодовой базе. В противном случае необходимо установить соединение с кодовой базой апплета для поиска класса или ресурса, и это может повлиять на производительность апплета время выполнения