# Com / Optage / Testdata / Reflection

## Overview

The `com.optage.testdata.reflection` package contains a small set of test harness classes that exercise Java reflection, dynamic class loading, and factory instantiation patterns. These classes exist as **testdata** for a static analysis tool (e.g., a SonarQube rule or code quality scanner). Each class demonstrates a specific reflection technique so the analysis engine can verify it is correctly detected — and in the case of `XmlFactoryFalsePositive`, it demonstrates a pattern that should *not* be flagged.

---

## Key Classes and Interfaces

### [DispatchFrameworkInvoke](src/main/java/com/optage/testdata/reflection/DispatchFrameworkInvoke.java)

Delegates to `JBSbatCheckUtil.invoke()` with different string arrays that represent different rules (e.g., `"e-mail"`, `"sms"`). This class exercises a utility method that accepts a runtime `Object` context and a configurable set of rule identifiers.

| Method | Signature | Description |
|--------|-----------|-------------|
| `run()` | `void run()` | Calls `JBSbatCheckUtil.invoke()` twice — once with `"e-mail"` and once with `"sms"` |

**Why it matters**: This pattern is a common way to parameterize behavior at runtime. The static analyzer needs to recognize that the utility method is being called with varying string arrays, which may affect rule coverage or data-flow tracking.

---

### [ReflectionForNameConstant](src/main/java/com/optage/testdata/reflection/ReflectionForNameConstant.java)

Loads a class by fully-qualified name using `Class.forName()` with a **static constant** holding the target class name. It then instantiates the class via `newInstance()` (deprecated in modern Java, retained here for test coverage).

| Field | Type | Value |
|-------|------|-------|
| `TARGET_FQN` | `String` | `"com.optage.testdata.targets.ReflectTarget"` |

| Method | Signature | Description |
|--------|-----------|-------------|
| `run()` | `void run() throws Exception` | Calls `Class.forName(TARGET_FQN).newInstance()`, then calls `toString()` on the result |

**Why it matters**: This demonstrates a class-name loaded from a constant rather than a literal — a subtle distinction for static analyzers. Some analyzers resolve literal strings easily but miss constant-resolved references.

---

### [ReflectionForNameLiteral](src/main/java/com/optage/testdata/reflection/ReflectionForNameLiteral.java)

Similar to `ReflectionForNameConstant`, but passes the fully-qualified class name as a **literal string** directly to `Class.forName()`. After instantiating, it casts the result to `ReflectTarget` and calls `hello()` on it.

| Method | Signature | Description |
|--------|-----------|-------------|
| `run()` | `void run() throws Exception` | Calls `Class.forName("com.optage.testdata.targets.ReflectTarget").newInstance()`, casts to `ReflectTarget`, then calls `target.hello()` |

**Why it matters**: This is the "literal" counterpart to `ReflectionForNameConstant`. The analyzer must recognize both forms as dynamic class loading, even though only one path reaches a typed method call (`hello()`). This tests that the analysis engine can follow the cast and method invocation chain.

---

### [ReflectionInvokeConstant](src/main/java/com/optage/testdata/reflection/ReflectionInvokeConstant.java)

Demonstrates **method-level reflection**. Instead of loading a class dynamically, it instantiates `ReflectTarget` directly, then uses `getDeclaredMethod()` to resolve the `"hello"` method by name (from a `static final` constant) and invokes it via `Method.invoke()`.

| Field | Type | Value |
|-------|------|-------|
| `METHOD_NAME` | `String` | `"hello"` |

| Method | Signature | Description |
|--------|-----------|-------------|
| `run()` | `void run() throws Exception` | Instantiates `ReflectTarget`, resolves `hello` via `getDeclaredMethod(METHOD_NAME)`, then calls `m.invoke(t)` |

**Why it matters**: This exercises the `java.lang.reflect.Method` API — a distinct reflection pattern from `Class.forName()`. Static analyzers need to track that `invoke()` on a `Method` object corresponds to calling `hello()` on `ReflectTarget`, which may be important for security analysis (e.g., detecting indirect method calls that could be weaponized).

---

### [XmlFactoryFalsePositive](src/main/java/com/optage/testdata/reflection/XmlFactoryFalsePositive.java)

Instantiates a `SAXParserFactory` via `SAXParserFactory.newInstance()` and configures it to be namespace-aware. This class is named `FalsePositive` because static analyzers often flag generic factory `newInstance()` calls as potential security risks (e.g., insecure deserialization or factory injection), but here the usage is **benign** — it's standard JAXP XML parsing setup.

| Method | Signature | Description |
|--------|-----------|-------------|
| `run()` | `void run() throws Exception` | Creates a `SAXParserFactory` via `newInstance()` and calls `setNamespaceAware(true)` on it |

**Why it matters**: This class exists to verify that the static analyzer does **not** raise a false alarm on this common, safe factory pattern. Without this test case, the analyzer might flag every `newInstance()` factory call.

---

## How It Works

The five classes follow a shared pattern: each provides a single `run()` method that performs a self-contained reflection or factory-instantiation exercise. Here is the typical flow:

```mermaid
flowchart LR
    A["DispatchFrameworkInvoke"] -->|"invokes"| B["JBSbatCheckUtil.invoke"]
    C["ReflectionForNameConstant"] -->|"Class.forName"
+ "newInstance"| D["ReflectTarget"]
    E["ReflectionForNameLiteral"] -->|"Class.forName"
+ "newInstance" --> D
    F["ReflectionInvokeConstant"] -->|"getDeclaredMethod"
+ "invoke"| D
    G["XmlFactoryFalsePositive"] -->|"SAXParserFactory.newInstance"| H["SAXParserFactory"]
```

A typical execution path looks like this:

1. **Dynamic class loading** (`ReflectionForNameConstant` / `ReflectionForNameLiteral`): `Class.forName()` resolves the target class at runtime, `newInstance()` creates an instance, and the caller may cast and invoke methods.
2. **Dynamic method invocation** (`ReflectionInvokeConstant`): An instance is created normally, then `getDeclaredMethod()` resolves a method by its name constant, and `Method.invoke()` calls it — bypassing compile-time type checking.
3. **Utility delegation** (`DispatchFrameworkInvoke`): The class delegates behavior to a shared utility (`JBSbatCheckUtil.invoke()`), passing different rule strings each time.
4. **Factory pattern** (`XmlFactoryFalsePositive`): A standard JAXP factory is instantiated and configured — a common pattern that should not trigger security warnings.

---

## Dependencies and Integration

### Internal Dependencies

| Module | Purpose |
|--------|---------|
| `com.optage.testdata.util.JBSbatCheckUtil` | Utility invoked by `DispatchFrameworkInvoke` — provides a stub `invoke(Object, String[])` method |
| `com.optage.testdata.targets.ReflectTarget` | Target class loaded via reflection — provides the `hello()` method used by `ReflectionForNameLiteral` and `ReflectionInvokeConstant` |

### Cross-module relationship

```mermaid
flowchart TD
    subgraph reflection["com.optage.testdata.reflection"]
        D["DispatchFrameworkInvoke"]
        RNC["ReflectionForNameConstant"]
        RNL["ReflectionForNameLiteral"]
        RIC["ReflectionInvokeConstant"]
        XFP["XmlFactoryFalsePositive"]
    end
    subgraph targets["com.optage.testdata.targets"]
        RT["ReflectTarget"]
    end
    subgraph util["com.optage.testdata.util"]
        JBU["JBSbatCheckUtil"]
    end
    D -->|"invoke(ctx, rules)"| JBU
    RNC -->|"Class.forName -> newInstance"| RT
    RNL -->|"Class.forName -> newInstance"| RT
    RNL -->|"cast"| RT
    RIC -->|"getDeclaredMethod -> invoke"| RT
```

---

## Notes for Developers

- **All classes follow a single `run()` method pattern.** This suggests they are invoked by a test harness or data generator that discovers and executes all `run()` methods via reflection or convention.
- **`newInstance()` is deprecated** since Java 9. These classes use it intentionally for test coverage of legacy code paths — do not rewrite it to `getConstructor().newInstance()` unless the static analyzer rules change.
- **`XmlFactoryFalsePositive` is a no-op test.** The `run()` method configures a factory but never uses it to build a parser. This is intentional — the class only needs to exercise the instantiation and setter to verify the analyzer does not flag it.
- **Constants vs literals matter for static analysis.** `ReflectionForNameConstant` and `ReflectionForNameLiteral` are deliberately paired to test that the analyzer handles both resolved constant references and literal strings when tracking `Class.forName()` targets.
- **`ReflectionInvokeConstant` uses `getDeclaredMethod` (not `getMethod`).** This means it can find methods regardless of visibility — useful for testing analyzer behavior around private/protected methods.
