Skip to content

include ref in path as WW-5011 workaround#353

Merged
yasserzamani merged 5 commits intoapache:struts-2-5-xfrom
yasserzamani:WW-5011-2-5
May 28, 2019
Merged

include ref in path as WW-5011 workaround#353
yasserzamani merged 5 commits intoapache:struts-2-5-xfrom
yasserzamani:WW-5011-2-5

Conversation

@yasserzamani
Copy link
Copy Markdown
Member

@yasserzamani yasserzamani commented Apr 23, 2019

include ref in path for StrutsApplicationResource as WW-5011 workaround (when real path or filename contains "#" character)

@yasserzamani
Copy link
Copy Markdown
Member Author

FYI I checked all references (usages) of org.apache.tiles.request.ApplicationResource and org.apache.struts2.tiles.StrutsApplicationResource and couldn't find any scenario that proofs this PR breaks backward-compatibility. do you?

@coveralls
Copy link
Copy Markdown

coveralls commented Apr 23, 2019

Coverage Status

Coverage decreased (-0.01%) to 47.014% when pulling fd91e75 on yasserzamani:WW-5011-2-5 into b23bfd4 on apache:struts-2-5-x.

@lukaszlenart
Copy link
Copy Markdown
Member

This will break backward-compatibility if someone extends StrutsApplicationResource in his app.

@yasserzamani yasserzamani changed the title WW-5011 use Tiles already provided URLApplicationResource include ref in path as WW-5011 workaround Apr 24, 2019
@yasserzamani
Copy link
Copy Markdown
Member Author

👍 I reset the PR to minimize backward-compatibility issues as much as possible :)

@yasserzamani
Copy link
Copy Markdown
Member Author

yasserzamani commented Apr 24, 2019

Oh I realized .toURI().getPath() itself fixes issue. If wasn't possible, now it follows my previous solution.

ℹ️ Squash is recommended if accepted

Copy link
Copy Markdown
Contributor

@JCgH4164838Gh792C124B5 JCgH4164838Gh792C124B5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @yasserzamani .

Thanks for advising me of this PR. 😄

After reviewing the changes I've commented in locations where some risks could be addressed.

For 2.5.x I'm still more comfortable with an opt-in/opt-out mechanism, even with a fallback-oriented logic like you've created in this PR.

Maybe this PR could consider using the new logic by default but allow an opt-out flag "struts.tiles.originalFileResourceHandling" (similar but opposite to the opt-in flag in PR#348) ?

That strategy would essentially eliminate backwards-compatibility risk for 2.5.x but still allow for the "new and improved" logic to be transparent by default.

Either way good work on the PR so far. 👍

Let me know what you think and let me know if my comments make sense or not.

String path;
try {
//workarounds WW-5011 because includes ref in path
path = url.toURI().getPath();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might work, but I'm not sure whether a sub-context representation will always equate to a URL/URI anchor/fragment.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if I could understand well but URI doesn't have getRef method while URL has which means URI has included ref (i.e. what is after "#") in path. My added unit tests verify this.

// fallback solution
path = url.getPath();

if (url.getRef() != null && !new File(path).exists()) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar comment about sub-context representation and anchor/fragment "#".

A larger concern is there is now a File existence check happening here. That seems very risky as the URL can represent a non-file protocol resource.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But getLastModified method already considers it should be a file.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems getLastModified() considers the possibility that resource (path) is a file, but it doesn't assume it has to be a file.

If the path doesn't exist as a file (e.g. nonexistent file or non-file URL) then exists() will be false and getLastModified() just returns 0. (As a side note the base Tiles interface also allows for an IOException to be thrown if there's no modified date available ... but Struts has attempted to avoid that).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed :) - learnt from tiles URLApplicationResource.

/**
* workarounds WW-5011
*/
private static String getExistedPath(URL url) throws MalformedURLException {
Copy link
Copy Markdown
Contributor

@JCgH4164838Gh792C124B5 JCgH4164838Gh792C124B5 Apr 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe getExistedPath() would be clearer with a name like getExtractedPath() ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I named such because WW-5011 is because url.getPath doesn't exist always. What does Extracted refer?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought "Extracted" was more general - just indicates the method attempts to extract the path from the URL (whether it actually exists or not).
Since the URL resource may not be a file, a File.exists() test cannot always determine if the path actually exists or not...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed :) - learnt from tiles URLApplicationResource.

@Override
public long getLastModified() throws IOException {
File file = new File(url.getPath());
File file = new File(super.getLocalePath());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should call getExistedPath(url) (or its equivalent if it gets renamed).

The constructor used to call url.getPath() for its parameter, just like this method used to.
Since the constructor now calls getExistedPath(url), this method should probably call it too (for consistency).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have passed it to super and we don't need compute it once again. My added unit tests show it seems work.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is super.getLocalePath() (from the Tiles code) doesn't guarantee return of the exact path string passed to super. Unfortunately the unit test can't easily check all possibilities, and changing the parameter passed risks breaking existing applications unexpectedly (in hard to predict ways).

If we want to avoid re-computing the path value, then maybe we should just add a new attribute to cache the URL path string in this PR and modify it like this:

    final String urlPath;
    // Code up to the constructor
    public StrutsApplicationResource(URL url) throws MalformedURLException {
        urlPath = getExistedPath(url);
        super(urlPath);
        this.url = url;
    }
    // Intervening code
    @Override
    public long getLastModified() throws IOException {
        File file = new File(urlPath);
    // Rest of code

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed :) - learnt from tiles URLApplicationResource.

try {
resources.add(new StrutsApplicationResource(entry.getValue()));
} catch (MalformedURLException e) {
LOG.warn("Cannot access [{}]", entry.getValue(), e);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this is better as a debug level instead of warn ?
It's clearer with a warn, but users might not expect warnings in the logs (since it wouldn't happen before), so a debug might be "safer".

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have warn in current code a few lines above this newly added line :)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True ... but that warn it isn't in a loop like this one (which was what "caught my eye") 😉

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 throw exception removed at all to honor lazy file existence check .

}
}

if (!new File(path).exists()) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Oops ... comment accidentally dropped from my review, re-adding as a single comment)

The File existence checks are dangerous because the URL can be a non-file protocol resource.

For that reason it is recommended that the two File existence checks are either removed or the logic changed so that File existence checks are only performed after verifying the URL represents a file protocol resource. The check could be something like:

if ("file".equalsIgnoreCase(url.getProtocol())) {
  // Perform file existence checks
}
// Return extracted path String (for non-File URLs or File URLs that pass existence checks).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 good idea, thanks!


public StrutsApplicationResource(URL url) {
super(url.getPath());
super(getFilePath(url));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One last suggestion 😄 for the constructor (avoids calling getFilePath twice/regenerating the path string):

final String urlPath = getFilePath(url);
super(urlPath);
this.url = url;
this.file = new File(urlPath);

@JCgH4164838Gh792C124B5
Copy link
Copy Markdown
Contributor

Hello @yasserzamani .

After your latest changes it LGTM 👍

Sorry to be a pain ... but I made one (last) minor suggestion above concerning the constructor, It's actually something you suggested earlier to avoid re-generating the path string twice, I'll go ahead and set feedback as approved whether you decide that additional change is worth it or not.

Thanks for all of your work on this PR. 😄

p.s. It looks like this PR had the same Java 8 Travis CI failure that shows up intermittently too.

@yasserzamani
Copy link
Copy Markdown
Member Author

No, it's fine :) thanks for your support! - actually this PR is very better now than mine :)

I had tried to avoid re-computing the path but it says Call to super must be first statement in the constructor 😢

Travis build fixed by another commit 👍

@JCgH4164838Gh792C124B5
Copy link
Copy Markdown
Contributor

Hello @lukaszlenart and @aleksandr-m.

It looks like this PR is ready to go once one of you reviews the latest version and thinks it can be approved. Assuming it is approved/merged, then I can close my original PR for this issue. :)

@lukaszlenart
Copy link
Copy Markdown
Member

Looks good to me, LGTM 👍

@yasserzamani yasserzamani merged commit b0dd7c1 into apache:struts-2-5-x May 28, 2019
@yasserzamani yasserzamani deleted the WW-5011-2-5 branch May 28, 2019 05:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants