diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..d5d65d6
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,18 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 4
+trim_trailing_whitespace = true
+
+[*.{yaml,yml}]
+indent_size = 2
+
+[*.md]
+trim_trailing_whitespace = false
+
+[*.{bat,cmd}]
+end_of_line = crlf
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..edf4192
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,11 @@
+# Normalize repository text while preserving binary artifacts and fixtures.
+* text=auto eol=lf
+*.bat text eol=crlf
+*.cmd text eol=crlf
+*.gif binary
+*.ico binary
+*.jar binary
+*.jpg binary
+*.pdf binary
+*.png binary
+*.zip binary
diff --git a/.gitignore b/.gitignore
index adc5f64..fd4967b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,4 @@
-*/target/**
-/target/**
+target/
# Intellij project files
*.iml
*.ipr
@@ -15,12 +14,6 @@ maven-eclipse.xml
nb-configuration.xml
*/nbproject/*
-/jsp/target/
-/esapi/target/
-/target/
-/jakarta/target/
-/jakarta-test/target/
-
# Python CI/compatibility tooling
__pycache__/
*.pyc
diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF
deleted file mode 100644
index 2aaee67..0000000
--- a/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,9 +0,0 @@
-Manifest-Version: 1.0
-Bnd-LastModified: 1533328833261
-Bundle-ManifestVersion: 2
-Bundle-Name: org.owasp.encoder
-Bundle-SymbolicName: org.owasp.encoder
-Bundle-Version: 1.2.1
-Created-By: 1.8.0_181 (Oracle Corporation)
-Export-Package: org.owasp.encoder
-Tool: Bnd-1.50.0
diff --git a/compatibility/README.md b/compatibility/README.md
index 2e23c63..490f44b 100644
--- a/compatibility/README.md
+++ b/compatibility/README.md
@@ -126,3 +126,9 @@ reports, preparation output, and each runtime's output even when a step fails.
The Docker-free [Jasper engine fixture](jsp-engine/README.md) also runs in normal
`verify`: it compiles and serves both packaged TLD surfaces on maintained javax
and Jakarta engines, with exact-byte and translation-rejection assertions.
+
+Preparation also verifies each source attachment against the main sources and
+requires its Java 9 descriptor at `META-INF/versions/9/module-info.java`, plus a
+Javadoc index in every documentation attachment. Descriptor sources are added
+only after compilation/resource copying; Java 8 compiler inputs and the binary
+multi-release layout remain unchanged.
diff --git a/compatibility/consumers.py b/compatibility/consumers.py
index 1bc5752..4aee51e 100644
--- a/compatibility/consumers.py
+++ b/compatibility/consumers.py
@@ -147,6 +147,20 @@ def metadata(kind, jar, core):
print('Metadata passed:', jar.name)
+def source_metadata(kind, source_jar):
+ """A complete source attachment includes the separate Java 9 descriptor."""
+ with zipfile.ZipFile(source_jar) as archive:
+ names = archive.namelist()
+ assert len(names) == len(set(names)), ('duplicate source entry', source_jar)
+ for source in (ROOT / kind / 'src/main/java').rglob('*.java'):
+ name = source.relative_to(ROOT / kind / 'src/main/java').as_posix()
+ assert archive.read(name) == source.read_bytes(), ('source mismatch', name)
+ assert archive.read('META-INF/versions/9/module-info.java') == (
+ ROOT / kind / 'src/main/java9/module-info.java').read_bytes(), kind
+ assert 'module-info.java' not in names, ('descriptor in Java 8 source root', kind)
+ print('Source attachment passed:', source_jar.name)
+
+
def prepare(args):
out = args.directory.resolve()
if out.exists() and any(out.iterdir()):
@@ -166,6 +180,9 @@ def prepare(args):
target.parent.mkdir(exist_ok=True)
shutil.copy2(candidates[0], target)
jars[kind] = target
+ source_metadata(kind, candidates[0].with_name(candidates[0].stem + '-sources.jar'))
+ with zipfile.ZipFile(candidates[0].with_name(candidates[0].stem + '-javadoc.jar')) as docs:
+ assert 'index.html' in docs.namelist(), ('missing Javadoc index', kind)
for kind, jar in jars.items(): metadata(kind, jar, jars['core'])
run('javac', '--release', '9', '-d', out / 'metadata', SOURCE / 'ModuleMetadata.java')
run('java', '-cp', out / 'metadata', 'consumer.ModuleMetadata', *jars.values())
diff --git a/compatibility/tests/test_guards.py b/compatibility/tests/test_guards.py
index 83acd34..d6a945e 100644
--- a/compatibility/tests/test_guards.py
+++ b/compatibility/tests/test_guards.py
@@ -118,6 +118,22 @@ def test_changed_symbolic_name(self):
self.rejected('jakarta', lambda entries: self.header(
entries, 'Bundle-SymbolicName', lambda value: 'org.owasp.encoder.jakarta'))
+ def test_source_attachments(self):
+ for kind, jar in self.jars.items():
+ with self.subTest(artifact=kind):
+ consumers.source_metadata(kind, jar.with_name(jar.stem + '-sources.jar'))
+
+ def test_missing_source_descriptor(self):
+ original = self.jars['core'].with_name(self.jars['core'].stem + '-sources.jar')
+ with tempfile.TemporaryDirectory(prefix='encoder-source-guard-') as directory:
+ target = Path(directory) / original.name
+ with zipfile.ZipFile(original) as source, zipfile.ZipFile(target, 'w') as broken:
+ for name in source.namelist():
+ if name != 'META-INF/versions/9/module-info.java':
+ broken.writestr(name, source.read(name))
+ with self.assertRaises(KeyError):
+ consumers.source_metadata('core', target)
+
if __name__ == '__main__':
unittest.main()
diff --git a/core/pom.xml b/core/pom.xml
index 7893375..520c4eb 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -1,132 +1,132 @@
-
-
-
-
- 4.0.0
-
-
- org.owasp.encoder
- encoder-parent
- 1.5.0-SNAPSHOT
-
-
- encoder
- jar
-
- Java Encoder
-
- The OWASP Encoders package is a collection of high-performance low-overhead
- contextual encoders, that when utilized correctly, is an effective tool in
- preventing Web Application security vulnerabilities such as Cross-Site
- Scripting.
-
-
-
- org.owasp.encoder
- org.owasp.encoder
-
-
-
-
-
- org.apache.felix
- org.apache.felix.framework
- 5.6.12
- test
-
-
-
- com.fasterxml.jackson.core
- jackson-databind
- 2.22.3
- test
-
-
-
- org.jsoup
- jsoup
- 1.23.2
- test
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
-
-
- reactor-jar
- process-classes
-
- jar
-
-
-
-
- default-jar
- none
-
- jar
-
-
-
-
-
- org.apache.maven.plugins
- maven-failsafe-plugin
-
-
- ${project.build.directory}/${project.build.finalName}.jar
-
-
-
-
- osgi-compatibility
-
- integration-test
- verify
-
-
-
-
-
-
-
+
+
+
+
+ 4.0.0
+
+
+ org.owasp.encoder
+ encoder-parent
+ 1.5.0-SNAPSHOT
+
+
+ encoder
+ jar
+
+ Java Encoder
+
+ The OWASP Encoders package is a collection of high-performance low-overhead
+ contextual encoders, that when utilized correctly, is an effective tool in
+ preventing Web Application security vulnerabilities such as Cross-Site
+ Scripting.
+
+
+
+ org.owasp.encoder
+ org.owasp.encoder
+
+
+
+
+
+ org.apache.felix
+ org.apache.felix.framework
+ 5.6.12
+ test
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.22.3
+ test
+
+
+
+ org.jsoup
+ jsoup
+ 1.23.2
+ test
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+ reactor-jar
+ process-classes
+
+ jar
+
+
+
+
+ default-jar
+ none
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+ ${project.build.directory}/${project.build.finalName}.jar
+
+
+
+
+ osgi-compatibility
+
+ integration-test
+ verify
+
+
+
+
+
+
+
diff --git a/esapi/pom.xml b/esapi/pom.xml
index daa2f32..9a7fc4e 100644
--- a/esapi/pom.xml
+++ b/esapi/pom.xml
@@ -1,4 +1,4 @@
-
+
+ prepare-package
+ add-resource
+
+ true
+
+
+ ${project.basedir}/src/main/java9
+ META-INF/versions/9
+
+
+
+
+
+
org.apache.maven.plugins
maven-source-plugin
@@ -446,7 +468,7 @@
attach-sources
package
- jar
+ jar-no-fork
diff --git a/src/main/config/checkstyle.xml b/src/main/config/checkstyle.xml
index 0a5f0da..6656e95 100644
--- a/src/main/config/checkstyle.xml
+++ b/src/main/config/checkstyle.xml
@@ -1,4 +1,4 @@
-
+