JDBC Lotus-Oracle ошибка: Java.lang.ArrayIndexOutOfBoundsException: индекс массива вне диапазона: -1 - PullRequest
1 голос
/ 24 августа 2011

Я использую jdbc для подключения к базе данных Oracle 10g. Построение соединения в Eclipse / Java работает нормально. Однако, когда я перемещаю код в агент Lotus 8.5.2, я получаю следующие ошибки:

Java.lang.ArrayIndexOutOfBoundsException: Array index out of range: -1
 at oracle.jdbc.driver.T4CTTIoauthenticate.setSessionFields(T4CTTIoauthenticate.java:1019)
 at oracle.jdbc.driver.T4CTTIoauthenticate.<init>(T4CTTIoauthenticate.java:186)
 at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:354)
 at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:454)
 at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:165)
 at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:35)
 at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:802)
 at oracle.jdbc.pool.OracleDataSource.getPhysicalConnection(OracleDataSource.java:298)
 at oracle.jdbc.pool.OracleDataSource.getConnection(OracleDataSource.java:222)
 at oracle.jdbc.pool.OracleDataSource.getConnection(OracleDataSource.java:166)
 at JavaAgent.NotesMain(Unknown Source)
 at lotus.domino.AgentBase.runNotes(Unknown Source)
 at lotus.domino.NotesThread.run(Unknown Source)

Это код, используемый для подключения:

Class.forName("oracle.jdbc.OracleDriver");
Connection conn = DriverManager.getConnection(
 "jdbc:oracle:thin:@:xx.xx.xx.xx:1521:xx", "xx", "xx");

Я пытался решить эту проблему по-разному: - используйте Lotus JVM в затмении - использовать разные jdbc банки в eclipse - использовать разные способы построения соединения в Lotus - используйте различные jdbc jars jar в lotus

Наконец-то я переместил в каталог ojdbc14.jar файл Lotus \ Notes \ jvm \ lib \ ext, и теперь он работает нормально. Это решение будет работать, но, очевидно, я предпочитаю распространять этот jar вместе с nsf. Есть ли способ, которым я могу это сделать?

В соответствии с предложением leyrer . Я попытался добавить следующую строку в файл "/jvm/lib/security/java.policy"

permission java.security.AllPermission;

Это приводит к тому же сообщению об ошибке. Сейчас я остановлюсь на размещении ojdbc5.jar в каталоге / ext.

Ответы [ 3 ]

2 голосов
/ 23 февраля 2012

Если вы используете распакованный файл ojdbc jar, убедитесь, что вы не исключаете файлы oracle / sql / converter_xcharset / *. Glb. Я получал ту же ошибку, когда мой исполняемый файл jar был собран с использованием Maven, но не включал эти файлы. Блок ниже явно включает их.

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <executions>
    <execution>
      <id>unpack-dependencies</id>
      <phase>prepare-package</phase>
      <goals>
        <goal>unpack-dependencies</goal>
      </goals>
      <configuration>
        <excludeTypes>pom</excludeTypes>
        <includes>**/*.class,**/*.glb</includes>
        <outputDirectory>${project.build.directory}/classes</outputDirectory>
        <overWriteReleases>false</overWriteReleases>
        <overWriteSnapshots>true</overWriteSnapshots>
      </configuration>
    </execution>
  </executions>
</plugin>
1 голос
/ 25 августа 2011

Я полагаю, что диспетчер безопасности JVM не разрешает доступ к сети, поскольку в политике безопасности не указано, разрешать это действие. Подробнее см. Летающая тарелка в Lotus Notes .

0 голосов
/ 23 октября 2017

Давным-давно эта проблема возникла ... Но мне пришлось открыть ее для клиента в этом месяце.И нигде я не нашел решения, кроме некоторых ложных притворств и неполных анализов.Поэтому, и для всех вас, сталкивающихся с этим, я поделюсь своими выводами, коренной причиной проблемы и вашими возможностями ее решить.Я проверил это с версией 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), либо изменение процесса загрузки класса следующим образом:

  1. создание пользовательского загрузчика классов: открытый класс 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();
    }
    
  2. В агенте 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";
...