From 40b6ab9eac53c582e0d9662ca3702ee3793e8b70 Mon Sep 17 00:00:00 2001 From: jansupol Date: Fri, 10 Nov 2023 12:46:03 +0100 Subject: [PATCH 1/2] Allow to set the UpgradeResponse status and headers Invoke ClientEndpointConfig.Configurator#afterResponse when error status Signed-off-by: jansupol --- .../resources/archetype-resources/pom.xml | 1 + bundles/samples/pom.xml | 3 +- bundles/websocket-ri-archive/pom.xml | 4 +- bundles/websocket-risrc-licensee/pom.xml | 6 +- .../tyrus/client/TyrusClientEngine.java | 4 +- .../tyrus/servlet/TyrusServletFilter.java | 17 +++-- .../tyrus/core/TyrusWebSocketEngine.java | 19 ++++- docs/pom.xml | 8 +- pom.xml | 10 ++- samples/pom.xml | 4 +- .../test/standard_config/HandshakeTest.java | 76 ++++++++++++++++++- .../glassfish/tyrus/tests/qa/BrowserTest.java | 6 +- .../tyrus/tests/qa/SeleniumToolkit.java | 19 +++-- 13 files changed, 142 insertions(+), 35 deletions(-) diff --git a/archetypes/echo/src/main/resources/archetype-resources/pom.xml b/archetypes/echo/src/main/resources/archetype-resources/pom.xml index 682032ae..19dd4862 100644 --- a/archetypes/echo/src/main/resources/archetype-resources/pom.xml +++ b/archetypes/echo/src/main/resources/archetype-resources/pom.xml @@ -23,6 +23,7 @@ org.apache.maven.plugins maven-compiler-plugin + 3.9.0 true ${java.version} diff --git a/bundles/samples/pom.xml b/bundles/samples/pom.xml index 68271662..e40cb0ed 100644 --- a/bundles/samples/pom.xml +++ b/bundles/samples/pom.xml @@ -114,6 +114,7 @@ maven-assembly-plugin + 3.6.0 src/main/assembly/examples-assembly.xml @@ -124,7 +125,7 @@ make-assembly package - attached + single diff --git a/bundles/websocket-ri-archive/pom.xml b/bundles/websocket-ri-archive/pom.xml index 8e14fdb4..3ffd6913 100755 --- a/bundles/websocket-ri-archive/pom.xml +++ b/bundles/websocket-ri-archive/pom.xml @@ -1,7 +1,7 @@ - attached + single diff --git a/bundles/websocket-risrc-licensee/pom.xml b/bundles/websocket-risrc-licensee/pom.xml index 68a4302b..7e83c334 100755 --- a/bundles/websocket-risrc-licensee/pom.xml +++ b/bundles/websocket-risrc-licensee/pom.xml @@ -1,7 +1,7 @@ - attached + single diff --git a/client/src/main/java/org/glassfish/tyrus/client/TyrusClientEngine.java b/client/src/main/java/org/glassfish/tyrus/client/TyrusClientEngine.java index 0a5bae98..1625a535 100644 --- a/client/src/main/java/org/glassfish/tyrus/client/TyrusClientEngine.java +++ b/client/src/main/java/org/glassfish/tyrus/client/TyrusClientEngine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2023 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -294,6 +294,8 @@ public ClientUpgradeInfo processResponse(final UpgradeResponse upgradeResponse, LocalizationMessages.HANDSHAKE_HTTP_RETRY_AFTER_MESSAGE(), delay)); return UPGRADE_INFO_FAILED; default: + ((ClientEndpointConfig) endpointWrapper.getEndpointConfig()).getConfigurator().afterResponse(upgradeResponse); + clientEngineState = TyrusClientEngineState.FAILED; HandshakeException e = new HandshakeException( upgradeResponse.getStatus(), diff --git a/containers/servlet/src/main/java/org/glassfish/tyrus/servlet/TyrusServletFilter.java b/containers/servlet/src/main/java/org/glassfish/tyrus/servlet/TyrusServletFilter.java index 9fa26bdc..eb96fda1 100644 --- a/containers/servlet/src/main/java/org/glassfish/tyrus/servlet/TyrusServletFilter.java +++ b/containers/servlet/src/main/java/org/glassfish/tyrus/servlet/TyrusServletFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2017 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -229,7 +229,7 @@ public boolean isUserInRole(String role) { final WebSocketEngine.UpgradeInfo upgradeInfo = engine.upgrade(requestContext, tyrusUpgradeResponse); switch (upgradeInfo.getStatus()) { case HANDSHAKE_FAILED: - appendTraceHeaders(httpServletResponse, tyrusUpgradeResponse); + appendAllHeaders(httpServletResponse, tyrusUpgradeResponse); httpServletResponse.sendError(tyrusUpgradeResponse.getStatus()); break; case NOT_APPLICABLE: @@ -253,9 +253,7 @@ public boolean isUserInRole(String role) { } httpServletResponse.setStatus(tyrusUpgradeResponse.getStatus()); - for (Map.Entry> entry : tyrusUpgradeResponse.getHeaders().entrySet()) { - httpServletResponse.addHeader(entry.getKey(), Utils.getHeaderFromList(entry.getValue())); - } + appendAllHeaders(httpServletResponse, tyrusUpgradeResponse); response.flushBuffer(); LOGGER.fine("Handshake Complete"); @@ -283,7 +281,7 @@ public boolean isUserInRole(String role) { } } - private void appendTraceHeaders(HttpServletResponse httpServletResponse, TyrusUpgradeResponse + private static void appendTraceHeaders(HttpServletResponse httpServletResponse, TyrusUpgradeResponse tyrusUpgradeResponse) { for (Map.Entry> entry : tyrusUpgradeResponse.getHeaders().entrySet()) { if (entry.getKey().contains(UpgradeResponse.TRACING_HEADER_PREFIX)) { @@ -292,6 +290,13 @@ private void appendTraceHeaders(HttpServletResponse httpServletResponse, TyrusUp } } + private static void appendAllHeaders(HttpServletResponse httpServletResponse, TyrusUpgradeResponse + tyrusUpgradeResponse) { + for (Map.Entry> entry : tyrusUpgradeResponse.getHeaders().entrySet()) { + httpServletResponse.addHeader(entry.getKey(), Utils.getHeaderFromList(entry.getValue())); + } + } + private synchronized JAXBContext getWsadlJaxbContext() throws JAXBException { if (wsadlJaxbContext == null) { wsadlJaxbContext = JAXBContext.newInstance(Application.class.getPackage().getName()); diff --git a/core/src/main/java/org/glassfish/tyrus/core/TyrusWebSocketEngine.java b/core/src/main/java/org/glassfish/tyrus/core/TyrusWebSocketEngine.java index 7533735b..52751a70 100644 --- a/core/src/main/java/org/glassfish/tyrus/core/TyrusWebSocketEngine.java +++ b/core/src/main/java/org/glassfish/tyrus/core/TyrusWebSocketEngine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -401,8 +401,21 @@ public Map getProperties() { } response.getHeaders().putAll(debugContext.getTracingHeaders()); - return new SuccessfulUpgradeInfo(endpointWrapper, protocolHandler, incomingBufferSize, request, response, - extensionContext, debugContext); + switch (response.getStatus()) { + case 101: + case 300: + case 301: + case 302: + case 303: + case 307: + case 308: + case 401: + case 503: + return new SuccessfulUpgradeInfo(endpointWrapper, protocolHandler, incomingBufferSize, request, response, + extensionContext, debugContext); + default: + return new NoConnectionUpgradeInfo(UpgradeStatus.HANDSHAKE_FAILED); + } } response.setStatus(500); diff --git a/docs/pom.xml b/docs/pom.xml index 4a258ee3..76252f87 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -1,7 +1,7 @@ - 4.0.4 + 1.3.5 + 1.2.2 + 2.0.2 2.4.4 + 1.0 3.2.6 - 2.0.2 + 2.3.3 + 2.3.8 + 2.14.5 1.1.6 1.1.6 + 4.0.4 2.6.7 + 3.11.0 + 3.0.1 + 3.2.1 + 3.4.0 + javax.websocket org.glassfish 0.0 @@ -137,11 +148,6 @@ ${new_spec_version}-b${build_number} gf-cddl-gpl - - 3.0.1 - 2.3.3 - 2.3.8 - 1.3.5 @@ -159,86 +165,54 @@ - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - attach-sources - verify - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.8 - 1.8 - UTF-8 - - - - org.apache.maven.plugins - maven-release-plugin - - forked-path - false - ${release.arguments} - - - - org.apache.maven.plugins - maven-deploy-plugin - 2.8.1 - - 10 - - - - org.apache.maven.plugins - maven-checkstyle-plugin - 3.0.0 - - - com.puppycrawl.tools - checkstyle - 8.18 - - - - - validate - - check - - - true - true - etc/config/checkstyle-build.xml - true - **/guide/*,**/org/glassfish/tyrus/core/wsadl/model/**/*,**/LocalizationMessages.java - - - - - - + + maven-antrun-plugin + 3.1.0 + maven-assembly-plugin 3.6.0 - maven-antrun-plugin - 3.1.0 + maven-source-plugin + 3.3.0 + + + maven-compiler-plugin + ${maven.compiler.plugin} + + + maven-release-plugin + 3.0.1 + + + maven-dependency-plugin + 3.6.1 + + + maven-deploy-plugin + 3.1.1 + + + maven-surefire-plugin + ${maven.surefire.plugin.version} + + + maven-failsafe-plugin + 3.2.1 + + + maven-shade-plugin + 3.5.1 + + + maven-war-plugin + ${maven.war.plugin.version} + + false + org.glassfish.copyright @@ -256,6 +230,7 @@ true false + false false etc/config/copyright.txt @@ -264,7 +239,7 @@ org.codehaus.mojo build-helper-maven-plugin - 1.8 + 3.4.0 generate-sources @@ -313,23 +288,16 @@ org.apache.felix maven-bundle-plugin - 2.4.0 + 5.1.4 true <_versionpolicy>[$(version;==;$(@)),$(version;+;$(@))) <_nodefaultversion>false + {maven-resources},${project.build.directory}/legal - - org.apache.maven.plugins - maven-war-plugin - 3.4.0 - - false - - org.apache.maven.plugins maven-javadoc-plugin @@ -355,31 +323,196 @@ - - org.apache.maven.plugins - maven-surefire-plugin - 2.17 - - - org.apache.maven.plugins - maven-shade-plugin - 2.1 - org.codehaus.mojo exec-maven-plugin - 1.2.1 + 3.1.0 com.sun.tools.xjc.maven2 maven-jaxb-plugin 1.1.1 + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.0.0 + + + com.puppycrawl.tools + checkstyle + 8.18 + + + + + + + org.commonjava.maven.plugins + directory-maven-plugin + 1.0 + + + directories + + highest-basedir + + initialize + + legal.source.folder + + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + verify + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + UTF-8 + + + + org.apache.maven.plugins + maven-release-plugin + + forked-path + false + ${release.arguments} + + + + org.apache.maven.plugins + maven-deploy-plugin + + 10 + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + validate + + check + + + true + true + etc/config/checkstyle-build.xml + true + **/guide/*,**/org/glassfish/tyrus/core/wsadl/model/**/*,**/LocalizationMessages.java + + + + + + + copy-legal-docs + + + ${basedir}/src/test/java/org/glassfish/tyrus/test + + + + + + + org.apache.maven.plugins + maven-resources-plugin + 2.6 + true + + + + + copy-legaldocs + + copy-resources + + process-sources + + ${project.build.outputDirectory} + + + ${legal.source.folder} + META-INF/ + + NOTICE.md + LICENSE.md + + + + + + + + copy-legaldocs-to-sources + + copy-resources + + process-sources + + ${project.build.directory}/generated-sources/rsrc-gen + + + ${legal.source.folder} + META-INF/ + + NOTICE.md + LICENSE.md + + + + + + + + copy-legaldocs-to-osgi-bundles + + copy-resources + + process-sources + + ${project.build.directory}/legal + + + ${legal.source.folder} + META-INF/ + + NOTICE.md + LICENSE.md + + + + + + + + + + + release @@ -388,7 +521,6 @@ org.apache.maven.plugins maven-release-plugin - 2.5 forked-path false @@ -399,7 +531,6 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.9.1 128m 512m @@ -425,7 +556,6 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.9.1 *.tests.*,*.sample.* 128m @@ -467,7 +597,6 @@ org.apache.maven.plugins maven-checkstyle-plugin - 3.0.0 etc/config/checkstyle.xml diff --git a/tests/pom.xml b/tests/pom.xml index ecd1347b..438d0d25 100755 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -91,5 +91,14 @@ + + JDK11+ + + [11,) + + + release-test + + diff --git a/tests/release-test/README.MD b/tests/release-test/README.MD new file mode 100644 index 00000000..a8e96a58 --- /dev/null +++ b/tests/release-test/README.MD @@ -0,0 +1,20 @@ +[//]: # " Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. " +[//]: # " " +[//]: # " This program and the accompanying materials are made available under the " +[//]: # " terms of the Eclipse Public License v. 2.0, which is available at " +[//]: # " http://www.eclipse.org/legal/epl-2.0. " +[//]: # " " +[//]: # " This Source Code may also be made available under the following Secondary " +[//]: # " Licenses when the conditions for such availability set forth in the " +[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, " +[//]: # " version 2 with the GNU Classpath Exception, which is available at " +[//]: # " https://www.gnu.org/software/classpath/license.html. " +[//]: # " " +[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 " + +This module is to check the built artifacts before release. + +The module can check Tyrus 1.x, 2.0.x, and 2.1.x versions. + +Usage: + * mvn test -Dtyrus.version= [-Pstaging] diff --git a/tests/release-test/pom.xml b/tests/release-test/pom.xml new file mode 100644 index 00000000..202e8da0 --- /dev/null +++ b/tests/release-test/pom.xml @@ -0,0 +1,180 @@ + + + + + 4.0.0 + + + org.glassfish.tyrus + tyrus-project + 1.99-SNAPSHOT + ../../pom.xml + + + org.glassfish.tyrus.tests + tyrus-release-test + jar + Tyrus Release Test + + Tyrus post-release validation tests + + + 11 + 11 + 3.8.6 + 1.7.3 + 4.5.14 + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + 1 + false + false + + **/ArchetypesTest + **/NoticeFilesTest + + + + + + + + + + org.glassfish.tyrus + tyrus-bom + ${project.version} + import + pom + + + + + + + junit + junit + 4.13.2 + test + + + + + org.apache.maven + maven-core + ${maven.version} + provided + + + org.apache.maven + maven-model + ${maven.version} + provided + + + org.apache.maven + maven-compat + ${maven.version} + provided + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + test + + + + org.apache.maven.plugin-testing + maven-plugin-testing-harness + 3.3.0 + test + + + org.apache.maven.resolver + maven-resolver-connector-basic + ${maven.resolver.version} + + + org.apache.maven.resolver + maven-resolver-transport-http + ${maven.resolver.version} + + + org.apache.httpcomponents + httpcore + + + + + + org.glassfish.tyrus + tyrus-core + + + + + + ReleaseTests + + + tyrus.version + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M7 + + 1 + false + false + + **/DownloadBomPomDependencies + **/*Test + + + + + + + + + org.glassfish.tyrus + tyrus-bom + ${tyrus.version} + import + pom + + + + + ${tyrus.version} + + + + diff --git a/tests/release-test/src/main/java/org/glassfish/tyrus/test/artifacts/ClassVersionChecker.java b/tests/release-test/src/main/java/org/glassfish/tyrus/test/artifacts/ClassVersionChecker.java new file mode 100644 index 00000000..f988c01f --- /dev/null +++ b/tests/release-test/src/main/java/org/glassfish/tyrus/test/artifacts/ClassVersionChecker.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.tyrus.test.artifacts; + +import java.io.DataInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +class ClassVersionChecker { + static TestResult checkClassVersion(JarFile jar, JarEntry entry, Properties properties) throws IOException { + final String tyrusVersion = MavenUtil.getTyrusVersion(properties); + final int minVersion = tyrusVersion.startsWith("2.1") ? 11 : 8; + return checkClassVersion(jar.getInputStream(entry), jar.getName() + File.separator + entry.getName(), minVersion); + } + + private static TestResult checkClassVersion(InputStream inputStream, String filename, int version) throws IOException { + TestResult result = new TestResult(); + DataInputStream in = new DataInputStream(inputStream); + + int magic = in.readInt(); + if (magic != -889275714) { + result.exception().append(filename).println(" is not a valid class!"); + } + + int minor = in.readUnsignedShort(); + int major = in.readUnsignedShort(); + int classVersion = convertMajorMinorToSE(major, minor); + TestResult.MessageBuilder builder = classVersion <= version ? result.ok() : result.exception(); + builder.append(filename).append(": ").append(major).append(".").append(minor).append(" = JDK ") + .println(String.valueOf(classVersion)); + in.close(); + return result; + } + + private static int convertMajorMinorToSE(int major, int minor) { + int comp = (major - 44 + minor); + return comp; + } +} diff --git a/tests/release-test/src/main/java/org/glassfish/tyrus/test/artifacts/DependencyPair.java b/tests/release-test/src/main/java/org/glassfish/tyrus/test/artifacts/DependencyPair.java new file mode 100644 index 00000000..73514601 --- /dev/null +++ b/tests/release-test/src/main/java/org/glassfish/tyrus/test/artifacts/DependencyPair.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.tyrus.test.artifacts; + +import java.util.Arrays; + +class DependencyPair { + private final String groupId; + private final String artifactId; + + DependencyPair(String groupId, String artifactId) { + this.groupId = groupId; + this.artifactId = artifactId; + } + + String artifactId() { + return artifactId; + } + + String groupId() { + return groupId; + } + + static DependencyPair[] concat(DependencyPair[] first, DependencyPair[] second) { + DependencyPair[] result = Arrays.copyOf(first, first.length + second.length); + System.arraycopy(second, 0, result, first.length, second.length); + return result; + } + + @Override + public String toString() { + return groupId + ':' + artifactId; + } +} diff --git a/tests/release-test/src/main/java/org/glassfish/tyrus/test/artifacts/DependencyResolver.java b/tests/release-test/src/main/java/org/glassfish/tyrus/test/artifacts/DependencyResolver.java new file mode 100644 index 00000000..6227b25b --- /dev/null +++ b/tests/release-test/src/main/java/org/glassfish/tyrus/test/artifacts/DependencyResolver.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.tyrus.test.artifacts; + +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.artifact.DefaultArtifact; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.resolution.ArtifactRequest; +import org.eclipse.aether.resolution.ArtifactResolutionException; + +import java.util.List; + +/** + * + * @author lukas + */ +final class DependencyResolver { + static Artifact resolveArtifact(org.apache.maven.model.Dependency d, List remoteRepos, + RepositorySystem repoSystem, RepositorySystemSession repoSession) + throws ArtifactResolutionException { + DefaultArtifact artifact = new DefaultArtifact( + d.getGroupId(), d.getArtifactId(), d.getClassifier(), d.getType(), d.getVersion() + ); + ArtifactRequest request = new ArtifactRequest(); + request.setArtifact(artifact); + request.setRepositories(remoteRepos); + return repoSystem.resolveArtifact(repoSession, request).getArtifact(); + } +} \ No newline at end of file diff --git a/tests/release-test/src/main/java/org/glassfish/tyrus/test/artifacts/MavenUtil.java b/tests/release-test/src/main/java/org/glassfish/tyrus/test/artifacts/MavenUtil.java new file mode 100644 index 00000000..a3fd4221 --- /dev/null +++ b/tests/release-test/src/main/java/org/glassfish/tyrus/test/artifacts/MavenUtil.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.tyrus.test.artifacts; + +import org.apache.maven.model.Dependency; +import org.apache.maven.model.Model; +import org.apache.maven.model.Profile; +import org.apache.maven.model.io.xpp3.MavenXpp3Reader; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +import java.io.File; +import java.io.IOException; +import java.io.Reader; +import java.nio.file.Files; +import java.util.Collections; +import java.util.List; +import java.util.Properties; +import java.util.stream.Stream; + +public final class MavenUtil { + + static final String TYRUS_VERSION = "tyrus.version"; + private static final String PROJECT_VERSION = "project.version"; + + static File getArtifactJar(File repositoryRoot, Dependency dependency, Properties properties) { + return getArtifactFile(repositoryRoot, dependency, properties, "jar"); + } + + private static File getArtifactFile(File repositoryRoot, Dependency dependency, Properties properties, String extension) { + StringBuilder fileSuffix = new StringBuilder(); + String groupIdParts[] = dependency.getGroupId().split("\\."); + for (String groupIdPart : groupIdParts) { + fileSuffix.append(groupIdPart).append(File.separator); + } + String artifactIdParts[] = dependency.getArtifactId().split("\\."); + for (String artifactIdPart : artifactIdParts) { + fileSuffix.append(artifactIdPart).append(File.separator); + } + String version = MavenUtil.getDependencyVersion(dependency, properties); + fileSuffix.append(version).append(File.separator); + fileSuffix.append(dependency.getArtifactId()).append('-').append(version).append(".").append(extension); + return new File(repositoryRoot, fileSuffix.toString()); + } + + static String getDependencyVersion(Dependency dependency, Properties properties) { + String version = dependency.getVersion(); + if (version.startsWith("${") && version.endsWith("}")) { + String property = version.substring(2, version.length() - 1); + final String value; + switch (property) { + case TYRUS_VERSION: // in pom.xml + case PROJECT_VERSION: // in bom.pom + value = getTyrusVersion(properties); + break; + default: + value = properties.getProperty(property); + break; + } + version = value == null ? version : value; + } + return version; + } + + static File getLocalMavenRepository() { + String folder = System.getProperty("localRepository"); + return new File(folder); + } + + static Properties getMavenProperties() { + try { + Model model = getModelFromFile("pom.xml"); + return model.getProperties(); + } catch (XmlPullParserException | IOException e) { + throw new RuntimeException(e); + } + } + + static Stream keepTyrusJars(Stream stream, DependencyPair... keep) { + return stream.filter(dependency -> { + for (DependencyPair pair : keep) { + if (dependency.getGroupId().equals(pair.groupId()) && dependency.getArtifactId().equals(pair.artifactId())) { + return true; + } + } + return false; + }); + } + + static Stream streamTyrusJars() throws IOException, XmlPullParserException { + Model model = getModelFromFile("pom.xml"); + List deps = getBomPomDependencies(model); + + return deps.stream() + .filter(dep -> dep.getGroupId().startsWith("org.glassfish.tyrus")) + .filter(dep -> dep.getType().equals("jar")); + } + + static Model getModelFromFile(String fileName) throws IOException, XmlPullParserException { + File pomFile = new File(fileName); + return getModelFromFile(pomFile); + } + + private static Model getModelFromFile(File file) throws IOException, XmlPullParserException { + MavenXpp3Reader mavenReader = new MavenXpp3Reader(); + try (Reader fileReader = Files.newBufferedReader(file.toPath())) { + Model model = mavenReader.read(fileReader); + return model; + } + } + + private static List getBomPomDependencies(Model model) throws IOException, XmlPullParserException { + Dependency bomPom = null; + List dependencies = model.getDependencyManagement().getDependencies(); + for (Dependency dependency : dependencies) { + if (dependency.getGroupId().equals("org.glassfish.tyrus") && dependency.getArtifactId().equals("tyrus-bom")) { + bomPom = dependency; + break; + } + } + if (bomPom == null) { + throw new IllegalStateException("Bom pom not found"); + } + File pom = getArtifactFile(getLocalMavenRepository(), bomPom, model.getProperties(), "pom"); + Model bomPomModel = getModelFromFile(pom); + return bomPomModel.getDependencyManagement().getDependencies(); + } + + static String getTyrusVersion(Properties properties) { + String property = properties.getProperty(TYRUS_VERSION); // when it is in the pom.file + if (property == null || property.startsWith("${")) { + property = System.getProperty(TYRUS_VERSION); // not in pom, but -Dtyrus.version + } + if (property == null || property.startsWith("${")) { + throw new IllegalStateException("Property " + TYRUS_VERSION + " not set (-Dtyrus.version=)"); + } + return property; + } + + /* Unused at the moment, but could be useful in the future in the case of profiles are needed */ + private static List getProfileDependency(Model model) { + List profileDependencies = Collections.EMPTY_LIST; + List profiles = model.getProfiles(); + String activeProfile = getActiveProfile(); + for (Profile profile : profiles) { + if (activeProfile.equals(profile.getId())) { + profileDependencies = profile.getDependencies(); + break; + } + } + return profileDependencies; + } + + private static String getActiveProfile() { + String profileId = System.getProperty("profileId"); // set this to the surefire plugin + return profileId; + } +} diff --git a/tests/release-test/src/main/java/org/glassfish/tyrus/test/artifacts/TestResult.java b/tests/release-test/src/main/java/org/glassfish/tyrus/test/artifacts/TestResult.java new file mode 100644 index 00000000..b707f741 --- /dev/null +++ b/tests/release-test/src/main/java/org/glassfish/tyrus/test/artifacts/TestResult.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.tyrus.test.artifacts; + +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +class TestResult { + private List oks = new LinkedList<>(); + private List exceptions = new LinkedList<>(); + + MessageBuilder ok() { + return new MessageBuilder(oks); + } + + MessageBuilder exception() { + return new MessageBuilder(exceptions); + } + boolean result() { + for (String ok : oks) { + System.out.append("(pass) ").print(ok); + } + + for (String exception : exceptions) { + System.out.append("\u001b[31;1m(FAIL) ").append(exception).print("\u001b[0m"); + } + + return exceptions.isEmpty(); + } + + public TestResult append(TestResult result) throws IOException { + oks.addAll(result.oks); + exceptions.addAll(result.exceptions); + return this; + } + + class MessageBuilder implements Appendable { + final List list; + final StringBuilder builder = new StringBuilder(); + + MessageBuilder(List list) { + this.list = list; + } + + @Override + public MessageBuilder append(CharSequence csq) { + builder.append(csq); + return this; + } + + public MessageBuilder append(int i) { + builder.append(i); + return this; + } + + @Override + public MessageBuilder append(CharSequence csq, int start, int end) { + builder.append(csq, start, end); + return this; + } + + @Override + public MessageBuilder append(char c) { + builder.append(c); + return this; + } + + public TestResult println(String message) { + builder.append(message).append('\n'); + list.add(builder.toString()); + return TestResult.this; + } + } +} diff --git a/tests/release-test/src/test/java/org/glassfish/tyrus/test/artifacts/ArchetypesTest.java b/tests/release-test/src/test/java/org/glassfish/tyrus/test/artifacts/ArchetypesTest.java new file mode 100644 index 00000000..ad785982 --- /dev/null +++ b/tests/release-test/src/test/java/org/glassfish/tyrus/test/artifacts/ArchetypesTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ +package org.glassfish.tyrus.test.artifacts; + +import org.apache.maven.model.Model; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.junit.Assert; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.util.Map; +import java.util.Properties; + +public class ArchetypesTest { + public static final String[] archetypePoms = { + "../../archetypes/echo/src/main/resources/archetype-resources/pom.xml", + }; + + @Test + public void testPropertiesVersion() throws XmlPullParserException, IOException { + Properties properties = MavenUtil.getModelFromFile("../../pom.xml").getProperties(); +// System.out.println(properties); + TestResult testResult = new TestResult(); + for (String pom : archetypePoms) { + File pomFile = new File(pom); + Assert.assertTrue("The pom file " + pom + " does not exist", pomFile.exists()); + Assert.assertTrue("The pom file " + pom + " cannot be read", pomFile.canRead()); + + boolean failed = false; + Model pomModel = MavenUtil.getModelFromFile(pom); + Properties pomProperties = pomModel.getProperties(); + for (Map.Entry pomEntry : pomProperties.entrySet()) { + // Update the names with the ones in Tyrus + Map.Entry updatedEntry = updateEntry(pomEntry); + // Check the properties are there + if (properties.getProperty(updatedEntry.getKey().toString()) == null) { + testResult.ok().append("Property ") + .append(pomEntry.getKey().toString()) + .append(" from ").append(pom).println(" not in Tyrus"); + failed = true; + } else if (!properties.getProperty(updatedEntry.getKey().toString()).equals(updatedEntry.getValue())) { + /* check the values */ + testResult.exception().append("The property ") + .append(pomEntry.getKey().toString()) + .append(" in archetype pom ") + .append(pom) + .append(" not equals Tyrus ") + .println(properties.getProperty(pomEntry.getKey().toString())); + failed = true; + } else { + testResult.ok().append("The property ") + .append(pomEntry.getKey().toString()) + .append(" in archetype pom ") + .append(pom) + .append(" is equal to Tyrus ") + .println(properties.getProperty(pomEntry.getKey().toString())); + } + } + if (!failed) { + testResult.ok().append("The properties in archetype pom ").append(pom).println(" equals Tyrus"); + } + } + + if (!testResult.result()) { + Assert.fail(); + } + } + + private Map.Entry updateEntry(Map.Entry pomEntry) { + if (pomEntry.getKey().equals("junit-jupiter.version")) { + return new Map.Entry() { + @Override + public Object getKey() { + return "junit5.version"; + } + + @Override + public Object getValue() { + return pomEntry.getValue(); + } + + @Override + public Object setValue(Object value) { + return value; + } + }; + } + return pomEntry; + } +} diff --git a/tests/release-test/src/test/java/org/glassfish/tyrus/test/artifacts/DownloadBomPomDependencies.java b/tests/release-test/src/test/java/org/glassfish/tyrus/test/artifacts/DownloadBomPomDependencies.java new file mode 100644 index 00000000..528238ac --- /dev/null +++ b/tests/release-test/src/test/java/org/glassfish/tyrus/test/artifacts/DownloadBomPomDependencies.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.tyrus.test.artifacts; + +import org.eclipse.aether.DefaultRepositorySystemSession; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.impl.DefaultServiceLocator; +import org.eclipse.aether.repository.LocalRepository; +import org.eclipse.aether.resolution.ArtifactResolutionException; +import org.eclipse.aether.spi.connector.RepositoryConnectorFactory; +import org.eclipse.aether.spi.connector.transport.TransporterFactory; +import org.eclipse.aether.transport.http.HttpTransporterFactory; + +import org.apache.maven.execution.DefaultMavenExecutionRequest; +import org.apache.maven.execution.MavenExecutionRequest; +import org.apache.maven.model.Dependency; +import org.apache.maven.plugin.testing.AbstractMojoTestCase; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.ProjectBuilder; +import org.apache.maven.project.ProjectBuildingRequest; +import org.apache.maven.project.ProjectBuildingResult; +import org.apache.maven.repository.internal.MavenRepositorySystemUtils; + +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory; +import org.junit.Test; + +import java.io.File; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.List; +import java.util.Properties; +import java.util.stream.Collectors; + +public class DownloadBomPomDependencies extends AbstractMojoTestCase { + + @Test + public void testDownloadBomPomDependencies() throws Exception { + MavenEnvironment mavenEnvironment = new MavenEnvironment(); + List memberDeps = MavenUtil.streamTyrusJars().collect(Collectors.toList()); + for (Dependency member : memberDeps) { + Artifact m = mavenEnvironment.resolveArtifact(member); + System.out.append("Resolved ").append(member.getGroupId()).append(":").append(member.getArtifactId()).append(":") + .append(member.getVersion()).append(" to ").println(m.getFile().getName()); + } + } + + @Test + public void testDownloadNonBomPomDependencies() throws Exception { + MavenEnvironment mavenEnvironment = new MavenEnvironment(); + MavenProject project = mavenEnvironment.getMavenProjectForResourceFile("/non-bom-pom-deps.xml"); + for (Dependency dependency : project.getDependencies()) { + Artifact m = mavenEnvironment.resolveArtifact(dependency); + System.out.append("Resolved ").append(dependency.getGroupId()).append(":") + .append(dependency.getArtifactId()).append(":") + .append(dependency.getVersion()).append(" to ").println(m.getFile().getName()); + } + } + + private class MavenEnvironment { + private final RepositorySystem repositorySystem; + private final RepositorySystemSession repoSession; + private final List remoteRepos; + private final String tyrusVersion; + + MavenEnvironment() throws Exception { + DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator(); + locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class); + locator.addService(TransporterFactory.class, HttpTransporterFactory.class); + + repositorySystem = locator.getService(RepositorySystem.class); + repoSession = getRepoSession(); + + remoteRepos = getRemoteRepositories(); + + Properties properties = MavenUtil.getMavenProperties(); + tyrusVersion = MavenUtil.getTyrusVersion(properties); + } + + Artifact resolveArtifact(Dependency dependency) throws ArtifactResolutionException { + dependency.setVersion(tyrusVersion); + return DependencyResolver.resolveArtifact(dependency, remoteRepos, repositorySystem, repoSession); + } + + private List getRemoteRepositories() throws Exception { + MavenProject project = getMavenProjectForResourceFile("/release-test-pom.xml"); + List remoteArtifactRepositories = project.getRemoteProjectRepositories(); + return remoteArtifactRepositories; + } + + private MavenProject getMavenProjectForResourceFile(String resourceFile) + throws Exception { + File pom = lookupResourcesPom(resourceFile); + MavenExecutionRequest request = new DefaultMavenExecutionRequest(); + request.setPom(pom); + request.addActiveProfile("staging"); + ProjectBuildingRequest buildingRequest = request + .getProjectBuildingRequest() + .setRepositorySession(repoSession) + .setResolveDependencies(true); + + ProjectBuilder projectBuilder = lookup(ProjectBuilder.class); + ProjectBuildingResult projectBuildingResult = projectBuilder.build(pom, buildingRequest); + MavenProject project = projectBuildingResult.getProject(); + + return project; + } + + private RepositorySystemSession getRepoSession() { + DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession(); + LocalRepository localRepo = new LocalRepository(MavenUtil.getLocalMavenRepository().getAbsolutePath()); + session.setLocalRepositoryManager(repositorySystem.newLocalRepositoryManager(session, localRepo)); + return session; + } + + private File lookupResourcesPom(String pomFile) throws URISyntaxException { + URL resource = DownloadBomPomDependencies.class.getResource(pomFile); + if (resource == null) { + throw new IllegalStateException("Pom file " + pomFile + " was not located on classpath!"); + } + File file = new File(resource.toURI()); + if (!file.exists()) { + throw new IllegalStateException("Cannot locate test pom xml file!"); + } + return file; + } + } +} diff --git a/tests/release-test/src/test/java/org/glassfish/tyrus/test/artifacts/LegalDocsIncludedTest.java b/tests/release-test/src/test/java/org/glassfish/tyrus/test/artifacts/LegalDocsIncludedTest.java new file mode 100644 index 00000000..0013904a --- /dev/null +++ b/tests/release-test/src/test/java/org/glassfish/tyrus/test/artifacts/LegalDocsIncludedTest.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.tyrus.test.artifacts; + +import org.apache.maven.plugin.testing.AbstractMojoTestCase; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.junit.Assert; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Properties; +import java.util.jar.JarFile; +import java.util.stream.Collectors; + +public class LegalDocsIncludedTest extends AbstractMojoTestCase { + private static final File localRepository = MavenUtil.getLocalMavenRepository(); + private static final Properties properties = MavenUtil.getMavenProperties(); + + private static final String LICENSE_FILE = "LICENSE.md"; + private static final String NOTICE_FILE = "NOTICE.md"; + + @Test + public void testLegalFiles() throws IOException, XmlPullParserException { + TestResult testResult = new TestResult(); + List jars = MavenUtil.streamTyrusJars() + .map(dependency -> MavenUtil.getArtifactJar(localRepository, dependency, properties)) + .collect(Collectors.toList()); + + for (File jar : jars) { + for (String filename : new String[]{LICENSE_FILE, NOTICE_FILE}) { + JarFile jarFile = new JarFile(jar); + String value; + try { + value = jarFile.getEntry("META-INF/" + filename).getName(); + } catch (NullPointerException npe) { + value = null; + } + TestResult.MessageBuilder builder = value != null ? testResult.ok() : testResult.exception(); + builder.append(jar.getName()).append(value == null ? " DOES NOT CONTAIN " : " CONTAINS ") + .append(filename).println(" file"); + } + } + + //Assertions.assertTrue(testResult.result(), "Some error occurred, see previous messages"); + Assert.assertTrue("Some error occurred, see previous messages", testResult.result()); + } +} diff --git a/tests/release-test/src/test/java/org/glassfish/tyrus/test/artifacts/ManifestTest.java b/tests/release-test/src/test/java/org/glassfish/tyrus/test/artifacts/ManifestTest.java new file mode 100644 index 00000000..0e8109c3 --- /dev/null +++ b/tests/release-test/src/test/java/org/glassfish/tyrus/test/artifacts/ManifestTest.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ +package org.glassfish.tyrus.test.artifacts; + +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.junit.Assert; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Properties; +import java.util.jar.JarFile; +import java.util.stream.Collectors; + +public class ManifestTest { + private static final File localRepository = MavenUtil.getLocalMavenRepository(); + private static final Properties properties = MavenUtil.getMavenProperties(); + + private static final String BUNDLE_NAME_ATTRIBUTE = "Bundle-Name"; + private static final String BUNDLE_VERSION_ATTRIBUTE = "Bundle-Version"; + private static final String[] EXCLUDED_JARS = {}; + + @Test + public void testHasOsgiManifest() throws IOException, XmlPullParserException { + TestResult testResult = new TestResult(); + List jars = MavenUtil.streamTyrusJars() + .filter(dependency -> { + for (String excluded : EXCLUDED_JARS) { + if (dependency.getArtifactId().contains(excluded)) { + return false; + } + } + return true; + }) + .map(dependency -> MavenUtil.getArtifactJar(localRepository, dependency, properties)) + .collect(Collectors.toList()); + + for (String ATTRIBUTE : new String[]{BUNDLE_NAME_ATTRIBUTE, BUNDLE_VERSION_ATTRIBUTE}) { + for (File jar : jars) { + JarFile jarFile = new JarFile(jar); + String value = jarFile.getManifest().getMainAttributes().getValue(ATTRIBUTE); + TestResult.MessageBuilder builder = value != null ? testResult.ok() : testResult.exception(); + builder.append(jar.getName()).append(value == null ? " DOES NOT CONTAIN " : " CONTAINS ") + .append(ATTRIBUTE).println(" attribute"); + } + } + + //Assertions.assertTrue(testResult.result(), "Some error occurred, see previous messages"); + Assert.assertTrue("Some error occurred, see previous messages", testResult.result()); + } + +} diff --git a/tests/release-test/src/test/java/org/glassfish/tyrus/test/artifacts/NoticeFilesTest.java b/tests/release-test/src/test/java/org/glassfish/tyrus/test/artifacts/NoticeFilesTest.java new file mode 100644 index 00000000..8622bd91 --- /dev/null +++ b/tests/release-test/src/test/java/org/glassfish/tyrus/test/artifacts/NoticeFilesTest.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.tyrus.test.artifacts; + +import org.apache.maven.model.Model; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.junit.Assert; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.LinkedList; +import java.util.List; +import java.util.StringTokenizer; +import java.util.regex.Pattern; + +public class NoticeFilesTest { + + @Test + public void test() throws IOException, XmlPullParserException { + Model model = MavenUtil.getModelFromFile("../../pom.xml"); + List mainExpectedNoticeDeps = mainExpectedDependencies(); + + File mainNotice = new File("../../NOTICE.md"); + List mainNoticeDeps = parseNoticeFileVersions(mainNotice); + TestResult testResult = compareDependencies(mainExpectedNoticeDeps, mainNoticeDeps, model, mainNotice.getCanonicalPath()); + + Assert.assertTrue("Some error occurred, see previous messages", testResult.result()); + } + + private TestResult compareDependencies(List expectedDeps, + List actualDeps, + Model model, String noticeName) { + TestResult testResult = new TestResult(); + NextExpected: + for (NoticeDependencyVersionPair expectedDep : expectedDeps) { + for (NoticeDependencyVersionPair actualDep : actualDeps) { + if (expectedDep.dependency.equals(actualDep.dependency)) { + String expectedVersion = findVersionInModel(expectedDep, model); + testResult.ok().append("Expected dependency ").append(expectedDep.dependency).println(" found"); + if (expectedVersion.equals(actualDep.version)) { + testResult.ok().append("Dependency ").append(actualDep.dependency).append(" contains expected version ") + .append(expectedVersion).append(" in ").println(noticeName); + } else { + testResult.exception().append("Dependency ").append(actualDep.dependency).append(" differs version ") + .append(expectedVersion).append(" from ").append(noticeName).append(" version ") + .println(actualDep.version); + } + continue NextExpected; + } + } + testResult.exception().append("Expected dependency ").append(expectedDep.dependency).append(" not found in ") + .println(noticeName); + } + return testResult; + } + + private static String findVersionInModel(NoticeDependencyVersionPair pair, Model model) { + if (pair.version.startsWith("${")) { + String version = pair.version.substring(2, pair.version.length() - 1); + return model.getProperties().getProperty(version); + } else { + return pair.version; + } + } + + private void cat(File path) throws IOException { + StringTokenizer tokenizer = tokenizerFromNoticeFile(path); + while (tokenizer.hasMoreTokens()) { + String token = tokenizer.nextToken(); + if (token.trim().length() > 1 && !token.trim().startsWith("*")) { + System.out.println(token); +// String filteredToken = removeUnnecessary(token); +// System.out.println(filteredToken); +// Pattern versionizer = Pattern.compile("([.*])?([\\d])"); +// System.out.println(versionizer.matcher(filteredToken).replaceFirst("$1:$2")); + } + } + } + + private List parseNoticeFileVersions(File path) throws IOException { + List list = new LinkedList<>(); + StringTokenizer tokenizer = tokenizerFromNoticeFile(path); + while (tokenizer.hasMoreTokens()) { + String token = tokenizer.nextToken(); + if (token.trim().length() > 1 && !token.trim().startsWith("*")) { + String filteredToken = removeUnnecessary(token); + Pattern versionizer = Pattern.compile("([.*])?([\\d])"); + String[] args = versionizer.matcher(filteredToken).replaceFirst("$1:$2").split(":", 2); + NoticeDependencyVersionPair pair = args.length == 2 + ? new NoticeDependencyVersionPair(args[0], args[1]) + : new NoticeDependencyVersionPair(args[0], ""); + list.add(pair); + } + } + + return list; + } + + private StringTokenizer tokenizerFromNoticeFile(File path) throws IOException { + StringTokenizer tokenizer = new StringTokenizer(getFile(path), "\n"); + while (tokenizer.hasMoreTokens()) { + String token = tokenizer.nextToken(); + if (token.trim().startsWith("## Third-party Content")) { + break; + } + } + return tokenizer; + } + + private String getFile(File path) throws IOException { + return new String(Files.newInputStream(path.toPath()).readAllBytes()); + } + + private String removeUnnecessary(String dependency) { + String filtered = dependency + .replace(" Version", "").replace(" version", "") + .replace(" API ", "") + .replace(" v", "") + .replace(", ", "").replace(",", "") + .replace(": ", "").replace(": ", "") + .replace("(", "").replace(")", ""); + return filtered; + } + + /** + * Return pair of Notice file dependency name & pom.xml version property name + */ + private List mainExpectedDependencies() { + final List dependencyPairs = new LinkedList<>(); + dependencyPairs.add(new NoticeDependencyVersionPair("jakarta.activation", "${activation.api.version}")); + dependencyPairs.add(new NoticeDependencyVersionPair("jakarta.enterprise.cdi-api", "${cdi-api.version}")); + dependencyPairs.add(new NoticeDependencyVersionPair("jakarta.inject", "${inject.api.version}")); + dependencyPairs.add(new NoticeDependencyVersionPair("jakarta.xml.bind-api", "${jaxb.api.version}")); + dependencyPairs.add(new NoticeDependencyVersionPair("jline", "${jline.version}")); + return dependencyPairs; + } + + private static class NoticeDependencyVersionPair { + private final String dependency; + private final String version; + + private NoticeDependencyVersionPair(String dependency, String version) { + this.dependency = dependency.trim(); + this.version = version.trim(); + } + } +} diff --git a/tests/release-test/src/test/resources/non-bom-pom-deps.xml b/tests/release-test/src/test/resources/non-bom-pom-deps.xml new file mode 100644 index 00000000..eb5c762f --- /dev/null +++ b/tests/release-test/src/test/resources/non-bom-pom-deps.xml @@ -0,0 +1,37 @@ + + + + + 4.0.0 + + + org.eclipse.ee4j + project + 1.0.9 + + + org.glassfish.tyrus.tests + release-test-test + 0.0.1-SNAPSHOT + + + + + \ No newline at end of file diff --git a/tests/release-test/src/test/resources/release-test-pom.xml b/tests/release-test/src/test/resources/release-test-pom.xml new file mode 100644 index 00000000..4e223022 --- /dev/null +++ b/tests/release-test/src/test/resources/release-test-pom.xml @@ -0,0 +1,34 @@ + + + + + 4.0.0 + + + org.eclipse.ee4j + project + 1.0.9 + + + org.glassfish.tyrus.tests + release-test-test + 0.0.1-SNAPSHOT + + \ No newline at end of file