diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index c651c7a..3e04d3a 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -12,7 +12,7 @@ jobs: strategy: fail-fast: false matrix: - java: [ '11' ] + java: [ '17' ] os: [ 'ubuntu-latest' ] name: Java ${{ matrix.Java }} (${{ matrix.os }}) steps: diff --git a/CLAUDE.md b/CLAUDE.md index 5bcce6b..e419c0d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Project Overview -Java SAML toolkit (forked from SAML-Toolkits/java-saml, maintained by CodeLibs) implementing SAML 2.0 SP operations. Multi-module Maven project targeting Java 11+. +Java SAML toolkit (forked from SAML-Toolkits/java-saml, maintained by CodeLibs) implementing SAML 2.0 SP operations. Multi-module Maven project targeting Java 17+. ## Build Commands @@ -18,7 +18,7 @@ mvn test -Dtest=AuthnRequestTest # Run single test class mvn test -Dtest=AuthnRequestTest#testMethod # Run single test method ``` -No code formatter or linter is configured. CI runs `mvn -B package` on Java 11/Ubuntu via GitHub Actions. +No code formatter or linter is configured. CI runs `mvn -B package` on Java 17/Ubuntu via GitHub Actions. ## Module Structure diff --git a/core/pom.xml b/core/pom.xml index 55019d5..039dcfe 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -3,7 +3,7 @@ org.codelibs java-saml-toolkit - 3.0.2-SNAPSHOT + 3.1.0-SNAPSHOT jar diff --git a/core/src/main/java/org/codelibs/saml2/core/settings/Saml2Settings.java b/core/src/main/java/org/codelibs/saml2/core/settings/Saml2Settings.java index f82a318..4f17e28 100644 --- a/core/src/main/java/org/codelibs/saml2/core/settings/Saml2Settings.java +++ b/core/src/main/java/org/codelibs/saml2/core/settings/Saml2Settings.java @@ -1117,11 +1117,11 @@ public boolean checkSPCerts() { * @return true if the SP settings are valid */ private boolean checkRequired(final Object value) { - if ((value == null) || (value instanceof String && ((String) value).isEmpty())) { + if ((value == null) || (value instanceof String s && s.isEmpty())) { return false; } - if (value instanceof List && ((List) value).isEmpty()) { + if (value instanceof List l && l.isEmpty()) { return false; } return true; diff --git a/core/src/main/java/org/codelibs/saml2/core/settings/SettingsBuilder.java b/core/src/main/java/org/codelibs/saml2/core/settings/SettingsBuilder.java index 12dc56f..18ba39e 100644 --- a/core/src/main/java/org/codelibs/saml2/core/settings/SettingsBuilder.java +++ b/core/src/main/java/org/codelibs/saml2/core/settings/SettingsBuilder.java @@ -697,7 +697,7 @@ private SortedMap extractIndexedValues(final String prefix, fin */ private List toStringList(final Map indexedValues) { return indexedValues.values().stream().map(value -> isString(value) ? StringUtils.trimToNull((String) value) : null) - .filter(Objects::nonNull).collect(Collectors.toList()); + .filter(Objects::nonNull).toList(); } /** @@ -812,8 +812,8 @@ private Boolean loadBooleanProperty(final String propertyKey) { return Boolean.parseBoolean(((String) propValue).trim()); } - if (propValue instanceof Boolean) { - return (Boolean) propValue; + if (propValue instanceof Boolean b) { + return b; } return null; } @@ -835,8 +835,8 @@ private List loadListProperty(final String propertyKey) { return Arrays.asList(values); } - if (propValue instanceof List) { - return (List) propValue; + if (propValue instanceof List list) { + return (List) list; } return null; } @@ -861,8 +861,8 @@ private URL loadURLProperty(final String propertyKey) { } } - if (propValue instanceof URL) { - return (URL) propValue; + if (propValue instanceof URL url) { + return url; } return null; @@ -873,8 +873,8 @@ protected PrivateKey getPrivateKeyFromKeyStore(final KeyStore keyStore, final St try { if (keyStore.containsAlias(alias)) { key = keyStore.getKey(alias, password.toCharArray()); - if (key instanceof PrivateKey) { - return (PrivateKey) key; + if (key instanceof PrivateKey pk) { + return pk; } } else { LOGGER.warn("Entry for alias {} not found in keystore", alias); @@ -891,8 +891,8 @@ protected X509Certificate getCertificateFromKeyStore(final KeyStore keyStore, fi final Key key = keyStore.getKey(alias, password.toCharArray()); if (key instanceof PrivateKey) { final Certificate cert = keyStore.getCertificate(alias); - if (cert instanceof X509Certificate) { - return (X509Certificate) cert; + if (cert instanceof X509Certificate x509) { + return x509; } } } else { @@ -922,8 +922,8 @@ protected X509Certificate loadCertificateFromProp(final Object propValue) { } } - if (propValue instanceof X509Certificate) { - return (X509Certificate) propValue; + if (propValue instanceof X509Certificate cert) { + return cert; } return null; @@ -1018,8 +1018,8 @@ protected PrivateKey loadPrivateKeyFromProp(final String propertyKey) { } } - if (propValue instanceof PrivateKey) { - return (PrivateKey) propValue; + if (propValue instanceof PrivateKey pk) { + return pk; } return null; @@ -1055,6 +1055,6 @@ private void parseKeyStore(final KeyStoreSettings setting) { * @param propValue the Object to be verified */ private boolean isString(final Object propValue) { - return propValue instanceof String && StringUtils.isNotBlank((String) propValue); + return propValue instanceof String s && StringUtils.isNotBlank(s); } } diff --git a/core/src/main/java/org/codelibs/saml2/core/util/SchemaFactory.java b/core/src/main/java/org/codelibs/saml2/core/util/SchemaFactory.java index 3122950..a71a830 100644 --- a/core/src/main/java/org/codelibs/saml2/core/util/SchemaFactory.java +++ b/core/src/main/java/org/codelibs/saml2/core/util/SchemaFactory.java @@ -47,40 +47,35 @@ public LSInput resolveResource(final String type, final String namespaceURI, fin final String baseURI) { try { if (namespaceURI != null) { - switch (namespaceURI) { - case "urn:oasis:names:tc:SAML:2.0:assertion": - return getLocalResource("saml-schema-assertion-2.0.xsd"); - case "urn:oasis:names:tc:SAML:2.0:ac": - return getLocalResource("saml-schema-authn-context-2.0.xsd"); - case "urn:oasis:names:tc:SAML:2.0:metadata": - return getLocalResource("saml-schema-metadata-2.0.xsd"); - case "urn:oasis:names:tc:SAML:2.0:protocol": - return getLocalResource("saml-schema-protocol-2.0.xsd"); - case "urn:oasis:names:tc:SAML:metadata:attribute": - return getLocalResource("sstc-metadata-attr.xsd"); - case "urn:oasis:names:tc:SAML:attribute:ext": - return getLocalResource("sstc-saml-attribute-ext.xsd"); - case "urn:oasis:names:tc:SAML:metadata:algsupport": - return getLocalResource("sstc-saml-metadata-algsupport-v1.0.xsd"); - case "urn:oasis:names:tc:SAML:metadata:ui": - return getLocalResource("sstc-saml-metadata-ui-v1.0.xsd"); - case "http://www.w3.org/2001/04/xmlenc#": - return getLocalResource("xenc-schema.xsd"); - case "http://www.w3.org/XML/1998/namespace": - return getLocalResource("xml.xsd"); - case "http://www.w3.org/2000/09/xmldsig#": - return getLocalResource("xmldsig-core-schema.xsd"); + final LSInput result = switch (namespaceURI) { + case "urn:oasis:names:tc:SAML:2.0:assertion" -> getLocalResource("saml-schema-assertion-2.0.xsd"); + case "urn:oasis:names:tc:SAML:2.0:ac" -> getLocalResource("saml-schema-authn-context-2.0.xsd"); + case "urn:oasis:names:tc:SAML:2.0:metadata" -> getLocalResource("saml-schema-metadata-2.0.xsd"); + case "urn:oasis:names:tc:SAML:2.0:protocol" -> getLocalResource("saml-schema-protocol-2.0.xsd"); + case "urn:oasis:names:tc:SAML:metadata:attribute" -> getLocalResource("sstc-metadata-attr.xsd"); + case "urn:oasis:names:tc:SAML:attribute:ext" -> getLocalResource("sstc-saml-attribute-ext.xsd"); + case "urn:oasis:names:tc:SAML:metadata:algsupport" -> getLocalResource("sstc-saml-metadata-algsupport-v1.0.xsd"); + case "urn:oasis:names:tc:SAML:metadata:ui" -> getLocalResource("sstc-saml-metadata-ui-v1.0.xsd"); + case "http://www.w3.org/2001/04/xmlenc#" -> getLocalResource("xenc-schema.xsd"); + case "http://www.w3.org/XML/1998/namespace" -> getLocalResource("xml.xsd"); + case "http://www.w3.org/2000/09/xmldsig#" -> getLocalResource("xmldsig-core-schema.xsd"); + default -> null; + }; + if (result != null) { + return result; } } if ("saml-schema-authn-context-types-2.0.xsd".equals(systemId)) { return getLocalResource("saml-schema-authn-context-types-2.0.xsd"); } if (publicId != null) { - switch (publicId.toUpperCase(Locale.ROOT)) { - case "-//W3C//DTD XMLSCHEMA 200102//EN": - return getLocalResource("XMLSchema.dtd"); - case "DATATYPES": - return getLocalResource("datatypes.dtd"); + final LSInput result = switch (publicId.toUpperCase(Locale.ROOT)) { + case "-//W3C//DTD XMLSCHEMA 200102//EN" -> getLocalResource("XMLSchema.dtd"); + case "DATATYPES" -> getLocalResource("datatypes.dtd"); + default -> null; + }; + if (result != null) { + return result; } } } catch (final Throwable e) { diff --git a/core/src/main/java/org/codelibs/saml2/core/util/Util.java b/core/src/main/java/org/codelibs/saml2/core/util/Util.java index c4db522..c041212 100644 --- a/core/src/main/java/org/codelibs/saml2/core/util/Util.java +++ b/core/src/main/java/org/codelibs/saml2/core/util/Util.java @@ -68,7 +68,7 @@ import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; -import javax.xml.xpath.XPathFactoryConfigurationException; + import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.digest.DigestUtils; @@ -187,33 +187,6 @@ public static Document loadXML(final String xml) { } private static XPathFactory getXPathFactory() { - try { - /* - * Since different environments may return a different XPathFactoryImpl, we should try to initialize the factory - * using specific implementation that way the XML is parsed in an expected way. - * - * We should use the standard XPathFactoryImpl that comes standard with Java. - * - * NOTE: We could implement a check to see if the "javax.xml.xpath.XPathFactory" System property exists and is set - * to a value, if people have issues with using the specified implementor. This would allow users to always - * override the implementation if they so need to. - */ - return XPathFactory.newInstance(XPathFactory.DEFAULT_OBJECT_MODEL_URI, - "com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl", java.lang.ClassLoader.getSystemClassLoader()); - } catch (final XPathFactoryConfigurationException e) { - LOGGER.debug("Exception generating XPathFactory instance with default implementation.", e); - } - - /* - * If the expected XPathFactory did not exist, we fallback to loading the one defined as the default. - * - * If this is still throwing an error, the developer can set the "javax.xml.xpath.XPathFactory" system property - * to specify the default XPathFactoryImpl implementation to use. For example: - * - * -Djavax.xml.xpath.XPathFactory:http://java.sun.com/jaxp/xpath/dom=net.sf.saxon.xpath.XPathFactoryImpl - * -Djavax.xml.xpath.XPathFactory:http://java.sun.com/jaxp/xpath/dom=com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl - * - */ return XPathFactory.newInstance(); } diff --git a/pom.xml b/pom.xml index 3bfca41..2a0a906 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 org.codelibs java-saml-toolkit - 3.0.2-SNAPSHOT + 3.1.0-SNAPSHOT pom java-saml Toolkit Project A Java SAML toolkit @@ -94,7 +94,7 @@ maven-compiler-plugin 3.11.0 - 11 + 17 UTF-8 @@ -119,7 +119,7 @@ UTF-8 UTF-8 en_US - 11 + 17 diff --git a/samples/java-saml-tookit-jspsample/src/main/webapp/WEB-INF/web.xml b/samples/java-saml-tookit-jspsample/src/main/webapp/WEB-INF/web.xml index c1ea795..f8acc06 100644 --- a/samples/java-saml-tookit-jspsample/src/main/webapp/WEB-INF/web.xml +++ b/samples/java-saml-tookit-jspsample/src/main/webapp/WEB-INF/web.xml @@ -1,7 +1,7 @@ - + xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee + https://jakarta.ee/xml/ns/jakartaee/web-app_6_1.xsd" + version="6.1"> \ No newline at end of file diff --git a/toolkit/pom.xml b/toolkit/pom.xml index 6b7c30c..16f0974 100644 --- a/toolkit/pom.xml +++ b/toolkit/pom.xml @@ -3,7 +3,7 @@ org.codelibs java-saml-toolkit - 3.0.2-SNAPSHOT + 3.1.0-SNAPSHOT jar java-saml Toolkit