Project

General

Profile

Feature #3565

provide better support for file system access across platforms

Added by Eric Faulhaber almost 6 years ago. Updated almost 6 years ago.

Status:
WIP
Priority:
High
Target version:
-
Start date:
Due date:
% Done:

0%

billable:
No
vendor_id:
GCD

3556a_rev_11269.diff Magnifier (16.9 KB) Sergey Ivanovskiy, 05/11/2018 09:21 AM

test-file-info.p Magnifier (618 Bytes) Sergey Ivanovskiy, 05/21/2018 06:58 AM

StreamDaemon.diff Magnifier (712 Bytes) Sergey Ivanovskiy, 05/28/2018 05:32 PM


Related issues

Related to Base Language - Bug #4682: modify FILE-INFO processing to honor searches for 4GL programs Closed
Related to Base Language - Feature #3396: shift searchpath and other pathing lists in the directory to use the platform neutral comma WIP

History

#1 Updated by Eric Faulhaber almost 6 years ago

There is an impedance mismatch when a converted application accesses file system resources, if the original system ran on a platform with a different file system.

The main issues between the source and target systems are:

  • mismatch in the file separators used (slash and backslash);
  • mismatch in the case-sensitivity of file system names;
  • absolute paths are prefixed differently and thus paths which were valid for the old system can't work in the converted environment.

The classes responsible for direct file system access by the application on the client are:

  • FileSystemDaemon
  • StreamDaemon

File Separators

Some rationalization of file separators already takes place. But I'm not sure it's fully handled across both of these classes. The level of support needs to be investigated and completed, if it is not fully implemented currently.

We currently have a directory setting for the file system under the file-system node which specifies the case-sensitivity for the original 4GL system: file-separator (\ or /).

Case-Sensitivity

We currently have a directory setting for the file system under the file-system node which specifies the case-sensitivity for the original 4GL system: case-sensitive (true or false).

This seems to be honored by the search/propath APIs, but not for direct file and stream access. The value in the directory needs to be checked when a new client is launched and sent down to the client, so that the client can behave in the same manner as the original platform w.r.t. filename case-sensitivity.

Absolute Path Prefixes

Many applications hard-code absolute paths into the source code or into the database. Those hard-coded into the source code can be found via analytics, but it is a time-consuming process to identify all of them and to replace them with code to conditionally use one path for one OS and another for a different OS. When absolute paths are pulled from the database (or from some other runtime source), a mismatch will cause that file system operation to fail at runtime.

The idea is to map well-known path prefixes (e.g., c:\tmp) to the appropriate replacement for the target platform (e.g., /tmp). These mappings will be maintained in the directory, in a new container node absolute-path-prefix-map, which will be a child of the existing file-system node. The @absolute-path-prefix-map would contain zero or more child nodes like this (for example, to map from a Windows source system to a Linux target system):

<node class="string" name="c:">
  <node-attribute name="value" value="/opt/my_app"/>
</node>
<node class="string" name="c:\tmp">
  <node-attribute name="value" value="/tmp"/>
</node>

The most specific match on the original path should be used to find a mapping. So, given the examples above, the original path c:\tmp\some_file.txt should be translated to /tmp/some_file.txt and NOT to /opt/my_app/tmp/some_file.txt.

Implementation

The separator, case, and absolute path prefix characteristics specific to a client should be looked up in the directory and pushed down to the client when the client is launched. The client will be responsible for applying those settings.

To keep the initial implementation simple, absolute path prefix mappings, case-sensitivity, and file separator settings will only be supported at the server level. If we find in the future we need to implement these at the account level for better granularity, we can do this as a separate task.

For directory lookup helpers, see the findDirectoryNodePath and getDirectoryNode* APIs in com.goldencode.p2j.util.Utils.

For case-insensitive file system helpers, see matchPathCaseInsensitively in the same class. You might need to do some refactoring of this to make it useful for your purposes here.

#2 Updated by Sergey Ivanovskiy almost 6 years ago

Don't know it is reasonable to use 3556a. Although 3556a contains timer changes, r-file search improvements and selection list layout validation changes, planning to work on this task within 3556a. Are there any objections?

#3 Updated by Eric Faulhaber almost 6 years ago

Sergey Ivanovskiy wrote:

Don't know it is reasonable to use 3556a. Although 3556a contains timer changes, r-file search improvements and selection list layout validation changes, planning to work on this task within 3556a. Are there any objections?

Unless there is something in 3556a on top of which you need to build this feature set (possibly the r-file search changes?), I would prefer you get 3556a into testing and start a new branch 3565a for this work.

#4 Updated by Sergey Ivanovskiy almost 6 years ago

OK. The task branch 3565a rev 11253 - created.

#5 Updated by Sergey Ivanovskiy almost 6 years ago

Constantin, in this revision 11269 (branch 3556a) you added similar mapping as described in this task Absolute Task Prefixes. Please could you share your visions here since this change 11269 is not in the trunc now.

#6 Updated by Constantin Asofiei almost 6 years ago

Sergey Ivanovskiy wrote:

Constantin, in this revision 11269 (branch 3556a) you added similar mapping as described in this task Absolute Task Prefixes. Please could you share your visions here since this change 11269 is not in the trunc now.

This is not related to OS-level file lookups - this is related to resolving the target of RUN statement, if this is specified via i.e RUN prog.r and the program exists as prog.p or if specified as RUN obj/prog.p and the program exists as src/prog.p; the mappings are like obj=src, where individual folder names in the path are aliased.

You will need something similar for OS lookup; first, you need to specify in directory.xml some OS-level prefix matches, as Eric mentioned - to map i.e. c:\tmp to /tmp. If you need help to define these in the directory, you can inspire from SourceNameMapper.loadPathAliases and the dir_schema.xml change.

#7 Updated by Sergey Ivanovskiy almost 6 years ago

OK. It seems I considered another tasks. Thanks for explanations. Thus in this task we should add a windows path support to these FileSystemDaemon and StreamDaemon via "legacy" file directory mapping from original OS to host OS, shouldn't?

#8 Updated by Eric Faulhaber almost 6 years ago

Sergey Ivanovskiy wrote:

OK. It seems I considered another tasks. Thanks for explanations. Thus in this task we should add a windows path support to these FileSystemDaemon and StreamDaemon via "legacy" file directory mapping from original OS to host OS, shouldn't?

Yes, this is not about SEARCH, it is about the client opening files and streams for reading and writing. However, if there is something in Constantin's implementation to solve a similar problem for SEARCH that you can use, refactor, or just learn from, it might be helpful to review his solution. Also, it is not just about a "windows path" -- the solution should be generic; the legacy path could be a Windows-style or a Unix-style file system. It is for this reason that the directory nodes defining the configuration are generically named, not named according to platform: file-separator, case-sensitive, absolute-path-prefix-map.

#9 Updated by Sergey Ivanovskiy almost 6 years ago

Let us consider these hypothetical settings

<node class="string" name="c:">
  <node-attribute name="value" value="/opt/my_app"/>
</node>
<node class="string" name="c:\app\environment">
  <node-attribute name="value" value="/opt/my_app/env"/>
</node>
<node class="string" name="c:\tmp">
  <node-attribute name="value" value="/tmp"/>
</node>

What path can be resolved for this file c:\app\doc\help.doc?
The mapped tree has c:\, c:\app\environment and c:\tmp. The most common path with c:\app\doc\help.doc is c:\app, but c:\app is not mapped directly. The closest mapped path is c:\. Thus we can resolve this path as /opt/my_app/app/doc/help.doc. Is it our goal?

#10 Updated by Greg Shah almost 6 years ago

Yes.

The idea is to accept the longest exact match (case-insensitive) to a prefix of a path. That match must only be accepted for "whole segments" of the path:

c:\app\environment will match C:\aPp\enVIRONment\something\file.txt but it WILL NOT match c:\app\environmentS\something\file.txt.

#11 Updated by Sergey Ivanovskiy almost 6 years ago

It seems that with file-separator and case-sensitive under file-system node this task needs native-file-separator and native-case-sensitive. My simple server directory has these settings

 
        <node class="container" name="runtime">
          <node class="container" name="default">
            <node class="container" name="file-system">
              <node class="string" name="pkgroot">
                <node-attribute name="value" value="com.goldencode.testcases"/>
              </node>
              <node class="string" name="propath">
                <node-attribute name="value" value=".:./icons/"/>
              </node>
              <node class="string" name="path-separator">
                <node-attribute name="value" value=":"/>
              </node>
              <node class="string" name="file-separator">
                <node-attribute name="value" value="/"/>
              </node>
              <node class="boolean" name="case-sensitive">
                <node-attribute name="value" value="TRUE"/>
              </node>
            </node>
          </node>
        </node>

These values define native file separator and case insensitive mode, don't they? The host file path separator can be detected at the run-time.

#12 Updated by Sergey Ivanovskiy almost 6 years ago

Please don't mind. These values define the native file separator and the native case sensitive mode.

#13 Updated by Sergey Ivanovskiy almost 6 years ago

Committed revision 11254 (3565a) added PathResolver defined in Utils module.

#14 Updated by Sergey Ivanovskiy almost 6 years ago

It seems that the client gets directory settings via BootstrapConfig. And there are no usages of DirectoryService on the client side. The ClientCore uses a simple version of this service defined by Directory interface via DirectoryManager. The target absolute-path-prefix-map map should be downloaded by the client in order to set up PathResolver for its usages in StreamDaemon and FileSystemDaemon.

#15 Updated by Greg Shah almost 6 years ago

Consider sending absolute-path-prefix-map down to the client in FileSystemOps.ContextContainer.initialValue().

#16 Updated by Sergey Ivanovskiy almost 6 years ago

OK. It is unclear how to support absolute-path-prefix-map if there are Windows and Linux clients simultaneously accessed to the FWD server?

#17 Updated by Greg Shah almost 6 years ago

  • Status changed from New to WIP

1. I think we need to track the original system OPSYS value.

Today we have the capability to override the OPSYS return value in the directory. See EnvironmentOps.getOperatingSystem() where we have this code:

String osname = Utils.getDirectoryNodeString(null, "opsys/override", "");

The idea is that we can hard code the OPSYS value in the directory instead of reporting what the FWD client OS actually is.

This code is probably WRONG. I think we added it for a previous GUI application where we found that it got us past enough of the OPSYS EQ "win32" checks that it seemed to make the application work. But with the recent GUI application, the use of this override is causing us to try to execute WIN32 native API calls and other code paths that are not correct. This is why Eric recently introduced the RT-OPSYS which is always the true OS of the current session's FWD client.

We probably should always report the true FWD client OS as the result of OPSYS. This probably should be fixed in this task.

If we separately track the legacy OPSYS, then we could use that for the purposes of deciding on whether the FWD client needs to be fixed up (with absolute path prefix mapping or case-insensitivity handling...).

2. We probably need to store the legacy file system (and OPSYS) values in a more obvious way.

Today we do not store the legacy OPSYS. We optionally store the legacy file system values using the file-system/ prefix. See usage of file-system/propath, file-system/path-separator, file-system/file-separator and file-system/case-sensitive in EnvironmentOps.

I think these existing values should be placed in a legacy-system/ prefix instead of file-system/ and we should add legacy-system/opsys as a value.

This would also be the location to store the absolute-path-prefix-map mapping data.

3. All of these should be read at the start of the client session and sent down to the client so that the data would be local and all further calculations can be handled on the FWD client side. Broadly speaking, the decision to implement these transformations would be done if the local client OS was different than the legacy client OS. More specifically, we might track the legacy/case-sensitive value and compare that at startup with the actual FWD client file-system case-sensitivity and then set a static flag that tells us if we need to implement case-insensitive path/file matching.

The place to send all of these legacy values down to the client is in FileSystemOps.ContextContainer.initialValue() as noted above.

#18 Updated by Sergey Ivanovskiy almost 6 years ago

My code failed to read file-system node due to it has no read access writes to the target nodes. It seems that the search algorithm looks up only these paths:
/server/standard/ and /server/default but in my directory there exists only this path to file-system /server/standard/runtime/default/file-system. Thus this code is failed to find file-system node

      DirectoryService ds = DirectoryService.getInstance();
      ds.bind();
      String testPath = Utils.findDirectoryNodePath(ds,
               "file-system/file-separator",
               "string",
               false);
      String resolverMapNodePath = Utils.findDirectoryNodePath(ds,
               "file-system/absolute-path-prefix-map",
               "container",
               false);

#19 Updated by Sergey Ivanovskiy almost 6 years ago

Please don't mind. If the scope of search is defined to be accounts search, then similar paths to /server/standard/runtime/default/file-system can be found.

#20 Updated by Sergey Ivanovskiy almost 6 years ago

We can't use : colon character, / slash and \ back slash in node names. It seems that these nodes are invalid

<node class="string" name="c:">
  <node-attribute name="value" value="/opt/my_app"/>
</node>
<node class="string" name="c:\app\environment">
  <node-attribute name="value" value="/opt/my_app/env"/>
</node>

#21 Updated by Greg Shah almost 6 years ago

That is true for the name attribute since it is part of the "path" to the node.

You will need to implement something like what Constantin suggested in #3565-6.

#22 Updated by Sergey Ivanovskiy almost 6 years ago

Planning to use redundant data for the same mapping

<node class="entry" name="entry1">
  <node-attribute name="key" value="c:"/>
  <node-attribute name="value" value="/opt/my_app"/>
</node>
<node class="entry" name="entry2">
  <node-attribute name="key" value="c:\app\environment"/>
  <node-attribute name="value" value="/opt/my_app/env"/>
</node>

Committed revision 11255 added usages of PathResolver. Planning to fix these issues #3565-17, #3565-20 for the review later.

#23 Updated by Sergey Ivanovskiy almost 6 years ago

Greg, if we add legacy-system node, then what is the responsibility file-system node? There are file-system/pkgroot and file-system/4gl-src-root nodes. Do these changes just extend/rename file-system to legacy-system? All related java docs state that these nodes under file-system are legacy system parameters.

#24 Updated by Greg Shah almost 6 years ago

then what is the responsibility file-system node?

It won't exist.

Do these changes just extend/rename file-system to legacy-system?

The idea is to rename file-system to legacy-system.

There are file-system/pkgroot and file-system/4gl-src-root nodes.

These would exist under legacy-system.

#25 Updated by Sergey Ivanovskiy almost 6 years ago

Thank you, see the idea now.

#26 Updated by Sergey Ivanovskiy almost 6 years ago

There is "legacyPlatform"

   public static String getLegacyPlatform()
   {
      WorkArea wa = work.obtain();

      if (wa.legacyPlatform == null)
      {
         String os = getOperatingSystem().toStringMessage();
         wa.legacyPlatform = Utils.getDirectoryNodeString(null, "legacyPlatform", os);
      }

      return wa.legacyPlatform;
   }

It seems that this "legacyPlatform" has similar meaning as new proposed legacy-system/opsys.

#27 Updated by Sergey Ivanovskiy almost 6 years ago

Greg, please help to explain the propath values. Is it correct that if propath lists legacy paths, then it must be mapped to the client host system paths? (legacy-system/propath)

#28 Updated by Greg Shah almost 6 years ago

It seems that this "legacyPlatform" has similar meaning as new proposed legacy-system/opsys.

You are right.

Please shift the usage of legacyPlatform (only in ColorSpec today) to the new legacy-platform/opsys.

#29 Updated by Sergey Ivanovskiy almost 6 years ago

It seems that my changes in file-separator has an impact on the conversion of windows path strings

path = "c:\app\environment\test-path-resolver.txt".

is converted into
path.assign("c:appenvironment\test-path-resolver.txt");

I have no idea what is a root cause.

#30 Updated by Sergey Ivanovskiy almost 6 years ago

I need advices how to convert this program correctly

def var path as char.
path = "c:\app\environment\test-path-resolver.txt".
message path.

#31 Updated by Sergey Ivanovskiy almost 6 years ago

Testing this committed revision 11258. Please look at this revision. The directory changes are

      <node class="container" name="standard">
        <node class="container" name="runtime">
          <node class="container" name="default">
            <node class="container" name="legacy-system">
              <node class="string" name="pkgroot">
                <node-attribute name="value" value="com.goldencode.testcases"/>
              </node>
              <node class="string" name="opsys">
                <node-attribute name="value" value="WIN32"/>
              </node>
              <node class="string" name="propath">
                <node-attribute name="value" value=".;.\icons\"/>
              </node>
              <node class="string" name="path-separator">
                <node-attribute name="value" value=";"/>
              </node>
              <node class="string" name="file-separator">
                <node-attribute name="value" value="\"/>
              </node>
              <node class="boolean" name="case-sensitive">
                <node-attribute name="value" value="FALSE"/>
              </node>
              <node class="container" name="absolute-path-prefix-map">
                <node class="entry" name="entry1">
                  <node-attribute name="key" value="c:"/>
                  <node-attribute name="value" value="/opt/gui"/>
                </node>
                <node class="entry" name="entry2">
                  <node-attribute name="key" value="c:\app\environment"/>
                  <node-attribute name="value" value="/opt/gui/Environments"/>
                </node>
                <node class="entry" name="entry3">
                  <node-attribute name="key" value="c:\tmp"/>
                  <node-attribute name="value" value="/tmp"/>
                </node>
              </node>
            </node>
          </node>
        </node>

#32 Updated by Sergey Ivanovskiy almost 6 years ago

I don't understand why this converted code works with "\\", but doesn't work with "\"

def var path as char.
path = "c:\\app\\environment\\test-path-resolver.txt".
message path.

   output to value(path) page-size 10.

   repeat i = 1 to 1000:
     display "this is a test line" i.
   end.

   output close.

On the native system it works.

#33 Updated by Greg Shah almost 6 years ago

Sergey Ivanovskiy wrote:

Greg, please help to explain the propath values. Is it correct that if propath lists legacy paths, then it must be mapped to the client host system paths? (legacy-system/propath)

The PROPATH is used in 3 ways:

1. We use it on the server-side in SourceNameMapper as a kind of set of relative "virtual file system" paths that can be used to resolve 4GL program names to 4GL source programs that have been converted. In this usage, we already provide the 4gl-src-root value to handle absolute path prefixes. We likewise already handle the case-insensitive searching (if needed) and we canonicalize the paths (everything is shifted to /). I believe that SourceNameMapper needs no changes.

2. We use it on the server-side in LogicalTerminal.getImageStreamFromApplication() and LogicalTerminal.getResourceStreamFromApplication() along with the pkgroot to search in the application jar files for resources like images, icons, mouse pointers and jasper report definitions. It is possible we might need to honor 4gl-src-root here. The absolute-path-prefix-map would be a similar solution but it is not quite right. In SourceNameMapper, any match to a value in the 4gl-src-root list is removed from the search string and then the result is treated as a relative name for the rest of the search. This is the same idea in the LT except we don't honor the 4gl-src-root here yet. We should. But no other changes are needed since it already handles path separators and case-insensitivity.

3. In any usage of FileSystemDaemon.search*() on the client side, we use it for lookup in the actual file system. Some of these use cases are for the converted 4GL SEARCH() built-in function. It is also used during conversion from FileOperationsWorker, from ThinClient.getImageFileName() and from FileSystemDaemon.accessFileInfo() which is for the converted 4GL FILE-INFO system handle support. Some of these use cases are only useful for relative paths BUT others can work with absolute paths. For this reason I think it does make sense to implement the absolute-path-prefix-map mapping here.

Does anyone else have some thoughts or opinions?

#34 Updated by Greg Shah almost 6 years ago

Sergey Ivanovskiy wrote:

I need advices how to convert this program correctly
[...]

There is no file system usage here. This has nothing to do with your changes. It is just displaying a string.

#35 Updated by Greg Shah almost 6 years ago

Sergey Ivanovskiy wrote:

I don't understand why this converted code works with "\\", but doesn't work with "\"
[...]
On the native system it works.

In cfg/p2j.cfg.xml, do you have opsys set to win32 (e.g. <parameter name="opsys" value="win32" />)?

If not, then the conversion will assume that the original system was UNIX and it will treat \ characters as escape chars. That is why doubling them works because it leaves behind a single \ as a result.

#36 Updated by Sergey Ivanovskiy almost 6 years ago

I added this setting <parameter name="opsys" value="win32" />

      <!-- values from the original system on which Progress 4GL ran -->
      <parameter name="path-separator"   value=":" />
      <parameter name="file-separator"   value="/" />
      <parameter name="case-sensitive"   value="true" />
      <parameter name="propath"          value=".:" />
      <parameter name="basepath"         value="." />
      <parameter name="oo-skeleton-path" value="./skeleton/" />
      <parameter name="unix-escapes"     value="false" /> <!-- I changed this value to be false -->
      <parameter name="opsys" value="win32" />

but it seems that "unix-escapes" is more important. With the settings above the string with "\" is converted to java "\\".

#37 Updated by Constantin Asofiei almost 6 years ago

Greg Shah wrote:

3. In any usage of FileSystemDaemon.search*() on the client side, we use it for lookup in the actual file system. Some of these use cases are for the converted 4GL SEARCH() built-in function. It is also used during conversion from FileOperationsWorker, from ThinClient.getImageFileName() and from FileSystemDaemon.accessFileInfo() which is for the converted 4GL FILE-INFO system handle support. Some of these use cases are only useful for relative paths BUT others can work with absolute paths. For this reason I think it does make sense to implement the absolute-path-prefix-map mapping here.

Does anyone else have some thoughts or opinions?

I'll add besside FileSystemDaemon.search all other FileSystemDaemon APIs (rename, delete, mkdirs, etc), and also the FileStream class, which is used (as in note #3565-32) to open a file stream. The idea is: any file access done by FWD at OS-level should be intercepted and the file path be matched/resolved via the absolute-path-prefix-map.

#38 Updated by Sergey Ivanovskiy almost 6 years ago

Please review the committed revision 11264. It should cover all file path usages.

#39 Updated by Sergey Ivanovskiy almost 6 years ago

It seems that OPEN-MIME-RESOURCE and OPEN-URL should resolve the file path if they open the local file. Correct?

path = "c:\app\file.txt".
output to value(path).
...................
output close.
...................
open-mime-resource string("text/plain") string("file:///" + replace(path, "\", "/")) true.
................
os-delete value(path).

can't find this document "file:///" + replace(path, "\", "/"), but the following code works because path is resolved.
path = "c:\app\file.txt".
output to value(path).
...................
output close.
...................
FILE-INFO:FILE-NAME = path.
path = FILE-INFO:FULL-PATHNAME. /* resolved path */
open-mime-resource string("text/plain") string("file:///" + replace(path, "\", "/")) true.

It seems that the usage of open-mime-resource can be improved if we add the 4th optional parameter local and let it be true by default. Then
open-mime-resource mime-type file-path embedded.

can be valid for file-path. And if local is false, then it accepts only url strings as its second parameter
open-mime-resource mime-type url embedded false.

#40 Updated by Constantin Asofiei almost 6 years ago

Sergey, please test folder names with FILE-INFO handle, like FILE-INFO:FILENAME = "." (and other folder names), for both case sensitive and insensitive settings. FWD has problems here.

#41 Updated by Constantin Asofiei almost 6 years ago

At least this patch I think is required:

### Eclipse Workspace Patch 1.0
#P p2j
Index: src/com/goldencode/p2j/util/FileSystemDaemon.java
===================================================================
--- src/com/goldencode/p2j/util/FileSystemDaemon.java    (revision 1566)
+++ src/com/goldencode/p2j/util/FileSystemDaemon.java    (working copy)
@@ -1183,7 +1183,7 @@
                                      File    file,
                                      String  filename)
    {
-      return caseSens ? ((file.exists() && (file.isFile() || allowDir)) ? filename : null) :
+      return (file.exists() && (file.isFile() || allowDir)) ? filename : caseSens ? null :
                         getCaseInsensitiveMatch(file, false);
    }
 }
\ No newline at end of file

Also, note that if the folder is not found and we are in case-insensitive, getCaseInsensitiveMatch(file, false) will never look for a folder, just files (the false argument disables folder lookup) - this needs to be fixed, too.

#42 Updated by Sergey Ivanovskiy almost 6 years ago

Constantin Asofiei wrote:

Sergey, please test folder names with FILE-INFO handle, like FILE-INFO:FILENAME = "." (and other folder names), for both case sensitive and insensitive settings. FWD has problems here.

OK, I will test relative paths. My changes covers only how to resolve absolute paths with help of the given absolute-path-prefix-map. I don't know the exact algorithm that 4GL uses to resolve relative paths.
Constantin, What is the issue? Please write it here or create a new issue.

#43 Updated by Constantin Asofiei almost 6 years ago

Test FILE-INFO:FILENAME and associated attributes like PATHNAME and FULL-PATHNAME, with FWD configured for legacy OS Windows and Linux, with paths like ., relative folders, full folder names. At least this patch for the issue in #3567-53 is needed:

### Eclipse Workspace Patch 1.0
#P p2j
Index: src/com/goldencode/p2j/util/FileSystemDaemon.java
===================================================================
--- src/com/goldencode/p2j/util/FileSystemDaemon.java    (revision 1566)
+++ src/com/goldencode/p2j/util/FileSystemDaemon.java    (working copy)
@@ -48,6 +48,8 @@
 **                           of usage are safe.
 ** 020 EVL 20180205          Fix for Windows Matcher.replaceAll() method issue with file
 **                           separator as input parameter.
+** 021 CA  20180520          Fixed getFileName - if the file/folder exists, use it, regardless of
+**                           case-sensitivity.
 */

 /*
@@ -1183,7 +1185,7 @@
                                      File    file,
                                      String  filename)
    {
-      return caseSens ? ((file.exists() && (file.isFile() || allowDir)) ? filename : null) :
+      return (file.exists() && (file.isFile() || allowDir)) ? filename : caseSens ? null :
                         getCaseInsensitiveMatch(file, false);
    }
 }
\ No newline at end of file

The getCaseInsensitiveMatch(file, false) is incorrect, as for case-insensitive legacy OS, it will never look for folders, only for files.

#44 Updated by Eric Faulhaber almost 6 years ago

Sergey, will your changes handle image loading from the file system as well? I am not that familiar with the UI side of the runtime, but as I recall, that operates through a different API, doesn't it? If so, how much effort will it be to apply the same technique to that API?

#45 Updated by Sergey Ivanovskiy almost 6 years ago

Eric, could you point on the case where the image loading problem appeared? There is LogicalTerminal.getImageStreamFromAplication

   /**
    * Gets the image stream from application jar file or nul if the resource is not found.
    * 
    * @param    imgName
    *           The image name to be loaded on server side.
    *
    * @return   Stream object to load image data or NULL if data is not found.
*/
private static InputStream getImageStreamFromApplication(String imgName)

It seems that its implementation should cover its usages. I need to understand what is incorrect in this implementation. It looks via the converted application jar file.

#46 Updated by Sergey Ivanovskiy almost 6 years ago

Don't mind it is due to java doc doesn't describe that if the target resource is not found in its application jar, then PROPATH must be taken into account

               // not found in root continue with PROPATH entries
               if (isRes == null)
               {
                  for (String header : propathHeader)
                  {
                     // look through PROPATH related locations, clean up possible Windows
                     // separators
                     header = header.replace(WIN_SEP, JAR_SEP);
                     // inside jar we need to use UNIX-style file separator even on Windows
                     String name = getRefinedPathName(
                        pkgRootPath + header + JAR_SEP + imgName, JAR_SEP_STR);
                     // try to search new name based on PROPATH header
                     resName = ServerImageWorker.getResourceName(jcl, name, caseSens);
                     if (resName != null)
                     {
                        isRes = jcl.getResourceAsStream(resName);
                     }
                     // first match is enough to stop searching in PRPPATH
                     if (isRes != null)
                     {
                        break;
                     }
                  }
               }
 

I think it needs to be specified what files must be searched. Are jar files only the place where the target resource is in?

#47 Updated by Sergey Ivanovskiy almost 6 years ago

If we investigate the PROPATH of the converted application, then we can find that all these paths are relative to the current application.
absolute-path-prefix-map considers only absolute paths.

#48 Updated by Sergey Ivanovskiy almost 6 years ago

In this function the target resource is looking through the value of searchpath defined by the directory. This is the place in StandardServer where its value is retrieved

      if (token != null && !token.isEmpty())
      {
         Utils.setProjectToken(token);
         // some settings could have been already set at a previous moment when project_token was
         // not available yet
         EnvironmentOps.setSearchPath(Utils.getDirectoryNodeString(ds, "searchpath", "."), false);
         // TODO: update other settings
      }

#49 Updated by Eric Faulhaber almost 6 years ago

Sergey Ivanovskiy wrote:

Eric, could you point on the case where the image loading problem appeared?

The problem occurs in a customer project. I haven't tracked down the code yet, but it seems to be loading an image from the file system using an absolute path. I'll follow up with more info later today.

#50 Updated by Constantin Asofiei almost 6 years ago

Eric Faulhaber wrote:

Sergey Ivanovskiy wrote:

Eric, could you point on the case where the image loading problem appeared?

The problem occurs in a customer project. I haven't tracked down the code yet, but it seems to be loading an image from the file system using an absolute path. I'll follow up with more info later today.

If you are seeing FILE-INFO:FILENAME then it will not find it without the patch I mentioned.

#51 Updated by Sergey Ivanovskiy almost 6 years ago

Constantin Asofiei wrote:

Test FILE-INFO:FILENAME and associated attributes like PATHNAME and FULL-PATHNAME, with FWD configured for legacy OS Windows and Linux, with paths like ., relative folders, full folder names. At least this patch for the issue in #3567-53 is needed:
[...]

The getCaseInsensitiveMatch(file, false) is incorrect, as for case-insensitive legacy OS, it will never look for folders, only for files.

Yes, you are correct. It seems that this function Utils.matchPathCaseInsensitively should be heavy because it traverses file system roots to find matches.

private static void matchPathCaseInsensitively(File leading, String fullPath, List<File> list)

I used this simple test. Is it correct that 4GL resolves relative paths to the current directory if it can't find them in PROPATH? The dvref.pdf states
The FILE-NAME attribute of the FILE-INFO or RCODE-INFO handle is the name of the
file used by subsequent references to the handle. You can specify the filename with a
.p , .r , or no extension. If you set FILE-NAME to a relative pathname, the AVM
searches the PROPATH to find the file. Otherwise, the AVM looks for the file specified by
the absolute pathname.

#52 Updated by Sergey Ivanovskiy almost 6 years ago

It seems that this implementation of the search FileSystemDaemon.searchAll searches file system roots first and if it is found returns found matches

  public static List<String> searchAll(String[] paths,
                                        boolean  caseSens,
                                        String   filename,
                                        boolean  allowDir)
   {
      // make sure there is something to search for (the code below needs to be protected)
      if (filename == null)
      {
         return null;
      }

      // if the the OS is windows replace all / to \ from the search paths
      String fn = normalizeFileSeparators(filename);

      String result = getAbsoluteOrCurrent(caseSens, fn, allowDir);

      if (result != null)
      {
         List<String> ret = new ArrayList<>(1);
         ret.add(result);
         return ret;
      }

      // not found in root or current, try PROPATH entries
      if (paths == null)
      {
         return null;
      }
.........................
   }

#53 Updated by Sergey Ivanovskiy almost 6 years ago

Eric Faulhaber wrote:

Sergey, will your changes handle image loading from the file system as well? I am not that familiar with the UI side of the runtime, but as I recall, that operates through a different API, doesn't it? If so, how much effort will it be to apply the same technique to that API?

Please review the committed rev 11265-66 that applies legacy absolute path resolver to entries in searchpath in order to resolve absolute path names correctly by LogicalTerminal.getImageStreamFromAplication. To resolve relative path names the fix #3565-43 is given by Constantin in #3567.

#54 Updated by Greg Shah almost 6 years ago

It seems that OPEN-MIME-RESOURCE and OPEN-URL should resolve the file path if they open the local file. Correct?

Yes.

#55 Updated by Greg Shah almost 6 years ago

Code Review Task Branch 3565a Revision 11266

1. Why is this code duplicated in multiple FileSystemDaemon locations?

   int size = paths != null ? paths.length : 0;

   for(int i = 0; i < size; i++)
   {
      paths[i] = getLegacyPathResolver().resolvePath(paths[i]);
   }

If the path array needs fixups, why not do that one time, during setLegacyPathResolver()?

2. Is it really necessary to call getLegacyPathResolver() multiple times in the same method? This seems to add extra cost of creating a new PathResolverContainer instance each time. Is there a functional reason for that?

3. Don't the following FileSystemDaemon methods also need path resolver processing? getCaseInsensitiveMatch(), searchPathWithExts(), searchAll(), search()

4. Constantin's patch from #3565-41 is missing.

5. Shouldn't the client (e.g FileSystemDaemon...) know the legacy OPSYS value (getLegacyPlatform())? It seems like some processing on the client should be done based on this value and how it compares to the actual client operating system. A "mismatch" flag could be calculated once and then checked when needed. I think the current code handles this by passing null for the pathResolver. I would prefer if this "decision" was easier to see in the code. It could be hidden in a helper in Utils. The current approach with the PathResolverContainer seems to add more complication and hide the true nature of the processing.

6. Some of the comments (e.g. Utils) refer to the "native file system". This is confusing as it is not clear that this is the same as the legacy system. If these are meant to be the same thing, please be consistent and use "legacy" instead of "native".

7. Please make the PathResolver and PathResolverImpl into separate classes. I don't see the value in hiding them inside Utils. There is no special data access, data hiding or method usage that makes them a good fit to be inner classes.

#56 Updated by Sergey Ivanovskiy almost 6 years ago

Greg Shah wrote:

Code Review Task Branch 3565a Revision 11266

3. Don't the following FileSystemDaemon methods also need path resolver processing? getCaseInsensitiveMatch(), searchPathWithExts(), searchAll(), search()

I checked these static usages
searchAll is used only

com.goldencode.p2j.pattern.FileOperationsWorker.FileOps.findFiles(String)

and it doesn't need path resolution since it is used by conversion process and propath is used via Configuration read from p2j.cfg.xml.
search is used by
com.goldencode.p2j.pattern.FileOperationsWorker.FileOps.findFile(String)
com.goldencode.p2j.util.FileSystemDaemon.accessFileInfo(String)
com.goldencode.p2j.util.FileSystemDaemon.searchPath(String)

and it seems that com.goldencode.p2j.pattern.FileOperationsWorker.FileOps.findFile(String) doesn't need path resolution for the same reason.
For these instance methods we already apply the legacy path names resolver
com.goldencode.p2j.util.FileSystemDaemon.accessFileInfo(String)
com.goldencode.p2j.util.FileSystemDaemon.searchPath(String)

searchPathWithExts() is used by
com.goldencode.p2j.ui.chui.ThinClient.getImageFileName(String)

and it is really missed. Planning to apply path resolution to this instance method searchPathWithExts()
This static method getCaseInsensitiveMatch() is used by
com.goldencode.p2j.uast.SymbolResolver.exists(File, boolean)
com.goldencode.p2j.util.FileSystemDaemon.getFileName(boolean, boolean, File, String)

It seems that com.goldencode.p2j.uast.SymbolResolver.exists(File, boolean) is broken according to these code comments(?)
   private boolean exists(File file, boolean caseSens)
   {
      // quick out: does the exact match exist?
      if (file.exists())
      {
         return true;
      }

      if (!caseSens)
      {
         // TODO: this is broken!!!!  It was found to fail when the exact case-sensitive match
         //       actually existed (resolved by checking for that first, above).  It is not
         //       known if it fails in other cases too.
         return FileSystemDaemon.getCaseInsensitiveMatch(file, true) != null;
      }

      return false;
   }

Is it really needed to apply path resolution here?
And in this instance method com.goldencode.p2j.util.FileSystemDaemon.getFileName(boolean, boolean, File, String) PathResolver is already applied.

#57 Updated by Sergey Ivanovskiy almost 6 years ago

I searched usages of FileSystemDaemon constructor

com.goldencode.p2j.ui.chui.ThinClient.ThinClient(boolean)
com.goldencode.p2j.ui.client.Editor<O extends OutputManager<?>>.editorReadFile(String)

Is the second usage correct? Why it needs the second instance of FileSystemDaemon.

Greg, could I fix it to

=== modified file 'src/com/goldencode/p2j/ui/client/Editor.java'
--- src/com/goldencode/p2j/ui/client/Editor.java    2017-05-18 15:27:32 +0000
+++ src/com/goldencode/p2j/ui/client/Editor.java    2018-05-21 17:15:53 +0000
@@ -672,7 +672,7 @@
    {
       //todo client-side stream classes should probably be used for read/write of the files 
       //todo (instead of NIO) to ensure that the I18N behavior of the 4GL is honored.
-      FileSystemDaemon fsd  = new FileSystemDaemon(false);
+      FileSystemDaemon fsd  = ThinClient.getInstance().getFileSystemDaemon();
       String fileNameToLoad = fsd.searchPath(name);
       if (fileNameToLoad == null)
       {

#58 Updated by Sergey Ivanovskiy almost 6 years ago

Greg Shah wrote:

Code Review Task Branch 3565a Revision 11266

1. Why is this code duplicated in multiple FileSystemDaemon locations?

[...]

If the path array needs fixups, why not do that one time, during setLegacyPathResolver()?

this.paths field is set from void setSearchPath(String[] paths, boolean caseSens). If we applied path resolution to this field in setLegacyPathResolver(), then we should be sure that setSearchPath is used before setLegacyPathResolver(). Another variant is to unite these two method in one method with this name setLegacySearchPath(....).

#59 Updated by Greg Shah almost 6 years ago

searchAll is used only
search is used only

OK, good analysis. Please add comments to both of these to explain why they don't need the absolute path processing.

This static method getCaseInsensitiveMatch() is used by

com.goldencode.p2j.uast.SymbolResolver.exists(File, boolean)

...
Is it really needed to apply path resolution here?

No. The SymbolResolver is only used for conversion purposes and we don't need the path resolution at that time.

It seems that com.goldencode.p2j.uast.SymbolResolver.exists(File, boolean) is broken according to these code comments(?)

Possibly, but we don't have a recreate. Anyway, it is for conversion so we can ignore it for this task.

Is the second usage correct? Why it needs the second instance of FileSystemDaemon.

I don't know.

Constantin?

#60 Updated by Constantin Asofiei almost 6 years ago

Sergey Ivanovskiy wrote:

I searched usages of FileSystemDaemon constructor
[...]
Is the second usage correct? Why it needs the second instance of FileSystemDaemon.

The second usage is not correct. All client-side Daemon classes should be singletons. Please fix it as you proposed.

#61 Updated by Sergey Ivanovskiy almost 6 years ago

I did a mistake

And in this instance method com.goldencode.p2j.util.FileSystemDaemon.getFileName(boolean, boolean, File, String) PathResolver is already applied.

This is a static method too and PathResolver is not applied here. In static methods we can use something like this

ThinClient.getInstance().getFileSystemDaemon().getFileSystemResolver()

#62 Updated by Greg Shah almost 6 years ago

ThinClient.getInstance().getFileSystemDaemon()

Surely we should not need to call ThinClient from FileSystemDaemon in order to get the singleton instance of the same class. Let's change the initialization to cache the FileSystemDaemon singleton instance inside FileSystemDaemon.

#63 Updated by Sergey Ivanovskiy almost 6 years ago

Greg, please review 11268. I encountered text conflict in Utils.java that it is possible that your changes can be lost due to these classes PathResolver and PathResolverImpl are in separate files.

#64 Updated by Sergey Ivanovskiy almost 6 years ago

Committed revision 11269 fixed java docs.

#65 Updated by Sergey Ivanovskiy almost 6 years ago

Committed revision 11270 added src/com/goldencode/p2j/util/PathResolverContainer.java.

#66 Updated by Sergey Ivanovskiy almost 6 years ago

3565a rev 11272 has been updated over trunc rev 11257.

#67 Updated by Sergey Ivanovskiy almost 6 years ago

Can I start regression testing for 3565a?

#68 Updated by Greg Shah almost 6 years ago

Code Review Task Branch 3565a Revision 11272

I am OK with the changes.

this.paths field is set from void setSearchPath(String[] paths, boolean caseSens). If we applied path resolution to this field in setLegacyPathResolver(), then we should be sure that setSearchPath is used before setLegacyPathResolver(). Another variant is to unite these two method in one method with this name setLegacySearchPath(....).

This is the last issue to resolve. setSearchPath can be called multiple times, even from converted code (PROPATH = some_expression.).

1. Change the initialization to send down all the FSD configuration (the propath, case-sensitive, absolute path map...) in 1 call when the session starts.

2. Move the path array fixup code to a separate method. Call that method from the initialization processing AND from setSearchPath().

#69 Updated by Eric Faulhaber almost 6 years ago

I just tried using this branch with a project that does not have any directory changes. I got:

Caused by: java.lang.NullPointerException
        at com.goldencode.p2j.util.EnvironmentOps.getLegacyAbsolutePathPrefixMap(EnvironmentOps.java:952)
        at com.goldencode.p2j.util.FileSystemOps$ContextContainer.initialValue(FileSystemOps.java:1223)
        at com.goldencode.p2j.security.ContextLocal.get(ContextLocal.java:462)
        at com.goldencode.p2j.security.ContextLocal.get(ContextLocal.java:419)
        at com.goldencode.p2j.util.FileSystemOps$ContextContainer.obtain(FileSystemOps.java:1191)
        at com.goldencode.p2j.util.FileSystemOps.init(FileSystemOps.java:261)
        at com.goldencode.p2j.ui.LogicalTerminal.init(LogicalTerminal.java:1226)
        at com.goldencode.p2j.security.ContextLocal.initializeValue(ContextLocal.java:596)
        at com.goldencode.p2j.security.ContextLocal.get(ContextLocal.java:464)
        at com.goldencode.p2j.security.ContextLocal.get(ContextLocal.java:419)
        at com.goldencode.p2j.ui.LogicalTerminal.locate(LogicalTerminal.java:11125)
        at com.goldencode.p2j.ui.LogicalTerminal.lambda$initialize$3(LogicalTerminal.java:12199)
        at com.goldencode.p2j.util.TransactionManager$ContextContainer.obtain(TransactionManager.java:6337)
        at com.goldencode.p2j.util.TransactionManager.isHeadless(TransactionManager.java:3451)
        at com.goldencode.p2j.util.ErrorManager$ServerDataAccess.isHeadless(ErrorManager.java:2672)
        at com.goldencode.p2j.util.ErrorManager.isHeadless(ErrorManager.java:2087)
        at com.goldencode.p2j.util.SessionUtils$1.initialValue(SessionUtils.java:141)
        at com.goldencode.p2j.util.SessionUtils$1.initialValue(SessionUtils.java:125)
        at com.goldencode.p2j.security.ContextLocal.get(ContextLocal.java:462)
        at com.goldencode.p2j.security.ContextLocal.get(ContextLocal.java:419)
        at com.goldencode.p2j.util.SessionUtils.getSessionTooltips(SessionUtils.java:877)
        at com.goldencode.p2j.ui.LogicalTerminal.getSessionTooltips(LogicalTerminal.java:15137)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at com.goldencode.p2j.util.MethodInvoker.invoke(MethodInvoker.java:124)
        at com.goldencode.p2j.net.Dispatcher.processInbound(Dispatcher.java:757)
        at com.goldencode.p2j.net.Conversation.block(Conversation.java:412)
        at com.goldencode.p2j.net.Conversation.run(Conversation.java:232)
        at java.lang.Thread.run(Thread.java:748)

This is an optional feature, so the runtime must work even if the directory contains no legacy-system/absolute-path-prefix-map path.

#70 Updated by Sergey Ivanovskiy almost 6 years ago

It seems that I missed this issue because I got this case too without proper settings. Thank you, planning to fix it with the last review.

#71 Updated by Eric Faulhaber almost 6 years ago

Sergey Ivanovskiy wrote:

Testing this committed revision 11258. Please look at this revision. The directory changes are
[...]

Does the opsys node now under legacy-system in the directory replace the existing opsys node under the runtime/default path?

            <node class="container" name="opsys">
              <node class="string" name="override">
                <node-attribute name="value" value="WIN32"/>
              </node>
            </node>

Note that the old opsys node is a container with that override node as a child. We don't have that in the proposed new opsys node under legacy-system. Is it needed?

#72 Updated by Greg Shah almost 6 years ago

legacy-system/opsys is the definition of the original OPSYS value from the legacy system (the system on which the 4GL version of the application executed. We don't expose this to the converted 4GL code. We just use this in our decision making in the runtime.

The runtime/default/opsys/override is the way that we force the converted OPSYS to report something different from the actual client OS.

They are 2 different things.

#73 Updated by Sergey Ivanovskiy almost 6 years ago

Please review the committed revision 11273.

#74 Updated by Eric Faulhaber almost 6 years ago

This is not a code review, but I have a minor request: please rename UnResolvedPathException to UnresolvedPathException (i.e., lowercase "r").

#75 Updated by Sergey Ivanovskiy almost 6 years ago

OK. It has been fixed in committed revision 11274.

#76 Updated by Greg Shah almost 6 years ago

Code Review Task Branch 3565a Revision 11274

I'm good with the changes.

Please use Level.FINER instead of Level.CONFIG.

After that, if the code is working well in the current customer application being tested, then we can go with this code.

#77 Updated by Sergey Ivanovskiy almost 6 years ago

Committed revision 11275 reduced the log level to FINER. My environment is not ready now. I am building the customer application.

#79 Updated by Sergey Ivanovskiy almost 6 years ago

  • File corrugated_style.png added

#80 Updated by Sergey Ivanovskiy almost 6 years ago

  • File deleted (corrugated_style.png)

#81 Updated by Eric Faulhaber almost 6 years ago

Sergey, please rebase 3565a. I have a converted project that depends upon changes in trunk revision 11259. Thanks.

#82 Updated by Sergey Ivanovskiy almost 6 years ago

OK. 3565a has been updated over the trunc rev. 11259 up to the rev. 11277.

#83 Updated by Sergey Ivanovskiy almost 6 years ago

I started regression testing for rev 11280, but forgot to setup manually the directory that has changes.

#84 Updated by Sergey Ivanovskiy almost 6 years ago

remote 3565a branch for regression testing was created with corresponding directory changes: file-system to legacy-system and regression testing has been started.

#85 Updated by Sergey Ivanovskiy almost 6 years ago

3565a passed regression testing, planning to merge it into the trunk now.

#86 Updated by Sergey Ivanovskiy almost 6 years ago

3565a has been merged into the trunc as bzr revision 11261 and archived.

#87 Updated by Eric Faulhaber almost 6 years ago

Sergey, I'm getting errors loading files using relative paths. The use case:

StreamFactory.openFileStream((relativePath).toStringMessage(), false, false)

...where relativePath represents a Windows path from the legacy system that uses different case than the actual file on disk (on Linux). The physical file does exist at the specified location, but some characters in the path or in the filename itself don't match the case of the specified path. Permissions on the directories leading to the file from the current directory and on the file itself are wide open (777).

The error I get:

** "./<path to file>/<file name>" was not found. (293)

or

** "<path to file>/<file name>" was not found. (293)

The directory is configured as follows:


            <node class="container" name="legacy-system">
              ...
              <node class="string" name="opsys">
                <node-attribute name="value" value="WIN32"/>
              </node>
              <node class="string" name="propath">
                 ...
              </node>
              <node class="string" name="path-separator">
                <node-attribute name="value" value=";"/>
              </node>
              <node class="string" name="file-separator">
                <node-attribute name="value" value="\"/>
              </node>
              <node class="boolean" name="case-sensitive">
                <node-attribute name="value" value="FALSE"/>
              </node>
              <node class="container" name="absolute-path-prefix-map">
                 ...
              </node>
            </node>

Could you please double-check this use case?

#88 Updated by Sergey Ivanovskiy almost 6 years ago

OK. StreamDaemon.openFileStream doesn't implement case insensitive search. It only maps absolute legacy paths to host file paths.

#89 Updated by Eric Faulhaber almost 6 years ago

Sergey Ivanovskiy wrote:

OK. StreamDaemon.openFileStream doesn't implement case insensitive search. It is only map absolute legacy paths to host file paths.

How much effort to add this? It is pretty urgent.

#90 Updated by Sergey Ivanovskiy almost 6 years ago

Please specify how it should work precisely. Should this relative path name be searched in PROPATH or SEARCHPATH that set up via FileSystemDaemon.setSearchPath(String[] paths, boolean caseSens)? It can be implemented similarly to ThinClient.getImageFileName if I understand this task correctly.

#91 Updated by Eric Faulhaber almost 6 years ago

Sergey Ivanovskiy wrote:

Please specify how it should work precisely. Should this relative path name be searched in PROPATH or SEARCHPATH that set up via FileSystemDaemon.setSearchPath(String[] paths, boolean caseSens)? It can be implemented similarly to ThinClient.getImageFileName if I understand this task correctly.

Greg, I need your input on this one.

#92 Updated by Sergey Ivanovskiy almost 6 years ago

Eric Faulhaber wrote:

How much effort to add this? It is pretty urgent.

Eric, please test this one

=== modified file 'src/com/goldencode/p2j/util/StreamDaemon.java'
--- src/com/goldencode/p2j/util/StreamDaemon.java    2018-05-18 16:52:45 +0000
+++ src/com/goldencode/p2j/util/StreamDaemon.java    2018-05-28 21:29:16 +0000
@@ -215,11 +215,7 @@
       boolean isTerminal = false;
       if (filename != null)
       {
-         PathResolverContainer pathResolver = terminal.getFileSystemDaemon().getLegacyPathResolver();
-         
-         filename = pathResolver.resolvePath(filename);
-         
-         filename = FileSystemDaemon.normalizeFileSeparators(filename);
+         filename = terminal.getFileSystemDaemon().searchPath(filename);

          String term = filename.toLowerCase();

#93 Updated by Greg Shah almost 6 years ago

StreamDaemon.openFileStream comes from two language statements:

1. INPUT FROM which opens a file for reading. This does NOT support PROPATH. From the 4GL docs:

The absolute or relative pathname of a file that contains the data you want to input. Any relative pathname is relative to the current working directory.

2. OUTPUT TO which opens a file for writing (optionally append but by default overwrite). This will create a file that is not there, but if it exists it must open it or delete and then recreate it. Again, there is no PROPATH usage. From the 4GL docs:

The absolute or relative pathname of a file to which you want to direct output. If you specify a relative pathname, the AVM locates the pathname relative to the current working directory. The pathname can contain up to 255 characters. If a file with the specified pathname already exists, the AVM overwrites it.

The APPEND option modifies the default overwrite mode.

To summarize: no PROPATH but path and filename processing for existing paths and filenames must honor case insensitivity.

#94 Updated by Eric Faulhaber almost 6 years ago

Sergey Ivanovskiy wrote:

Eric, please test this one
[...]

Based on Greg's response, that doesn't look right.

#95 Updated by Sergey Ivanovskiy almost 6 years ago

Created 3565b task branch.

#96 Updated by Eric Faulhaber almost 6 years ago

I can confirm that INPUT FROM does not use the search path, as Sergey found through separate testing.

So, the two things to fix in 3565b are:

  • make the FWD SEARCH implementation work the same as Progress w.r.t. leading .\ or ./ file name qualifiers;
  • make StreamDaemon honor the case sensitivity setting.

#97 Updated by Sergey Ivanovskiy almost 6 years ago

Eric Faulhaber wrote:

So, the two things to fix in 3565b are:

  • make the FWD SEARCH implementation work the same as Progress w.r.t. leading .\ or ./ file name qualifiers;

Now I didn't find a way to fix it correctly. It seems that it is a minor issue because it looks odd that Progress treats ./ as an absolute path from the current directory.

  • make StreamDaemon honor the case sensitivity setting.

Committed rev 11263 should implement this functionality.

#98 Updated by Greg Shah almost 4 years ago

  • Related to Bug #4682: modify FILE-INFO processing to honor searches for 4GL programs added

#100 Updated by Greg Shah about 3 years ago

  • Related to Feature #3396: shift searchpath and other pathing lists in the directory to use the platform neutral comma added

Also available in: Atom PDF