Давным-давно эта проблема возникла ... Но мне пришлось открыть ее для клиента в этом месяце.И нигде я не нашел решения, кроме некоторых ложных притворств и неполных анализов.Поэтому, и для всех вас, сталкивающихся с этим, я поделюсь своими выводами, коренной причиной проблемы и вашими возможностями ее решить.Я проверил это с версией 11.2.0.4 драйвера (ojdbc6.jar).Кроме того, если ваша база данных использует кодировку UTF-8, она работает только с настройками java.policy.В моем случае это была база данных с кодировкой windows 1252.
Прежде всего, драйвер oracle jdbc нуждается в некоторых настройках безопасности ... лучше установить их явно, а не permission java.security.AllPermission;
.Используйте эти разрешения, взятые со страницы загрузки драйвера ocacle jdbc (файл ojdbc.policy):
permission java.util.PropertyPermission "user.name", "read";
permission java.util.PropertyPermission "oracle.jdbc.*", "read";
permission java.util.PropertyPermission "oracle.net.wallet_location", "read";
permission java.util.PropertyPermission "oracle.net.tns_admin", "read";
permission javax.management.MBeanServerPermission "createMBeanServer";
permission javax.management.MBeanPermission "oracle.jdbc.driver.OracleDiagnosabilityMBean#[com.oracle.jdbc:type=diagnosability,*]", "registerMBean";
permission javax.management.MBeanTrustPermission "register";
После установки этих параметров вы столкнетесь с проблемой Java.lang.ArrayIndexOutOfBoundsException: Array index out of range: -1
.Основной причиной этого является то, что загрузчик классов агентов java (lotus.domino.AgentLoader) не реализует getResource (имя строки), и это приводит к тому, что всегда вызывается null
вызывающему методу.Так как драйверу orcale jdbc нужны файлы glb из папки oracle.sql.converter_xcharset
в jar-файле для правильной работы, и они были загружены с помощью метода getRousource, упомянутого выше, это не будет работать!Результатом является ArrayIndexOutOfBoundsException.
Таким образом, единственными решениями являются либо использование драйвера из файловой системы (и использование загрузчика классов по умолчанию для jvm), либо изменение процесса загрузки класса следующим образом:
создание пользовательского загрузчика классов: открытый класс CustomLoader extends ClassLoader {
private final AgentLoader loader;
public CustomLoader(AgentLoader agentLoader, ClassLoader parent) {
super(parent);
loader = agentLoader;
}
@Override
public URL getResource(String name) {
InputStream is = loader.getResourceAsStream(name);
if (is == null) {
return super.getResource(name);
}
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
return null;
}
try {
URL url = new URL("dominoinmemory", "", -1, name, new DominoInMemoryStreamHandler(name));
System.out.println(url);
return url;
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
}
}
private class DominoInMemoryStreamHandler extends URLStreamHandler {
private String resName;
byte[] content = null;
public DominoInMemoryStreamHandler(String resName) {
this.resName = resName;
}
@Override
protected URLConnection openConnection(final URL u) throws IOException {
if (!u.getProtocol().equals("dominoinmemory"))
throw new IOException("Cannot handle protocol: " + u.getProtocol());
InputStream is = loader.getResourceAsStream(resName);
content = toByteArray(is);
return new URLConnection(u) {
@Override
public int getContentLength() {
if (content != null) {
return content.length;
} else {
return super.getContentLength();
}
}
@Override
public void connect() throws IOException {
if (content != null) {
connected = true;
} else {
throw new IOException("The resource '" + resName + "' was not found");
}
}
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(content);
}
};
}
}
public static byte[] toByteArray(InputStream input) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
long count = 0;
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return output.toByteArray();
}
В агенте domino перед любой другой операцией измените родительский загрузчик классовAgentLoader с отражением
public void NotesMain() {
try {
AgentLoader agentLoader = (AgentLoader) getClass().getClassLoader();
Field f1 = agentLoader.getClass().getSuperclass().getDeclaredField("parent");
f1.setAccessible(true);
ClassLoader parent = (ClassLoader) f1.get(agentLoader);
f1.set(agentLoader, new CustomLoader(agentLoader, parent));
...
Внимание:
- Используйте это на свой страх и риск!
- Этот код требует две дополнительные записив файле политики:
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
permission java.net.NetPermission "specifyStreamHandler";