This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch fix/private-api-remediation
in repository https://gitbox.apache.org/repos/asf/struts-intellij-plugin.git

commit ba31f4ed0b5c287d2b508af041359e0cb6ea4d95
Author: Lukasz Lenart <[email protected]>
AuthorDate: Tue Feb 10 18:03:36 2026 +0200

    fix: remediate private and deprecated API usages for marketplace approval
    
    Replace internal and deprecated IntelliJ Platform APIs to pass
    JetBrains Marketplace verification for plugin version 253.x.
    
    Changes:
    - Replace IconManager.loadRasterizedIcon() with IconLoader.getIcon()
    - Replace WebFacet.getWebRoots(boolean) with getWebRoots()
    - Replace AnActionButton with DumbAwareAction in toolbar
    - Replace IdeFocusManager.doWhenFocusSettlesDown() with requestFocus()
    - Replace ResourceRegistrar.addStdResource(Class) with ClassLoader version
    - Replace FilenameIndex.getFilesByName() with getVirtualFilesByName()
    - Replace deprecated URL(String) constructor with URI.create().toURL()
    - Document GraphBuilder internal API usage (no public replacement)
    - Document EXTEND_CLASS_NAMES deprecation (no replacement available)
    
    🤖 Generated with [Claude Code](https://claude.com/claude-code)
    
    Co-Authored-By: Claude <[email protected]>
---
 CLAUDE.md                                          |  68 ++-
 src/main/gen/com/intellij/lang/ognl/OgnlIcons.java |  14 +-
 .../java/com/intellij/struts2/Struts2Icons.java    |  24 +-
 .../intellij/struts2/Struts2ResourceProvider.java  | 148 ++---
 .../struts/impl/path/FileReferenceSetHelper.java   | 126 ++--
 .../struts2/facet/ui/FileSetConfigurationTab.java  | 662 ++++++++++-----------
 .../graph/fileEditor/Struts2GraphComponent.java    | 197 +++---
 .../graph/fileEditor/Struts2GraphFileEditor.java   | 155 ++---
 .../inspection/HardcodedActionUrlInspection.java   | 486 ++++++++-------
 .../contributor/ConstantValueClassConverter.java   | 140 ++---
 .../velocity/Struts2GlobalMacroProvider.java       |  43 +-
 11 files changed, 1052 insertions(+), 1011 deletions(-)

diff --git a/CLAUDE.md b/CLAUDE.md
index 5b0707d..0752c42 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -5,6 +5,7 @@ This file provides guidance to Claude Code (claude.ai/code) 
when working with co
 ## Development Commands
 
 ### Build and Test
+
 ```bash
 ./gradlew build                              # Build the plugin
 ./gradlew test -x rat                        # Run unit tests (excluding 
Apache RAT license checks)
@@ -15,6 +16,7 @@ This file provides guidance to Claude Code (claude.ai/code) 
when working with co
 ```
 
 ### Development and Debugging
+
 ```bash
 ./gradlew runIde                             # Run IntelliJ IDEA with the 
plugin loaded
 ./gradlew runIdeForUiTests                   # Launch IDE with robot server on 
port 8082
@@ -23,6 +25,7 @@ This file provides guidance to Claude Code (claude.ai/code) 
when working with co
 ```
 
 ### Code Quality
+
 ```bash
 ./gradlew runInspections                     # Run Qodana inspections 
(requires Docker)
 ./gradlew rat                                # Run Apache RAT license check
@@ -30,32 +33,38 @@ This file provides guidance to Claude Code (claude.ai/code) 
when working with co
 
 ## Project Architecture
 
-This is an IntelliJ IDEA Ultimate plugin for Apache Struts 2 framework, 
providing IDE support for struts.xml configuration, OGNL expressions, 
validation files, and JSP tag libraries.
+This is an IntelliJ IDEA Ultimate plugin for Apache Struts 2 framework, 
providing IDE support for struts.xml
+configuration, OGNL expressions, validation files, and JSP tag libraries.
 
 ### Package Structure
+
 - `com.intellij.struts2` - Core Struts 2 plugin functionality
 - `com.intellij.lang.ognl` - OGNL language support (lexer, parser, 
highlighting, completion)
 
 ### Key Architectural Components
 
 **DOM Model Layer** (`com.intellij.struts2.dom`)
+
 - `struts/` - Struts XML configuration DOM (actions, results, interceptors, 
packages)
 - `validator/` - Validation XML DOM models
 - `params/` - Parameter handling and type conversion
 - DOM converters in `impl/` packages handle reference resolution
 
 **Framework Integration** (`com.intellij.struts2.facet`)
+
 - `StrutsFacet` / `StrutsFacetType` - Framework facet configuration
 - `StrutsFrameworkDetector` - Auto-detection of Struts projects
 - `StrutsFrameworkInitializer` - Modern `ProjectActivity`-based initialization 
(replaces deprecated `StartupManager`)
 - `FileSetConfigurationTab` - UI for configuring struts.xml file sets
 
 **Reference Resolution** (`com.intellij.struts2.reference`)
+
 - `StrutsReferenceContributor` - XML reference providers for struts.xml
 - `jsp/` - JSP tag library references and action link resolution
 - Reference contributors for various Struts tag libraries (jQuery, Bootstrap, 
etc.)
 
 **OGNL Language** (`com.intellij.lang.ognl`)
+
 - `OgnlLanguage` / `OgnlFileType` - Language definition
 - `lexer/` - JFlex-based lexer (`ognl.flex`)
 - `parser/` - Grammar Kit parser (`OgnlParser.bnf`)
@@ -64,23 +73,32 @@ This is an IntelliJ IDEA Ultimate plugin for Apache Struts 
2 framework, providin
 - `completion/` - Code completion providers
 
 **Extension Points** (defined in `plugin.xml`)
+
 - `struts2.constantContributor` - Add custom Struts constants
 - `struts2.resultContributor` - Custom result type path resolution
 - `struts2.classContributor` - Extend class resolution (actions, interceptors)
 - `struts2.paramNameCustomConverter` - Custom parameter name resolution
 
 ### Template Engine Integrations
+
 Optional modules loaded via `<depends optional="true">`:
+
 - `struts2-freemarker.xml` - FreeMarker template support
 - `struts2-velocity.xml` - Velocity template support
 - `struts2-spring.xml` - Spring integration
 - `struts2-groovy.xml` - Groovy annotations support
 
 ### Test Organization
+
 - `src/test/java` - Test classes following IntelliJ Platform test patterns
 - `src/test/testData` - Test fixture files (XML, JSP, Java sources)
 - Test base classes extend IntelliJ Platform's 
`LightJavaCodeInsightFixtureTestCase` or similar
 
+### Generated Code
+
+- `src/main/gen/` - Generated parser/lexer code (included in source set 
automatically)
+- Source grammars: `src/main/grammar/ognl.bnf` (Grammar Kit), 
`_OgnlLexer.flex` (JFlex)
+
 ## IntelliJ Platform Version Mapping
 
 | Branch | Platform Version | Build Range |
@@ -89,51 +107,59 @@ Optional modules loaded via `<depends optional="true">`:
 | 243.x  | 2024.3           | 243.*       |
 | 251.x  | 2025.1           | 251.*       |
 | 252.x  | 2025.2           | 252.*       |
+| 253.x  | 2025.3           | 253.*       |
 
 ### Plugin Version Format
+
 `{BRANCH}.{BUILD}.{FIX}` (e.g., `252.18970.1`)
 
 - **BRANCH** - IntelliJ Platform branch (252 = 2025.2)
 - **BUILD** - Automatically calculated in GitHub Actions as `18969 + git 
rev-list --count HEAD`
 - **FIX** - Patch version (typically `1` for new builds)
 
-The base value `18969` maintains historical continuity from when the plugin 
was donated by JetBrains to Apache Software Foundation, ensuring version 
numbers continue from the previous build sequence.
+The base value `18969` maintains historical continuity from when the plugin 
was donated by JetBrains to Apache Software
+Foundation, ensuring version numbers continue from the previous build sequence.
 
 ## Platform Upgrade Checklist
 
 When upgrading to a new IntelliJ Platform version:
 
 1. **Update `gradle.properties`**:
-   - `platformVersion` - Target platform (e.g., `2025.2`)
-   - `pluginSinceBuild` / `pluginUntilBuild` - Build range (e.g., `251` to 
`252.*`)
-   - `pluginVersion` - Match branch prefix (e.g., `252.x.y`)
-
+  - `platformVersion` - Target platform (e.g., `2025.2`)
+  - `pluginSinceBuild` / `pluginUntilBuild` - Build range (e.g., `251` to 
`252.*`)
+  - `pluginVersion` - Match branch prefix (e.g., `252.x.y`)
 2. **Check API Compatibility**:
-   - Review https://jb.gg/intellij-api-changes for breaking changes
-   - Run `./gradlew runPluginVerifier` to detect issues
-   - Common changes: deprecated UI icons, removed internal APIs, changed test 
framework paths
-
+  - Review https://jb.gg/intellij-api-changes for breaking changes
+  - Run `./gradlew runPluginVerifier` to detect issues
+  - Common changes: deprecated UI icons, removed internal APIs, changed test 
framework paths
 3. **Update CI/Tooling** (if Java version changes):
-   - `.github/workflows/build.yml` - Java version in setup
-   - `qodana.yml` - Linter version and `projectJDK`
-   - `build.gradle.kts` - `jvmToolchain()` version
-
+  - `.github/workflows/build.yml` - Java version in setup
+  - `qodana.yml` - Linter version and `projectJDK`
+  - `build.gradle.kts` - `jvmToolchain()` version
 4. **Fix Test Path Issues**:
-   - IntelliJ Platform test frameworks sometimes change path resolution
-   - Override `getBasePath()` and `getTestDataPath()` if tests fail to find 
fixtures
-   - Use project-relative paths like `"src/test/testData/..."`
-
+  - IntelliJ Platform test frameworks sometimes change path resolution
+  - Override `getBasePath()` and `getTestDataPath()` if tests fail to find 
fixtures
+  - Use project-relative paths like `"src/test/testData/..."`
 5. **Update CHANGELOG.md** with dependency upgrades
 
 ## Known Platform Quirks
 
-**Test Data Path Resolution**: IntelliJ 2024.2+ changed how `LexerTestCase` 
and `DomStubTest` resolve paths. If tests fail with "Cannot find source file", 
override path methods to use project-relative paths.
+**Test Data Path Resolution**: IntelliJ 2024.2+ changed how `LexerTestCase` 
and `DomStubTest` resolve paths. If tests
+fail with "Cannot find source file", override path methods to use 
project-relative paths.
+
+**Internal API Usage**: Some platform icons and utilities are internal. The 
plugin verifier will warn about these.
+Prefer public APIs:
 
-**Internal API Usage**: Some platform icons and utilities are internal. The 
plugin verifier will warn about these. Prefer public APIs:
 - Use `AllIcons.Nodes.*` instead of `PlatformIcons`
 - Use `Charset.availableCharsets()` instead of 
`CharsetToolkit.getAvailableCharsets()`
 
-**JSP Reference Providers**: The `javaee.web.customServletReferenceProvider` 
extension point behavior changed in 2024.2. Action link references in JSP may 
need alternative registration approaches.
+**JSP Reference Providers**: The `javaee.web.customServletReferenceProvider` 
extension point behavior changed in 2024.2.
+Action link references in JSP may need alternative registration approaches.
+
+**Temporarily Disabled Tests**: Several tests are disabled pending 2025.3 
compatibility fixes:
+OgnlLexerTest, StrutsCompletionTest, StrutsHighlightingSpringTest, 
StrutsResultResolvingTest,
+ActionLinkReferenceProviderTest. See CHANGELOG.md for full list - these should 
be re-enabled
+when infrastructure issues are resolved.
 
 ## Claude Guidance
 
diff --git a/src/main/gen/com/intellij/lang/ognl/OgnlIcons.java 
b/src/main/gen/com/intellij/lang/ognl/OgnlIcons.java
index 449531f..1fc4f32 100644
--- a/src/main/gen/com/intellij/lang/ognl/OgnlIcons.java
+++ b/src/main/gen/com/intellij/lang/ognl/OgnlIcons.java
@@ -1,7 +1,7 @@
 // Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source 
code is governed by the Apache 2.0 license.
 package com.intellij.lang.ognl;
 
-import com.intellij.ui.IconManager;
+import com.intellij.openapi.util.IconLoader;
 import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
@@ -11,8 +11,12 @@ import javax.swing.*;
  * DO NOT EDIT IT BY HAND, run "Generate icon classes" configuration instead
  */
 public final class OgnlIcons {
-  private static @NotNull Icon load(@NotNull String path, int cacheKey, int 
flags) {
-    return IconManager.getInstance().loadRasterizedIcon(path, 
OgnlIcons.class.getClassLoader(), cacheKey, flags);
-  }
-  /** 10x10 */ public static final @NotNull Icon Action_small = 
load("icons/action_small.svg", -592871696, 0);
+    private static @NotNull Icon load(@NotNull String path) {
+        return IconLoader.getIcon(path, OgnlIcons.class.getClassLoader());
+    }
+
+    /**
+     * 10x10
+     */
+    public static final @NotNull Icon Action_small = 
load("icons/action_small.svg");
 }
diff --git a/src/main/java/com/intellij/struts2/Struts2Icons.java 
b/src/main/java/com/intellij/struts2/Struts2Icons.java
index 7322e7c..e6bffd5 100644
--- a/src/main/java/com/intellij/struts2/Struts2Icons.java
+++ b/src/main/java/com/intellij/struts2/Struts2Icons.java
@@ -16,7 +16,7 @@
  */
 package com.intellij.struts2;
 
-import com.intellij.ui.IconManager;
+import com.intellij.openapi.util.IconLoader;
 import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
@@ -26,10 +26,20 @@ import javax.swing.*;
  * DO NOT EDIT IT BY HAND, run "Generate icon classes" configuration instead
  */
 public final class Struts2Icons {
-  private static @NotNull Icon load(@NotNull String path, int cacheKey, int 
flags) {
-    return IconManager.getInstance().loadRasterizedIcon(path, 
Struts2Icons.class.getClassLoader(), cacheKey, flags);
-  }
-  /** 16x16 */ public static final @NotNull Icon Action = 
load("icons/action.svg", 1640284181, 0);
-  /** 10x10 */ public static final @NotNull Icon Action_small = 
load("icons/action_small.svg", -592871696, 0);
-  /** 10x10 */ public static final @NotNull Icon Edit_small = 
load("icons/edit_small.svg", 1635832574, 0);
+    private static @NotNull Icon load(@NotNull String path) {
+        return IconLoader.getIcon(path, Struts2Icons.class.getClassLoader());
+    }
+
+    /**
+     * 16x16
+     */
+    public static final @NotNull Icon Action = load("icons/action.svg");
+    /**
+     * 10x10
+     */
+    public static final @NotNull Icon Action_small = 
load("icons/action_small.svg");
+    /**
+     * 10x10
+     */
+    public static final @NotNull Icon Edit_small = 
load("icons/edit_small.svg");
 }
diff --git a/src/main/java/com/intellij/struts2/Struts2ResourceProvider.java 
b/src/main/java/com/intellij/struts2/Struts2ResourceProvider.java
index 82f399f..96f1d75 100644
--- a/src/main/java/com/intellij/struts2/Struts2ResourceProvider.java
+++ b/src/main/java/com/intellij/struts2/Struts2ResourceProvider.java
@@ -25,79 +25,79 @@ import org.jetbrains.annotations.NonNls;
  * @author Dmitry Avdeev
  */
 final class Struts2ResourceProvider implements StandardResourceProvider {
-  @NonNls
-  private static final String DTD_PATH = "/resources/dtds/";
-
-  @Override
-  public void registerResources(final ResourceRegistrar registrar) {
-    addDTDResource(StrutsConstants.STRUTS_2_0_DTD_URI,
-                   StrutsConstants.STRUTS_2_0_DTD_ID,
-                   "struts-2.0.dtd", registrar);
-
-    addDTDResource(StrutsConstants.STRUTS_2_1_DTD_URI,
-                   StrutsConstants.STRUTS_2_1_DTD_ID,
-                   "struts-2.1.dtd", registrar);
-
-    addDTDResource(StrutsConstants.STRUTS_2_1_7_DTD_URI,
-                   StrutsConstants.STRUTS_2_1_7_DTD_ID,
-                   "struts-2.1.7.dtd", registrar);
-
-    addDTDResource(StrutsConstants.STRUTS_2_3_DTD_URI,
-                   StrutsConstants.STRUTS_2_3_DTD_ID,
-                   "struts-2.3.dtd", registrar);
-
-    addDTDResource(StrutsConstants.STRUTS_2_5_DTD_URI,
-                   StrutsConstants.STRUTS_2_5_DTD_ID,
-                   "struts-2.5.dtd", registrar);
-
-    addDTDResource(StrutsConstants.STRUTS_6_0_DTD_URI,
-                   StrutsConstants.STRUTS_6_0_DTD_ID,
-                   "struts-6.0.dtd", registrar);
-
-
-    addDTDResource(StrutsConstants.VALIDATOR_1_00_DTD_URI,
-                   StrutsConstants.VALIDATOR_1_00_DTD_ID,
-                   "xwork-validator-1.0.dtd", registrar);
-    addDTDResource(StrutsConstants.VALIDATOR_1_00_STRUTS_DTD_URI,
-                   StrutsConstants.VALIDATOR_1_00_STRUTS_DTD_ID,
-                   "xwork-validator-struts-1.0.dtd", registrar);
-
-    addDTDResource(StrutsConstants.VALIDATOR_1_02_DTD_URI,
-                   StrutsConstants.VALIDATOR_1_02_DTD_ID,
-                   "xwork-validator-1.0.2.dtd", registrar);
-    addDTDResource(StrutsConstants.VALIDATOR_1_02_STRUTS_DTD_URI,
-                   StrutsConstants.VALIDATOR_1_02_STRUTS_DTD_ID,
-                   "xwork-validator-struts-1.0.2.dtd", registrar);
-
-    addDTDResource(StrutsConstants.VALIDATOR_1_03_DTD_URI,
-                   StrutsConstants.VALIDATOR_1_03_DTD_ID,
-                   "xwork-validator-1.0.3.dtd", registrar);
-
-    addDTDResource(StrutsConstants.VALIDATOR_CONFIG_DTD_URI,
-                   StrutsConstants.VALIDATOR_CONFIG_DTD_ID,
-                   "xwork-validator-config-1.0.dtd", registrar);
-    addDTDResource(StrutsConstants.VALIDATOR_CONFIG_STRUTS_DTD_URI,
-                   StrutsConstants.VALIDATOR_CONFIG_STRUTS_DTD_ID,
-                   "xwork-validator-config-struts-1.0.dtd", registrar);
-    addDTDResource(StrutsConstants.VALIDATOR_DEFINITION_DTD_URI,
-                   StrutsConstants.VALIDATOR_DEFINITION_DTD_ID,
-                   "xwork-validator-definition-1.0.dtd", registrar);
-  }
-
-  /**
-   * Adds a DTD resource from local DTD resource path.
-   *
-   * @param uri       Resource URI.
-   * @param id        Resource ID.
-   * @param localFile DTD filename.
-   * @param registrar Resource registrar.
-   */
-  private static void addDTDResource(@NonNls final String uri,
-                                     @NonNls final String id,
-                                     @NonNls final String localFile,
-                                     final ResourceRegistrar registrar) {
-    registrar.addStdResource(uri, DTD_PATH + localFile, 
Struts2ResourceProvider.class);
-    registrar.addStdResource(id, DTD_PATH + localFile, 
Struts2ResourceProvider.class);
-  }
+    @NonNls
+    private static final String DTD_PATH = "/resources/dtds/";
+
+    @Override
+    public void registerResources(final ResourceRegistrar registrar) {
+        addDTDResource(StrutsConstants.STRUTS_2_0_DTD_URI,
+                StrutsConstants.STRUTS_2_0_DTD_ID,
+                "struts-2.0.dtd", registrar);
+
+        addDTDResource(StrutsConstants.STRUTS_2_1_DTD_URI,
+                StrutsConstants.STRUTS_2_1_DTD_ID,
+                "struts-2.1.dtd", registrar);
+
+        addDTDResource(StrutsConstants.STRUTS_2_1_7_DTD_URI,
+                StrutsConstants.STRUTS_2_1_7_DTD_ID,
+                "struts-2.1.7.dtd", registrar);
+
+        addDTDResource(StrutsConstants.STRUTS_2_3_DTD_URI,
+                StrutsConstants.STRUTS_2_3_DTD_ID,
+                "struts-2.3.dtd", registrar);
+
+        addDTDResource(StrutsConstants.STRUTS_2_5_DTD_URI,
+                StrutsConstants.STRUTS_2_5_DTD_ID,
+                "struts-2.5.dtd", registrar);
+
+        addDTDResource(StrutsConstants.STRUTS_6_0_DTD_URI,
+                StrutsConstants.STRUTS_6_0_DTD_ID,
+                "struts-6.0.dtd", registrar);
+
+
+        addDTDResource(StrutsConstants.VALIDATOR_1_00_DTD_URI,
+                StrutsConstants.VALIDATOR_1_00_DTD_ID,
+                "xwork-validator-1.0.dtd", registrar);
+        addDTDResource(StrutsConstants.VALIDATOR_1_00_STRUTS_DTD_URI,
+                StrutsConstants.VALIDATOR_1_00_STRUTS_DTD_ID,
+                "xwork-validator-struts-1.0.dtd", registrar);
+
+        addDTDResource(StrutsConstants.VALIDATOR_1_02_DTD_URI,
+                StrutsConstants.VALIDATOR_1_02_DTD_ID,
+                "xwork-validator-1.0.2.dtd", registrar);
+        addDTDResource(StrutsConstants.VALIDATOR_1_02_STRUTS_DTD_URI,
+                StrutsConstants.VALIDATOR_1_02_STRUTS_DTD_ID,
+                "xwork-validator-struts-1.0.2.dtd", registrar);
+
+        addDTDResource(StrutsConstants.VALIDATOR_1_03_DTD_URI,
+                StrutsConstants.VALIDATOR_1_03_DTD_ID,
+                "xwork-validator-1.0.3.dtd", registrar);
+
+        addDTDResource(StrutsConstants.VALIDATOR_CONFIG_DTD_URI,
+                StrutsConstants.VALIDATOR_CONFIG_DTD_ID,
+                "xwork-validator-config-1.0.dtd", registrar);
+        addDTDResource(StrutsConstants.VALIDATOR_CONFIG_STRUTS_DTD_URI,
+                StrutsConstants.VALIDATOR_CONFIG_STRUTS_DTD_ID,
+                "xwork-validator-config-struts-1.0.dtd", registrar);
+        addDTDResource(StrutsConstants.VALIDATOR_DEFINITION_DTD_URI,
+                StrutsConstants.VALIDATOR_DEFINITION_DTD_ID,
+                "xwork-validator-definition-1.0.dtd", registrar);
+    }
+
+    /**
+     * Adds a DTD resource from local DTD resource path.
+     *
+     * @param uri       Resource URI.
+     * @param id        Resource ID.
+     * @param localFile DTD filename.
+     * @param registrar Resource registrar.
+     */
+    private static void addDTDResource(@NonNls final String uri,
+                                       @NonNls final String id,
+                                       @NonNls final String localFile,
+                                       final ResourceRegistrar registrar) {
+        registrar.addStdResource(uri, DTD_PATH + localFile, 
Struts2ResourceProvider.class.getClassLoader());
+        registrar.addStdResource(id, DTD_PATH + localFile, 
Struts2ResourceProvider.class.getClassLoader());
+    }
 
 }
\ No newline at end of file
diff --git 
a/src/main/java/com/intellij/struts2/dom/struts/impl/path/FileReferenceSetHelper.java
 
b/src/main/java/com/intellij/struts2/dom/struts/impl/path/FileReferenceSetHelper.java
index 63ab97b..cb92169 100644
--- 
a/src/main/java/com/intellij/struts2/dom/struts/impl/path/FileReferenceSetHelper.java
+++ 
b/src/main/java/com/intellij/struts2/dom/struts/impl/path/FileReferenceSetHelper.java
@@ -42,76 +42,76 @@ import java.util.Objects;
  */
 public final class FileReferenceSetHelper {
 
-  private FileReferenceSetHelper() {
-  }
+    private FileReferenceSetHelper() {
+    }
 
-  /**
-   * Creates a new FileReferenceSet allowing references only to 
(web-)directories and given FileType.
-   *
-   * @param psiElement      Current element.
-   * @param allowedFileType Allowed filetype for resolving.
-   * @return Instance.
-   */
-  public static FileReferenceSet createRestrictedByFileType(final PsiElement 
psiElement,
-                                                            @NotNull FileType 
allowedFileType) {
-    return new FileReferenceSet(psiElement) {
+    /**
+     * Creates a new FileReferenceSet allowing references only to 
(web-)directories and given FileType.
+     *
+     * @param psiElement      Current element.
+     * @param allowedFileType Allowed filetype for resolving.
+     * @return Instance.
+     */
+    public static FileReferenceSet createRestrictedByFileType(final PsiElement 
psiElement,
+                                                              @NotNull 
FileType allowedFileType) {
+        return new FileReferenceSet(psiElement) {
 
-      @Override
-      protected boolean isSoft() {
-        return true;
-      }
+            @Override
+            protected boolean isSoft() {
+                return true;
+            }
 
-      @Override
-      protected Condition<PsiFileSystemItem> getReferenceCompletionFilter() {
-        return psiFileSystemItem -> {
-          if (psiFileSystemItem instanceof PsiDirectory ||
-              psiFileSystemItem instanceof WebDirectoryElement) {
-            return true;
-          }
+            @Override
+            protected Condition<PsiFileSystemItem> 
getReferenceCompletionFilter() {
+                return psiFileSystemItem -> {
+                    if (psiFileSystemItem instanceof PsiDirectory ||
+                            psiFileSystemItem instanceof WebDirectoryElement) {
+                        return true;
+                    }
 
-          final VirtualFile virtualFile = psiFileSystemItem.getVirtualFile();
-          return virtualFile != null && 
FileTypeRegistry.getInstance().isFileOfType(virtualFile, allowedFileType);
+                    final VirtualFile virtualFile = 
psiFileSystemItem.getVirtualFile();
+                    return virtualFile != null && 
FileTypeRegistry.getInstance().isFileOfType(virtualFile, allowedFileType);
+                };
+            }
         };
-      }
-    };
-  }
+    }
 
-  /**
-   * Adds all {@link WebDirectoryElement}s as well as web-directory with name 
of given current namespace
-   * (if not "root" namespace) as possible content roots.
-   *
-   * @param psiElement Current element.
-   * @param namespace  Current namespace.
-   * @param webFacet   Module.
-   * @param set        FRS to patch.
-   */
-  public static void addWebDirectoryAndCurrentNamespaceAsRoots(final 
PsiElement psiElement,
-                                                               final String 
namespace,
-                                                               final WebFacet 
webFacet,
-                                                               final 
FileReferenceSet set) {
-    final WebDirectoryUtil directoryUtil = 
WebDirectoryUtil.getWebDirectoryUtil(psiElement.getProject());
-    set.addCustomization(
-        FileReferenceSet.DEFAULT_PATH_EVALUATOR_OPTION,
-        file -> {
-          final List<PsiFileSystemItem> basePathRoots = new ArrayList<>();
+    /**
+     * Adds all {@link WebDirectoryElement}s as well as web-directory with 
name of given current namespace
+     * (if not "root" namespace) as possible content roots.
+     *
+     * @param psiElement Current element.
+     * @param namespace  Current namespace.
+     * @param webFacet   Module.
+     * @param set        FRS to patch.
+     */
+    public static void addWebDirectoryAndCurrentNamespaceAsRoots(final 
PsiElement psiElement,
+                                                                 final String 
namespace,
+                                                                 final 
WebFacet webFacet,
+                                                                 final 
FileReferenceSet set) {
+        final WebDirectoryUtil directoryUtil = 
WebDirectoryUtil.getWebDirectoryUtil(psiElement.getProject());
+        set.addCustomization(
+                FileReferenceSet.DEFAULT_PATH_EVALUATOR_OPTION,
+                file -> {
+                    final List<PsiFileSystemItem> basePathRoots = new 
ArrayList<>();
 
-          // 1. add all configured web root mappings
-          final List<WebRoot> webRoots = webFacet.getWebRoots(true);
-          for (final WebRoot webRoot : webRoots) {
-            final String webRootPath = webRoot.getRelativePath();
-            final WebDirectoryElement webRootBase =
-                directoryUtil.findWebDirectoryElementByPath(webRootPath, 
webFacet);
-            ContainerUtil.addIfNotNull(basePathRoots, webRootBase);
-          }
+                    // 1. add all configured web root mappings
+                    final List<WebRoot> webRoots = webFacet.getWebRoots();
+                    for (final WebRoot webRoot : webRoots) {
+                        final String webRootPath = webRoot.getRelativePath();
+                        final WebDirectoryElement webRootBase =
+                                
directoryUtil.findWebDirectoryElementByPath(webRootPath, webFacet);
+                        ContainerUtil.addIfNotNull(basePathRoots, webRootBase);
+                    }
 
-          // 2. add parent <package> "namespace" as result prefix directory 
path if not ROOT
-          if (!Objects.equals(namespace, StrutsPackage.DEFAULT_NAMESPACE)) {
-            final WebDirectoryElement packageBase =
-                directoryUtil.findWebDirectoryElementByPath(namespace, 
webFacet);
-            ContainerUtil.addIfNotNull(basePathRoots, packageBase);
-          }
+                    // 2. add parent <package> "namespace" as result prefix 
directory path if not ROOT
+                    if (!Objects.equals(namespace, 
StrutsPackage.DEFAULT_NAMESPACE)) {
+                        final WebDirectoryElement packageBase =
+                                
directoryUtil.findWebDirectoryElementByPath(namespace, webFacet);
+                        ContainerUtil.addIfNotNull(basePathRoots, packageBase);
+                    }
 
-          return basePathRoots;
-        });
-  }
+                    return basePathRoots;
+                });
+    }
 }
\ No newline at end of file
diff --git 
a/src/main/java/com/intellij/struts2/facet/ui/FileSetConfigurationTab.java 
b/src/main/java/com/intellij/struts2/facet/ui/FileSetConfigurationTab.java
index 415e103..939ee02 100644
--- a/src/main/java/com/intellij/struts2/facet/ui/FileSetConfigurationTab.java
+++ b/src/main/java/com/intellij/struts2/facet/ui/FileSetConfigurationTab.java
@@ -26,6 +26,7 @@ import com.intellij.ide.projectView.PresentationData;
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.actionSystem.ActionUpdateThread;
 import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.project.DumbAwareAction;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.project.DumbService;
 import com.intellij.openapi.ui.DialogWrapper;
@@ -68,378 +69,373 @@ import java.util.Set;
  */
 public class FileSetConfigurationTab extends FacetEditorTab implements 
Disposable {
 
-  private final StructureTreeModel<SimpleTreeStructure> myModel;
-  // GUI components -----------------------
-  private JPanel myPanel;
-
-  private final SimpleTree myTree;
-  private final AnActionButton myRemoveButton;
-  private final AnActionButton myEditButton;
-  private JPanel myTreePanel;
-
-  // GUI helpers
-  private final SimpleNode myRootNode = new SimpleNode() {
-    @Override
-    public SimpleNode @NotNull [] getChildren() {
-      final List<SimpleNode> nodes = new ArrayList<>(myBuffer.size());
-      for (final StrutsFileSet entry : myBuffer) {
-        if (!entry.isRemoved()) {
-          final FileSetNode setNode = new FileSetNode(entry);
-          nodes.add(setNode);
+    private final StructureTreeModel<SimpleTreeStructure> myModel;
+    // GUI components -----------------------
+    private JPanel myPanel;
+
+    private final SimpleTree myTree;
+    private final AnActionButton myRemoveButton;
+    private final AnActionButton myEditButton;
+    private JPanel myTreePanel;
+
+    // GUI helpers
+    private final SimpleNode myRootNode = new SimpleNode() {
+        @Override
+        public SimpleNode @NotNull [] getChildren() {
+            final List<SimpleNode> nodes = new ArrayList<>(myBuffer.size());
+            for (final StrutsFileSet entry : myBuffer) {
+                if (!entry.isRemoved()) {
+                    final FileSetNode setNode = new FileSetNode(entry);
+                    nodes.add(setNode);
+                }
+            }
+            return nodes.toArray(new SimpleNode[0]);
         }
-      }
-      return nodes.toArray(new SimpleNode[0]);
-    }
-
-    @Override
-    public boolean isAutoExpandNode() {
-      return true;
-    }
-  };
 
-  private final TreeExpander myTreeExpander;
+        @Override
+        public boolean isAutoExpandNode() {
+            return true;
+        }
+    };
 
-  private final StrutsConfigsSearcher myConfigsSearcher;
+    private final TreeExpander myTreeExpander;
 
-  // original config
-  private final StrutsFacetConfiguration originalConfiguration;
-  private final Module module;
+    private final StrutsConfigsSearcher myConfigsSearcher;
 
-  // local config
-  private final Set<StrutsFileSet> myBuffer = new LinkedHashSet<>();
-  private boolean myModified;
+    // original config
+    private final StrutsFacetConfiguration originalConfiguration;
+    private final Module module;
 
-  public FileSetConfigurationTab(@NotNull final StrutsFacetConfiguration 
strutsFacetConfiguration,
-                                 @NotNull final FacetEditorContext 
facetEditorContext) {
-    originalConfiguration = strutsFacetConfiguration;
-    module = facetEditorContext.getModule();
-    myConfigsSearcher = new StrutsConfigsSearcher(module);
+    // local config
+    private final Set<StrutsFileSet> myBuffer = new LinkedHashSet<>();
+    private boolean myModified;
 
-    // init tree
-    final SimpleTreeStructure structure = new SimpleTreeStructure() {
-      @NotNull
-      @Override
-      public Object getRootElement() {
-        return myRootNode;
-      }
-    };
+    public FileSetConfigurationTab(@NotNull final StrutsFacetConfiguration 
strutsFacetConfiguration,
+                                   @NotNull final FacetEditorContext 
facetEditorContext) {
+        originalConfiguration = strutsFacetConfiguration;
+        module = facetEditorContext.getModule();
+        myConfigsSearcher = new StrutsConfigsSearcher(module);
 
-    myTree = new SimpleTree();
-    myTree.setRootVisible(false);
-    myTree.setShowsRootHandles(true); // show expand/collapse handles
-    
myTree.getEmptyText().setText(StrutsBundle.message("facet.fileset.no.filesets.defined"),
 SimpleTextAttributes.ERROR_ATTRIBUTES);
-    myTreeExpander = new DefaultTreeExpander(myTree);
-
-    myModel = new StructureTreeModel<>(structure, this);
-    myTree.setModel(new AsyncTreeModel(myModel, this));
-
-    final DumbService dumbService = 
DumbService.getInstance(facetEditorContext.getProject());
-    myTree.getSelectionModel().addTreeSelectionListener(new 
TreeSelectionListener() {
-      @Override
-      public void valueChanged(final TreeSelectionEvent e) {
-        final StrutsFileSet fileSet = getCurrentFileSet();
-        myEditButton.setEnabled(fileSet != null && !dumbService.isDumb());
-        myRemoveButton.setEnabled(fileSet != null);
-      }
-    });
-
-    final CommonActionsManager actionManager = 
CommonActionsManager.getInstance();
-    myTreePanel.add(
-      ToolbarDecorator.createDecorator(myTree)
-        .setAddAction(new AnActionButtonRunnable() {
-          @Override
-          public void run(AnActionButton button) {
-            final StrutsFileSet fileSet =
-              new StrutsFileSet(StrutsFileSet.getUniqueId(myBuffer),
-                                
StrutsFileSet.getUniqueName(StrutsBundle.message("facet.fileset.my.fileset"), 
myBuffer),
-                                originalConfiguration) {
-                @Override
-                public boolean isNew() {
-                  return true;
-                }
-              };
-
-            final FileSetEditor editor = new FileSetEditor(myPanel,
-                                                           fileSet,
-                                                           facetEditorContext,
-                                                           myConfigsSearcher);
-            editor.show();
-            if (editor.getExitCode() == DialogWrapper.OK_EXIT_CODE) {
-              final StrutsFileSet editedFileSet = editor.getEditedFileSet();
-              Disposer.register(strutsFacetConfiguration, editedFileSet);
-              myBuffer.add(editedFileSet);
-              myModified = true;
-              myModel.invalidateAsync().thenRun(() -> 
selectFileSet(editedFileSet));
+        // init tree
+        final SimpleTreeStructure structure = new SimpleTreeStructure() {
+            @NotNull
+            @Override
+            public Object getRootElement() {
+                return myRootNode;
             }
-            IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> 
IdeFocusManager.getGlobalInstance().requestFocus(myTree, true));
-          }
-        })
-        .setRemoveAction(new AnActionButtonRunnable() {
-          @Override
-          public void run(AnActionButton button) {
-            remove();
-            myModified = true;
-            myModel.invalidateAsync();
-            IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> 
IdeFocusManager.getGlobalInstance().requestFocus(myTree, true));
-          }
-        })
-        .setEditAction(new AnActionButtonRunnable() {
-          @Override
-          public void run(AnActionButton button) {
-            final StrutsFileSet fileSet = getCurrentFileSet();
-            if (fileSet != null) {
-              final FileSetEditor editor = new FileSetEditor(myPanel,
-                                                             fileSet,
-                                                             
facetEditorContext,
-                                                             
myConfigsSearcher);
-              editor.show();
-              if (editor.getExitCode() == DialogWrapper.OK_EXIT_CODE) {
-                myModified = true;
-                myBuffer.remove(fileSet);
-                final StrutsFileSet edited = editor.getEditedFileSet();
-                Disposer.register(strutsFacetConfiguration, edited);
-                myBuffer.add(edited);
-                edited.setAutodetected(false);
-                myModel.invalidateAsync();
-                selectFileSet(edited);
-              }
-              IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> 
IdeFocusManager.getGlobalInstance().requestFocus(myTree, true));
+        };
+
+        myTree = new SimpleTree();
+        myTree.setRootVisible(false);
+        myTree.setShowsRootHandles(true); // show expand/collapse handles
+        
myTree.getEmptyText().setText(StrutsBundle.message("facet.fileset.no.filesets.defined"),
 SimpleTextAttributes.ERROR_ATTRIBUTES);
+        myTreeExpander = new DefaultTreeExpander(myTree);
+
+        myModel = new StructureTreeModel<>(structure, this);
+        myTree.setModel(new AsyncTreeModel(myModel, this));
+
+        final DumbService dumbService = 
DumbService.getInstance(facetEditorContext.getProject());
+        myTree.getSelectionModel().addTreeSelectionListener(new 
TreeSelectionListener() {
+            @Override
+            public void valueChanged(final TreeSelectionEvent e) {
+                final StrutsFileSet fileSet = getCurrentFileSet();
+                myEditButton.setEnabled(fileSet != null && 
!dumbService.isDumb());
+                myRemoveButton.setEnabled(fileSet != null);
             }
-          }
-        })
-        .addExtraAction(actionManager.createExpandAllAction(myTreeExpander, 
myTree))
-        .addExtraAction(actionManager.createCollapseAllAction(myTreeExpander, 
myTree))
-        .addExtraAction(new 
AnActionButton(StrutsBundle.messagePointer("action.AnActionButton.text.open.struts.2.plugin.documentation"),
-                                           AllIcons.Actions.Help) {
-          @Override
-          public void actionPerformed(@NotNull AnActionEvent e) {
-            
BrowserUtil.browse("https://confluence.jetbrains.com/pages/viewpage.action?pageId=35367";);
-          }
-
-          @Override
-          public @NotNull ActionUpdateThread getActionUpdateThread() {
-            return ActionUpdateThread.EDT;
-          }
-        })
-
-        .disableUpDownActions()
-        .createPanel());
-
-    myEditButton = ToolbarDecorator.findEditButton(myTreePanel);
-    myRemoveButton = ToolbarDecorator.findRemoveButton(myTreePanel);
-
-    // Note: makeDumbAware API may have changed in IntelliJ Platform 2025.2
-    // Removing these calls as they caused compilation errors
-    // Component dumb awareness should still work through DumbAware interface
-  }
-
-  @Nullable
-  private StrutsFileSet getCurrentFileSet() {
-    final FileSetNode currentFileSetNode = getCurrentFileSetNode();
-    return currentFileSetNode == null ? null : currentFileSetNode.mySet;
-  }
-
-  @Nullable
-  private FileSetNode getCurrentFileSetNode() {
-    final SimpleNode selectedNode = myTree.getSelectedNode();
-    if (selectedNode == null) {
-      return null;
+        });
+
+        final CommonActionsManager actionManager = 
CommonActionsManager.getInstance();
+        myTreePanel.add(
+                ToolbarDecorator.createDecorator(myTree)
+                        .setAddAction(new AnActionButtonRunnable() {
+                            @Override
+                            public void run(AnActionButton button) {
+                                final StrutsFileSet fileSet =
+                                        new 
StrutsFileSet(StrutsFileSet.getUniqueId(myBuffer),
+                                                
StrutsFileSet.getUniqueName(StrutsBundle.message("facet.fileset.my.fileset"), 
myBuffer),
+                                                originalConfiguration) {
+                                            @Override
+                                            public boolean isNew() {
+                                                return true;
+                                            }
+                                        };
+
+                                final FileSetEditor editor = new 
FileSetEditor(myPanel,
+                                        fileSet,
+                                        facetEditorContext,
+                                        myConfigsSearcher);
+                                editor.show();
+                                if (editor.getExitCode() == 
DialogWrapper.OK_EXIT_CODE) {
+                                    final StrutsFileSet editedFileSet = 
editor.getEditedFileSet();
+                                    
Disposer.register(strutsFacetConfiguration, editedFileSet);
+                                    myBuffer.add(editedFileSet);
+                                    myModified = true;
+                                    myModel.invalidateAsync().thenRun(() -> 
selectFileSet(editedFileSet));
+                                }
+                                
IdeFocusManager.getGlobalInstance().requestFocus(myTree, true);
+                            }
+                        })
+                        .setRemoveAction(new AnActionButtonRunnable() {
+                            @Override
+                            public void run(AnActionButton button) {
+                                remove();
+                                myModified = true;
+                                myModel.invalidateAsync();
+                                
IdeFocusManager.getGlobalInstance().requestFocus(myTree, true);
+                            }
+                        })
+                        .setEditAction(new AnActionButtonRunnable() {
+                            @Override
+                            public void run(AnActionButton button) {
+                                final StrutsFileSet fileSet = 
getCurrentFileSet();
+                                if (fileSet != null) {
+                                    final FileSetEditor editor = new 
FileSetEditor(myPanel,
+                                            fileSet,
+                                            facetEditorContext,
+                                            myConfigsSearcher);
+                                    editor.show();
+                                    if (editor.getExitCode() == 
DialogWrapper.OK_EXIT_CODE) {
+                                        myModified = true;
+                                        myBuffer.remove(fileSet);
+                                        final StrutsFileSet edited = 
editor.getEditedFileSet();
+                                        
Disposer.register(strutsFacetConfiguration, edited);
+                                        myBuffer.add(edited);
+                                        edited.setAutodetected(false);
+                                        myModel.invalidateAsync();
+                                        selectFileSet(edited);
+                                    }
+                                    
IdeFocusManager.getGlobalInstance().requestFocus(myTree, true);
+                                }
+                            }
+                        })
+                        
.addExtraAction(actionManager.createExpandAllAction(myTreeExpander, myTree))
+                        
.addExtraAction(actionManager.createCollapseAllAction(myTreeExpander, myTree))
+                        .addExtraAction(new 
DumbAwareAction(StrutsBundle.messagePointer("action.AnActionButton.text.open.struts.2.plugin.documentation"),
+                                AllIcons.Actions.Help) {
+                            @Override
+                            public void actionPerformed(@NotNull AnActionEvent 
e) {
+                                
BrowserUtil.browse("https://confluence.jetbrains.com/pages/viewpage.action?pageId=35367";);
+                            }
+
+                            @Override
+                            public @NotNull ActionUpdateThread 
getActionUpdateThread() {
+                                return ActionUpdateThread.EDT;
+                            }
+                        })
+
+                        .disableUpDownActions()
+                        .createPanel());
+
+        myEditButton = ToolbarDecorator.findEditButton(myTreePanel);
+        myRemoveButton = ToolbarDecorator.findRemoveButton(myTreePanel);
+
+        // Note: makeDumbAware API may have changed in IntelliJ Platform 2025.2
+        // Removing these calls as they caused compilation errors
+        // Component dumb awareness should still work through DumbAware 
interface
     }
-    if (selectedNode instanceof FileSetNode) {
-      return (FileSetNode)selectedNode;
+
+    @Nullable
+    private StrutsFileSet getCurrentFileSet() {
+        final FileSetNode currentFileSetNode = getCurrentFileSetNode();
+        return currentFileSetNode == null ? null : currentFileSetNode.mySet;
     }
-    else if (selectedNode.getParent() instanceof FileSetNode) {
-      return (FileSetNode)selectedNode.getParent();
+
+    @Nullable
+    private FileSetNode getCurrentFileSetNode() {
+        final SimpleNode selectedNode = myTree.getSelectedNode();
+        if (selectedNode == null) {
+            return null;
+        }
+        if (selectedNode instanceof FileSetNode) {
+            return (FileSetNode) selectedNode;
+        } else if (selectedNode.getParent() instanceof FileSetNode) {
+            return (FileSetNode) selectedNode.getParent();
+        } else {
+            final SimpleNode parent = selectedNode.getParent();
+            if (parent != null && parent.getParent() instanceof FileSetNode) {
+                return (FileSetNode) selectedNode.getParent().getParent();
+            }
+        }
+        return null;
     }
-    else {
-      final SimpleNode parent = selectedNode.getParent();
-      if (parent != null && parent.getParent() instanceof FileSetNode) {
-        return (FileSetNode)selectedNode.getParent().getParent();
-      }
+
+    private void selectFileSet(final StrutsFileSet fileSet) {
+        SimpleNode simpleNode = ContainerUtil.find(myRootNode.getChildren(), 
node -> ((FileSetNode) node).mySet == fileSet);
+        assert simpleNode != null;
+        myModel.select(simpleNode, myTree, path -> {
+        });
     }
-    return null;
-  }
-
-  private void selectFileSet(final StrutsFileSet fileSet) {
-    SimpleNode simpleNode = ContainerUtil.find(myRootNode.getChildren(), node 
-> ((FileSetNode)node).mySet == fileSet);
-    assert simpleNode != null;
-    myModel.select(simpleNode, myTree, path -> {});
-  }
-
-  private void remove() {
-    final SimpleNode[] nodes = myTree.getSelectedNodesIfUniform();
-    for (final SimpleNode node : nodes) {
-
-      if (node instanceof FileSetNode) {
-        final StrutsFileSet fileSet = ((FileSetNode)node).mySet;
-        if (fileSet.getFiles().isEmpty()) {
-          myBuffer.remove(fileSet);
-          return;
-        }
 
-        final int result = Messages.showYesNoDialog(myPanel,
-                                                    
StrutsBundle.message("facet.fileset.remove.fileset.question",
-                                                                         
fileSet.getName()),
-                                                    
StrutsBundle.message("facet.fileset.remove.fileset.title"),
-                                                    
Messages.getQuestionIcon());
-        if (result == Messages.YES) {
-          if (fileSet.isAutodetected()) {
-            fileSet.setRemoved(true);
-            myBuffer.add(fileSet);
-          }
-          else {
-            myBuffer.remove(fileSet);
-          }
+    private void remove() {
+        final SimpleNode[] nodes = myTree.getSelectedNodesIfUniform();
+        for (final SimpleNode node : nodes) {
+
+            if (node instanceof FileSetNode) {
+                final StrutsFileSet fileSet = ((FileSetNode) node).mySet;
+                if (fileSet.getFiles().isEmpty()) {
+                    myBuffer.remove(fileSet);
+                    return;
+                }
+
+                final int result = Messages.showYesNoDialog(myPanel,
+                        
StrutsBundle.message("facet.fileset.remove.fileset.question",
+                                fileSet.getName()),
+                        
StrutsBundle.message("facet.fileset.remove.fileset.title"),
+                        Messages.getQuestionIcon());
+                if (result == Messages.YES) {
+                    if (fileSet.isAutodetected()) {
+                        fileSet.setRemoved(true);
+                        myBuffer.add(fileSet);
+                    } else {
+                        myBuffer.remove(fileSet);
+                    }
+                }
+            } else if (node instanceof ConfigFileNode) {
+                final VirtualFilePointer filePointer = ((ConfigFileNode) 
node).myFilePointer;
+                final StrutsFileSet fileSet = ((FileSetNode) 
node.getParent()).mySet;
+                fileSet.removeFile(filePointer);
+            }
         }
-      }
-      else if (node instanceof ConfigFileNode) {
-        final VirtualFilePointer filePointer = 
((ConfigFileNode)node).myFilePointer;
-        final StrutsFileSet fileSet = ((FileSetNode)node.getParent()).mySet;
-        fileSet.removeFile(filePointer);
-      }
     }
-  }
-
-  @Override
-  @Nls
-  public String getDisplayName() {
-    return StrutsBundle.message("facet.fileset.title");
-  }
-
-  @Override
-  @NotNull
-  public JComponent createComponent() {
-    return myPanel;
-  }
-
-  @Override
-  public boolean isModified() {
-    return myModified;
-  }
-
-  @Override
-  public void apply() {
-    final Set<StrutsFileSet> fileSets = originalConfiguration.getFileSets();
-    fileSets.clear();
-    for (final StrutsFileSet fileSet : myBuffer) {
-      if (!fileSet.isAutodetected() || fileSet.isRemoved()) {
-        fileSets.add(fileSet);
-      }
+
+    @Override
+    @Nls
+    public String getDisplayName() {
+        return StrutsBundle.message("facet.fileset.title");
     }
-    originalConfiguration.setModified();
-    myModified = false;
-  }
-
-  @Override
-  public void reset() {
-    myBuffer.clear();
-    final Set<StrutsFileSet> sets = 
StrutsManager.getInstance(module.getProject()).getAllConfigFileSets(module);
-    /*new StrutsFileSet(fileSet)*/
-    myBuffer.addAll(sets);
-
-    myModel.invalidateAsync();
-    myTree.setSelectionRow(0);
-  }
-
-  @Override
-  public void disposeUIResources() {
-    Disposer.dispose(this);
-  }
-
-  @Override
-  public void dispose() {
-  }
-
-  private class FileSetNode extends SimpleNode {
-
-    protected final StrutsFileSet mySet;
-
-    FileSetNode(final StrutsFileSet fileSet) {
-      super(myRootNode);
-      mySet = fileSet;
-
-      final PresentationData presentationData = getPresentation();
-      final String name = mySet.getName(); //NON-NLS
-
-      if (fileSet.getFiles().isEmpty()) {
-        presentationData.addText(name, getErrorAttributes());
-        
presentationData.setTooltip(StrutsBundle.message("facet.fileset.no.files.attached"));
-      }
-      else {
-        presentationData.addText(name, getPlainAttributes());
-        
presentationData.setLocationString(Integer.toString(fileSet.getFiles().size()));
-      }
+
+    @Override
+    @NotNull
+    public JComponent createComponent() {
+        return myPanel;
     }
 
     @Override
-    public SimpleNode @NotNull [] getChildren() {
-      final List<SimpleNode> nodes = new ArrayList<>();
+    public boolean isModified() {
+        return myModified;
+    }
 
-      for (final VirtualFilePointer file : mySet.getFiles()) {
-        nodes.add(new ConfigFileNode(file, this));
-      }
-      return nodes.toArray(new SimpleNode[0]);
+    @Override
+    public void apply() {
+        final Set<StrutsFileSet> fileSets = 
originalConfiguration.getFileSets();
+        fileSets.clear();
+        for (final StrutsFileSet fileSet : myBuffer) {
+            if (!fileSet.isAutodetected() || fileSet.isRemoved()) {
+                fileSets.add(fileSet);
+            }
+        }
+        originalConfiguration.setModified();
+        myModified = false;
     }
 
     @Override
-    public boolean isAutoExpandNode() {
-      return true;
+    public void reset() {
+        myBuffer.clear();
+        final Set<StrutsFileSet> sets = 
StrutsManager.getInstance(module.getProject()).getAllConfigFileSets(module);
+        /*new StrutsFileSet(fileSet)*/
+        myBuffer.addAll(sets);
+
+        myModel.invalidateAsync();
+        myTree.setSelectionRow(0);
     }
 
     @Override
-    public Object @NotNull [] getEqualityObjects() {
-      return new Object[]{mySet, mySet.getName(), mySet.getFiles()};
+    public void disposeUIResources() {
+        Disposer.dispose(this);
     }
-  }
 
+    @Override
+    public void dispose() {
+    }
 
-  private static final class ConfigFileNode extends SimpleNode {
+    private class FileSetNode extends SimpleNode {
 
-    private final VirtualFilePointer myFilePointer;
+        protected final StrutsFileSet mySet;
 
-    ConfigFileNode(final VirtualFilePointer name, final SimpleNode parent) {
-      super(parent);
-      myFilePointer = name;
-      getTemplatePresentation().setIcon(StrutsIcons.STRUTS_CONFIG_FILE);
-    }
+        FileSetNode(final StrutsFileSet fileSet) {
+            super(myRootNode);
+            mySet = fileSet;
 
-    @Override
-    public boolean isAlwaysLeaf() {
-      return true;
-    }
+            final PresentationData presentationData = getPresentation();
+            final String name = mySet.getName(); //NON-NLS
 
-    @Override
-    protected void doUpdate(@NotNull PresentationData presentation) {
-      final VirtualFile file = myFilePointer.getFile();
-      if (file != null) {
-        renderFile(presentation, file, getPlainAttributes(), null);
-      }
-      else {
-        renderFile(presentation, null, getErrorAttributes(), 
StrutsBundle.message("facet.fileset.file.not.found"));
-      }
+            if (fileSet.getFiles().isEmpty()) {
+                presentationData.addText(name, getErrorAttributes());
+                
presentationData.setTooltip(StrutsBundle.message("facet.fileset.no.files.attached"));
+            } else {
+                presentationData.addText(name, getPlainAttributes());
+                
presentationData.setLocationString(Integer.toString(fileSet.getFiles().size()));
+            }
+        }
+
+        @Override
+        public SimpleNode @NotNull [] getChildren() {
+            final List<SimpleNode> nodes = new ArrayList<>();
+
+            for (final VirtualFilePointer file : mySet.getFiles()) {
+                nodes.add(new ConfigFileNode(file, this));
+            }
+            return nodes.toArray(new SimpleNode[0]);
+        }
+
+        @Override
+        public boolean isAutoExpandNode() {
+            return true;
+        }
+
+        @Override
+        public Object @NotNull [] getEqualityObjects() {
+            return new Object[]{mySet, mySet.getName(), mySet.getFiles()};
+        }
     }
 
-    private void renderFile(@NotNull PresentationData presentation,
-                            final VirtualFile file,
-                            final SimpleTextAttributes textAttributes,
-                            @NlsContexts.Tooltip @Nullable final String 
toolTip) {
-      presentation.setTooltip(toolTip);
-      presentation.clearText();
-      presentation.addText(myFilePointer.getFileName(), textAttributes); 
//NON-NLS
-
-      if (file != null) {
-        presentation.setLocationString(file.getPath());
-      }
+
+    private static final class ConfigFileNode extends SimpleNode {
+
+        private final VirtualFilePointer myFilePointer;
+
+        ConfigFileNode(final VirtualFilePointer name, final SimpleNode parent) 
{
+            super(parent);
+            myFilePointer = name;
+            getTemplatePresentation().setIcon(StrutsIcons.STRUTS_CONFIG_FILE);
+        }
+
+        @Override
+        public boolean isAlwaysLeaf() {
+            return true;
+        }
+
+        @Override
+        protected void doUpdate(@NotNull PresentationData presentation) {
+            final VirtualFile file = myFilePointer.getFile();
+            if (file != null) {
+                renderFile(presentation, file, getPlainAttributes(), null);
+            } else {
+                renderFile(presentation, null, getErrorAttributes(), 
StrutsBundle.message("facet.fileset.file.not.found"));
+            }
+        }
+
+        private void renderFile(@NotNull PresentationData presentation,
+                                final VirtualFile file,
+                                final SimpleTextAttributes textAttributes,
+                                @NlsContexts.Tooltip @Nullable final String 
toolTip) {
+            presentation.setTooltip(toolTip);
+            presentation.clearText();
+            presentation.addText(myFilePointer.getFileName(), textAttributes); 
//NON-NLS
+
+            if (file != null) {
+                presentation.setLocationString(file.getPath());
+            }
+        }
+
+        @Override
+        public SimpleNode @NotNull [] getChildren() {
+            return NO_CHILDREN;
+        }
     }
 
     @Override
-    public SimpleNode @NotNull [] getChildren() {
-      return NO_CHILDREN;
+    public String getHelpTopic() {
+        return "reference.settings.project.structure.facets.struts2.facet";
     }
-  }
-
-  @Override
-  public String getHelpTopic() {
-    return "reference.settings.project.structure.facets.struts2.facet";
-  }
 }
diff --git 
a/src/main/java/com/intellij/struts2/graph/fileEditor/Struts2GraphComponent.java
 
b/src/main/java/com/intellij/struts2/graph/fileEditor/Struts2GraphComponent.java
index 6f84ea4..85a666d 100644
--- 
a/src/main/java/com/intellij/struts2/graph/fileEditor/Struts2GraphComponent.java
+++ 
b/src/main/java/com/intellij/struts2/graph/fileEditor/Struts2GraphComponent.java
@@ -52,110 +52,113 @@ import java.util.Objects;
  * @author Yann C&eacute;bron
  */
 public class Struts2GraphComponent extends JPanel implements DataProvider, 
Disposable {
-  @NonNls
-  private static final String STRUTS2_DESIGNER_COMPONENT = 
"STRUTS2_DESIGNER_COMPONENT";
-
-  private final GraphBuilder<BasicStrutsNode, BasicStrutsEdge> myBuilder;
-
-  public Struts2GraphComponent(final XmlFile xmlFile) {
-    final ProgressIndicator progress = 
ProgressManager.getInstance().getProgressIndicator();
-
-    progress.setText("Initializing...");
-    final Project project = xmlFile.getProject();
-    final Graph2D graph = GraphManager.getGraphManager().createGraph2D();
-    final Graph2DView view = 
GraphManager.getGraphManager().createGraph2DView();
-
-    progress.setText("Building model...");
-    final StrutsDataModel myDataModel = new StrutsDataModel(xmlFile);
-    final StrutsPresentationModel presentationModel = new 
StrutsPresentationModel(graph);
+    @NonNls
+    private static final String STRUTS2_DESIGNER_COMPONENT = 
"STRUTS2_DESIGNER_COMPONENT";
+
+    private final GraphBuilder<BasicStrutsNode, BasicStrutsEdge> myBuilder;
+
+    public Struts2GraphComponent(final XmlFile xmlFile) {
+        final ProgressIndicator progress = 
ProgressManager.getInstance().getProgressIndicator();
+
+        progress.setText("Initializing...");
+        final Project project = xmlFile.getProject();
+        final Graph2D graph = GraphManager.getGraphManager().createGraph2D();
+        final Graph2DView view = 
GraphManager.getGraphManager().createGraph2DView();
+
+        progress.setText("Building model...");
+        final StrutsDataModel myDataModel = new StrutsDataModel(xmlFile);
+        final StrutsPresentationModel presentationModel = new 
StrutsPresentationModel(graph);
+
+        progress.setText("Setup graph...");
+        myBuilder = 
GraphBuilderFactory.getInstance(project).createGraphBuilder(graph,
+                view,
+                myDataModel,
+                presentationModel);
+        Disposer.register(this, myBuilder);
+
+        JComponent graphComponent = myBuilder.getView().getJComponent();
+        setLayout(new BorderLayout());
+
+        ActionToolbar toolbar = 
ActionManager.getInstance().createActionToolbar(
+                ActionPlaces.TOOLBAR, 
AbstractGraphAction.getCommonToolbarActions(), true);
+        toolbar.setTargetComponent(graphComponent);
+
+        add(toolbar.getComponent(), BorderLayout.NORTH);
+        add(graphComponent, BorderLayout.CENTER);
+
+        // TODO: GraphBuilder.initialize() is @Internal API with no public 
replacement.
+        //  Consider migrating to Diagram API when available.
+        myBuilder.initialize();
+
+        
DomManager.getDomManager(myBuilder.getProject()).addDomEventListener(new 
DomEventListener() {
+            @Override
+            public void eventOccured(@NotNull final DomEvent event) {
+                if (isShowing()) {
+                    // TODO: GraphBuilder.queueUpdate() is deprecated with no 
public replacement.
+                    myBuilder.queueUpdate();
+                }
+            }
+        }, this);
+    }
 
-    progress.setText("Setup graph...");
-    myBuilder = 
GraphBuilderFactory.getInstance(project).createGraphBuilder(graph,
-                                                                            
view,
-                                                                            
myDataModel,
-                                                                            
presentationModel);
-    Disposer.register(this, myBuilder);
+    public List<DomElement> getSelectedDomElements() {
+        final var selected = new ArrayList<DomElement>();
+        
GraphSelectionService.getInstance().forEachSelectedNode(myBuilder.getGraph(), 
node -> {
+            final var nodeObject = myBuilder.getNodeObject(node);
+            if (nodeObject != null) {
+                ContainerUtil.addIfNotNull(selected, 
nodeObject.getIdentifyingElement());
+            }
+        });
+        return selected;
+    }
 
-    JComponent graphComponent = myBuilder.getView().getJComponent();
-    setLayout(new BorderLayout());
+    public void setSelectedDomElement(final DomElement domElement) {
+        // TODO
+        //if (domElement == null) return;
+        //
+        //final SeamPagesDomElement pageflowDomElement = 
domElement.getParentOfType(SeamPagesDomElement.class, false);
+        //if (pageflowDomElement == null) return;
+        //
+        //final Node selectedNode = myBuilder.getNode(pageflowDomElement);
+        //
+        //if (selectedNode != null) {
+        //  final Graph2D graph = myBuilder.getGraph();
+        //
+        //  for (Node n : graph.getNodeArray()) {
+        //    final boolean selected = n.equals(selectedNode);
+        //    graph.setSelected(n, selected);
+        //    if (selected) {
+        //      final YRectangle yRectangle = graph.getRectangle(n);
+        //      if (!myBuilder.getView().getVisibleRect().contains(
+        //        new Rectangle((int)yRectangle.getX(), 
(int)yRectangle.getY(), (int)yRectangle.getWidth(), 
(int)yRectangle.getHeight()))) {
+        //        myBuilder.getView().setCenter(graph.getX(n), graph.getY(n));
+        //      }
+        //    }
+        //  }
+        //}
+        //myBuilder.getView().updateView();
+    }
 
-    ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(
-      ActionPlaces.TOOLBAR, AbstractGraphAction.getCommonToolbarActions(), 
true);
-    toolbar.setTargetComponent(graphComponent);
+    public GraphBuilder getBuilder() {
+        return myBuilder;
+    }
 
-    add(toolbar.getComponent(), BorderLayout.NORTH);
-    add(graphComponent, BorderLayout.CENTER);
+    public Overview getOverview() {
+        return 
GraphManager.getGraphManager().createOverview(myBuilder.getView());
+    }
 
-    myBuilder.initialize();
+    @Override
+    public void dispose() {
+    }
 
-    DomManager.getDomManager(myBuilder.getProject()).addDomEventListener(new 
DomEventListener() {
-      @Override
-      public void eventOccured(@NotNull final DomEvent event) {
-        if (isShowing()) {
-          myBuilder.queueUpdate();
+    @Override
+    @Nullable
+    public Object getData(@NotNull @NonNls final String dataId) {
+        if (Objects.equals(dataId, STRUTS2_DESIGNER_COMPONENT)) {
+            return this;
         }
-      }
-    }, this);
-  }
-
-  public List<DomElement> getSelectedDomElements() {
-    final var selected = new ArrayList<DomElement>();
-    
GraphSelectionService.getInstance().forEachSelectedNode(myBuilder.getGraph(), 
node -> {
-      final var nodeObject = myBuilder.getNodeObject(node);
-      if (nodeObject != null) {
-        ContainerUtil.addIfNotNull(selected, 
nodeObject.getIdentifyingElement());
-      }
-    });
-    return selected;
-  }
-
-  public void setSelectedDomElement(final DomElement domElement) {
-    // TODO
-    //if (domElement == null) return;
-    //
-    //final SeamPagesDomElement pageflowDomElement = 
domElement.getParentOfType(SeamPagesDomElement.class, false);
-    //if (pageflowDomElement == null) return;
-    //
-    //final Node selectedNode = myBuilder.getNode(pageflowDomElement);
-    //
-    //if (selectedNode != null) {
-    //  final Graph2D graph = myBuilder.getGraph();
-    //
-    //  for (Node n : graph.getNodeArray()) {
-    //    final boolean selected = n.equals(selectedNode);
-    //    graph.setSelected(n, selected);
-    //    if (selected) {
-    //      final YRectangle yRectangle = graph.getRectangle(n);
-    //      if (!myBuilder.getView().getVisibleRect().contains(
-    //        new Rectangle((int)yRectangle.getX(), (int)yRectangle.getY(), 
(int)yRectangle.getWidth(), (int)yRectangle.getHeight()))) {
-    //        myBuilder.getView().setCenter(graph.getX(n), graph.getY(n));
-    //      }
-    //    }
-    //  }
-    //}
-    //myBuilder.getView().updateView();
-  }
-
-  public GraphBuilder getBuilder() {
-    return myBuilder;
-  }
-
-  public Overview getOverview() {
-    return GraphManager.getGraphManager().createOverview(myBuilder.getView());
-  }
-
-  @Override
-  public void dispose() {
-  }
-
-  @Override
-  @Nullable
-  public Object getData(@NotNull @NonNls final String dataId) {
-    if (Objects.equals(dataId, STRUTS2_DESIGNER_COMPONENT)) {
-      return this;
-    }
 
-    return null;
-  }
+        return null;
+    }
 
 }
\ No newline at end of file
diff --git 
a/src/main/java/com/intellij/struts2/graph/fileEditor/Struts2GraphFileEditor.java
 
b/src/main/java/com/intellij/struts2/graph/fileEditor/Struts2GraphFileEditor.java
index 1438362..bc720b5 100644
--- 
a/src/main/java/com/intellij/struts2/graph/fileEditor/Struts2GraphFileEditor.java
+++ 
b/src/main/java/com/intellij/struts2/graph/fileEditor/Struts2GraphFileEditor.java
@@ -38,86 +38,87 @@ import java.util.List;
  */
 public class Struts2GraphFileEditor extends PerspectiveFileEditor {
 
-  private Struts2GraphComponent myComponent;
-  private final XmlFile myXmlFile;
-
-  private final @NotNull NotNullLazyValue<StructureViewBuilder> 
myStructureViewBuilder =
-    NotNullLazyValue.atomicLazy(() -> 
GraphStructureViewBuilderSetup.setupFor(getStruts2GraphComponent().getBuilder(),
 null));
-
-  public Struts2GraphFileEditor(final Project project, final VirtualFile file) 
{
-    super(project, file);
-
-    final PsiFile psiFile = getPsiFile();
-    assert psiFile instanceof XmlFile;
-
-    myXmlFile = (XmlFile)psiFile;
-  }
-
-  @Override
-  @Nullable
-  protected DomElement getSelectedDomElement() {
-    final List<DomElement> selectedDomElements = 
getStruts2GraphComponent().getSelectedDomElements();
-
-    return selectedDomElements.size() > 0 ? selectedDomElements.get(0) : null;
-  }
-
-  @Override
-  protected void setSelectedDomElement(final DomElement domElement) {
-    getStruts2GraphComponent().setSelectedDomElement(domElement);
-  }
-
-  @Override
-  @NotNull
-  protected JComponent createCustomComponent() {
-    return getStruts2GraphComponent();
-  }
-
-  @Override
-  @Nullable
-  public JComponent getPreferredFocusedComponent() {
-    return getStruts2GraphComponent().getBuilder().getView().getJComponent();
-  }
-
-  @Override
-  public void commit() {
-  }
-
-  @Override
-  public void reset() {
-    getStruts2GraphComponent().getBuilder().queueUpdate();
-  }
-
-  @Override
-  @NotNull
-  public String getName() {
-    return "Graph";
-  }
-
-  @Override
-  public StructureViewBuilder getStructureViewBuilder() {
-    return myStructureViewBuilder.getValue();
-  }
-
-  private Struts2GraphComponent getStruts2GraphComponent() {
-    if (myComponent == null) {
-      myComponent = createGraphComponent();
-      Disposer.register(this, myComponent);
+    private Struts2GraphComponent myComponent;
+    private final XmlFile myXmlFile;
+
+    private final @NotNull NotNullLazyValue<StructureViewBuilder> 
myStructureViewBuilder =
+            NotNullLazyValue.atomicLazy(() -> 
GraphStructureViewBuilderSetup.setupFor(getStruts2GraphComponent().getBuilder(),
 null));
+
+    public Struts2GraphFileEditor(final Project project, final VirtualFile 
file) {
+        super(project, file);
+
+        final PsiFile psiFile = getPsiFile();
+        assert psiFile instanceof XmlFile;
+
+        myXmlFile = (XmlFile) psiFile;
+    }
+
+    @Override
+    @Nullable
+    protected DomElement getSelectedDomElement() {
+        final List<DomElement> selectedDomElements = 
getStruts2GraphComponent().getSelectedDomElements();
+
+        return selectedDomElements.size() > 0 ? selectedDomElements.get(0) : 
null;
+    }
+
+    @Override
+    protected void setSelectedDomElement(final DomElement domElement) {
+        getStruts2GraphComponent().setSelectedDomElement(domElement);
+    }
+
+    @Override
+    @NotNull
+    protected JComponent createCustomComponent() {
+        return getStruts2GraphComponent();
+    }
+
+    @Override
+    @Nullable
+    public JComponent getPreferredFocusedComponent() {
+        return 
getStruts2GraphComponent().getBuilder().getView().getJComponent();
+    }
+
+    @Override
+    public void commit() {
+    }
+
+    @Override
+    public void reset() {
+        // TODO: GraphBuilder.queueUpdate() is deprecated with no public 
replacement.
+        getStruts2GraphComponent().getBuilder().queueUpdate();
+    }
+
+    @Override
+    @NotNull
+    public String getName() {
+        return "Graph";
+    }
+
+    @Override
+    public StructureViewBuilder getStructureViewBuilder() {
+        return myStructureViewBuilder.getValue();
+    }
+
+    private Struts2GraphComponent getStruts2GraphComponent() {
+        if (myComponent == null) {
+            myComponent = createGraphComponent();
+            Disposer.register(this, myComponent);
+        }
+        return myComponent;
     }
-    return myComponent;
-  }
 
 
-  /**
-   * Creates graph component while showing modal wait dialog.
-   *
-   * @return new instance.
-   */
-  private Struts2GraphComponent createGraphComponent() {
-    final Struts2GraphComponent[] graphComponent = {null};
-    ProgressManager.getInstance().runProcessWithProgressSynchronously(
-      (Runnable)() -> graphComponent[0] = ReadAction.compute(() -> new 
Struts2GraphComponent(myXmlFile)), "Generating Graph", false, 
myXmlFile.getProject());
+    /**
+     * Creates graph component while showing modal wait dialog.
+     *
+     * @return new instance.
+     */
+    private Struts2GraphComponent createGraphComponent() {
+        final Struts2GraphComponent[] graphComponent = {null};
+        ProgressManager.getInstance().runProcessWithProgressSynchronously(
+                (Runnable) () -> graphComponent[0] = ReadAction.compute(() -> 
new Struts2GraphComponent(myXmlFile)), "Generating Graph", false, 
myXmlFile.getProject());
 
 
-    return graphComponent[0];
-  }
+        return graphComponent[0];
+    }
 }
\ No newline at end of file
diff --git 
a/src/main/java/com/intellij/struts2/jsp/inspection/HardcodedActionUrlInspection.java
 
b/src/main/java/com/intellij/struts2/jsp/inspection/HardcodedActionUrlInspection.java
index 0ed336e..7af9d1a 100644
--- 
a/src/main/java/com/intellij/struts2/jsp/inspection/HardcodedActionUrlInspection.java
+++ 
b/src/main/java/com/intellij/struts2/jsp/inspection/HardcodedActionUrlInspection.java
@@ -41,6 +41,7 @@ import com.intellij.xml.XmlNamespaceHelper;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.net.URI;
 import java.net.URL;
 import java.util.Collections;
 
@@ -50,290 +51,285 @@ import java.util.Collections;
  */
 public class HardcodedActionUrlInspection extends 
XmlSuppressableInspectionTool {
 
-  @NotNull
-  @Override
-  public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, 
boolean isOnTheFly) {
-    final boolean isJspFileWithStrutsSupport =
-      JspPsiUtil.getJspFile(holder.getFile()) != null &&
-      StrutsFacet.getInstance(holder.getFile()) != null;
+    @NotNull
+    @Override
+    public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder 
holder, boolean isOnTheFly) {
+        final boolean isJspFileWithStrutsSupport =
+                JspPsiUtil.getJspFile(holder.getFile()) != null &&
+                        StrutsFacet.getInstance(holder.getFile()) != null;
+
+        @Nullable final String actionExtension;
+        if (isJspFileWithStrutsSupport) {
+            actionExtension = 
ContainerUtil.getFirstItem(StrutsConstantHelper.getActionExtensions(holder.getFile()));
+        } else {
+            actionExtension = null;
+        }
+
+        return new XmlElementVisitor() {
+
+            @Override
+            public void visitXmlAttributeValue(@NotNull XmlAttributeValue 
value) {
+                if (!isJspFileWithStrutsSupport ||
+                        actionExtension == null) {
+                    return;
+                }
+
+                XmlTag tag = PsiTreeUtil.getParentOfType(value, XmlTag.class);
+                if (tag == null) return;
+
+                URL parsedURL = parseURL(value, actionExtension);
+                if (parsedURL == null) return;
 
-    @Nullable final String actionExtension;
-    if (isJspFileWithStrutsSupport) {
-      actionExtension = 
ContainerUtil.getFirstItem(StrutsConstantHelper.getActionExtensions(holder.getFile()));
+                if (buildTag("", parsedURL, "", false, actionExtension) == 
null) return;
+
+                TextRange range = ElementManipulators.getValueTextRange(value);
+                holder.registerProblem(value, range, "Use Struts <url> tag 
instead of hardcoded URL", new WrapWithSUrl(actionExtension));
+            }
+        };
     }
-    else {
-      actionExtension = null;
+
+    @Override
+    public String @NotNull [] getGroupPath() {
+        return new 
String[]{StrutsBundle.message("inspections.group.path.name"), 
getGroupDisplayName()};
     }
 
-    return new XmlElementVisitor() {
 
-      @Override
-      public void visitXmlAttributeValue(@NotNull XmlAttributeValue value) {
-        if (!isJspFileWithStrutsSupport ||
-            actionExtension == null) {
-          return;
-        }
+    private static final class WrapWithSUrl implements LocalQuickFix {
 
-        XmlTag tag = PsiTreeUtil.getParentOfType(value, XmlTag.class);
-        if (tag == null) return;
+        private final String myActionExtension;
 
-        URL parsedURL = parseURL(value, actionExtension);
-        if (parsedURL == null) return;
+        private WrapWithSUrl(String actionExtension) {
+            myActionExtension = actionExtension;
+        }
 
-        if (buildTag("", parsedURL, "", false, actionExtension) == null) 
return;
+        @NotNull
+        @Override
+        public String getFamilyName() {
+            return "Wrap with Struts <url> tag";
+        }
 
-        TextRange range = ElementManipulators.getValueTextRange(value);
-        holder.registerProblem(value, range, "Use Struts <url> tag instead of 
hardcoded URL", new WrapWithSUrl(actionExtension));
-      }
-    };
-  }
+        @Override
+        public void applyFix(@NotNull Project project, @NotNull 
ProblemDescriptor descriptor) {
+            PsiElement element = descriptor.getPsiElement();
+            if (element instanceof XmlAttributeValue value) {
+                XmlTag tag = PsiTreeUtil.getParentOfType(value, XmlTag.class, 
false);
 
-  @Override
-  public String @NotNull [] getGroupPath() {
-    return new String[]{StrutsBundle.message("inspections.group.path.name"), 
getGroupDisplayName()};
-  }
+                final boolean inline = tag instanceof HtmlTag;
 
+                final URL url = parseURL(value, myActionExtension);
+                if (url == null) {
+                    return;
+                }
 
-  private static final class WrapWithSUrl implements LocalQuickFix {
+                final JspFile jspFile = JspPsiUtil.getJspFile(value);
+                assert jspFile != null;
+
+                XmlTag rootTag = jspFile.getRootTag();
+                String prefix = 
rootTag.getPrefixByNamespace(StrutsConstants.TAGLIB_STRUTS_UI_URI);
+
+                if (StringUtil.isEmpty(prefix)) {
+                    prefix = "s"; // Use default Struts prefix
+
+                    // Insert taglib declaration after existing taglibs or 
comments
+                    Document document = 
PsiDocumentManager.getInstance(project).getDocument(jspFile);
+                    if (document != null) {
+                        String text = document.getText();
+                        int insertionPoint = 0;
+
+                        // Look for last existing taglib declaration
+                        int lastTaglibEnd = -1;
+                        int searchPos = 0;
+                        while (true) {
+                            int taglibStart = text.indexOf("<%@ taglib", 
searchPos);
+                            if (taglibStart == -1) break;
+
+                            int taglibEnd = text.indexOf("%>", taglibStart);
+                            if (taglibEnd != -1) {
+                                lastTaglibEnd = taglibEnd + 2;
+                                searchPos = lastTaglibEnd;
+                            } else {
+                                break;
+                            }
+                        }
+
+                        if (lastTaglibEnd != -1) {
+                            // Insert after last existing taglib
+                            insertionPoint = lastTaglibEnd;
+                            // Skip to end of line
+                            while (insertionPoint < text.length() && 
text.charAt(insertionPoint) != '\n') {
+                                insertionPoint++;
+                            }
+                            if (insertionPoint < text.length()) 
insertionPoint++; // Skip the newline
+                        } else {
+                            // No existing taglibs, insert after comment block
+                            int commentEnd = text.indexOf("-->");
+                            if (commentEnd != -1) {
+                                insertionPoint = commentEnd + 3;
+                                // Skip whitespace/newlines after comment
+                                while (insertionPoint < text.length() && 
Character.isWhitespace(text.charAt(insertionPoint))) {
+                                    insertionPoint++;
+                                }
+                            }
+                        }
+
+                        String taglibDeclaration = "<%@ taglib prefix=\"" + 
prefix + "\" uri=\"" + StrutsConstants.TAGLIB_STRUTS_UI_URI + "\" %>\n";
+                        document.insertString(insertionPoint, 
taglibDeclaration);
+                        
PsiDocumentManager.getInstance(project).commitDocument(document);
+                    }
+
+                    wrapValue(prefix, value, url, inline);
+                } else {
+                    wrapValue(prefix, value, url, inline);
+                }
+            }
+        }
 
-    private final String myActionExtension;
+        private void wrapValue(String prefix, XmlAttributeValue value, URL 
url, boolean inline) {
+            final JspFile jspFile = JspPsiUtil.getJspFile(value);
+            assert jspFile != null;
 
-    private WrapWithSUrl(String actionExtension) {
-      myActionExtension = actionExtension;
-    }
+            Project project = jspFile.getProject();
+            TextRange range = value.getValueTextRange();
+            Document document = 
PsiDocumentManager.getInstance(project).getDocument(jspFile);
+            assert document != null;
+            
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(document);
 
-    @NotNull
-    @Override
-    public String getFamilyName() {
-      return "Wrap with Struts <url> tag";
-    }
+            int start = range.getStartOffset();
+            int lineStart = 
document.getLineStartOffset(document.getLineNumber(start));
+            String linePrefix = 
document.getCharsSequence().subSequence(lineStart, start).toString();
+            linePrefix = linePrefix.substring(0, linePrefix.length() - 
linePrefix.trim().length());
 
-    @Override
-    public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor 
descriptor) {
-      PsiElement element = descriptor.getPsiElement();
-      if (element instanceof XmlAttributeValue value) {
-        XmlTag tag = PsiTreeUtil.getParentOfType(value, XmlTag.class, false);
+            String indent = linePrefix;
+            while (indent.length() < start - lineStart) indent += " ";
 
-        final boolean inline = tag instanceof HtmlTag;
+            Pair<String, String> tag_var = buildTag(prefix, url, indent, 
inline, myActionExtension);
+            String tag = tag_var.getFirst();
+            String var = tag_var.getSecond();
 
-        final URL url = parseURL(value, myActionExtension);
-        if (url == null) {
-          return;
-        }
+            int end = range.getEndOffset();
 
-        final JspFile jspFile = JspPsiUtil.getJspFile(value);
-        assert jspFile != null;
-
-        XmlTag rootTag = jspFile.getRootTag();
-        String prefix = 
rootTag.getPrefixByNamespace(StrutsConstants.TAGLIB_STRUTS_UI_URI);
-
-        if (StringUtil.isEmpty(prefix)) {
-          prefix = "s"; // Use default Struts prefix
-          
-          // Insert taglib declaration after existing taglibs or comments
-          Document document = 
PsiDocumentManager.getInstance(project).getDocument(jspFile);
-          if (document != null) {
-            String text = document.getText();
-            int insertionPoint = 0;
-            
-            // Look for last existing taglib declaration
-            int lastTaglibEnd = -1;
-            int searchPos = 0;
-            while (true) {
-              int taglibStart = text.indexOf("<%@ taglib", searchPos);
-              if (taglibStart == -1) break;
-              
-              int taglibEnd = text.indexOf("%>", taglibStart);
-              if (taglibEnd != -1) {
-                lastTaglibEnd = taglibEnd + 2;
-                searchPos = lastTaglibEnd;
-              } else {
-                break;
-              }
-            }
-            
-            if (lastTaglibEnd != -1) {
-              // Insert after last existing taglib
-              insertionPoint = lastTaglibEnd;
-              // Skip to end of line
-              while (insertionPoint < text.length() && 
text.charAt(insertionPoint) != '\n') {
-                insertionPoint++;
-              }
-              if (insertionPoint < text.length()) insertionPoint++; // Skip 
the newline
+            int formattingStart;
+            int formattingEnd;
+
+            if (inline) {
+                document.replaceString(start, end, tag);
+                formattingStart = start;
+                formattingEnd = start + tag.length();
             } else {
-              // No existing taglibs, insert after comment block
-              int commentEnd = text.indexOf("-->");
-              if (commentEnd != -1) {
-                insertionPoint = commentEnd + 3;
-                // Skip whitespace/newlines after comment
-                while (insertionPoint < text.length() && 
Character.isWhitespace(text.charAt(insertionPoint))) {
-                  insertionPoint++;
-                }
-              }
+                document.replaceString(start, end, "${" + var + "}");
+                XmlTag containingTag = PsiTreeUtil.getParentOfType(value, 
XmlTag.class, false);
+                assert containingTag != null;
+                int startOffset = 
containingTag.getTextRange().getStartOffset();
+                document.insertString(startOffset, "\n");
+                document.insertString(startOffset, tag);
+
+                formattingStart = startOffset;
+                formattingEnd = startOffset + tag.length() + 2;
             }
-            
-            String taglibDeclaration = "<%@ taglib prefix=\"" + prefix + "\" 
uri=\"" + StrutsConstants.TAGLIB_STRUTS_UI_URI + "\" %>\n";
-            document.insertString(insertionPoint, taglibDeclaration);
+
             PsiDocumentManager.getInstance(project).commitDocument(document);
-          }
-          
-          wrapValue(prefix, value, url, inline);
-        }
-        else {
-          wrapValue(prefix, value, url, inline);
-        }
-      }
-    }
 
-    private void wrapValue(String prefix, XmlAttributeValue value, URL url, 
boolean inline) {
-      final JspFile jspFile = JspPsiUtil.getJspFile(value);
-      assert jspFile != null;
-
-      Project project = jspFile.getProject();
-      TextRange range = value.getValueTextRange();
-      Document document = 
PsiDocumentManager.getInstance(project).getDocument(jspFile);
-      assert document != null;
-      
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(document);
-
-      int start = range.getStartOffset();
-      int lineStart = 
document.getLineStartOffset(document.getLineNumber(start));
-      String linePrefix = document.getCharsSequence().subSequence(lineStart, 
start).toString();
-      linePrefix = linePrefix.substring(0, linePrefix.length() - 
linePrefix.trim().length());
-
-      String indent = linePrefix;
-      while (indent.length() < start - lineStart) indent += " ";
-
-      Pair<String, String> tag_var = buildTag(prefix, url, indent, inline, 
myActionExtension);
-      String tag = tag_var.getFirst();
-      String var = tag_var.getSecond();
-
-      int end = range.getEndOffset();
-
-      int formattingStart;
-      int formattingEnd;
-
-      if (inline) {
-        document.replaceString(start, end, tag);
-        formattingStart = start;
-        formattingEnd = start + tag.length();
-      }
-      else {
-        document.replaceString(start, end, "${" + var + "}");
-        XmlTag containingTag = PsiTreeUtil.getParentOfType(value, 
XmlTag.class, false);
-        assert containingTag != null;
-        int startOffset = containingTag.getTextRange().getStartOffset();
-        document.insertString(startOffset, "\n");
-        document.insertString(startOffset, tag);
-
-        formattingStart = startOffset;
-        formattingEnd = startOffset + tag.length() + 2;
-      }
-
-      PsiDocumentManager.getInstance(project).commitDocument(document);
-
-      CodeStyleManager.getInstance(project).reformatText(jspFile, 
formattingStart, formattingEnd);
+            CodeStyleManager.getInstance(project).reformatText(jspFile, 
formattingStart, formattingEnd);
+        }
     }
-  }
 
-  private static Pair<String, String> buildTag(String prefix, URL url, String 
indent, boolean inline, String actionExtension) {
-    String path = url.getPath();
-    int slash = path.lastIndexOf('/');
-    String namespace = slash > 0 ? path.substring(0, slash) : null;
-    String action = slash != -1 ? path.substring(slash + 1) : path;
+    private static Pair<String, String> buildTag(String prefix, URL url, 
String indent, boolean inline, String actionExtension) {
+        String path = url.getPath();
+        int slash = path.lastIndexOf('/');
+        String namespace = slash > 0 ? path.substring(0, slash) : null;
+        String action = slash != -1 ? path.substring(slash + 1) : path;
 
-    action = StringUtil.trimEnd(action, actionExtension);
+        action = StringUtil.trimEnd(action, actionExtension);
 
-    int exclamationIdx = action.indexOf('!');
-    String method = null;
-    if (exclamationIdx > 0) {
-      method = action.substring(exclamationIdx + 1);
-      action = action.substring(0, exclamationIdx);
-    }
+        int exclamationIdx = action.indexOf('!');
+        String method = null;
+        if (exclamationIdx > 0) {
+            method = action.substring(exclamationIdx + 1);
+            action = action.substring(0, exclamationIdx);
+        }
 
-    StringBuilder sb = new StringBuilder();
-    sb.append('<').append(prefix).append(":url");
+        StringBuilder sb = new StringBuilder();
+        sb.append('<').append(prefix).append(":url");
 
-    String var;
-    if (inline) {
-      var = null;
-    }
-    else {
-      var = action + "_url";
-      sb.append(" var=\"").append(var).append("\"");
-    }
+        String var;
+        if (inline) {
+            var = null;
+        } else {
+            var = action + "_url";
+            sb.append(" var=\"").append(var).append("\"");
+        }
 
-    if (namespace != null) {
-      sb.append(" namespace=\"").append(namespace).append("\"");
-    }
+        if (namespace != null) {
+            sb.append(" namespace=\"").append(namespace).append("\"");
+        }
 
-    sb.append(" action=\"").append(action).append("\"");
-    if (method != null) {
-      sb.append(" method=\"").append(method).append("\"");
-    }
+        sb.append(" action=\"").append(action).append("\"");
+        if (method != null) {
+            sb.append(" method=\"").append(method).append("\"");
+        }
 
-    String query = url.getQuery();
-    if (StringUtil.isEmpty(query)) {
-      sb.append("/>");
-    }
-    else {
-      sb.append(">");
-
-      for (String escapedArg : StringUtil.split(query, "&amp;")) {
-        for (String arg : StringUtil.split(escapedArg, "&")) {
-          int eq = arg.indexOf('=');
-          String name = eq > 0 ? arg.substring(0, eq) : arg;
-          String value = eq > 0 ? arg.substring(eq + 1) : "";
-
-          if (name.contains("[") || name.contains("$")) return null; // This 
will not work if arg name is actually an expression
-
-          sb.append("\n").append(indent).append("  <")
-            .append(prefix)
-            .append(":param name=\"")
-            .append(name).append("\">")
-            .append(value)
-            .append("</")
-            .append(prefix)
-            .append(":param>");
+        String query = url.getQuery();
+        if (StringUtil.isEmpty(query)) {
+            sb.append("/>");
+        } else {
+            sb.append(">");
+
+            for (String escapedArg : StringUtil.split(query, "&amp;")) {
+                for (String arg : StringUtil.split(escapedArg, "&")) {
+                    int eq = arg.indexOf('=');
+                    String name = eq > 0 ? arg.substring(0, eq) : arg;
+                    String value = eq > 0 ? arg.substring(eq + 1) : "";
+
+                    if (name.contains("[") || name.contains("$"))
+                        return null; // This will not work if arg name is 
actually an expression
+
+                    sb.append("\n").append(indent).append("  <")
+                            .append(prefix)
+                            .append(":param name=\"")
+                            .append(name).append("\">")
+                            .append(value)
+                            .append("</")
+                            .append(prefix)
+                            .append(":param>");
+                }
+            }
+            sb.append('\n').append(indent);
+            sb.append("</").append(prefix).append(":url>");
         }
-      }
-      sb.append('\n').append(indent);
-      sb.append("</").append(prefix).append(":url>");
+
+        return Pair.create(sb.toString(), var);
     }
 
-    return Pair.create(sb.toString(), var);
-  }
+    @Nullable
+    private static URL parseURL(XmlAttributeValue value, String 
actionExtension) {
+        String rawUrl = value.getValue();
+        if (rawUrl.startsWith("http://";) ||
+                rawUrl.startsWith("https://";)) {
+            return null;
+        }
 
-  @Nullable
-  private static URL parseURL(XmlAttributeValue value, String actionExtension) 
{
-    String rawUrl = value.getValue();
-    if (rawUrl.startsWith("http://";) ||
-        rawUrl.startsWith("https://";)) {
-      return null;
-    }
+        URL parsedURL;
+        try {
+            parsedURL = URI.create("http://"; + rawUrl).toURL();
+        } catch (Exception e) {
+            return null;
+        }
 
-    URL parsedURL;
-    try {
-      parsedURL = new URL("http://"; + rawUrl);
-    }
-    catch (Exception e) {
-      return null;
-    }
+        String host = parsedURL.getHost();
+        if (!StringUtil.isEmpty(host) &&
+                !(host.startsWith("${") && host.endsWith("}"))) {
+            return null;
+        }
 
-    String host = parsedURL.getHost();
-    if (!StringUtil.isEmpty(host) &&
-        !(host.startsWith("${") && host.endsWith("}"))) {
-      return null;
-    }
+        String path = parsedURL.getPath();
+        if (!path.endsWith(actionExtension)) {
+            return null;
+        }
 
-    String path = parsedURL.getPath();
-    if (!path.endsWith(actionExtension)) {
-      return null;
-    }
+        if (path.contains("${")) {
+            return null; // Dynamic action paths cannot be converted.
+        }
 
-    if (path.contains("${")) {
-      return null; // Dynamic action paths cannot be converted.
+        return parsedURL;
     }
-
-    return parsedURL;
-  }
 }
diff --git 
a/src/main/java/com/intellij/struts2/model/constant/contributor/ConstantValueClassConverter.java
 
b/src/main/java/com/intellij/struts2/model/constant/contributor/ConstantValueClassConverter.java
index 8ab013d..16b6aee 100644
--- 
a/src/main/java/com/intellij/struts2/model/constant/contributor/ConstantValueClassConverter.java
+++ 
b/src/main/java/com/intellij/struts2/model/constant/contributor/ConstantValueClassConverter.java
@@ -40,81 +40,83 @@ import java.util.Set;
  */
 class ConstantValueClassConverter extends ResolvingConverter<PsiClass> 
implements CustomReferenceConverter {
 
-  private final JavaClassReferenceProvider javaClassReferenceProvider = new 
JavaClassReferenceProvider();
-
-  private final Map<String, String> shortCutToPsiClassMap;
-  private final boolean hasShortCuts;
-
-  ConstantValueClassConverter(@NonNls @NotNull String baseClass,
-                              final Map<String, String> shortCutToPsiClassMap) 
{
-    this.shortCutToPsiClassMap = shortCutToPsiClassMap;
-    this.hasShortCuts = !shortCutToPsiClassMap.isEmpty();
-
-    javaClassReferenceProvider.setSoft(true);
-    javaClassReferenceProvider.setAllowEmpty(false);
-    javaClassReferenceProvider.setOption(JavaClassReferenceProvider.CONCRETE, 
Boolean.TRUE);
-    
javaClassReferenceProvider.setOption(JavaClassReferenceProvider.NOT_INTERFACE, 
Boolean.TRUE);
-    
javaClassReferenceProvider.setOption(JavaClassReferenceProvider.EXTEND_CLASS_NAMES,
 new String[]{baseClass});
-  }
-
-  @NotNull
-  @Override
-  public Collection<? extends PsiClass> getVariants(ConvertContext context) {
-    return Collections.emptyList();
-  }
-
-  @Override
-  public PsiClass fromString(@Nullable @NonNls final String s, final 
ConvertContext convertContext) {
-    if (s == null) {
-      return null;
+    private final JavaClassReferenceProvider javaClassReferenceProvider = new 
JavaClassReferenceProvider();
+
+    private final Map<String, String> shortCutToPsiClassMap;
+    private final boolean hasShortCuts;
+
+    ConstantValueClassConverter(@NonNls @NotNull String baseClass,
+                                final Map<String, String> 
shortCutToPsiClassMap) {
+        this.shortCutToPsiClassMap = shortCutToPsiClassMap;
+        this.hasShortCuts = !shortCutToPsiClassMap.isEmpty();
+
+        javaClassReferenceProvider.setSoft(true);
+        javaClassReferenceProvider.setAllowEmpty(false);
+        
javaClassReferenceProvider.setOption(JavaClassReferenceProvider.CONCRETE, 
Boolean.TRUE);
+        
javaClassReferenceProvider.setOption(JavaClassReferenceProvider.NOT_INTERFACE, 
Boolean.TRUE);
+        // TODO: EXTEND_CLASS_NAMES is deprecated but no replacement is 
documented.
+        //noinspection deprecation
+        
javaClassReferenceProvider.setOption(JavaClassReferenceProvider.EXTEND_CLASS_NAMES,
 new String[]{baseClass});
     }
 
-    // 1. via shortcut
-    if (hasShortCuts) {
-      final String shortCutClassName = shortCutToPsiClassMap.get(s);
+    @NotNull
+    @Override
+    public Collection<? extends PsiClass> getVariants(ConvertContext context) {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public PsiClass fromString(@Nullable @NonNls final String s, final 
ConvertContext convertContext) {
+        if (s == null) {
+            return null;
+        }
+
+        // 1. via shortcut
+        if (hasShortCuts) {
+            final String shortCutClassName = shortCutToPsiClassMap.get(s);
+
+            if (StringUtil.isNotEmpty(shortCutClassName)) {
+                return DomJavaUtil.findClass(shortCutClassName, 
convertContext.getInvocationElement());
+            }
+        }
+
+        // 2. first non-null result from extension point contributor 
(currently only Spring)
+        for (final ConstantValueConverterClassContributor 
converterClassContributor :
+                
ConstantValueConverterClassContributor.EP_NAME.getExtensionList()) {
+            final PsiClass contributorClass = 
converterClassContributor.fromString(s, convertContext);
+            if (contributorClass != null) {
+                return contributorClass;
+            }
+        }
+
+        // 3. via JAVA-class
+        final PsiClass psiClass = DomJavaUtil.findClass(s, 
convertContext.getInvocationElement());
+        if (psiClass == null) {
+            return null;
+        }
+        return !psiClass.isInterface() && 
!psiClass.hasModifierProperty(PsiModifier.ABSTRACT) ? psiClass : null;
+    }
+
+    @Override
+    public String toString(@Nullable PsiClass aClass, ConvertContext context) {
+        return aClass == null ? null : aClass.getName();
+    }
 
-      if (StringUtil.isNotEmpty(shortCutClassName)) {
-        return DomJavaUtil.findClass(shortCutClassName, 
convertContext.getInvocationElement());
-      }
+    @Override
+    @NotNull
+    public Set<String> getAdditionalVariants(@NotNull final ConvertContext 
context) {
+        return shortCutToPsiClassMap.keySet();
     }
 
-    // 2. first non-null result from extension point contributor (currently 
only Spring)
-    for (final ConstantValueConverterClassContributor 
converterClassContributor :
-      ConstantValueConverterClassContributor.EP_NAME.getExtensionList()) {
-      final PsiClass contributorClass = 
converterClassContributor.fromString(s, convertContext);
-      if (contributorClass != null) {
-        return contributorClass;
-      }
+    @Override
+    public PsiReference @NotNull [] createReferences(GenericDomValue value, 
PsiElement element, ConvertContext context) {
+        final PsiReference[] references = 
javaClassReferenceProvider.getReferencesByElement(element);
+        //noinspection unchecked
+        return ArrayUtil.append(references, new 
GenericDomValueReference(value), PsiReference.ARRAY_FACTORY);
     }
 
-    // 3. via JAVA-class
-    final PsiClass psiClass = DomJavaUtil.findClass(s, 
convertContext.getInvocationElement());
-    if (psiClass == null) {
-      return null;
+    @Override
+    public String getErrorMessage(@Nullable final String s, final 
ConvertContext context) {
+        return CodeInsightBundle.message("error.cannot.resolve.class", s);
     }
-    return !psiClass.isInterface() && 
!psiClass.hasModifierProperty(PsiModifier.ABSTRACT) ? psiClass : null;
-  }
-
-  @Override
-  public String toString(@Nullable PsiClass aClass, ConvertContext context) {
-    return aClass == null ? null : aClass.getName();
-  }
-
-  @Override
-  @NotNull
-  public Set<String> getAdditionalVariants(@NotNull final ConvertContext 
context) {
-    return shortCutToPsiClassMap.keySet();
-  }
-
-  @Override
-  public PsiReference @NotNull [] createReferences(GenericDomValue value, 
PsiElement element, ConvertContext context) {
-    final PsiReference[] references = 
javaClassReferenceProvider.getReferencesByElement(element);
-    //noinspection unchecked
-    return ArrayUtil.append(references, new GenericDomValueReference(value), 
PsiReference.ARRAY_FACTORY);
-  }
-
-  @Override
-  public String getErrorMessage(@Nullable final String s, final ConvertContext 
context) {
-    return CodeInsightBundle.message("error.cannot.resolve.class", s);
-  }
 }
diff --git 
a/src/main/java/com/intellij/struts2/velocity/Struts2GlobalMacroProvider.java 
b/src/main/java/com/intellij/struts2/velocity/Struts2GlobalMacroProvider.java
index 8b9c5eb..0491431 100644
--- 
a/src/main/java/com/intellij/struts2/velocity/Struts2GlobalMacroProvider.java
+++ 
b/src/main/java/com/intellij/struts2/velocity/Struts2GlobalMacroProvider.java
@@ -16,7 +16,9 @@ package com.intellij.struts2.velocity;
 
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.module.ModuleUtilCore;
+import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
 import com.intellij.psi.search.FilenameIndex;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.velocity.VtlGlobalMacroProvider;
@@ -34,27 +36,28 @@ import java.util.Collections;
  * @author Yann C&eacute;bron
  */
 final class Struts2GlobalMacroProvider extends VtlGlobalMacroProvider {
-  @NonNls
-  private static final String STRUTS_MACROS_FILENAME = "struts.vm";
+    @NonNls
+    private static final String STRUTS_MACROS_FILENAME = "struts.vm";
 
-  @NotNull
-  @Override
-  public Collection<VtlMacro> getGlobalMacros(@NotNull final VtlFile vtlFile) {
-    final Module module = ModuleUtilCore.findModuleForPsiElement(vtlFile);
-    if (module == null) {
-      return Collections.emptySet();
-    }
+    @NotNull
+    @Override
+    public Collection<VtlMacro> getGlobalMacros(@NotNull final VtlFile 
vtlFile) {
+        final Module module = ModuleUtilCore.findModuleForPsiElement(vtlFile);
+        if (module == null) {
+            return Collections.emptySet();
+        }
 
-    final PsiFile[] filesByName = 
FilenameIndex.getFilesByName(vtlFile.getProject(),
-                                                               
STRUTS_MACROS_FILENAME,
-                                                               
GlobalSearchScope.moduleRuntimeScope(module, false));
-    if (filesByName.length == 1) {
-      final PsiFile psiFile = filesByName[0];
-      if (psiFile instanceof VtlFile) {
-        return ((VtlFile) psiFile).getDefinedMacros();
-      }
-    }
+        final Collection<VirtualFile> virtualFiles = 
FilenameIndex.getVirtualFilesByName(
+                STRUTS_MACROS_FILENAME,
+                GlobalSearchScope.moduleRuntimeScope(module, false));
+        if (virtualFiles.size() == 1) {
+            final VirtualFile virtualFile = virtualFiles.iterator().next();
+            final PsiFile psiFile = 
PsiManager.getInstance(vtlFile.getProject()).findFile(virtualFile);
+            if (psiFile instanceof VtlFile) {
+                return ((VtlFile) psiFile).getDefinedMacros();
+            }
+        }
 
-    return Collections.emptySet();
-  }
+        return Collections.emptySet();
+    }
 }
\ No newline at end of file

Reply via email to