2011-08-24 57 views
1

我正在使用jdbc連接到Oracle 10g數據庫。在Eclipse/Java中構建連接可以正常工作。然而,當我的代碼移動到一個Lotus 8.5.2劑我結束了以下錯誤(S):JDBC Lotus-Oracle錯誤:Java.lang.ArrayIndexOutOfBoundsException:數組索引超出範圍:-1

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在eclipse - 在Eclipse中使用 不同的JDBC罐子 - 用不同的方式來構建在Lotus 連接 - 蓮花使用不同的JDBC瓶瓶

最後我移動了ojdbc14.jar文件Lotus \ Notes \ jvm \ lib \ ext目錄,現在它工作正常。 這個解決方案可以工作,但顯然我更喜歡將這個jar和nsf一起發佈。我能做到這一點嗎?

leyrer所示。我嘗試添加以下行到「/jvm/lib/security/java.policy」文件

permission java.security.AllPermission; 

這並不在相同的錯誤消息的結果。 現在我會堅持把ojdbc5.jar放在/ ext目錄下。

+0

只是我的好奇心JDBC驅動程序使用的是這對LotusNotes,LotusDomino,因爲我知道, IBM長時間不支持用於LotusFamily的JDBC驅動程序 – mKorbel

+0

ojdbc14.jar類與Oracle站點中的JDK 1.4和1.5一起使用。我也嘗試了ojdbc5.jar。 –

+0

成像,不知道是否代理支持來自外部的JDBC,從Domino方面你可以做到這一點,有趣的我會標記爲通知 – mKorbel

回答

1

我猜測,JVM的安全管理器不允許訪問網絡,因爲安全策略沒有指定允許這個動作。 請參閱Flying Saucer in Lotus Notes瞭解更多詳情。

+0

堆棧跟蹤引起了我的錯誤。將jar放在ext目錄中證明這與安全性有關。我已在其他帖子中閱讀您的評論。但是添加「權限java.security.AllPermission;」到政策文件沒有幫助。 –

+0

對不起,延遲迴復。也許連接字符串是錯誤的? http://stackoverflow.com/questions/3573861/problem-in-connecting-oracle-11g-through-jdbc-thin-driver-domino-java – leyrer

2

如果您使用解包的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> 
0

很久以前,這個問題就出現了...但我不得不在本月爲客戶發現它。我找不到解決辦法,但有一些虛假的假設和不完整的分析。因此,對於所有人來說,我會分享我的發現,問題的根源以及解決問題的機會。我使用驅動程序的版本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(String name),並且導致始終將null返回給調用方法。由於orcale jdbc驅動程序需要jar中的oracle.sql.converter_xcharset文件夾中的glb文件才能正常工作,並且它們由上面提到的getRousource方法加載,所以這不起作用!結果是ArrayIndexOutOfBoundsException。

所以,唯一的解決方案是要麼使用從文件系統驅動程序(並使用JVM默認的類加載器),或者修改類加載過程如下:

  1. 創建自定義的類裝載器: 公共類CustomLoader延伸類加載器{

    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. 在多米諾劑,發生任何其它操作之前,用反射

    改變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";