【问题标题】:Creation of folders in Windows through Java in PLSQL在 PLSQL 中通过 Java 在 Windows 中创建文件夹
【发布时间】:2020-03-13 08:40:18
【问题描述】:

我正在尝试让我的 Oracle 11g 数据库在文件系统级别(Windows 操作系统)创建文件夹。

这是我在架构 ABC_DEF 上执行的代码:

CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED createFolder AS
public class FolderManagement {
   public static java.lang.String createFolder(java.lang.String folderPath) {
       java.lang.String folderCreated = “false”;
       try {
          java.io.File folder = new java.io.File(folderPath);
          if(folder.exists() == true){
             folderCreated = “true”; // folder already exists and is usable
          }
          else {
             folder.mkdirs(); // If the parent folder exists, create all necessary subdirectories
             if(folder.exists() == true){
                 folderCreated = “true”;
             }
          }
       }
       catch(Exception e){
           folderCreated = “false. Error message [” + e.getMessage() + “]”;
       }
       return folderCreated;
   }
};
/

CREATE OR REPLACE FUNCTION createFolder(folderPath IN VARCHAR2) RETURN VARCHAR2 AS LANGUAGE JAVA NAME ‘FolderManagement.createFolder(java.lang.String) return java.lang.String’;
/

然后,我有一个如下的 Oracle 包:

CREATE OR REPLACE PACKAGE ABC_DEF.FILE_UTILITIES AS
    parentFolder CONSTANT VARCHAR2(4000) := ‘H:\Oracle logs’;
    FUNCTION createDirectory(fullPathToFolder IN VARCHAR2) RETURN BOOLEAN;
END;
/

CREATE OR REPLACE PACKAGE BODY ABC_DEF.FILE_UTILITIES AS

    FUNCTION createDirectory(fullPathToFolder IN VARCHAR2) RETURN BOOLEAN IS
    folderCreated BOOLEAN := FALSE;
    returnedValue VARCHAR2(4000);
    BEGIN
       SELECT createFolder(fullPathToFolder)
       INTO returnedValue
       FROM DUAL;
       DBMS_OUTPUT.PUT_LINE(‘Returned value from folder creation is [’ || returnedValue || ‘]’);
       IF UPPER(returnedValue) = ‘TRUE’ THEN
           folderCreated := TRUE;
       END IF;
       RETURN folderCreated;
    EXCEPTION
        WHEN OTHERS THEN
           folderCreated := FALSE;
           RETURN folderCreated;
    END;

END;
/

现在,在我的 SYS(具有 SYSDBA 权限)架构上,我已执行以下命令,该命令应授予 ABC_DEF 架构权限,以在文件夹“H:\”的任何递归级别读取/写入/删除文件和文件夹Oracle 日志”。

BEGIN
  DBMS_JAVA.GRANT_PERMSSION(
     grantee => ‘ABC_DEF’,
     permission_type => ‘SYS:java.io.FilePermission’,
     permission_name => ABC_DEF.FILE_UTILITIES.parentFolder || ‘\-’, —- Should grant recursive permissions to any subfolder and any file located in any subfolder
     permission_action => ‘read,write,delete’
  );
END;
/

回到我的 ABC_DEF 架构,当我尝试执行以下代码时,我从 Java 代码中得到一个异常:

DECLARE
subfolderToCreate VARCHAR2(4000) := ‘\2019\November’;
folderWasCreated BOOLEAN := FALSE;
fullFolderPath VARCHAR2(4000);
BEGIN
   fullFolderPath := FILE_UTILITIES.parentFolder || subfolderToCreate;
   folderWasCreated := FILE_UTILITIES.createDirectory(fullFolderPath);
   IF folderWasCreated = TRUE THEN
     DBMS_OUTPUT.PUT_LINE(‘Folder was created.’);
   ELSE
     DBMS_OUTPUT.PUT_LINE(‘Folder was not created.’);
   END IF;
EXCEPTION
   WHEN OTHERS THEN
     DBMS_OUTPUT.PUT_LINE(‘Folder wasn’’t created. Exception message [’ || SQLERRM || ‘]’);
END;

我收到以下错误:

Permission (java.io.FilePermission H:\Oracle logs\2019\November read) has not been granted to ABC_DEF. The PL/SQL to grant this is dbms_java.grant_permission(‘ABC_DEF’, ‘SYS:java.io.FilePermission’, ‘H:\Oracle logs\2019\November’, ‘read’)

如果我使用父文件夹(文件系统级别已经存在),也会出现同样的错误。

关于为什么以及如何解决它的任何想法?

编辑:根据要求添加信息

查询

SELECT *
FROM DBA_JAVA_POLICY
WHERE GRANTEE = ‘ABC_DEF’AND TYPE_NAME LIKE ‘%File%’;

在 NAME 列下为文件夹“H:\Oracle logs\-”显示一行,对于“读、写、删除”操作启用。

关于 H: 驱动器,它是物理驱动器,而不是网络驱动器。

关于 Windows 级别的文件夹设置,“Oracle 日志”文件夹已经存在于 Windows 级别,访问权限是“所有人”的完全控制。

【问题讨论】:

  • 这里有很多无关的信息。错误消息似乎准确地告诉您需要做什么。问:执行“DBMS_JAVA.GRANT_PERMSSION”后,是否查看过“ABC_DEF”的权限?您是否看到错误消息“已授予”中提到的 EVERY 权限?问:“ABC_DEF”映射到的windows用户呢?问:“H:”是否恰好是网络共享?如果是这样,“ABC_DEF”是否具有 windows 域权限来读取/写入这些目录?
  • 我为您的问题添加了答案。我不同意无关的信息。我添加了有关 java 部分和调用它的存储过程的详细信息,以防我搞砸了该部分。想要彻底。

标签: java function plsql oracle11g directory


【解决方案1】:

我已经解决了,如下图:

  • 我通过以 SYS 身份运行此命令从 Oracle 端删除了权限:

    DECLARE
        permissionNumber NUMBER(35);
    BEGIN
        SELECT SEQ
        INTO permissionNumber
        FROM DBA_JAVA_POLICY
        WHERE TYPE_NAME LIKE ‘%File%’ AND GRANTEE = ‘ABC_DEF’;
        DBMS_JAVA.disable_permission(permissionNumber);
        DBMS_JAVA.delete_permission(permissionNumber);
    END;
    /
    

然后我执行了下面的命令,仍然是 SYS:

BEGIN
   DBMS_JAVA.GRANT_PERMISSION(
      GRANTEE           => ‘ABC_DEF’,
      PERMISSION_TYPE   => ‘java.io.FilePermission’
      PERMISSION_NAME   => ABC_DEF.FILE_UTILITIES.parentFolder || ‘\-’,
      PERMISSION_ACTION => ‘execute’
  );
END;
/

BEGIN
   DBMS_JAVA.GRANT_PERMISSION(
      GRANTEE           => ‘ABC_DEF’,
      PERMISSION_TYPE   => ‘java.io.FilePermission’
      PERMISSION_NAME   => ABC_DEF.FILE_UTILITIES.parentFolder || ‘\-’,
      PERMISSION_ACTION => ‘write’
  );
END;
/

BEGIN
   DBMS_JAVA.GRANT_PERMISSION(
      GRANTEE           => ‘ABC_DEF’,
      PERMISSION_TYPE   => ‘java.io.FilePermission’
      PERMISSION_NAME   => ABC_DEF.FILE_UTILITIES.parentFolder || ‘\-’,
      PERMISSION_ACTION => ‘read’
  );
END;
/

然后,我在 Windows 上的文件系统级别做了同样的事情:从文件夹设置中删除权限并重新添加它们。

最后,我重新运行了出现异常的代码。它成功了。还有一种情况是假阴性,即如果 subFolderToCreate 变量为空,则会引发异常。

我还注意到由于某种原因它没有立即起作用。它需要几分钟才能工作......

【讨论】:

  • 我认为自第一次尝试以来您可能会成功,我尝试立即授予所有权限而不会出现问题,因为要重新登录才能激活授权。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-03
  • 2016-04-06
  • 1970-01-01
  • 1970-01-01
  • 2011-05-05
相关资源
最近更新 更多