Copybara import of the project: - 94bb93a20812b7e398669c3d0aa8f67bf503feff Initial contribution by Tomas Kraus <tomas.kraus@oracle.com> - 411b1d2271efc9af0db28c48a4a05d7273ac776f Cleanup of copyright-exclude file by Tomas Kraus <tomas.kraus@oracle.com> - 993fc6c941ba05b51f346f82944dfc670f07f5a6 Project information update by Tomas Kraus <tomas.kraus@oracle.com> - c688b139db8913dc08c1fdcea53f95a91a901931 Parent updated to 1.0.2. (#10) by Tomáš Kraus <tomas.kraus@oracle.com> - a0353cffeef9f0013dfc420aa75e8d74ee40c046 JDK 11 preparation and jakarta uptake. (#13) by Tomáš Kraus <tomas.kraus@oracle.com> - 7df4ed8940829fbe01968294f6df84a62a366f8b Merge pull request #16 from bravehorsie/master by Roman Grigoriadi <bravehorsie@gmail.com> - 41617854b4dd03be4be18dfcb7ab6fbe1b03f940 Fixed jar content: added LICENSE and NOTICE. (#20) by Tomáš Kraus <tomas.kraus@oracle.com> - ad51c42688568aab60e7fd687ee084c7a372f726 Fixed missing module-info issue. (#22) by Tomáš Kraus <tomas.kraus@oracle.com> - 60c0c5b7fe0d0ad28602df579ace3a03c4c2e483 fix up dependencies (#24) by Lukas Jungmann <lukas.jungmann@oracle.com> - 02d87244d8848a1d193873eb98f8193f46af0e4b do not fail the build if resource folder does not exist (... by Lukas Jungmann <lukas.jungmann@oracle.com> - ee27612505a0b0e79c8cf9b483add8d811d40a2d remove dependency on dom4j (#32) by Lukas Jungmann <lukas.jungmann@oracle.com> - b9f61fda870a930d56d09d97ad80807dbcd36f81 moved sources to proper structure, coverage, dependency c... by Lukas Jungmann <lukas.jungmann@oracle.com> - 1029b46055ca76cb6458ccf4558d2c2634f5f677 exclude generated file (#33) by Lukas Jungmann <lukas.jungmann@oracle.com> - d1d595641e8c84482a47812ab8457f850f483f6c fix cp year for the release (#34) by Lukas Jungmann <lukas.jungmann@oracle.com> - 2931f6653df1320705cb4afa3cbb4bc9015ce2f8 remove emtpy folders by Lukas Jungmann <lukas.jungmann@oracle.com> - 0acb83be8ad8ebb18fa6bb18f8a975d3b4d7453e Prepare release com.sun.istack:istack-commons:3.0.9 by Eclipse JAXBimpl Bot <jaxb-impl-bot@eclipse.org> - 90a9b4456b1790ad26a894dcb46c2e03378657f8 Prepare next development cycle for 3.0.10-SNAPSHOT by Eclipse JAXBimpl Bot <jaxb-impl-bot@eclipse.org> - a2bd12433fed99d92ab952ee5c61ce96f7d0c576 Next release cycle version updated to 3.1.0-SNAPSHOT by Tomas Kraus <Tomas.Kraus@oracle.com> - 5b898c5cac7475d16c48c234565ba46a04e7df5b StackWalker used in logger for caller method resolution #37 by Daniel Kec <daniel@kecovi.cz> - 2942ad3f3c1840b43b66c03468301658647982c2 update plugin versions, clean up poms, add missing module... by Lukas Jungmann <lukas.jungmann@oracle.com> - ed23d828118a0752f5a18bd538bf05a862b193de Integrate codemodel 2.3.2-1 (#44) by Lukas Jungmann <lukas.jungmann@oracle.com> - 57171abaa2df83980618730916a920bf5e4bb98e fix vendor (#45) by Lukas Jungmann <lukas.jungmann@oracle.com> - b4f026b25249c6c9edf40d2c961ac4e974ea3738 update parent pom, dependencies, plugins, prepare for the... by Lukas Jungmann <lukas.jungmann@oracle.com> - cf98ff76cf0f9f9c94a35c8e549490e0bc6e1ff4 #51: XJC task is closing wrong ClassLoader - ClassNotFoun... by Lukas Jungmann <lukas.jungmann@oracle.com> - 162bc1d03f6622a83b5a867a0471d6f2b58bbc75 Integrate codemodel 2.3.2-2 by Lukas Jungmann <lukas.jungmann@oracle.com> - d4a280da6a188eec6ed5dac772d5595d0aafecbe fix cp year by Lukas Jungmann <lukas.jungmann@oracle.com> - e2f21bf526e257abf7c1c74c03054f6fcb8fff2f Prepare release com.sun.istack:istack-commons:3.0.11 by Eclipse JAXBimpl Bot <jaxb-impl-bot@eclipse.org> - 9c02bc5b425abd2c9c9a1beab9be3ae1d934e7f0 Prepare next development cycle for 3.1.0-SNAPSHOT by Eclipse JAXBimpl Bot <jaxb-impl-bot@eclipse.org> - 8ef227deb3e5f2ccc2c37c5d7e1c10460b62efa9 Update Jakarta Activation to 2.0.0-rc1 (#49) by Andy McCright <j.andrew.mccright@gmail.com> - 629b1083f37ea52d20c66693873c89fce143d4c4 update project version to 4.0.0-SNAPSHOT by Lukas Jungmann <lukas.jungmann@oracle.com> - e5bce223b3a12609c29984861a923eeeb3f26af8 prepare for jdk14 by Lukas Jungmann <lukas.jungmann@oracle.com> - 3ba915fd13baf94e0af1982b958d2c0e0ede3d54 update build plugins by Lukas Jungmann <lukas.jungmann@oracle.com> - 227267b8a1d43bfbea40c723625e067dc0965efd Prepare release com.sun.istack:istack-commons:4.0.0-M1 by Eclipse JAXBimpl Bot <jaxb-impl-bot@eclipse.org> - e1904a4633208ffd80ce98b59954b502cdaa3fb7 Prepare next development cycle for 4.0.0-SNAPSHOT by Eclipse JAXBimpl Bot <jaxb-impl-bot@eclipse.org> - 39a19b754583d1e9e09f12883ed6e15d1b6174fd integrate activation 2.0.0-RC3 by Lukas Jungmann <lukas.jungmann@oracle.com> - 372be10d977d9f842412666df1f71140b7d28074 Prepare release com.sun.istack:istack-commons:4.0.0-M2 by Eclipse JAXBimpl Bot <jaxb-impl-bot@eclipse.org> - 285d18c5daeb703da364d2e38aea55813ae5dd89 Prepare next development cycle for 4.0.0-SNAPSHOT by Eclipse JAXBimpl Bot <jaxb-impl-bot@eclipse.org> - 488c87a97446d6ef025c62ffc8a84174f3bbeca4 remove obsolete code from tools by Lukas Jungmann <lukas.jungmann@oracle.com> - 4df583ade52296ad8b899a24ef000b1f0836d04f Should generate jakarta annotation by Lukas Jungmann <lukas.jungmann@oracle.com> - 61fc9f14727b47e147f5a55e9fdb7f048939a01e #60: marking thread safety in maven plugins by Lukas Jungmann <lukas.jungmann@oracle.com> - e5eb55383a23aa51da83ba01a0f48fb6cffce7e0 Prepare release com.sun.istack:istack-commons:4.0.0-M3 by Eclipse JAXBimpl Bot <jaxb-impl-bot@eclipse.org> - 24e2da887f05b976f37fbcc3419a3eb6ae67c77e Prepare next development cycle for 4.0.0-SNAPSHOT by Eclipse JAXBimpl Bot <jaxb-impl-bot@eclipse.org> - 4e72ea5d513c84a906dbb833ea32dde2aab23037 Versions update. by Tomas Kraus <Tomas.Kraus@oracle.com> - 0995d1253d0ad8c90d1b5c695a59301ccbe97c94 Compiler plugin configuration updated. (#65) by Tomáš Kraus <tomas.kraus@oracle.com> - c56ffe5fb517df99b39a097ab3abe2a252209326 Prepare release com.sun.istack:istack-commons:4.0.0 by Eclipse JAXBimpl Bot <jaxb-impl-bot@eclipse.org> - 2e26ea2ddb48c7d9e967d88fece46c05d7822b01 Prepare next development cycle for 4.1.0-SNAPSHOT by Eclipse JAXBimpl Bot <jaxb-impl-bot@eclipse.org> - 984999f8d2df9720781fb6db4f5ecd6afecb29a9 move travis to jdk15 by Lukas Jungmann <lukas.jungmann@oracle.com> - 719eb051891654609b810bf9c08f8751b5d56e22 Bump junit from 4.13 to 4.13.1 in /istack-commons by dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> - 17afd94e3ce57018c6143559e0277e99322307c6 Bump junit in /istack-commons/maven-plugin/src/test/it/sa... by dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> - 916a9a51a0e75c8e99cc1a30fac3e1d2a82491b1 Bump ant.version from 1.10.8 to 1.10.9 in /istack-commons by dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> - 45b45bc24b8120d6914101f8f1cbc865af006229 fix cp year by Lukas Jungmann <lukas.jungmann@oracle.com> - 4f8109f71988232e2c1d3ac793f588a18923b990 update spotbugs, copyright plugin, testng by Lukas Jungmann <lukas.jungmann@oracle.com> - b1e6d05c124914b2d4dea2e8f186d69a1e2192ac Integrate activation 2.0.1 by Lukas Jungmann <lukas.jungmann@oracle.com> - cac71101470a880749d1ad0376c79e687d9a157f cp right by Lukas Jungmann <lukas.jungmann@oracle.com> - 6902fb3ec533c9402daabd4b5317d2e7e7badafd copyright adjustments before merge by Maxim Nesen <maxim.nesen@oracle.com> - d0785e0627f4e053bcef8495cfc02f3a118654a2 add option to not generate javadoc by Lukas Jungmann <lukas.jungmann@oracle.com> - ef49e4840127f2095684788e3edecbf8aa023993 Merge pull request #78 from eclipse-ee4j/4.0.1-RELEASE by Lukas Jungmann <lukas.jungmann@oracle.com> - 3e617cdc4da6c27b06ec0b53ec6116e68a27b4ce Enable latests JDK in Travis and GitHub actions by Jorge Bescos Gascon <jorge.bescos.gascon@oracle.com> - 24d0234b7ec0d17e8e0c4317a2ee51f998b98f7a Remove Travis by Jorge Bescos Gascon <jorge.bescos.gascon@oracle.com> - ca2a6a5848cfd57865f021ba3ea1aca0f6c88e07 fix warnings, update build plugins. by Lukas Jungmann <lukas.jungmann@oracle.com> - 77cb74cef04ca61ea257b340b48187369f6d15be Jakarta Activation dependency update (2.0.2-SNAPSHOT). by Tomas Kraus <Tomas.Kraus@oracle.com> - 3ab17c9cb7b9e322903d82cd0a108fe2348fa9b9 Jakarta Activation API updated to 2.1.0-RC1. by Tomas Kraus <tomas.kraus@oracle.com> - 768b3a0dfaea9affcad7957ac2496d3b0a0cf7f1 Version updated to 4.1.0-SNAPSHOT. by Tomas Kraus <tomas.kraus@oracle.com> - e6dc260892c602d6509d4d9fa18d3ba4abca2364 Project cleanup. by Tomas Kraus <tomas.kraus@oracle.com> - e90b1f873e58e25b36eb34af88990a4077035c48 Fixed build issue. by Tomas Kraus <tomas.kraus@oracle.com> - 4ee8a19904bef8a057e49650b75675d888ad3b83 update dependencies, by Lukas Jungmann <lukas.jungmann@oracle.com> - 4777b0cec99de7a2f54b0008277ff9c01d1c49df fix the path to the spotbugs filter file by Lukas Jungmann <lukas.jungmann@oracle.com> - 0280e00888eefe733286c9c0605b7a4307aeff66 Prepare release com.sun.istack:istack-commons:4.1.0 by Eclipse JAXBimpl Bot <jaxb-impl-bot@eclipse.org> - 39492d645d4d00be7a7905004eb89ec7f319f727 Prepare next development cycle for 4.1.1-SNAPSHOT by Eclipse JAXBimpl Bot <jaxb-impl-bot@eclipse.org> - b039f7d9ba565a9a55993ef2608d38362545095a generate private constructor in localization class by Lukas Jungmann <lukas.jungmann@oracle.com> - 81ebad83f8758ff448dff8acfcaeaab2b2af5b3b update dependencies, by Lukas Jungmann <lukas.jungmann@oracle.com> - 3a81d48b2c41c602eb922db737661010ff19353f Prepare release com.sun.istack:istack-commons:4.1.1 by Eclipse JAXBimpl Bot <jaxb-impl-bot@eclipse.org> - e2e64a865ca40ef59efdfa115b743a751be5732b Prepare next development cycle for 4.1.2-SNAPSHOT by Eclipse JAXBimpl Bot <jaxb-impl-bot@eclipse.org> - 2625e8c71cf9bf6be123a659883c5325ef6cdded fix cpright by Lukas Jungmann <lukas.jungmann@oracle.com> - 527fe11d187b1eba6e5d5f9d74b99e14105b4242 update gh action build by Lukas Jungmann <lukas.jungmann@oracle.com> - c96196f7ff3d2647ba5784cfc537317a679232b9 Bump testng from 7.5 to 7.7.0 in /istack-commons by dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> - 3bf4720adf99a7917e20959fe888f7295eb799f2 A mojo to generate implementations of jaxb Quick by Lukas Jungmann <lukas.jungmann@oracle.com> - b9357cc3d722827c6219038341abef35e3b60005 Update dependencies, build plugins by Lukas Jungmann <lukas.jungmann@oracle.com> - e4626a693aa49935e0b07411419006b9570f4734 update gh buld by Lukas Jungmann <lukas.jungmann@oracle.com> - 1ee5fc6a67c50381512383e65e63aa81ea80cd5c Minor code cleanup by Lukas Jungmann <lukas.jungmann@oracle.com> - 685bd782d32f9fa20670e0c5a9d7a2fc0b38845d Prepare release com.sun.istack:istack-commons:4.1.2 by Eclipse JAXBimpl Bot <jaxb-impl-bot@eclipse.org> - 4f63e8ebe2cdf5ab25a88f793ac06ce83265e42a Prepare next development cycle for 4.2.0-SNAPSHOT by Eclipse JAXBimpl Bot <jaxb-impl-bot@eclipse.org> - d80a798a4d4350f1f0d8afd91209edd935d0521a remove securitymanager by Lukas Jungmann <lukas.jungmann@oracle.com> - 19e68d9f7fc646987091a9e9bce87fd140d7d169 Prepare release com.sun.istack:istack-commons:4.2.0 by Eclipse JAXBimpl Bot <jaxb-impl-bot@eclipse.org> GitOrigin-RevId: 19e68d9f7fc646987091a9e9bce87fd140d7d169 Change-Id: I3573feb82f076f83620efc8251edfa662a60d1e4
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 0000000..679cac8 --- /dev/null +++ b/.github/workflows/maven.yml
@@ -0,0 +1,53 @@ +# +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# 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, +# or the Eclipse Distribution License v. 1.0 which is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause +# + +name: Jakarta IStack Commons + +on: + pull_request: + push: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + name: Test on JDK ${{ matrix.java_version }} + runs-on: ubuntu-latest + + strategy: + matrix: + java_version: [ 11, 17 , 21-ea] + + steps: + - name: Checkout for build + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Set up JDK + uses: actions/setup-java@v3 + with: + distribution: 'zulu' + java-version: ${{ matrix.java_version }} + cache: maven + - name: Verify + run: | + cd istack-commons + mvn -B -V -U -C -Pstaging,oss-release,license-check clean verify org.glassfish.copyright:glassfish-copyright-maven-plugin:check -Dgpg.skip=true -Dittest=true -Dcopyright.ignoreyear=true + - name: Upload license-check info + uses: actions/upload-artifact@v3 + with: + name: license-summary.txt + path: istack-commons/target/dash/summary
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9ad0824 --- /dev/null +++ b/.gitignore
@@ -0,0 +1,6 @@ +target/ +.idea +*.iml +.classpath +.project +.settings/ \ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..c109340 --- /dev/null +++ b/CONTRIBUTING.md
@@ -0,0 +1,51 @@ +[//]: # " Copyright (c) 2018, 2020 Oracle and/or its affiliates. All rights reserved. " +[//]: # " " +[//]: # " This program and the accompanying materials are made available under the " +[//]: # " terms of the Eclipse Distribution License v. 1.0, which is available at " +[//]: # " http://www.eclipse.org/org/documents/edl-v10.php. " +[//]: # " " +[//]: # " SPDX-License-Identifier: BSD-3-Clause " + +# Contributing to Eclipse Implementation of JAXB + +Thanks for your interest in this project. + +## Project description + +The Java™ Architecture for XML Binding (JAXB) provides an API and tools that +automate the mapping between XML documents and Java objects. This project +contains implementation of JAXB API. + +* https://projects.eclipse.org/projects/ee4j.jaxb-impl + +## Developer resources + +Information regarding source code management, builds, coding standards, and +more. + +* https://projects.eclipse.org/projects/ee4j.jaxb-impl/developer + +The project maintains the following source code repositories + + +## Eclipse Contributor Agreement + +Before your contribution can be accepted by the project team contributors must +electronically sign the Eclipse Contributor Agreement (ECA). + +* http://www.eclipse.org/legal/ECA.php + +Commits that are provided by non-committers must have a Signed-off-by field in +the footer indicating that the author is aware of the terms by which the +contribution has been provided to the project. The non-committer must +additionally have an Eclipse Foundation account and must have a signed Eclipse +Contributor Agreement (ECA) on file. + +For more information, please see the Eclipse Committer Handbook: +https://www.eclipse.org/projects/handbook/#resources-commit + +## Contact + +Contact the project developers via the project's "dev" list. + +* https://accounts.eclipse.org/mailing-list/jaxb-impl-dev
diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..c739f78 --- /dev/null +++ b/LICENSE.md
@@ -0,0 +1,29 @@ + + Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Eclipse Foundation, Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/NOTICE.md b/NOTICE.md new file mode 100644 index 0000000..95ad0b0 --- /dev/null +++ b/NOTICE.md
@@ -0,0 +1,198 @@ +[//]: # " Copyright (c) 2018, 2020 Oracle and/or its affiliates. All rights reserved. " +[//]: # " " +[//]: # " This program and the accompanying materials are made available under the " +[//]: # " terms of the Eclipse Distribution License v. 1.0, which is available at " +[//]: # " http://www.eclipse.org/org/documents/edl-v10.php. " +[//]: # " " +[//]: # " SPDX-License-Identifier: BSD-3-Clause " + +# Notices for Eclipse Implementation of JAXB + +This content is produced and maintained by the Eclipse Implementation of JAXB +project. + +* Project home: https://projects.eclipse.org/projects/ee4j.jaxb-impl + +## Trademarks + +Eclipse Implementation of JAXB is a trademark of the Eclipse Foundation. + +## Copyright + +All content is the property of the respective authors or their employers. For +more information regarding authorship of content, please consult the listed +source code repository logs. + +## Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Distribution License v. 1.0 which is available at +http://www.eclipse.org/org/documents/edl-v10.php. + +SPDX-License-Identifier: BSD-3-Clause + +## Source Code + +The project maintains the following source code repositories: + +* https://github.com/eclipse-ee4j/jaxb-ri +* https://github.com/eclipse-ee4j/jaxb-istack-commons +* https://github.com/eclipse-ee4j/jaxb-dtd-parser +* https://github.com/eclipse-ee4j/jaxb-fi +* https://github.com/eclipse-ee4j/jaxb-stax-ex +* https://github.com/eclipse-ee4j/jax-rpc-ri + +## Third-party Content + +This project leverages the following third party content. + +Apache Ant (1.10.2) + +* License: Apache-2.0 AND W3C AND LicenseRef-Public-Domain + +Apache Ant (1.10.2) + +* License: Apache-2.0 AND W3C AND LicenseRef-Public-Domain + +Apache Felix (1.2.0) + +* License: Apache License, 2.0 + +args4j (2.33) + +* License: MIT License + +dom4j (1.6.1) + +* License: Custom license based on Apache 1.1 + +file-management (3.0.0) + +* License: Apache-2.0 +* Project: https://maven.apache.org/shared/file-management/ +* Source: + https://svn.apache.org/viewvc/maven/shared/tags/file-management-3.0.0/ + +JUnit (4.12) + +* License: Eclipse Public License + +JUnit (4.12) + +* License: Eclipse Public License + +maven-compat (3.5.2) + +* License: Apache-2.0 +* Project: https://maven.apache.org/ref/3.5.2/maven-compat/ +* Source: + https://mvnrepository.com/artifact/org.apache.maven/maven-compat/3.5.2 + +maven-core (3.5.2) + +* License: Apache-2.0 +* Project: https://maven.apache.org/ref/3.5.2/maven-core/index.html +* Source: https://mvnrepository.com/artifact/org.apache.maven/maven-core/3.5.2 + +maven-plugin-annotations (3.5) + +* License: Apache-2.0 +* Project: https://maven.apache.org/plugin-tools/maven-plugin-annotations/ +* Source: + https://github.com/apache/maven-plugin-tools/tree/master/maven-plugin-annotations + +maven-plugin-api (3.5.2) + +* License: Apache-2.0 + +maven-resolver-api (1.1.1) + +* License: Apache-2.0 + +maven-resolver-api (1.1.1) + +* License: Apache-2.0 + +maven-resolver-connector-basic (1.1.1) + +* License: Apache-2.0 + +maven-resolver-impl (1.1.1) + +* License: Apache-2.0 + +maven-resolver-spi (1.1.1) + +* License: Apache-2.0 + +maven-resolver-transport-file (1.1.1) + +* License: Apache-2.0 +* Project: https://maven.apache.org/resolver/maven-resolver-transport-file/ +* Source: + https://github.com/apache/maven-resolver/tree/master/maven-resolver-transport-file + +maven-resolver-util (1.1.1) + +* License: Apache-2.0 + +maven-settings (3.5.2) + +* License: Apache-2.0 +* Source: + https://mvnrepository.com/artifact/org.apache.maven/maven-settings/3.5.2 + +OSGi Service Platform Core Companion Code (6.0) + +* License: Apache License, 2.0 + +plexus-archiver (3.5) + +* License: Apache-2.0 +* Project: https://codehaus-plexus.github.io/plexus-archiver/ +* Source: https://github.com/codehaus-plexus/plexus-archiver + +plexus-io (3.0.0) + +* License: Apache-2.0 + +plexus-utils (3.1.0) + +* License: Apache- 2.0 or Apache- 1.1 or BSD or Public Domain or Indiana + University Extreme! Lab Software License V1.1.1 (Apache 1.1 style) + +relaxng-datatype (1.0) + +* License: New BSD license + +Sax (0.2) + +* License: SAX-PD +* Project: http://www.megginson.com/downloads/SAX/ +* Source: http://sourceforge.net/project/showfiles.php?group_id=29449 + +testng (6.14.2) + +* License: Apache-2.0 AND (MIT OR GPL-1.0+) +* Project: https://testng.org/doc/index.html +* Source: https://github.com/cbeust/testng + +wagon-http-lightweight (3.0.0) + +* License: Pending +* Project: https://maven.apache.org/wagon/ +* Source: + https://mvnrepository.com/artifact/org.apache.maven.wagon/wagon-http-lightweight/3.0.0 + +xz for java (1.8) + +* License: LicenseRef-Public-Domain + +## Cryptography + +Content may contain encryption software. The country in which you are currently +may have restrictions on the import, possession, and use, and/or re-export to +another country, of encryption software. BEFORE using any encryption software, +please check the country's laws, regulations and policies concerning the import, +possession, or use, and re-export of encryption software, to see if this is +permitted.
diff --git a/README.md b/README.md new file mode 100644 index 0000000..ff22bb2 --- /dev/null +++ b/README.md
@@ -0,0 +1,30 @@ +[//]: # " Copyright (c) 2018, 2021 Oracle and/or its affiliates. All rights reserved. " +[//]: # " " +[//]: # " This program and the accompanying materials are made available under the " +[//]: # " terms of the Eclipse Distribution License v. 1.0, which is available at " +[//]: # " http://www.eclipse.org/org/documents/edl-v10.php. " +[//]: # " " +[//]: # " SPDX-License-Identifier: BSD-3-Clause " + +# iStack Common Utility Code + +[](https://github.com/eclipse-ee4j/jaxb-istack-commons/actions/workflows/maven.yml?branch=master) +[](https://jakarta.oss.sonatype.org/content/repositories/staging/com/sun/istack/istack-commons/) + +This project is part of [Eclipse Implementation of JAXB](https://projects.eclipse.org/projects/ee4j.jaxb-impl). + +## License + +iStack Common Utility Code is licensed under a license - [EDL 1.0](LICENSE.md). + +## Contributing + +We use [contribution policy](CONTRIBUTING.md), which means we can only accept contributions under +the terms of [Eclipse Contributor Agreement](http://www.eclipse.org/legal/ECA.php). + +## Links + +* [Runtime Utilities](https://javadoc.io/doc/com.sun.istack/istack-commons-runtime/latest/com.sun.istack.runtime/module-summary.html) +* [Tooltime Utilities](https://javadoc.io/doc/com.sun.istack/istack-commons-tools/latest/com.sun.istack.tools/module-summary.html) +* [Test Utilities](https://javadoc.io/doc/com.sun.istack/istack-commons-test/latest/com.sun.istack.test/module-summary.html) +* [Mailing list](https://accounts.eclipse.org/mailing-list/jaxb-impl-dev)
diff --git a/istack-commons/buildtools/pom.xml b/istack-commons/buildtools/pom.xml new file mode 100644 index 0000000..70d9c01 --- /dev/null +++ b/istack-commons/buildtools/pom.xml
@@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>com.sun.istack</groupId> + <artifactId>istack-commons</artifactId> + <version>4.2.0</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <artifactId>istack-commons-buildtools</artifactId> + <name>istack common utility buildtools</name> + + <dependencies> + <dependency> + <groupId>org.apache.ant</groupId> + <artifactId>ant</artifactId> + </dependency> + <dependency> + <groupId>org.glassfish.jaxb</groupId> + <artifactId>codemodel</artifactId> + </dependency> + </dependencies> + +</project>
diff --git a/istack-commons/buildtools/src/main/java/com/sun/istack/build/NameConverter.java b/istack-commons/buildtools/src/main/java/com/sun/istack/build/NameConverter.java new file mode 100644 index 0000000..847f469 --- /dev/null +++ b/istack-commons/buildtools/src/main/java/com/sun/istack/build/NameConverter.java
@@ -0,0 +1,283 @@ +/* + * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.build; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.StringTokenizer; + +/** + * Converts arbitrary strings into Java identifiers. + * + * @author + * <a href="mailto:kohsuke.kawaguchi@sun.com">Kohsuke KAWAGUCHI</a> + */ +public interface NameConverter +{ + /** + * converts a string into an identifier suitable for classes. + * + * In general, this operation should generate "NamesLikeThis". + * @param token string to convert + * @return converted token + */ + String toClassName( String token ); + + /** + * converts a string into an identifier suitable for interfaces. + * + * In general, this operation should generate "NamesLikeThis". + * But for example, it can prepend every interface with 'I'. + * @param token string to convert + * @return converted token + */ + String toInterfaceName( String token ); + + /** + * converts a string into an identifier suitable for properties. + * + * In general, this operation should generate "NamesLikeThis", + * which will be used with known prefixes like "get" or "set". + * @param token string to convert + * @return converted token + */ + String toPropertyName( String token ); + + /** + * converts a string into an identifier suitable for constants. + * + * In the standard Java naming convention, this operation should + * generate "NAMES_LIKE_THIS". + * @param token string to convert + * @return converted token + */ + String toConstantName( String token ); + + /** + * Converts a string into an identifier suitable for variables. + * + * In general it should generate "namesLikeThis". + * @param token string to convert + * @return converted token + */ + String toVariableName( String token ); + + /** + * Converts a namespace URI into a package name. + * This method should expect strings like + * "http://foo.bar.zot/org", "urn:abc:def:ghi" "", or even "###" + * (basically anything) and expected to return a package name, + * liks "org.acme.foo". + * + * @param namespaceUri ns uri to convert + * @return converted uri + */ + String toPackageName( String namespaceUri ); + + /** + * The name converter implemented by Code Model. + * + * This is the standard name conversion for JAXB. + */ + NameConverter standard = new Standard(); + + /** + * Default implementation of {@link NameConverter}. + */ + class Standard extends NameUtil implements NameConverter { + @Override + public String toClassName(String s) { + return toMixedCaseName(toWordList(s), true); + } + @Override + public String toVariableName(String s) { + return toMixedCaseName(toWordList(s), false); + } + @Override + public String toInterfaceName( String token ) { + return toClassName(token); + } + @Override + public String toPropertyName(String s) { + String prop = toClassName(s); + // property name "Class" with collide with Object.getClass, + // so escape this. + if(prop.equals("Class")) + prop = "Clazz"; + return prop; + } + @Override + public String toConstantName( String token ) { + return super.toConstantName(token); + } + /** + * Computes a Java package name from a namespace URI, + * as specified in the spec. + * + * @param nsUri to convert + * @return + * null if it fails to derive a package name. + */ + @Override + public String toPackageName( String nsUri ) { + // remove scheme and :, if present + // spec only requires us to remove 'http' and 'urn'... + int idx = nsUri.indexOf(':'); + String scheme = ""; + if(idx>=0) { + scheme = nsUri.substring(0,idx); + if( scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("urn") ) + nsUri = nsUri.substring(idx+1); + } + + // tokenize string + ArrayList<String> tokens = tokenize( nsUri, "/: " ); + if( tokens.isEmpty() ) { + return null; + } + + // remove trailing file type, if necessary + if( tokens.size() > 1 ) { + // for uri's like "www.foo.com" and "foo.com", there is no trailing + // file, so there's no need to look at the last '.' and substring + // otherwise, we loose the "com" (which would be wrong) + String lastToken = tokens.get( tokens.size()-1 ); + idx = lastToken.lastIndexOf( '.' ); + if( idx > 0 ) { + lastToken = lastToken.substring( 0, idx ); + tokens.set( tokens.size()-1, lastToken ); + } + } + + // tokenize domain name and reverse. Also remove :port if it exists + String domain = tokens.get( 0 ); + idx = domain.indexOf(':'); + if( idx >= 0) domain = domain.substring(0, idx); + ArrayList<String> r = reverse( tokenize( domain, scheme.equals("urn")?".-":"." ) ); + if( r.get( r.size()-1 ).equalsIgnoreCase( "www" ) ) { + // remove leading www + r.remove( r.size()-1 ); + } + + // replace the domain name with tokenized items + tokens.addAll( 1, r ); + tokens.remove( 0 ); + + // iterate through the tokens and apply xml->java name algorithm + for( int i = 0; i < tokens.size(); i++ ) { + + // get the token and remove illegal chars + String token = tokens.get( i ); + token = removeIllegalIdentifierChars( token ); + + // this will check for reserved keywords + if( !NameUtil.isJavaIdentifier( token ) ) { + token = '_' + token; + } + + tokens.set( i, token.toLowerCase(Locale.ENGLISH) ); + } + + // concat all the pieces and return it + return combine( tokens, '.' ); + } + + + private static String removeIllegalIdentifierChars(String token) { + StringBuilder newToken = new StringBuilder(); + for( int i = 0; i < token.length(); i++ ) { + char c = token.charAt( i ); + + if( i ==0 && !Character.isJavaIdentifierStart( c ) ) { + // prefix an '_' if the first char is illegal + newToken.append('_').append(c); + } else if( !Character.isJavaIdentifierPart( c ) ) { + // replace the char with an '_' if it is illegal + newToken.append( '_' ); + } else { + // add the legal char + newToken.append( c ); + } + } + return newToken.toString(); + } + + + private static ArrayList<String> tokenize( String str, String sep ) { + StringTokenizer tokens = new StringTokenizer(str,sep); + ArrayList<String> r = new ArrayList<>(); + + while(tokens.hasMoreTokens()) + r.add( tokens.nextToken() ); + + return r; + } + + private static <T> ArrayList<T> reverse( List<T> a ) { + ArrayList<T> r = new ArrayList<>(); + + for( int i=a.size()-1; i>=0; i-- ) + r.add( a.get(i) ); + + return r; + } + + private static String combine( List<String> r, char sep ) { + StringBuilder buf = new StringBuilder(r.get(0)); + + for( int i=1; i<r.size(); i++ ) { + buf.append(sep); + buf.append(r.get(i)); + } + + return buf.toString(); + } + } + + /** + * JAX-PRC compatible name converter implementation. + * + * The only difference is that we treat '_' as a valid character + * and not as a word separator. + */ + NameConverter jaxrpcCompatible = new Standard() { + @Override + protected boolean isPunct(char c) { + return (c == '.' || c == '-' || c == ';' /*|| c == '_'*/ || c == '\u00b7' + || c == '\u0387' || c == '\u06dd' || c == '\u06de'); + } + @Override + protected boolean isLetter(char c) { + return super.isLetter(c) || c=='_'; + } + + @Override + protected int classify(char c0) { + if(c0=='_') return NameUtil.OTHER_LETTER; + return super.classify(c0); + } + }; + + /** + * Smarter converter used for RELAX NG support. + */ + NameConverter smart = new Standard() { + @Override + public String toConstantName( String token ) { + String name = super.toConstantName(token); + if( NameUtil.isJavaIdentifier(name) ) + return name; + else + return '_'+name; + } + }; +}
diff --git a/istack-commons/buildtools/src/main/java/com/sun/istack/build/NameUtil.java b/istack-commons/buildtools/src/main/java/com/sun/istack/build/NameUtil.java new file mode 100644 index 0000000..bac6ef4 --- /dev/null +++ b/istack-commons/buildtools/src/main/java/com/sun/istack/build/NameUtil.java
@@ -0,0 +1,402 @@ +/* + * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.build; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; + +/** + * Methods that convert strings into various formats. + * + * <p> + * What JAX-RPC name binding tells us is that even such basic method + * like "isLetter" can be different depending on the situation. + * + * For this reason, a whole lot of methods are made non-static, + * even though they look like they should be static. + */ +class NameUtil { + protected boolean isPunct(char c) { + return c == '-' || c == '.' || c == ':' || c == '_' || c == '\u00b7' || c == '\u0387' || c == '\u06dd' || c == '\u06de'; + } + + protected static boolean isDigit(char c) { + return c >= '0' && c <= '9' || Character.isDigit(c); + } + + protected static boolean isUpper(char c) { + return c >= 'A' && c <= 'Z' || Character.isUpperCase(c); + } + + protected static boolean isLower(char c) { + return c >= 'a' && c <= 'z' || Character.isLowerCase(c); + } + + protected boolean isLetter(char c) { + return c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || Character.isLetter(c); + } + + /** + * Capitalizes the first character of the specified string, + * and de-capitalize the rest of characters. + */ + public String capitalize(String s) { + if (!isLower(s.charAt(0))) { + return s; + } + StringBuilder sb = new StringBuilder(s.length()); + sb.append(Character.toUpperCase(s.charAt(0))); + sb.append(s.substring(1).toLowerCase(Locale.ENGLISH)); + return sb.toString(); + } + + // Precondition: s[start] is not punctuation + private int nextBreak(String s, int start) { + int n = s.length(); + + char c1 = s.charAt(start); + int t1 = classify(c1); + + for (int i=start+1; i<n; i++) { + // shift (c1,t1) into (c0,t0) + // char c0 = c1; --- conceptually, but c0 won't be used + int t0 = t1; + + c1 = s.charAt(i); + t1 = classify(c1); + + switch(actionTable[t0*5+t1]) { + case ACTION_CHECK_PUNCT: + if(isPunct(c1)) return i; + break; + case ACTION_CHECK_C2: + if (i < n-1) { + char c2 = s.charAt(i+1); + if (isLower(c2)) + return i; + } + break; + case ACTION_BREAK: + return i; + } + } + return -1; + } + + // the 5-category classification that we use in this code + // to find work breaks + static protected final int UPPER_LETTER = 0; + static protected final int LOWER_LETTER = 1; + static protected final int OTHER_LETTER = 2; + static protected final int DIGIT = 3; + static protected final int OTHER = 4; + + /** + * Look up table for actions. + * type0*5+type1 would yield the action to be taken. + */ + private static final byte[] actionTable = new byte[5*5]; + + // action constants. see nextBreak for the meaning + static private final byte ACTION_CHECK_PUNCT = 0; + static private final byte ACTION_CHECK_C2 = 1; + static private final byte ACTION_BREAK = 2; + static private final byte ACTION_NOBREAK = 3; + + /** + * Decide the action to be taken given + * the classification of the preceding character 't0' and + * the classification of the next character 't1'. + */ + private static byte decideAction( int t0, int t1 ) { + if(t0==OTHER && t1==OTHER) return ACTION_CHECK_PUNCT; + if(!xor(t0==DIGIT,t1==DIGIT)) return ACTION_BREAK; + if(t0==LOWER_LETTER && t1!=LOWER_LETTER) return ACTION_BREAK; + if(!xor(t0<=OTHER_LETTER,t1<=OTHER_LETTER)) return ACTION_BREAK; + if(!xor(t0==OTHER_LETTER,t1==OTHER_LETTER)) return ACTION_BREAK; + + if(t0==UPPER_LETTER && t1==UPPER_LETTER) return ACTION_CHECK_C2; + + return ACTION_NOBREAK; + } + + private static boolean xor(boolean x,boolean y) { + return (x&&y) || (!x&&!y); + } + + static { + // initialize the action table + for( int t0=0; t0<5; t0++ ) + for( int t1=0; t1<5; t1++ ) + actionTable[t0*5+t1] = decideAction(t0,t1); + } + + /** + * Classify a character into 5 categories that determine the word break. + */ + protected int classify(char c0) { + switch(Character.getType(c0)) { + case Character.UPPERCASE_LETTER: return UPPER_LETTER; + case Character.LOWERCASE_LETTER: return LOWER_LETTER; + case Character.TITLECASE_LETTER: + case Character.MODIFIER_LETTER: + case Character.OTHER_LETTER: return OTHER_LETTER; + case Character.DECIMAL_DIGIT_NUMBER: return DIGIT; + default: return OTHER; + } + } + + + /** + * Tokenizes a string into words and capitalizes the first + * character of each word. + * + * <p> + * This method uses a change in character type as a splitter + * of two words. For example, "abc100ghi" will be splitted into + * {"Abc", "100","Ghi"}. + */ + public List<String> toWordList(String s) { + ArrayList<String> ss = new ArrayList<>(); + int n = s.length(); + for (int i = 0; i < n;) { + + // Skip punctuation + while (i < n) { + if (!isPunct(s.charAt(i))) + break; + i++; + } + if (i >= n) break; + + // Find next break and collect word + int b = nextBreak(s, i); + String w = (b == -1) ? s.substring(i) : s.substring(i, b); + ss.add(escape(capitalize(w))); + if (b == -1) break; + i = b; + } + +// we can't guarantee a valid Java identifier anyway, +// so there's not much point in rejecting things in this way. +// if (ss.size() == 0) +// throw new IllegalArgumentException("Zero-length identifier"); + return ss; + } + + protected String toMixedCaseName(List<String> ss, boolean startUpper) { + StringBuilder sb = new StringBuilder(); + if(!ss.isEmpty()) { + sb.append(startUpper ? ss.get(0) : ss.get(0).toLowerCase(Locale.ENGLISH)); + for (int i = 1; i < ss.size(); i++) + sb.append(ss.get(i)); + } + return sb.toString(); + } + + protected String toMixedCaseVariableName(String[] ss, + boolean startUpper, + boolean cdrUpper) { + if (cdrUpper) + for (int i = 1; i < ss.length; i++) + ss[i] = capitalize(ss[i]); + StringBuilder sb = new StringBuilder(); + if( ss.length>0 ) { + sb.append(startUpper ? ss[0] : ss[0].toLowerCase(Locale.ENGLISH)); + for (int i = 1; i < ss.length; i++) + sb.append(ss[i]); + } + return sb.toString(); + } + + + /** + * Formats a string into "THIS_KIND_OF_FORMAT_ABC_DEF". + * + * @return + * Always return a string but there's no guarantee that + * the generated code is a valid Java identifier. + */ + public String toConstantName(String s) { + return toConstantName(toWordList(s)); + } + + /** + * Formats a string into "THIS_KIND_OF_FORMAT_ABC_DEF". + * + * @return + * Always return a string but there's no guarantee that + * the generated code is a valid Java identifier. + */ + public String toConstantName(List<String> ss) { + StringBuilder sb = new StringBuilder(); + if( !ss.isEmpty() ) { + sb.append(ss.get(0).toUpperCase(Locale.ENGLISH)); + for (int i = 1; i < ss.size(); i++) { + sb.append('_'); + sb.append(ss.get(i).toUpperCase(Locale.ENGLISH)); + } + } + return sb.toString(); + } + + + + /** + * Escapes characters is the given string so that they can be + * printed by only using US-ASCII characters. + * + * The escaped characters will be appended to the given + * StringBuffer. + * + * @param sb + * StringBuffer that receives escaped string. + * @param s + * String to be escaped. <code>s.substring(start)</code> + * will be escaped and copied to the string buffer. + */ + public static void escape(StringBuilder sb, String s, int start) { + int n = s.length(); + for (int i = start; i < n; i++) { + char c = s.charAt(i); + if (Character.isJavaIdentifierPart(c)) + sb.append(c); + else { + sb.append('_'); + if (c <= '\u000f') sb.append("000"); + else if (c <= '\u00ff') sb.append("00"); + else if (c <= '\u0fff') sb.append('0'); + sb.append(Integer.toString(c, 16)); + } + } + } + + /** + * Escapes characters that are unusable as Java identifiers + * by replacing unsafe characters with safe characters. + */ + private static String escape(String s) { + int n = s.length(); + for (int i = 0; i < n; i++) + if (!Character.isJavaIdentifierPart(s.charAt(i))) { + StringBuilder sb = new StringBuilder(s.substring(0, i)); + escape(sb, s, i); + return sb.toString(); + } + return s; + } + + + /** + * Checks if a given string is usable as a Java identifier. + */ + public static boolean isJavaIdentifier(String s) { + if(s.length()==0) return false; + if( reservedKeywords.contains(s) ) return false; + + if(!Character.isJavaIdentifierStart(s.charAt(0))) return false; + + for (int i = 1; i < s.length(); i++) + if (!Character.isJavaIdentifierPart(s.charAt(i))) + return false; + + return true; + } + + /** + * Checks if the given string is a valid Java package name. + */ + public static boolean isJavaPackageName(String s) { + while(s.length()!=0) { + int idx = s.indexOf('.'); + if(idx==-1) idx=s.length(); + if( !isJavaIdentifier(s.substring(0,idx)) ) + return false; + + s = s.substring(idx); + if(s.length()!=0) s = s.substring(1); // remove '.' + } + return true; + } + + + /** All reserved keywords of Java. */ + private static HashSet<String> reservedKeywords = new HashSet<>(); + + static { + // see http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html + String[] words = new String[]{ + "abstract", + "boolean", + "break", + "byte", + "case", + "catch", + "char", + "class", + "const", + "continue", + "default", + "do", + "double", + "else", + "extends", + "final", + "finally", + "float", + "for", + "goto", + "if", + "implements", + "import", + "instanceof", + "int", + "interface", + "long", + "native", + "new", + "package", + "private", + "protected", + "public", + "return", + "short", + "static", + "strictfp", + "super", + "switch", + "synchronized", + "this", + "throw", + "throws", + "transient", + "try", + "void", + "volatile", + "while", + + // technically these are not reserved words but they cannot be used as identifiers. + "true", + "false", + "null", + + // and I believe assert is also a new keyword + "assert", + + // and 5.0 keywords + "enum" + }; + reservedKeywords.addAll(Arrays.asList(words)); + } +}
diff --git a/istack-commons/buildtools/src/main/java/com/sun/istack/build/ResourceGenTask.java b/istack-commons/buildtools/src/main/java/com/sun/istack/build/ResourceGenTask.java new file mode 100644 index 0000000..73a242f --- /dev/null +++ b/istack-commons/buildtools/src/main/java/com/sun/istack/build/ResourceGenTask.java
@@ -0,0 +1,321 @@ +/* + * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.build; + +import com.sun.codemodel.CodeWriter; +import com.sun.codemodel.JClass; +import com.sun.codemodel.JClassAlreadyExistsException; +import com.sun.codemodel.JCodeModel; +import com.sun.codemodel.JDefinedClass; +import com.sun.codemodel.JExpr; +import com.sun.codemodel.JFieldVar; +import com.sun.codemodel.JInvocation; +import com.sun.codemodel.JMethod; +import com.sun.codemodel.JMod; +import com.sun.codemodel.JPackage; +import com.sun.codemodel.writer.FileCodeWriter; +import com.sun.codemodel.writer.FilterCodeWriter; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.types.FileSet; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Writer; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +/** + * Generate source files from resource bundles, + * so that code can refer to resources as methods, + * instead of hard-coding string constants, which is + * much harder to search. + * + * @author Lukas Jungmann + * @author Kohsuke Kawaguchi + */ +public class ResourceGenTask extends Task { + /** + * Resource files to be compiled + */ + private FileSet resources; + + private File destDir; + + /** + * @since 2.12 + */ + private File license; + + /** + * @since 2.12 + */ + private String localizationUtilitiesPkgName; + + /** + * @since 2.12 + */ + private String encoding; + + public void addConfiguredResource( FileSet fs ) { + resources = fs; + } + + public void setDestDir(File dir) { + this.destDir = dir; + } + + /** + * @since 2.12 + */ + public void setLicense(File license) { + this.license = license; + } + + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + /** + * @since 2.12 + */ + public void setLocalizationUtilitiesPkgName(String localizationUtilitiesPkgName) { + this.localizationUtilitiesPkgName = localizationUtilitiesPkgName; + } + + @Override + public void execute() throws BuildException { + if(resources==null) + throw new BuildException("No resource file is specified"); + if(destDir==null) + throw new BuildException("No destdir attribute is specified"); + + if(localizationUtilitiesPkgName == null) { + localizationUtilitiesPkgName = "com.sun.istack.localization"; + } + + if (!destDir.exists() && !destDir.mkdirs()) { + throw new BuildException("Cannot create destdir"); + } + + if (!destDir.canWrite()) { + throw new BuildException("Cannot write to destdir"); + } + + if (encoding == null || encoding.trim().length() == 0) { + encoding = System.getProperty("file.encoding"); + log("File encoding has not been set, using platform encoding " + + encoding + ", i.e. build is platform dependent!", + Project.MSG_WARN); + } + + JCodeModel cm = new JCodeModel(); + + DirectoryScanner ds = resources.getDirectoryScanner(getProject()); + String[] includedFiles = ds.getIncludedFiles(); + File baseDir = ds.getBasedir(); + + for (String value : includedFiles) { + File res = new File(baseDir, value); + + if(res.getName().contains("_")) + continue; // this is a localized bundle, so ignore. + + String className = getClassName(res); + + String bundleName = value.substring(0, value.lastIndexOf('.')).replace('/', '.').replace('\\', '.');// cut off '.properties' + String dirName = bundleName.substring(0, bundleName.lastIndexOf('.')); + + File destFile = new File(new File(destDir,dirName.replace('.','/')),className+".java"); + if(destFile.lastModified() >= res.lastModified()) { + log("Skipping "+res,Project.MSG_INFO); + continue; + } + + log("Processing "+res,Project.MSG_INFO); + JPackage pkg = cm._package(dirName); + + Properties props = new Properties(); + FileInputStream in = null; + try { + in = new FileInputStream(res); + props.load(in); + } catch (IOException e) { + throw new BuildException(e.getMessage(), e); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException ioe) { + throw new BuildException(ioe.getMessage(), ioe); + } + } + } + + JDefinedClass clazz; + try { + clazz = pkg._class(JMod.PUBLIC | JMod.FINAL, className); + } catch (JClassAlreadyExistsException e) { + throw new BuildException("Name conflict "+className); + } + + clazz.javadoc().add( + "Defines string formatting method for each constant in the resource file" + ); + + /* + [RESULT] + + LocalizableMessageFactory messageFactory = + new LocalizableMessageFactory("com.sun.xml.ws.resources.client"); + Localizer localizer = new Localizer(); + */ + + JClass lmf_class; + JClass l_class; + JClass lable_class; + try { + lmf_class = cm.parseType(addLocalizationUtilityPackageName("LocalizableMessageFactory")).boxify(); + l_class = cm.parseType(addLocalizationUtilityPackageName("Localizer")).boxify(); + lable_class = cm.parseType(addLocalizationUtilityPackageName("Localizable")).boxify(); + } catch (Throwable e) { + throw new BuildException(e); // impossible -- but why parseType throwing Exception!? + } + + JFieldVar $msgFactory = clazz.field(JMod.PRIVATE|JMod.STATIC|JMod.FINAL, + lmf_class, "messageFactory", JExpr._new(lmf_class).arg(JExpr.lit(bundleName))); + + JFieldVar $localizer = clazz.field(JMod.PRIVATE|JMod.STATIC|JMod.FINAL, + l_class, "localizer", JExpr._new(l_class)); + + for (Map.Entry<Object,Object> e : props.entrySet()) { + // [RESULT] + // Localizable METHOD_localizable(Object arg1, Object arg2, ...) { + // return messageFactory.getMessage("servlet.html.notFound", message)); + // } + // String METHOD(Object arg1, Object arg2, ...) { + // return localizer.localize(METHOD_localizable(arg1,arg2,...)); + // } + String methodBaseName = NameConverter.smart.toConstantName(e.getKey().toString()); + + JMethod method = clazz.method(JMod.PUBLIC | JMod.STATIC, lable_class, "localizable"+methodBaseName); + + int countArgs = countArgs(e.getValue().toString()); + + JInvocation format = $msgFactory.invoke("getMessage").arg( + JExpr.lit(e.getKey().toString())); + + for( int i=0; i<countArgs; i++ ) { + format.arg( method.param(Object.class,"arg"+i)); + } + method.body()._return(format); + + JMethod method2 = clazz.method(JMod.PUBLIC|JMod.STATIC, String.class, methodBaseName); + method2.javadoc().add(e.getValue()); + + JInvocation localize = JExpr.invoke(method); + for( int i=0; i<countArgs; i++ ) { + localize.arg( method2.param(Object.class,"arg"+i)); + } + + method2.body()._return($localizer.invoke("localize").arg(localize)); + } + } + + try { + CodeWriter core = new FileCodeWriter(destDir, encoding); + if (license != null) { + core = new LicenseCodeWriter(core, license, encoding); + } + cm.build(core); + } catch (IOException e) { + throw new BuildException("Failed to generate code",e); + } + } + + private String addLocalizationUtilityPackageName(final String className) { + return String.format("%s.%s", localizationUtilitiesPkgName, className); + } + + /** + * Counts the number of arguments. + */ + private int countArgs(String value) { + List<String> x = new ArrayList<>(); + + while(true) { + String r1 = MessageFormat.format(value, x.toArray()); + x.add("xxxx"); + String r2 = MessageFormat.format(value, x.toArray()); + + if(r1.equals(r2)) + return x.size()-1; + } + } + + /** + * Computes the class name from the resource bundle name. + */ + private String getClassName(File res) { + String name = res.getName(); + int suffixIndex = name.lastIndexOf('.'); + name = name.substring(0,suffixIndex); + return NameConverter.smart.toClassName(name)+"Messages"; + } + + /** + * Writes all the source files under the specified file folder and + * inserts a license file each java source file. + * + * @author Jitendra Kotamraju + * + */ + public static class LicenseCodeWriter extends FilterCodeWriter { + private final File license; + + /** + * @param core + * This CodeWriter will be used to actually create a storage for files. + * LicenseCodeWriter simply decorates this underlying CodeWriter by + * adding prolog comments. + * @param license license File + */ + public LicenseCodeWriter(CodeWriter core, File license, String encoding) { + super(core); + this.license = license; + this.encoding = encoding; + } + + @Override + public Writer openSource(JPackage pkg, String fileName) throws IOException { + Writer w = super.openSource(pkg,fileName); + + PrintWriter out = new PrintWriter(w); + try (FileInputStream fin = new FileInputStream(license)) { + byte[] buf = new byte[8192]; + int len; + while ((len = fin.read(buf)) != -1) { + out.write(new String(buf, 0, len)); + } + } + out.flush(); // we can't close the stream for that would close the undelying stream. + + return w; + } + } +}
diff --git a/istack-commons/import-properties-plugin/exclude.xml b/istack-commons/import-properties-plugin/exclude.xml new file mode 100644 index 0000000..43ee8b0 --- /dev/null +++ b/istack-commons/import-properties-plugin/exclude.xml
@@ -0,0 +1,22 @@ +<!-- + + Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<FindBugsFilter> + <!-- + Generated by Maven. + --> + <Match> + <Or> + <Class name="com.oracle.istack.maven.HelpMojo"/> + </Or> + </Match> +</FindBugsFilter>
diff --git a/istack-commons/import-properties-plugin/pom.xml b/istack-commons/import-properties-plugin/pom.xml new file mode 100644 index 0000000..1c90108 --- /dev/null +++ b/istack-commons/import-properties-plugin/pom.xml
@@ -0,0 +1,168 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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 Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <parent> + <artifactId>istack-commons</artifactId> + <groupId>com.sun.istack</groupId> + <version>4.2.0</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <modelVersion>4.0.0</modelVersion> + <groupId>com.sun.istack</groupId> + <artifactId>import-properties-plugin</artifactId> + <packaging>maven-plugin</packaging> + <name>istack common import properties plugin</name> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <properties> + <findbugs.exclude>${project.basedir}/exclude.xml</findbugs.exclude> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-plugin-api</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-core</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-utils</artifactId> + </dependency> + <dependency> + <groupId>org.apache.maven.plugin-tools</groupId> + <artifactId>maven-plugin-annotations</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.maven.resolver</groupId> + <artifactId>maven-resolver-api</artifactId> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-model</artifactId> + <scope>provided</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-plugin-plugin</artifactId> + <executions> + <execution> + <id>mojo-descriptor</id> + <goals> + <goal>descriptor</goal> + <goal>helpmojo</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <profiles> + <profile> + <id>ittest</id> + <activation> + <property> + <name>ittest</name> + <value>true</value> + </property> + </activation> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.gmaven</groupId> + <artifactId>gmaven-plugin</artifactId> + <executions> + <execution> + <id>set-proxy</id> + <phase>pre-integration-test</phase> + <goals> + <goal>execute</goal> + </goals> + <configuration> + <source>${project.basedir}/src/test/script/setproxy.groovy</source> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-invoker-plugin</artifactId> + <configuration> + <localRepositoryPath>${project.build.directory}/it-repo</localRepositoryPath> + <streamLogs>true</streamLogs> + <addTestClassPath>true</addTestClassPath> + <settingsFile>${project.build.directory}/it-settings.xml</settingsFile> + <mavenOpts>${ittest-proxy}</mavenOpts> + <properties> + <ip.plugin.version>${project.version}</ip.plugin.version> + </properties> + </configuration> + <executions> + <execution> + <id>integration-test-installdeps</id> + <phase>pre-integration-test</phase> + <goals> + <goal>install</goal> + </goals> + </execution> + <execution> + <id>integration-test</id> + <goals> + <goal>run</goal> + </goals> + <configuration> + <projectsDirectory>src/test/it</projectsDirectory> + <cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-failsafe-plugin</artifactId> + <executions> + <execution> + <id>integration-test-verify</id> + <phase>post-integration-test</phase> + <goals> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + <configuration> + <systemPropertyVariables> + <it.projects.dir>${project.build.directory}/it</it.projects.dir> + </systemPropertyVariables> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> +</project>
diff --git a/istack-commons/import-properties-plugin/src/main/java/com/oracle/istack/maven/CommonLogger.java b/istack-commons/import-properties-plugin/src/main/java/com/oracle/istack/maven/CommonLogger.java new file mode 100644 index 0000000..aa0e1de --- /dev/null +++ b/istack-commons/import-properties-plugin/src/main/java/com/oracle/istack/maven/CommonLogger.java
@@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.oracle.istack.maven; + +import org.apache.maven.plugin.logging.Log; + +/** + * + * @author Martin Grebac + */ +public class CommonLogger { + + private final Log log; + + public CommonLogger(Log log) { + this.log = log; + } + + public void warn(String s) { + if (log != null) { + log.warn(s); + } + } + + public void info(String s) { + if (log != null) { + log.info(s); + } + } +}
diff --git a/istack-commons/import-properties-plugin/src/main/java/com/oracle/istack/maven/DependencyResolver.java b/istack-commons/import-properties-plugin/src/main/java/com/oracle/istack/maven/DependencyResolver.java new file mode 100644 index 0000000..d102621 --- /dev/null +++ b/istack-commons/import-properties-plugin/src/main/java/com/oracle/istack/maven/DependencyResolver.java
@@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.oracle.istack.maven; + +import java.util.List; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.collection.CollectRequest; +import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.resolution.DependencyRequest; +import org.eclipse.aether.resolution.DependencyResolutionException; +import org.eclipse.aether.resolution.DependencyResult; +import org.eclipse.aether.artifact.DefaultArtifact; + +/** + * + * @author lukas + */ +final class DependencyResolver { + + public static DependencyResult resolve(CollectRequest collectRequest, List<RemoteRepository> remoteRepos, + RepositorySystem repoSystem, RepositorySystemSession repoSession) throws DependencyResolutionException { + DependencyRequest dependencyRequest = new DependencyRequest(collectRequest, null); + return repoSystem.resolveDependencies(repoSession, dependencyRequest); + } + + public static DependencyResult resolve(org.apache.maven.model.Dependency dependency, List<RemoteRepository> remoteRepos, + RepositorySystem repoSystem, RepositorySystemSession repoSession) throws DependencyResolutionException { + CollectRequest collectRequest = new CollectRequest(createDependency(dependency), remoteRepos); + return resolve(collectRequest, remoteRepos, repoSystem, repoSession); + } + + private static Dependency createDependency(org.apache.maven.model.Dependency d) { + Artifact artifact = new DefaultArtifact(d.getGroupId(), d.getArtifactId(), "pom", d.getVersion()); + return new Dependency(artifact, d.getScope(), d.isOptional(), null); + } + +}
diff --git a/istack-commons/import-properties-plugin/src/main/java/com/oracle/istack/maven/ImportPropertiesMojo.java b/istack-commons/import-properties-plugin/src/main/java/com/oracle/istack/maven/ImportPropertiesMojo.java new file mode 100644 index 0000000..29a3d0d --- /dev/null +++ b/istack-commons/import-properties-plugin/src/main/java/com/oracle/istack/maven/ImportPropertiesMojo.java
@@ -0,0 +1,99 @@ +/* + * 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 Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.oracle.istack.maven; + +import java.io.IOException; +import java.util.List; +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.repository.RemoteRepository; + +/** + * The import-properties goal imports all properties from scope-import poms + * (boms) and sets them as project properties. + * + * @author Martin Grebac + */ +@Mojo(name = "import-pom-properties", threadSafe = true, + defaultPhase = LifecyclePhase.COMPILE, requiresDependencyResolution = ResolutionScope.NONE) +public class ImportPropertiesMojo extends AbstractMojo { + + /** + * The Maven Project Object. + */ + @Parameter(defaultValue = "${project}", readonly = true) + protected MavenProject project; + + /** + * The entry point to Aether, i.e. the component doing all the work. + * + * @since 2.3.1 + */ + @Component + private RepositorySystem repoSystem; + + /** + * The current repository/network configuration of Maven. + * + * @since 2.3.1 + */ + @Parameter(defaultValue = "${repositorySystemSession}", readonly = true) + private RepositorySystemSession repoSession; + + /** + * The project's remote repositories to use for the resolution of project + * and its dependencies. + * + * @since 2.3.1 + */ + @Parameter(defaultValue = "${project.remoteProjectRepositories}", readonly = true) + private List<RemoteRepository> projectRepos; + + private Properties projectProperties = null; + + @Override + public void execute() throws MojoExecutionException { + try { + projectProperties = project.getProperties(); + + MavenProject bomProject = project; + while (bomProject != null && !bomProject.getArtifactId().endsWith("-bom")) { + bomProject = bomProject.getParent(); + } + + if (bomProject == null || !bomProject.getArtifactId().endsWith("-bom")) { + getLog().warn("No '*-bom' project found in project hierarchy, using this project's pom for import search."); + bomProject = project; + } + + getLog().warn("Searching project: " + bomProject.getArtifactId()); + + PropertyResolver resolver = new PropertyResolver(new CommonLogger(getLog()), projectProperties, repoSession, repoSystem, projectRepos); + resolver.resolveProperties(bomProject); + + } catch (XmlPullParserException | IOException ex) { + Logger.getLogger(ImportPropertiesMojo.class.getName()).log(Level.SEVERE, null, ex); + } + } + +}
diff --git a/istack-commons/import-properties-plugin/src/main/java/com/oracle/istack/maven/PropertyResolver.java b/istack-commons/import-properties-plugin/src/main/java/com/oracle/istack/maven/PropertyResolver.java new file mode 100644 index 0000000..16e4834 --- /dev/null +++ b/istack-commons/import-properties-plugin/src/main/java/com/oracle/istack/maven/PropertyResolver.java
@@ -0,0 +1,123 @@ +/* + * 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 Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.oracle.istack.maven; + +import org.apache.maven.model.Dependency; +import org.apache.maven.model.DependencyManagement; +import org.apache.maven.model.Model; +import org.apache.maven.model.io.xpp3.MavenXpp3Reader; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.resolution.DependencyResolutionException; +import org.eclipse.aether.resolution.DependencyResult; + +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author Martin Grebac + */ +public class PropertyResolver { + + private final CommonLogger logger; + + private final MavenXpp3Reader mavenreader = new MavenXpp3Reader(); + + private final Properties properties; + + private final RepositorySystemSession repoSession; + + private final RepositorySystem repoSystem; + + private final List<RemoteRepository> pluginRepos; + + PropertyResolver(CommonLogger logger, Properties properties, RepositorySystemSession session, + RepositorySystem repoSystem, List<RemoteRepository> pluginRepositories) { + this.logger = logger; + this.properties = properties; + this.repoSession = session; + this.repoSystem = repoSystem; + this.pluginRepos = pluginRepositories; + } + + /** + * + * @param project maven project + * @throws FileNotFoundException properties not found + * @throws IOException IO error + * @throws XmlPullParserException error parsing xml + */ + public void resolveProperties(MavenProject project) throws FileNotFoundException, IOException, XmlPullParserException { + logger.info("Resolving properties for " + project.getGroupId() + ":" + project.getArtifactId()); + + Model model = null; + FileReader reader; + try { + reader = new FileReader(project.getFile()); + model = mavenreader.read(reader); + } catch (IOException ex) { + Logger.getLogger(ImportPropertiesMojo.class.getName()).log(Level.SEVERE, null, ex); + } + MavenProject loadedProject = new MavenProject(model); + + DependencyManagement dm = loadedProject.getDependencyManagement(); + if (dm == null) { + logger.warn("No dependency management section found in: " + loadedProject.getGroupId() + ":" + loadedProject.getArtifactId()); + return; + } + + List<Dependency> depList = dm.getDependencies(); + + DependencyResult result; + for (Dependency d : depList) { + if ("import".equals(d.getScope())) { + try { + String version = d.getVersion(); + logger.info("Imported via import-scope: " + d.getGroupId() + ":" + d.getArtifactId() + ":" + version); + if (version.contains("$")) { + version = properties.getProperty(version.substring(version.indexOf('{')+1, version.lastIndexOf('}'))); + logger.info("Imported version resolved to: " + version); + } + d.setVersion(version); + d.setType("pom"); + d.setClassifier("pom"); + result = DependencyResolver.resolve(d, pluginRepos, repoSystem, repoSession); + Artifact a = result.getArtifactResults().get(0).getArtifact(); + reader = new FileReader(a.getFile()); + Model m = mavenreader.read(reader); + MavenProject p = new MavenProject(m); + p.setFile(a.getFile()); + for (Map.Entry<Object,Object> e : p.getProperties().entrySet()) { + logger.info("Setting property: " + e.getKey() + ":" + e.getValue()); + properties.setProperty((String)e.getKey(), (String)e.getValue()); + } + + resolveProperties(p); + } catch (DependencyResolutionException ex) { + Logger.getLogger(ImportPropertiesMojo.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + } + + +}
diff --git a/istack-commons/import-properties-plugin/src/test/it/sample/bom/pom.xml b/istack-commons/import-properties-plugin/src/test/it/sample/bom/pom.xml new file mode 100644 index 0000000..97651e8 --- /dev/null +++ b/istack-commons/import-properties-plugin/src/test/it/sample/bom/pom.xml
@@ -0,0 +1,28 @@ +<!-- + + Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>com.sun.xml.ws</groupId> + <artifactId>imported-bom</artifactId> + <version>1.0-SNAPSHOT</version> + <packaging>pom</packaging> + + <name>sample bom</name> + + <properties> + <tested.property>IMPORTED</tested.property> + </properties> + +</project>
diff --git a/istack-commons/import-properties-plugin/src/test/it/sample/pom.xml b/istack-commons/import-properties-plugin/src/test/it/sample/pom.xml new file mode 100644 index 0000000..a483be4 --- /dev/null +++ b/istack-commons/import-properties-plugin/src/test/it/sample/pom.xml
@@ -0,0 +1,98 @@ +<!-- + + 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 Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>com.sun.xml.ws</groupId> + <artifactId>importsample-bom</artifactId> + <version>1.0-SNAPSHOT</version> + <packaging>pom</packaging> + + <name>sample main</name> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>com.sun.xml.ws</groupId> + <artifactId>imported-bom</artifactId> + <version>1.0-SNAPSHOT</version> + <scope>import</scope> + <type>pom</type> + </dependency> + </dependencies> + </dependencyManagement> + + <modules> + <module>bom</module> + </modules> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <ip.plugin.version>4.0.0-SNAPSHOT</ip.plugin.version> + </properties> + + <build> + <pluginManagement> + <plugins> + <plugin> + <groupId>com.sun.istack</groupId> + <artifactId>import-properties-plugin</artifactId> + <version>${ip.plugin.version}</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-enforcer-plugin</artifactId> + <version>3.3.0</version> + </plugin> + </plugins> + </pluginManagement> + <plugins> + <plugin> + <groupId>com.sun.istack</groupId> + <artifactId>import-properties-plugin</artifactId> + <executions> + <execution> + <phase>compile</phase> + <goals> + <goal>import-pom-properties</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-enforcer-plugin</artifactId> + <executions> + <execution> + <id>enforce-property</id> + <goals> + <goal>enforce</goal> + </goals> + <phase>compile</phase> + <configuration> + <rules> + <requireProperty> + <property>tested.property</property> + <message>Property not imported!</message> + </requireProperty> + </rules> + <fail>true</fail> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + +</project>
diff --git a/istack-commons/import-properties-plugin/src/test/resources/it-settings.xml b/istack-commons/import-properties-plugin/src/test/resources/it-settings.xml new file mode 100644 index 0000000..d4f5aa2 --- /dev/null +++ b/istack-commons/import-properties-plugin/src/test/resources/it-settings.xml
@@ -0,0 +1,67 @@ +<?xml version="1.0"?> +<!-- + + Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<settings> + <profiles> + <profile> + <id>it-repo</id> + <activation> + <activeByDefault>true</activeByDefault> + </activation> + <repositories> + <repository> + <id>local.central</id> + <url>@localRepositoryUrl@</url> + <releases> + <enabled>true</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </repository> + <repository> + <id>jakarta-sonatype-nexus</id> + <url>https://jakarta.oss.sonatype.org/service/local/staging/deploy/maven2/</url> + <layout>default</layout> + </repository> + <repository> + <id>jakarta-sonatype-nexus-staging</id> + <url>https://jakarta.oss.sonatype.org/content/repositories/staging/</url> + <layout>default</layout> + </repository> + </repositories> + <pluginRepositories> + <pluginRepository> + <id>local.central</id> + <url>@localRepositoryUrl@</url> + <releases> + <enabled>true</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </pluginRepository> + <pluginRepository> + <id>jakarta-sonatype-nexus-plugins</id> + <url>https://jakarta.oss.sonatype.org/service/local/staging/deploy/maven2/</url> + <layout>default</layout> + </pluginRepository> + <pluginRepository> + <id>jakarta-sonatype-nexus-staging-plugins</id> + <url>https://jakarta.oss.sonatype.org/content/repositories/staging/</url> + <layout>default</layout> + </pluginRepository> + </pluginRepositories> + </profile> + </profiles> +</settings>
diff --git a/istack-commons/import-properties-plugin/src/test/script/setproxy.groovy b/istack-commons/import-properties-plugin/src/test/script/setproxy.groovy new file mode 100644 index 0000000..241003e --- /dev/null +++ b/istack-commons/import-properties-plugin/src/test/script/setproxy.groovy
@@ -0,0 +1,53 @@ +/* + * 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 Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +log.info("Checking proxy...") +def itsettings = new XmlParser().parse(project.build.testResources.directory[0] + "/it-settings.xml") +def itproxy = "" +if (settings?.proxies) { + Node proxies = new Node(itsettings, "proxies") + settings?.proxies?.each { proxy -> + if (proxy.active) { + if ("http".equals(proxy.protocol)) { + itproxy += " -Dhttp.proxyHost=" + proxy.host + if (proxy.port) { + itproxy += " -Dhttp.proxyPort=" + proxy.port + } + } else if ("https".equals(proxy.protocol)) { + itproxy += " -Dhttps.proxyHost=" + proxy.host + if (proxy.port) { + itproxy += " -Dhttps.proxyPort=" + proxy.port + } + } + def p = new Node(proxies, "proxy") + new Node(p, "protocol", proxy.protocol) + new Node(p, "port", proxy.port) + if (proxy.username) {new Node(p, "username", proxy.username)} + if (proxy.password) {new Node(p, "password", proxy.password)} + if (proxy.id) {new Node(p, "id", proxy.id)} else {new Node(p, "id", proxy.protocol)} + new Node(p, "host", proxy.host) + new Node(p, "active", proxy.active) + new Node(p, "nonProxyHosts", proxy.nonProxyHosts) + } + } +} + +if (itproxy.trim().length() > 0) { + log.info("Setting: " + itproxy.trim()) +} else { + log.info("No proxy found") +} + +def writer = new FileWriter(new File(project.build.directory, "it-settings.xml")) +groovy.xml.XmlNodePrinter printer = new groovy.xml.XmlNodePrinter(new PrintWriter(writer)) +printer.setPreserveWhitespace(true) +printer.print(itsettings) + +project.getModel().addProperty("ittest-proxy", itproxy.trim())
diff --git a/istack-commons/maven-plugin/pom.xml b/istack-commons/maven-plugin/pom.xml new file mode 100644 index 0000000..48d8f3a --- /dev/null +++ b/istack-commons/maven-plugin/pom.xml
@@ -0,0 +1,169 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <parent> + <artifactId>istack-commons</artifactId> + <groupId>com.sun.istack</groupId> + <version>4.2.0</version> + <relativePath>../pom.xml</relativePath> + </parent> + <modelVersion>4.0.0</modelVersion> + <groupId>com.sun.istack</groupId> + <artifactId>istack-commons-maven-plugin</artifactId> + <packaging>maven-plugin</packaging> + <name>istack common maven mojo</name> + + <dependencies> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-plugin-api</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.maven.resolver</groupId> + <artifactId>maven-resolver-api</artifactId> + </dependency> + <dependency> + <groupId>org.apache.maven.resolver</groupId> + <artifactId>maven-resolver-impl</artifactId> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-artifact</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.maven.plugin-tools</groupId> + <artifactId>maven-plugin-annotations</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-core</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.glassfish.jaxb</groupId> + <artifactId>codemodel</artifactId> + </dependency> + </dependencies> + + <profiles> + <profile> + <id>ittest</id> + <activation> + <property> + <name>ittest</name> + <value>true</value> + </property> + </activation> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.gmaven</groupId> + <artifactId>gmaven-plugin</artifactId> + <executions> + <execution> + <id>set-proxy</id> + <phase>pre-integration-test</phase> + <goals> + <goal>execute</goal> + </goals> + <configuration> + <source>${project.basedir}/src/test/script/setproxy.groovy</source> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-invoker-plugin</artifactId> + <configuration> + <localRepositoryPath>${project.build.directory}/it-repo</localRepositoryPath> + <streamLogs>true</streamLogs> + <addTestClassPath>true</addTestClassPath> + <settingsFile>${project.build.directory}/it-settings.xml</settingsFile> + <mavenOpts>${ittest-proxy}</mavenOpts> + <properties> + <resgen.plugin.version>${project.version}</resgen.plugin.version> + <tp.compiler.release>${maven.compiler.release}</tp.compiler.release> + </properties> + </configuration> + <executions> + <execution> + <id>integration-test-installdeps</id> + <phase>pre-integration-test</phase> + <goals> + <goal>install</goal> + </goals> + </execution> + <execution> + <id>integration-test</id> + <goals> + <goal>run</goal> + </goals> + <configuration> + <projectsDirectory>src/test/it</projectsDirectory> + <cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-failsafe-plugin</artifactId> + <executions> + <execution> + <id>integration-test-verify</id> + <phase>post-integration-test</phase> + <goals> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + <configuration> + <systemPropertyVariables> + <it.projects.dir>${project.build.directory}/it</it.projects.dir> + </systemPropertyVariables> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-plugin-plugin</artifactId> + <executions> + <execution> + <id>descriptors</id> + <goals> + <goal>descriptor</goal> + <goal>helpmojo</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + +</project>
diff --git a/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/ArtifactItem.java b/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/ArtifactItem.java new file mode 100644 index 0000000..630404d --- /dev/null +++ b/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/ArtifactItem.java
@@ -0,0 +1,51 @@ +/* + * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.maven; + +/** + * + * @author japod + */ +public class ArtifactItem { + + private String artifactId; + private String groupId; + private String version; + + public String getVersion() { + return version; + } + + @Override + public String toString() { + return String.format("{groupId=%s, artifactId=%s, version=%s}", groupId, artifactId, version); + } + + public void setVersion(String version) { + this.version = version; + } + + public String getArtifactId() { + return artifactId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } +}
diff --git a/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/LicenseCodeWriter.java b/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/LicenseCodeWriter.java new file mode 100644 index 0000000..8037dbc --- /dev/null +++ b/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/LicenseCodeWriter.java
@@ -0,0 +1,78 @@ +/* + * 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 Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.maven; + +import com.sun.codemodel.CodeWriter; +import com.sun.codemodel.JPackage; +import com.sun.codemodel.writer.FilterCodeWriter; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Writer; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Calendar; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Writes all the source files under the specified file folder and inserts a + * license file each java source file. + */ +final class LicenseCodeWriter extends FilterCodeWriter { + + private static final String COPYRIGHT_LINE_TEMPLATE = "^.*Copyright \\(c\\) (YYYY) (by )?([A-Za-z].*)$"; + private static final Pattern PATTERN = Pattern.compile(COPYRIGHT_LINE_TEMPLATE, Pattern.MULTILINE); + private static final String CURRENT_YEAR = String.valueOf(Calendar.getInstance().get(Calendar.YEAR)); + + private final Path license; + + /** + * @param core This CodeWriter will be used to actually create a storage + * for files. LicenseCodeWriter simply decorates this underlying + * CodeWriter by adding prolog comments. + * @param license license File + * @param encoding encoding + */ + public LicenseCodeWriter(CodeWriter core, File license, String encoding) { + super(core); + this.license = license.toPath(); + this.encoding = encoding; + } + + @Override + public Writer openSource(JPackage pkg, String fileName) throws IOException { + Writer w = super.openSource(pkg, fileName); + + PrintWriter out = new PrintWriter(w); + try (BufferedReader br = Files.newBufferedReader(license, Charset.forName(encoding))) { + String line; + while ((line = br.readLine()) != null) { + Matcher m = PATTERN.matcher(line); + if (m.matches()) { + out.write(line, 0, m.start(1)); + out.write(CURRENT_YEAR); + out.write(line, m.end(1), line.length() - m.end(1)); + } else { + out.write(line); + } + out.write(System.lineSeparator()); + } + } + + out.flush(); // we can't close the stream for that would close the underlying stream. + + return w; + } +}
diff --git a/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/MetainfServicesCompilerMojo.java b/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/MetainfServicesCompilerMojo.java new file mode 100644 index 0000000..13c0236 --- /dev/null +++ b/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/MetainfServicesCompilerMojo.java
@@ -0,0 +1,172 @@ +/* + * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.maven; + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.artifact.DefaultArtifact; +import org.eclipse.aether.impl.ArtifactResolver; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.resolution.ArtifactRequest; +import org.eclipse.aether.resolution.ArtifactResolutionException; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +/** + * Goal which compiles META-INF/services files from various dependencies + * + * @author japod + * + * Goal: metainf-services + * + * Phase: generate-sources + */ +@Mojo(name = "metainf-services", defaultPhase = LifecyclePhase.GENERATE_SOURCES, threadSafe = true) +public class MetainfServicesCompilerMojo extends AbstractMojo { + + /** + * Collection of ArtifactItems to take the META-INF/services from. (ArtifactItem contains groupId, + * artifactId, version) + * + * parameter + * required + * @since 1.0 + */ + private List<ArtifactItem> artifactItems; + /** + * Collection of files from META-INF/services to compile + * + * parameter + * required + * @since 1.0 + */ + private List<String> providers; + /** + * Destination for the generated service registry files + * + * parameter + * required + * @since 1.0 + */ + private File destDir; + + /** + * component role="org.apache.maven.artifact.resolver.ArtifactResolver" + * required + * readonly + */ + protected ArtifactResolver artifactResolver; + /** + * parameter expression="${project.remoteArtifactRepositories}" + * readonly + * required + */ + protected List<RemoteRepository> remoteRepositories; + + /** + * The current repository/network configuration of Maven. + * + * parameter default-value="${repositorySystemSession}" + * readonly + */ + private RepositorySystemSession repoSession; + + @Override + public void execute() throws MojoExecutionException { + getLog().info("About to compile META-INF/services files"); + getLog().info("Artifact Items = " + artifactItems); + getLog().info("SPIs = " + providers); + getLog().info("dest dir = " + destDir); + File msDir = new File(destDir, "META-INF/services"); + boolean created =msDir.mkdirs(); + if (!created) { + Logger.getLogger(MetainfServicesCompilerMojo.class.getName()).log(Level.FINE, "Cannot create directory: {0}", msDir); + } + for (String spi : providers) { + PrintWriter registryWriter = null; + try { + File spiRegistry = new File(msDir, spi); + if (spiRegistry.exists()) { + boolean deleted = spiRegistry.delete(); + if (!deleted) { + Logger.getLogger(MetainfServicesCompilerMojo.class.getName()).log(Level.FINE, "Cannot delete file: {0}", spiRegistry); + } + } + created = spiRegistry.createNewFile(); + if (!created) { + Logger.getLogger(MetainfServicesCompilerMojo.class.getName()).log(Level.FINE, "Cannot create file: {0}", spiRegistry); + } + registryWriter = new PrintWriter(spiRegistry); + ZipFile zipFile = null; + try { + BufferedReader reader = null; + InputStreamReader isReader = null; + for (ArtifactItem ai : artifactItems) { + Artifact artifact; + artifact = new DefaultArtifact(ai.getGroupId(), ai.getArtifactId(), null, ai.getVersion()); +// artifact = artifactFactory.createExtensionArtifact(ai.getGroupId(), ai.getArtifactId(), VersionRange.createFromVersion(ai.getVersion())); + + ArtifactRequest request = new ArtifactRequest(); + request.setArtifact( artifact ); + request.setRepositories(remoteRepositories); + artifactResolver.resolveArtifact(repoSession, request); + zipFile = new ZipFile(artifact.getFile()); + final ZipEntry servicesEntry = zipFile.getEntry("META-INF/services/" + spi); + if (servicesEntry != null) { + try { + final InputStream inputStream = zipFile.getInputStream(servicesEntry); + isReader = new InputStreamReader(inputStream); + reader = new BufferedReader(isReader); + while (reader.ready()) { + registryWriter.println(reader.readLine()); + } + } finally { + if (reader != null) { + reader.close(); + } + if (isReader != null) { + isReader.close(); + } + } + } + } + } catch (ArtifactResolutionException ex) { + Logger.getLogger(MetainfServicesCompilerMojo.class.getName()).log(Level.SEVERE, null, ex); + throw new MojoExecutionException("Can not resolve artifact!", ex); + } finally { + if (zipFile != null) { + zipFile.close(); + } + } + } catch (IOException ex) { + throw new MojoExecutionException("Can not create spi registry file!", ex); + } finally { + if (registryWriter != null) { + registryWriter.close(); + } + } + } + } +}
diff --git a/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/NameConverter.java b/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/NameConverter.java new file mode 100644 index 0000000..6ad2194 --- /dev/null +++ b/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/NameConverter.java
@@ -0,0 +1,283 @@ +/* + * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.maven; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.StringTokenizer; + +/** + * Converts arbitrary strings into Java identifiers. + * + * @author + * <a href="mailto:kohsuke.kawaguchi@sun.com">Kohsuke KAWAGUCHI</a> + */ +public interface NameConverter +{ + /** + * converts a string into an identifier suitable for classes. + * + * In general, this operation should generate "NamesLikeThis". + * @param token string to convert + * @return converted token + */ + String toClassName( String token ); + + /** + * converts a string into an identifier suitable for interfaces. + * + * In general, this operation should generate "NamesLikeThis". + * But for example, it can prepend every interface with 'I'. + * @param token string to convert + * @return converted token + */ + String toInterfaceName( String token ); + + /** + * converts a string into an identifier suitable for properties. + * + * In general, this operation should generate "NamesLikeThis", + * which will be used with known prefixes like "get" or "set". + * @param token string to convert + * @return converted token + */ + String toPropertyName( String token ); + + /** + * converts a string into an identifier suitable for constants. + * + * In the standard Java naming convention, this operation should + * generate "NAMES_LIKE_THIS". + * @param token string to convert + * @return converted token + */ + String toConstantName( String token ); + + /** + * Converts a string into an identifier suitable for variables. + * + * In general it should generate "namesLikeThis". + * @param token string to convert + * @return converted token + */ + String toVariableName( String token ); + + /** + * Converts a namespace URI into a package name. + * This method should expect strings like + * "http://foo.bar.zot/org", "urn:abc:def:ghi" "", or even "###" + * (basically anything) and expected to return a package name, + * liks "org.acme.foo". + * + * @param namespaceUri ns uri to convert + * @return converted uri + */ + String toPackageName( String namespaceUri ); + + /** + * The name converter implemented by Code Model. + * + * This is the standard name conversion for JAXB. + */ + NameConverter standard = new Standard(); + + /** + * Default implementation of {@link NameConverter}. + */ + class Standard extends NameUtil implements NameConverter { + @Override + public String toClassName(String s) { + return toMixedCaseName(toWordList(s), true); + } + @Override + public String toVariableName(String s) { + return toMixedCaseName(toWordList(s), false); + } + @Override + public String toInterfaceName( String token ) { + return toClassName(token); + } + @Override + public String toPropertyName(String s) { + String prop = toClassName(s); + // property name "Class" with collide with Object.getClass, + // so escape this. + if(prop.equals("Class")) + prop = "Clazz"; + return prop; + } + @Override + public String toConstantName( String token ) { + return super.toConstantName(token); + } + /** + * Computes a Java package name from a namespace URI, + * as specified in the spec. + * + * @param nsUri to convert + * @return + * null if it fails to derive a package name. + */ + @Override + public String toPackageName( String nsUri ) { + // remove scheme and :, if present + // spec only requires us to remove 'http' and 'urn'... + int idx = nsUri.indexOf(':'); + String scheme = ""; + if(idx>=0) { + scheme = nsUri.substring(0,idx); + if( scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("urn") ) + nsUri = nsUri.substring(idx+1); + } + + // tokenize string + ArrayList<String> tokens = tokenize( nsUri, "/: " ); + if( tokens.isEmpty() ) { + return null; + } + + // remove trailing file type, if necessary + if( tokens.size() > 1 ) { + // for uri's like "www.foo.com" and "foo.com", there is no trailing + // file, so there's no need to look at the last '.' and substring + // otherwise, we loose the "com" (which would be wrong) + String lastToken = tokens.get( tokens.size()-1 ); + idx = lastToken.lastIndexOf( '.' ); + if( idx > 0 ) { + lastToken = lastToken.substring( 0, idx ); + tokens.set( tokens.size()-1, lastToken ); + } + } + + // tokenize domain name and reverse. Also remove :port if it exists + String domain = tokens.get( 0 ); + idx = domain.indexOf(':'); + if( idx >= 0) domain = domain.substring(0, idx); + ArrayList<String> r = reverse( tokenize( domain, scheme.equals("urn")?".-":"." ) ); + if( r.get( r.size()-1 ).equalsIgnoreCase( "www" ) ) { + // remove leading www + r.remove( r.size()-1 ); + } + + // replace the domain name with tokenized items + tokens.addAll( 1, r ); + tokens.remove( 0 ); + + // iterate through the tokens and apply xml->java name algorithm + for( int i = 0; i < tokens.size(); i++ ) { + + // get the token and remove illegal chars + String token = tokens.get( i ); + token = removeIllegalIdentifierChars( token ); + + // this will check for reserved keywords + if( !NameUtil.isJavaIdentifier( token ) ) { + token = '_' + token; + } + + tokens.set( i, token.toLowerCase(Locale.ENGLISH) ); + } + + // concat all the pieces and return it + return combine( tokens, '.' ); + } + + + private static String removeIllegalIdentifierChars(String token) { + StringBuilder newToken = new StringBuilder(); + for( int i = 0; i < token.length(); i++ ) { + char c = token.charAt( i ); + + if( i ==0 && !Character.isJavaIdentifierStart( c ) ) { + // prefix an '_' if the first char is illegal + newToken.append('_').append(c); + } else if( !Character.isJavaIdentifierPart( c ) ) { + // replace the char with an '_' if it is illegal + newToken.append( '_' ); + } else { + // add the legal char + newToken.append( c ); + } + } + return newToken.toString(); + } + + + private static ArrayList<String> tokenize( String str, String sep ) { + StringTokenizer tokens = new StringTokenizer(str,sep); + ArrayList<String> r = new ArrayList<>(); + + while(tokens.hasMoreTokens()) + r.add( tokens.nextToken() ); + + return r; + } + + private static <T> ArrayList<T> reverse( List<T> a ) { + ArrayList<T> r = new ArrayList<>(); + + for( int i=a.size()-1; i>=0; i-- ) + r.add( a.get(i) ); + + return r; + } + + private static String combine( List<String> r, char sep ) { + StringBuilder buf = new StringBuilder(r.get(0)); + + for( int i=1; i<r.size(); i++ ) { + buf.append(sep); + buf.append(r.get(i)); + } + + return buf.toString(); + } + } + + /** + * JAX-PRC compatible name converter implementation. + * + * The only difference is that we treat '_' as a valid character + * and not as a word separator. + */ + NameConverter jaxrpcCompatible = new Standard() { + @Override + protected boolean isPunct(char c) { + return (c == '.' || c == '-' || c == ';' /*|| c == '_'*/ || c == '\u00b7' + || c == '\u0387' || c == '\u06dd' || c == '\u06de'); + } + @Override + protected boolean isLetter(char c) { + return super.isLetter(c) || c=='_'; + } + + @Override + protected int classify(char c0) { + if(c0=='_') return NameUtil.OTHER_LETTER; + return super.classify(c0); + } + }; + + /** + * Smarter converter used for RELAX NG support. + */ + NameConverter smart = new Standard() { + @Override + public String toConstantName( String token ) { + String name = super.toConstantName(token); + if( NameUtil.isJavaIdentifier(name) ) + return name; + else + return '_'+name; + } + }; +}
diff --git a/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/NameUtil.java b/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/NameUtil.java new file mode 100644 index 0000000..adcc12e --- /dev/null +++ b/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/NameUtil.java
@@ -0,0 +1,401 @@ +/* + * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.maven; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; + +/** + * Methods that convert strings into various formats. + * + * <p> + * What JAX-RPC name binding tells us is that even such basic method + * like "isLetter" can be different depending on the situation. + * + * For this reason, a whole lot of methods are made non-static, + * even though they look like they should be static. + */ +class NameUtil { + protected boolean isPunct(char c) { + return c == '-' || c == '.' || c == ':' || c == '_' || c == '\u00b7' || c == '\u0387' || c == '\u06dd' || c == '\u06de'; + } + + protected static boolean isDigit(char c) { + return c >= '0' && c <= '9' || Character.isDigit(c); + } + + protected static boolean isUpper(char c) { + return c >= 'A' && c <= 'Z' || Character.isUpperCase(c); + } + + protected static boolean isLower(char c) { + return c >= 'a' && c <= 'z' || Character.isLowerCase(c); + } + + protected boolean isLetter(char c) { + return c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || Character.isLetter(c); + } + + /** + * Capitalizes the first character of the specified string, + * and de-capitalize the rest of characters. + */ + public String capitalize(String s) { + if (!isLower(s.charAt(0))) + return s; + StringBuilder sb = new StringBuilder(s.length()); + sb.append(Character.toUpperCase(s.charAt(0))); + sb.append(s.substring(1).toLowerCase(Locale.ENGLISH)); + return sb.toString(); + } + + // Precondition: s[start] is not punctuation + private int nextBreak(String s, int start) { + int n = s.length(); + + char c1 = s.charAt(start); + int t1 = classify(c1); + + for (int i=start+1; i<n; i++) { + // shift (c1,t1) into (c0,t0) + // char c0 = c1; --- conceptually, but c0 won't be used + int t0 = t1; + + c1 = s.charAt(i); + t1 = classify(c1); + + switch(actionTable[t0*5+t1]) { + case ACTION_CHECK_PUNCT: + if(isPunct(c1)) return i; + break; + case ACTION_CHECK_C2: + if (i < n-1) { + char c2 = s.charAt(i+1); + if (isLower(c2)) + return i; + } + break; + case ACTION_BREAK: + return i; + } + } + return -1; + } + + // the 5-category classification that we use in this code + // to find work breaks + static protected final int UPPER_LETTER = 0; + static protected final int LOWER_LETTER = 1; + static protected final int OTHER_LETTER = 2; + static protected final int DIGIT = 3; + static protected final int OTHER = 4; + + /** + * Look up table for actions. + * type0*5+type1 would yield the action to be taken. + */ + private static final byte[] actionTable = new byte[5*5]; + + // action constants. see nextBreak for the meaning + static private final byte ACTION_CHECK_PUNCT = 0; + static private final byte ACTION_CHECK_C2 = 1; + static private final byte ACTION_BREAK = 2; + static private final byte ACTION_NOBREAK = 3; + + /** + * Decide the action to be taken given + * the classification of the preceding character 't0' and + * the classification of the next character 't1'. + */ + private static byte decideAction( int t0, int t1 ) { + if(t0==OTHER && t1==OTHER) return ACTION_CHECK_PUNCT; + if(!xor(t0==DIGIT,t1==DIGIT)) return ACTION_BREAK; + if(t0==LOWER_LETTER && t1!=LOWER_LETTER) return ACTION_BREAK; + if(!xor(t0<=OTHER_LETTER,t1<=OTHER_LETTER)) return ACTION_BREAK; + if(!xor(t0==OTHER_LETTER,t1==OTHER_LETTER)) return ACTION_BREAK; + + if(t0==UPPER_LETTER && t1==UPPER_LETTER) return ACTION_CHECK_C2; + + return ACTION_NOBREAK; + } + + private static boolean xor(boolean x,boolean y) { + return (x&&y) || (!x&&!y); + } + + static { + // initialize the action table + for( int t0=0; t0<5; t0++ ) + for( int t1=0; t1<5; t1++ ) + actionTable[t0*5+t1] = decideAction(t0,t1); + } + + /** + * Classify a character into 5 categories that determine the word break. + */ + protected int classify(char c0) { + switch(Character.getType(c0)) { + case Character.UPPERCASE_LETTER: return UPPER_LETTER; + case Character.LOWERCASE_LETTER: return LOWER_LETTER; + case Character.TITLECASE_LETTER: + case Character.MODIFIER_LETTER: + case Character.OTHER_LETTER: return OTHER_LETTER; + case Character.DECIMAL_DIGIT_NUMBER: return DIGIT; + default: return OTHER; + } + } + + + /** + * Tokenizes a string into words and capitalizes the first + * character of each word. + * + * <p> + * This method uses a change in character type as a splitter + * of two words. For example, "abc100ghi" will be splitted into + * {"Abc", "100","Ghi"}. + */ + public List<String> toWordList(String s) { + ArrayList<String> ss = new ArrayList<>(); + int n = s.length(); + for (int i = 0; i < n;) { + + // Skip punctuation + while (i < n) { + if (!isPunct(s.charAt(i))) + break; + i++; + } + if (i >= n) break; + + // Find next break and collect word + int b = nextBreak(s, i); + String w = (b == -1) ? s.substring(i) : s.substring(i, b); + ss.add(escape(capitalize(w))); + if (b == -1) break; + i = b; + } + +// we can't guarantee a valid Java identifier anyway, +// so there's not much point in rejecting things in this way. +// if (ss.size() == 0) +// throw new IllegalArgumentException("Zero-length identifier"); + return ss; + } + + protected String toMixedCaseName(List<String> ss, boolean startUpper) { + StringBuilder sb = new StringBuilder(); + if(!ss.isEmpty()) { + sb.append(startUpper ? ss.get(0) : ss.get(0).toLowerCase(Locale.ENGLISH)); + for (int i = 1; i < ss.size(); i++) + sb.append(ss.get(i)); + } + return sb.toString(); + } + + protected String toMixedCaseVariableName(String[] ss, + boolean startUpper, + boolean cdrUpper) { + if (cdrUpper) + for (int i = 1; i < ss.length; i++) + ss[i] = capitalize(ss[i]); + StringBuilder sb = new StringBuilder(); + if( ss.length>0 ) { + sb.append(startUpper ? ss[0] : ss[0].toLowerCase(Locale.ENGLISH)); + for (int i = 1; i < ss.length; i++) + sb.append(ss[i]); + } + return sb.toString(); + } + + + /** + * Formats a string into "THIS_KIND_OF_FORMAT_ABC_DEF". + * + * @return + * Always return a string but there's no guarantee that + * the generated code is a valid Java identifier. + */ + public String toConstantName(String s) { + return toConstantName(toWordList(s)); + } + + /** + * Formats a string into "THIS_KIND_OF_FORMAT_ABC_DEF". + * + * @return + * Always return a string but there's no guarantee that + * the generated code is a valid Java identifier. + */ + public String toConstantName(List<String> ss) { + StringBuilder sb = new StringBuilder(); + if( !ss.isEmpty() ) { + sb.append(ss.get(0).toUpperCase(Locale.ENGLISH)); + for (int i = 1; i < ss.size(); i++) { + sb.append('_'); + sb.append(ss.get(i).toUpperCase(Locale.ENGLISH)); + } + } + return sb.toString(); + } + + + + /** + * Escapes characters is the given string so that they can be + * printed by only using US-ASCII characters. + * + * The escaped characters will be appended to the given + * StringBuffer. + * + * @param sb + * StringBuffer that receives escaped string. + * @param s + * String to be escaped. <code>s.substring(start)</code> + * will be escaped and copied to the string buffer. + */ + public static void escape(StringBuilder sb, String s, int start) { + int n = s.length(); + for (int i = start; i < n; i++) { + char c = s.charAt(i); + if (Character.isJavaIdentifierPart(c)) + sb.append(c); + else { + sb.append('_'); + if (c <= '\u000f') sb.append("000"); + else if (c <= '\u00ff') sb.append("00"); + else if (c <= '\u0fff') sb.append('0'); + sb.append(Integer.toString(c, 16)); + } + } + } + + /** + * Escapes characters that are unusable as Java identifiers + * by replacing unsafe characters with safe characters. + */ + private static String escape(String s) { + int n = s.length(); + for (int i = 0; i < n; i++) + if (!Character.isJavaIdentifierPart(s.charAt(i))) { + StringBuilder sb = new StringBuilder(s.substring(0, i)); + escape(sb, s, i); + return sb.toString(); + } + return s; + } + + + /** + * Checks if a given string is usable as a Java identifier. + */ + public static boolean isJavaIdentifier(String s) { + if(s.length()==0) return false; + if( reservedKeywords.contains(s) ) return false; + + if(!Character.isJavaIdentifierStart(s.charAt(0))) return false; + + for (int i = 1; i < s.length(); i++) + if (!Character.isJavaIdentifierPart(s.charAt(i))) + return false; + + return true; + } + + /** + * Checks if the given string is a valid Java package name. + */ + public static boolean isJavaPackageName(String s) { + while(s.length()!=0) { + int idx = s.indexOf('.'); + if(idx==-1) idx=s.length(); + if( !isJavaIdentifier(s.substring(0,idx)) ) + return false; + + s = s.substring(idx); + if(s.length()!=0) s = s.substring(1); // remove '.' + } + return true; + } + + + /** All reserved keywords of Java. */ + private static HashSet<String> reservedKeywords = new HashSet<>(); + + static { + // see http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html + String[] words = new String[]{ + "abstract", + "boolean", + "break", + "byte", + "case", + "catch", + "char", + "class", + "const", + "continue", + "default", + "do", + "double", + "else", + "extends", + "final", + "finally", + "float", + "for", + "goto", + "if", + "implements", + "import", + "instanceof", + "int", + "interface", + "long", + "native", + "new", + "package", + "private", + "protected", + "public", + "return", + "short", + "static", + "strictfp", + "super", + "switch", + "synchronized", + "this", + "throw", + "throws", + "transient", + "try", + "void", + "volatile", + "while", + + // technically these are not reserved words but they cannot be used as identifiers. + "true", + "false", + "null", + + // and I believe assert is also a new keyword + "assert", + + // and 5.0 keywords + "enum" + }; + reservedKeywords.addAll(Arrays.asList(words)); + } +}
diff --git a/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/QuickGenMojo.java b/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/QuickGenMojo.java new file mode 100644 index 0000000..634ab59 --- /dev/null +++ b/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/QuickGenMojo.java
@@ -0,0 +1,444 @@ +/* + * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.maven; + +import com.sun.codemodel.CodeWriter; +import com.sun.codemodel.JArray; +import com.sun.codemodel.JClass; +import com.sun.codemodel.JClassAlreadyExistsException; +import com.sun.codemodel.JCodeModel; +import com.sun.codemodel.JDefinedClass; +import com.sun.codemodel.JExpr; +import com.sun.codemodel.JFieldVar; +import com.sun.codemodel.JMethod; +import com.sun.codemodel.JMod; +import com.sun.codemodel.JPackage; +import com.sun.codemodel.writer.FileCodeWriter; +import org.apache.maven.artifact.DependencyResolutionRequiredException; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.project.MavenProject; + +import java.io.File; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.regex.Pattern; + +/** + * Generates implementations of {@code org.glassfish.jaxb.runtime.v2.model.annotation.Quick} classes + * for XML Binding annotations. Used exclusively by jaxb-ri project. + * + */ +@Mojo(name = "quick-gen", + defaultPhase = LifecyclePhase.GENERATE_SOURCES, + requiresDependencyResolution = ResolutionScope.COMPILE, + threadSafe = true) +public class QuickGenMojo extends AbstractMojo { + + private static final String LOCATABLE = "org.glassfish.jaxb.core.v2.model.annotation.Locatable"; + private static final String QUICK = "org.glassfish.jaxb.runtime.v2.model.annotation.Quick"; + + @Parameter(defaultValue = "false") + private boolean skip; + + /** + * Location of the destination directory. + */ + @Parameter(defaultValue = "${project.build.directory}/generated-sources/quick-sources") + private File destDir; + + /** + * File encoding for generated sources. + * @since 2.12 + */ + @Parameter(defaultValue = "${project.build.sourceEncoding}") + private String encoding; + + /** + * Annotations to generate implementations of {@code org.glassfish.jaxb.runtime.v2.model.annotation.Quick} for. + */ + @Parameter(required = true) + private List<String> classes; + + /** + * License file to use in generated sources. + */ + @Parameter + private File license; + + /** + * Package for generated implementations. + */ + @Parameter(required = true) + private String packageName; + + /** + * Attach generated sources to project sources. + */ + @Parameter(defaultValue = "true") + private boolean attach; + + @Parameter(defaultValue = "${project}", required = true, readonly = true) + private MavenProject project; + + private final List<Pattern> patterns = new ArrayList<>(); + + /** + * Used during the build to load annotation classes. + */ + private ClassLoader userLoader; + + /** + * Generated interfaces go into this codeModel. + */ + private JCodeModel codeModel = new JCodeModel(); + + /** + * Avoid compile-time dependency on {@code org.glassfish.jaxb.core.v2.model.annotation.Locatable} + */ + private final JClass locatable = codeModel.ref(LOCATABLE); + + /** + * Avoid compile-time dependency on {@code org.glassfish.jaxb.core.v2.model.annotation.Quick} + */ + private final JClass quick = codeModel.ref(QUICK); + + /** + * The writers will be generated into this package. + */ + private JPackage pkg = codeModel.rootPackage(); + + /** + * Map from annotation classes to their writers. + */ + private final Map<Class<? extends Annotation>, JDefinedClass> queue = new TreeMap<>(Comparator.comparing(Class::getName)); + + public QuickGenMojo() { + } + + @Override + public void execute() throws MojoExecutionException { + if (skip) { + getLog().info("Skipping execution."); + return; + } + + for (String s : classes) { + patterns.add(Pattern.compile(convertToRegex(s))); + } + pkg = codeModel._package(packageName); + try { + List<String> classpath = project.getCompileClasspathElements(); + Set<File> files = new HashSet<>(); + List<URL> cp = new ArrayList<>(); + for (String s : classpath) { + File f = new File(s); + files.add(f); + cp.add(f.toURI().toURL()); + } + userLoader = new URLClassLoader(cp.toArray(new URL[] {})); + + // find classes to be bound + for (File f : files) { + if (f.exists()) { + if (f.isDirectory()) { + processDir(f, ""); + } else { + processJar(f); + } + } + } + + // [RESULT] + // class Init { + // static Quick[] getAll() { + // ... return all Quick classes ... + // } + // } + try { + JArray all = JExpr.newArray(quick); + JDefinedClass init = pkg._class(0, "Init"); + init.method(JMod.STATIC, quick.array(), "getAll").body()._return(all); + + for (Map.Entry<Class<? extends Annotation>, JDefinedClass> e : queue.entrySet()) { + process(e.getKey(), e.getValue()); + all.add(JExpr._new(e.getValue()).arg(JExpr._null()).arg(JExpr._null())); + } + } catch (JClassAlreadyExistsException e) { + throw new MojoExecutionException(e); + } + + if (!destDir.mkdirs()) { + getLog().warn(destDir + " failed to be created."); + } + CodeWriter core = new FileCodeWriter(destDir, encoding); + if (license != null) { + core = new LicenseCodeWriter(core, license, encoding); + } + + codeModel.build(core); + + if (attach) { + project.addCompileSourceRoot(destDir.getAbsolutePath()); + } + } catch (IOException | DependencyResolutionRequiredException e) { + throw new MojoExecutionException(e); + } finally { + userLoader = null; + } + } + + /** + * Generate a {@code org.glassfish.jaxb.runtime.v2.model.annotation.Quick} implementation + * of the specified annotation in the specified package. + * + * @param ann + * annotation type to + */ + private void process(Class<? extends Annotation> ann, JDefinedClass c) { + // XXX - adding javax.annotation.processing.Generated implies dep on java.compiler, + //adding jakarta.annotation.Generated implies dep on jakarta.annotation + // => we don't want any of them + // [RESULT] + // public final class XmlAttributeQuick extends Quick implements XmlAttribute { + c.javadoc().add("<p><b>Auto-generated, do not edit.</b></p>"); + c._extends(quick); + c._implements(ann); + + // [RESULT] + // private final XmlAttribute core; + JFieldVar $core = c.field(JMod.PRIVATE | JMod.FINAL, ann, "core"); + + // [RESULT] + // public XmlAttributeQuick(Locatable upstream, XmlAttribute core) { + // super(upstream); + // this.core = core; + // } + { + JMethod m = c.constructor(JMod.PUBLIC); + m.body().invoke("super").arg(m.param(locatable, "upstream")); + m.body().assign(JExpr._this().ref($core), m.param(ann, "core")); + } + + // [RESULT] + // @Override + // protected Annotation getAnnotation() { + // return core; + // } + { + JMethod m = c.method(JMod.PROTECTED, Annotation.class, "getAnnotation"); + m.annotate(Override.class); + m.body()._return($core); + } + + // [RESULT] + // @Override + // protected Quick newInstance(Locatable upstream,Annotation core) { + // return new XmlAttributeQuick(upstream,(XmlAttribute)core); + // } + { + JMethod m = c.method(JMod.PROTECTED, quick, "newInstance"); + m.annotate(Override.class); + m.body()._return(JExpr._new(c).arg(m.param(locatable, "upstream")).arg(JExpr.cast(codeModel.ref(ann), m.param(Annotation.class, "core")))); + } + + // [RESULT] + // @Override + // public Class<XmlAttribute> annotationType() { + // return XmlAttribute.class; + // } + { + JMethod m = c.method(JMod.PUBLIC, + codeModel.ref(Class.class).narrow(ann), "annotationType"); + m.annotate(Override.class); + m.body()._return(codeModel.ref(ann).dotclass()); + } + + + // then for each annotation parameter just generate a delegation method + Method[] methods = ann.getDeclaredMethods(); + Arrays.sort(methods, Comparator.comparing(Method::getName)); + for (Method method : methods) { + // [RESULT] + // @Override + // public String name() { + // return core.name(); + //} + JMethod m = c.method(JMod.PUBLIC, method.getReturnType(), method.getName()); + m.annotate(Override.class); + m.body()._return($core.invoke(method.getName())); + } + } + + /** + * Gets the short name from a fully-qualified name. + */ + private static String getShortName(String className) { + int idx = className.lastIndexOf('.'); + return className.substring(idx + 1); + } + + private String convertToRegex(String pattern) { + StringBuilder regex = new StringBuilder(); + char nc = ' '; + if (pattern.length() > 0) { + for (int i = 0; i < pattern.length(); i++) { + char c = pattern.charAt(i); + nc = ' '; + if ((i + 1) != pattern.length()) { + nc = pattern.charAt(i + 1); + } + //escape single '.' + if ((c == '.') && (nc != '.')) { + regex.append('\\'); + regex.append('.'); + //do not allow patterns like a..b + } else if ((c == '.') && (nc == '.')) { + continue; + // "**" gets replaced by ".*" + } else if ((c == '*') && (nc == '*')) { + regex.append(".*"); + break; + //'*' replaced by anything but '.' i.e [^\\.]+ + } else if (c == '*') { + regex.append("[^\\.]+"); + continue; + //'?' replaced by anything but '.' i.e [^\\.] + } else if (c == '?') { + regex.append("[^\\.]"); + //else leave the chars as they occur in the pattern + } else { + regex.append(c); + } + } + } + return regex.toString(); + } + + + /** + * Visits a jar file and looks for classes that match the specified pattern. + */ + private void processJar(File jarfile) throws MojoExecutionException { + try (JarFile jar = new JarFile(jarfile)) { + for (Enumeration<JarEntry> en = jar.entries(); en.hasMoreElements(); ) { + JarEntry e = en.nextElement(); + process(e.getName(), e.getTime()); + } + } catch (IOException e) { + throw new MojoExecutionException("Unable to process " + jarfile, e); + } + } + + /** + * Visits a directory and looks for classes that match the specified pattern. + * + * @param prefix + * the package name prefix like "" or "foo/bar/" + */ + private void processDir(File dir, String prefix) throws MojoExecutionException { + // look for class files + String[] classes = dir.list((d, name) -> name.endsWith(".class")); + if (classes != null) { + for (String c : classes) { + process(prefix + c, new File(dir, c).lastModified()); + } + } + + // look for subdirectories + File[] subdirs = dir.listFiles(File::isDirectory); + if (subdirs != null) { + for (File f : subdirs) { + processDir(f, prefix + f.getName() + '/'); + } + } + } + + /** + * Process a file. + * + * @param name such as "jakarta/xml/bind/Abc.class" + */ + private void process(String name, long timestamp) throws MojoExecutionException { + if (!name.endsWith(".class")) { + return; // not a class + } + name = name.substring(0, name.length() - 6); + name = name.replace('/', '.'); // make it a class naem + // find a match + for (Pattern p : patterns) { + if (p.matcher(name).matches()) { + queue(name, timestamp); + return; + } + } + } + + /** + * Queues a file for generation. + */ + @SuppressWarnings({"unchecked"}) + private void queue(String className, long timestamp) throws MojoExecutionException { + getLog().debug("Processing " + className); + Class<? extends Annotation> ann; + try { + ann = (Class<? extends Annotation>) userLoader.loadClass(className); + } catch (ClassNotFoundException e) { + throw new MojoExecutionException(e); + } + + if (!Annotation.class.isAssignableFrom(ann)) { + getLog().debug("Skipping " + className + ". Not an annotation"); + return; + } + + JDefinedClass w; + try { + w = pkg._class(JMod.FINAL, getShortName(ann.getName()) + "Quick"); + } catch (JClassAlreadyExistsException e) { + throw new MojoExecutionException("Class name collision on " + className, e); + } + + // up to date check + String name = pkg.name(); + if (name.length() == 0) { + name = getShortName(className); + } else { + name += '.' + getShortName(className); + } + + File dst = new File(destDir, name.replace('.', File.separatorChar) + "Quick.java"); + if (dst.exists() && dst.lastModified() > timestamp) { + getLog().debug("Skipping " + className + ". Up to date."); + w.hide(); + } + + queue.put(ann, w); + } +}
diff --git a/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/RSFileSet.java b/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/RSFileSet.java new file mode 100644 index 0000000..02dd7b2 --- /dev/null +++ b/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/RSFileSet.java
@@ -0,0 +1,107 @@ +/* + * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.maven; + +import java.io.IOException; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.FileVisitResult; +import static java.nio.file.FileVisitResult.CONTINUE; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.Path; +import java.nio.file.PathMatcher; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author lukas + */ +public class RSFileSet { + + private Path root; + private List<String> inc; + private final PathMatcher exMatcher; + + public RSFileSet() { + inc = new ArrayList<>(); + exMatcher = FileSystems.getDefault().getPathMatcher("glob:*_*.properties"); + } + + public void setDirectory(String dir) { + root = Paths.get(dir); + } + + public String getDirectory() { + return root.toString(); + } + + public boolean exists() { + return Files.isDirectory(root, LinkOption.NOFOLLOW_LINKS); + } + public void addInclude(String include) { + inc.add(include); + } + + public List<String> getIncludes() { + return inc; + } + + public void setIncludes(List<String> inc) { + this.inc = inc; + } + + public Path resolve(Path path) { + return root.resolve(path); + } + + public List<Path> getIncludedFiles() { + final List<Path> result = new ArrayList<>(); + if (inc.isEmpty()) { + inc.add("**"); + } + FileSystem fs = FileSystems.getDefault(); + for (final String i : inc) { + int idx = i.indexOf('/'); + final PathMatcher matcher; + final PathMatcher dirMatcher; + if (idx < 0) { + matcher = fs.getPathMatcher("glob:" + i); + dirMatcher = null; + } else { + matcher = fs.getPathMatcher("glob:" + i.substring(idx + 1)); + dirMatcher = fs.getPathMatcher("glob:" + i.substring(0, idx)); + } + try { + Files.walkFileTree(root, new SimpleFileVisitor<Path>() { + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + if (dirMatcher == null || (dirMatcher.matches(file.getParent()))) { + Path name = file.getFileName(); + if (name != null && matcher.matches(name) && !exMatcher.matches(name)) { + result.add(root.relativize(file)); + } + } + return CONTINUE; + } + }); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + return result; + } +}
diff --git a/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/ResourceGenMojo.java b/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/ResourceGenMojo.java new file mode 100644 index 0000000..f45e60c --- /dev/null +++ b/istack-commons/maven-plugin/src/main/java/com/sun/istack/maven/ResourceGenMojo.java
@@ -0,0 +1,366 @@ +/* + * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.maven; + +import com.sun.codemodel.CodeWriter; +import com.sun.codemodel.JAnnotationUse; +import com.sun.codemodel.JClass; +import com.sun.codemodel.JClassAlreadyExistsException; +import com.sun.codemodel.JCodeModel; +import com.sun.codemodel.JDefinedClass; +import com.sun.codemodel.JExpr; +import com.sun.codemodel.JFieldVar; +import com.sun.codemodel.JInvocation; +import com.sun.codemodel.JMethod; +import com.sun.codemodel.JMod; +import com.sun.codemodel.JPackage; +import com.sun.codemodel.JVar; +import com.sun.codemodel.writer.FileCodeWriter; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.file.Path; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Properties; + + +/** + * Goal which generates source files from resource bundles. + * You can then refer to resources as methods rather than hard-coding string constants. + * + * @author Lukas Jungmann + * @author Jakub Podlesak + * @author Kohsuke Kawaguchi + * + * Goal: rs-gen + * RequiresProject: false + * Phase: process-sources + */ +@Mojo(name = "rs-gen", requiresProject = false, threadSafe = true, + defaultPhase = LifecyclePhase.PROCESS_SOURCES) +public class ResourceGenMojo extends AbstractMojo { + + /** + * Location of the destination directory. + */ + @Parameter(required = true, property = "destDir", defaultValue = "${project.build.directory}/generated-sources/resources") + private File destDir; + + /** + * File set of the properties files to be processed. + */ + @Parameter + private RSFileSet resources; + + /** + * Directory with properties files to be processed from the command line. + * @since 2.12 + */ + @Parameter(property = "resources") + private String cliResource; + + /** + * Package to be used for the localization utility classes. + */ + @Parameter(property = "localizationUtilitiesPkgName", defaultValue = "com.sun.istack.localization") + private String localizationUtilitiesPkgName; + + /** + * License file to use in generated sources. + * @since 2.12 + */ + @Parameter(property = "license") + private File license; + + /** + * Mark generated sources with {@code @jakarta.annotation.Generated}. + * @since 3.0.5 + */ + @Parameter(property = "atGenerated", defaultValue = "false") + private boolean atGenerated; + + /** + * Generate javadoc comments. + * @since 4.0.1 + */ + @Parameter(property = "rs.javadoc", defaultValue = "true") + private boolean javadoc; + + /** + * File encoding for generated sources. + * @since 2.12 + */ + @Parameter(property = "encoding", defaultValue = "${project.build.sourceEncoding}") + private String encoding; + + /** + * @since 2.12 + */ + @Parameter(property = "project", readonly = true) + private MavenProject project; + + @Override + public void execute() throws MojoExecutionException { + + if(resources == null && cliResource == null) { + throw new MojoExecutionException("No resource file is specified"); + } + if(destDir == null) { + throw new MojoExecutionException("No destdir attribute is specified"); + } + + if(localizationUtilitiesPkgName == null) { + localizationUtilitiesPkgName = "com.sun.istack.localization"; + } + + if (!destDir.exists() && !destDir.mkdirs()) { + throw new MojoExecutionException("Cannot create destdir"); + } + + if (!destDir.canWrite()) { + throw new MojoExecutionException("Cannot write to destdir"); + } + + if (encoding == null || encoding.trim().isEmpty()) { + encoding = System.getProperty("file.encoding"); + getLog().warn("File encoding has not been set, using platform encoding " + + encoding + ", i.e. build is platform dependent!"); + } + + if (resources == null && cliResource != null) { + RSFileSet fs = new RSFileSet(); + fs.setDirectory(System.getProperty("user.dir")); + List<String> l = new ArrayList<>(); + l.add(cliResource); + fs.setIncludes(l); + resources = fs; + } + + if (resources == null || !resources.exists()) { + getLog().info("No resources specified."); + return; + } + + List<Path> includedFiles = resources.getIncludedFiles(); + + getLog().info("Resources:"); + for(Path s : includedFiles) { + getLog().info(s.toString()); + } + + JCodeModel cm = new JCodeModel(); + + for (Path p : includedFiles) { + File res = resources.resolve(p).toFile(); + String value = p.toString(); + + String className = getClassName(res); + + String bundleName = value.substring(0, value.lastIndexOf('.')).replace('/', '.').replace('\\', '.');// cut off '.properties' + String dirName = bundleName.substring(0, bundleName.lastIndexOf('.')); + + File destFile = destDir.toPath().resolve(dirName.replace('.', '/')).resolve(className+".java").toFile(); + if(destFile.exists() && (destFile.lastModified() >= res.lastModified())) { + getLog().info("Skipping " + res); + continue; + } + + getLog().info("Processing "+res); + + if (!destFile.getParentFile().mkdirs()) { + if (getLog().isDebugEnabled()) { + getLog().debug("Reusing existing " + destFile.getParentFile().getAbsolutePath() + " directory."); + } + } + JPackage pkg = cm._package(dirName); + + Properties props = new Properties(); + FileInputStream in = null; + try { + in = new FileInputStream(res); + props.load(in); + } catch (IOException e) { + throw new MojoExecutionException(e.getMessage(), e); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException ioe) { + throw new MojoExecutionException(ioe.getMessage(), ioe); + } + } + } + + JDefinedClass clazz; + try { + clazz = pkg._class(JMod.PUBLIC | JMod.FINAL, className); + } catch (JClassAlreadyExistsException e) { + throw new MojoExecutionException("Name conflict "+className); + } + + if (javadoc) { + clazz.javadoc().add( + "Defines string formatting method for each constant in the resource file" + ); + } + + if (atGenerated) { + // no direct dependency on Jakarta annotations API + JClass annotation = cm.ref("jakarta.annotation.Generated"); + JAnnotationUse generated = clazz.annotate(annotation); + generated.param("value", ResourceGenMojo.class.getName()); + } + + /* + [RESULT] + + String BUNDLE_NAME = "com.sun.xml.ws.resources.client"; + LocalizableMessageFactory MESSAGE_FACTORY = + new LocalizableMessageFactory(BUNDLE_NAME, new BundleSupplier()); + Localizer LOCALIZER = new Localizer(); + + class BundleSupplier implements ResourceBundleSupplier { + + public ResourceBundle getResourceBundle(Locale locale) { + return ResourceBundle.getBundle(BUNDLE_NAME, locale); + } + } + */ + + JClass lmf_class, l_class, lable_class; + JClass supplier_class, rbundle_class, locale_class; + try { + lmf_class = cm.parseType(addLocalizationUtilityPackageName("LocalizableMessageFactory")).boxify(); + l_class = cm.parseType(addLocalizationUtilityPackageName("Localizer")).boxify(); + lable_class = cm.parseType(addLocalizationUtilityPackageName("Localizable")).boxify(); + supplier_class = cm.parseType(addLocalizationUtilityPackageName("LocalizableMessageFactory.ResourceBundleSupplier")).boxify(); + rbundle_class = cm.parseType("java.util.ResourceBundle").boxify(); + locale_class = cm.parseType("java.util.Locale").boxify(); + } catch (Throwable e) { + throw new MojoExecutionException(e.getMessage(), e); // impossible -- but why parseType throwing Exception!? + } + + JFieldVar $bundle = clazz.field(JMod.PRIVATE | JMod.STATIC | JMod.FINAL, + String.class, "BUNDLE_NAME", JExpr.lit(bundleName)); + + JDefinedClass supplier; + try { + supplier = clazz._class(JMod.PRIVATE | JMod.STATIC, "BundleSupplier"); + supplier._implements(supplier_class); + JMethod rb = supplier.method(JMod.PUBLIC, rbundle_class, "getResourceBundle"); + JVar ploc = rb.param(locale_class, "locale"); + rb.body()._return(rbundle_class.staticInvoke("getBundle").arg($bundle).arg(ploc)); + } catch (JClassAlreadyExistsException e) { + throw new MojoExecutionException(e.getMessage(), e); + } + + JFieldVar $msgFactory = clazz.field(JMod.PRIVATE | JMod.STATIC | JMod.FINAL, + lmf_class, "MESSAGE_FACTORY", JExpr._new(lmf_class).arg($bundle).arg(JExpr._new(supplier))); + JFieldVar $localizer = clazz.field(JMod.PRIVATE | JMod.STATIC | JMod.FINAL, + l_class, "LOCALIZER", JExpr._new(l_class)); + + // [RESULT] + // private CLASS() {} + clazz.constructor(JMod.PRIVATE); + + for (Map.Entry<Object,Object> e : props.entrySet()) { + // [RESULT] + // Localizable METHOD_localizable(Object arg1, Object arg2, ...) { + // return messageFactory.getMessage("servlet.html.notFound", message)); + // } + // String METHOD(Object arg1, Object arg2, ...) { + // return localizer.localize(METHOD_localizable(arg1,arg2,...)); + // } + String methodBaseName = NameConverter.smart.toConstantName(e.getKey().toString()); + + JMethod method = clazz.method(JMod.PUBLIC | JMod.STATIC, lable_class, "localizable"+methodBaseName); + + int countArgs = countArgs(e.getValue().toString()); + + JInvocation format = $msgFactory.invoke("getMessage").arg( + JExpr.lit(e.getKey().toString())); + + for( int i=0; i<countArgs; i++ ) { + format.arg( method.param(Object.class,"arg"+i)); + } + method.body()._return(format); + + JMethod method2 = clazz.method(JMod.PUBLIC|JMod.STATIC, String.class, methodBaseName); + if (javadoc) { + method2.javadoc().add(escape(e.getValue().toString())); + } + + JInvocation localize = JExpr.invoke(method); + for( int i=0; i<countArgs; i++ ) { + localize.arg( method2.param(Object.class,"arg"+i)); + } + + method2.body()._return($localizer.invoke("localize").arg(localize)); + } + } + + try { + CodeWriter core = new FileCodeWriter(destDir, encoding); + if (license != null) { + core = new LicenseCodeWriter(core, license, encoding); + } + cm.build(core); + } catch (IOException e) { + throw new MojoExecutionException("Failed to generate code",e); + } + + if (project != null) { + project.addCompileSourceRoot(destDir.getAbsolutePath()); + } + } + + private String addLocalizationUtilityPackageName(final String className) { + return String.format("%s.%s", localizationUtilitiesPkgName, className); + } + + private int countArgs(String value) { + List<String> x = new ArrayList<>(); + + while(true) { + String r1 = MessageFormat.format(value, x.toArray()); + x.add("xxxx"); + String r2 = MessageFormat.format(value, x.toArray()); + + if(r1.equals(r2)) + return x.size()-1; + } + } + + /** + * Computes the class name from the resource bundle name. + */ + private String getClassName(File res) { + String name = res.getName(); + int suffixIndex = name.lastIndexOf('.'); + name = name.substring(0,suffixIndex); + return NameConverter.smart.toClassName(name)+"Messages"; + } + + private String escape(String s) { + return s.replaceAll("<", "{@code <}").replaceAll(">", "{@code >}"); + } + +}
diff --git a/istack-commons/maven-plugin/src/test/it/sample/pom.xml b/istack-commons/maven-plugin/src/test/it/sample/pom.xml new file mode 100644 index 0000000..ab9aab9 --- /dev/null +++ b/istack-commons/maven-plugin/src/test/it/sample/pom.xml
@@ -0,0 +1,109 @@ +<!-- + + 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 Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>com.sun.xml.ws</groupId> + <artifactId>sample</artifactId> + <version>1.0-SNAPSHOT</version> + <packaging>jar</packaging> + + <name>sample</name> + <url>http://maven.apache.org</url> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <resgen.plugin.version>4.0.0-SNAPSHOT</resgen.plugin.version> + <maven.compiler.release>${tp.compiler.release}</maven.compiler.release> + <maven.compiler.testRelease>${maven.compiler.release}</maven.compiler.testRelease> + </properties> + + <dependencies> + <dependency> + <groupId>com.sun.istack</groupId> + <artifactId>istack-commons-runtime</artifactId> + <version>${resgen.plugin.version}</version> + </dependency> + <dependency> + <groupId>jakarta.xml.bind</groupId> + <artifactId>jakarta.xml.bind-api</artifactId> + <version>4.0.0</version> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.13.1</version> + <scope>test</scope> + </dependency> + </dependencies> + <build> + <pluginManagement> + <plugins> + <plugin> + <groupId>com.sun.istack</groupId> + <artifactId>istack-commons-maven-plugin</artifactId> + <version>${resgen.plugin.version}</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.11.0</version> + </plugin> + </plugins> + </pluginManagement> + <plugins> + <plugin> + <groupId>com.sun.istack</groupId> + <artifactId>istack-commons-maven-plugin</artifactId> + <executions> + <execution> + <id>resource-gen</id> + <goals> + <goal>rs-gen</goal> + </goals> + <configuration> + <resources> + <directory>${project.basedir}/src/main/resources</directory> + </resources> + </configuration> + </execution> + <execution> + <id>quick-gen</id> + <goals> + <goal>quick-gen</goal> + </goals> + <configuration> + <packageName>org.app.annotation</packageName> + <classes> + <class>jakarta.xml.bind.annotation.XmlAttribute</class> + <class>jakarta.xml.bind.annotation.XmlElement</class> + <class>jakarta.xml.bind.annotation.XmlElementDecl</class> + <class>jakarta.xml.bind.annotation.XmlElementRef</class> + <class>jakarta.xml.bind.annotation.XmlElementRefs</class> + <class>jakarta.xml.bind.annotation.XmlEnum</class> + <class>jakarta.xml.bind.annotation.XmlRootElement</class> + <class>jakarta.xml.bind.annotation.XmlSchema</class> + <class>jakarta.xml.bind.annotation.XmlSchemaType</class> + <class>jakarta.xml.bind.annotation.XmlTransient</class> + <class>jakarta.xml.bind.annotation.XmlType</class> + <class>jakarta.xml.bind.annotation.XmlValue</class> + </classes> + <attach>false</attach> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project>
diff --git a/istack-commons/maven-plugin/src/test/it/sample/src/main/java/com/sun/xml/ws/App.java b/istack-commons/maven-plugin/src/test/it/sample/src/main/java/com/sun/xml/ws/App.java new file mode 100644 index 0000000..7b6492b --- /dev/null +++ b/istack-commons/maven-plugin/src/test/it/sample/src/main/java/com/sun/xml/ws/App.java
@@ -0,0 +1,23 @@ +/* + * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.xml.ws; + +/** + * Hello world! + * + */ +public class App +{ + public static void main( String[] args ) + { + System.out.println( "Hello World!" ); + } +}
diff --git a/istack-commons/maven-plugin/src/test/it/sample/src/main/resources/org/aaa/aprop.properties b/istack-commons/maven-plugin/src/test/it/sample/src/main/resources/org/aaa/aprop.properties new file mode 100644 index 0000000..c82c9e6 --- /dev/null +++ b/istack-commons/maven-plugin/src/test/it/sample/src/main/resources/org/aaa/aprop.properties
@@ -0,0 +1,12 @@ +# +# Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Distribution License v. 1.0, which is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +aaa=fdsa +bb.d=rewq
diff --git a/istack-commons/maven-plugin/src/test/it/sample/src/main/resources/org/aaa/aprop_de.properties b/istack-commons/maven-plugin/src/test/it/sample/src/main/resources/org/aaa/aprop_de.properties new file mode 100644 index 0000000..b8d21f7 --- /dev/null +++ b/istack-commons/maven-plugin/src/test/it/sample/src/main/resources/org/aaa/aprop_de.properties
@@ -0,0 +1,12 @@ +# +# Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Distribution License v. 1.0, which is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +aaa=fdsa-de +bb.d=rewq-de
diff --git a/istack-commons/maven-plugin/src/test/java/com/sun/istack/maven/QuickGenMojoITCase.java b/istack-commons/maven-plugin/src/test/java/com/sun/istack/maven/QuickGenMojoITCase.java new file mode 100644 index 0000000..706e737 --- /dev/null +++ b/istack-commons/maven-plugin/src/test/java/com/sun/istack/maven/QuickGenMojoITCase.java
@@ -0,0 +1,33 @@ +/* + * 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 Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.maven; + +import org.junit.Assert; +import org.junit.Test; + +import java.io.File; + +public class QuickGenMojoITCase { + + private static final File PROJECTS_DIR = new File(System.getProperty("it.projects.dir")); + + public QuickGenMojoITCase() { + } + + @Test + public void testGeneration() { + File project = new File(PROJECTS_DIR, "sample"); + File f = new File(project, "target/generated-sources/quick-sources/org/app/annotation/XmlEnumQuick.java"); + Assert.assertTrue("Not found " + f.getAbsolutePath(), f.exists()); + f = new File(project, "target/classes/org/app/annotation/Init.class"); + Assert.assertFalse("Found " + f.getAbsolutePath(), f.exists()); + } +}
diff --git a/istack-commons/maven-plugin/src/test/java/com/sun/istack/maven/ResourceGenMojoITCase.java b/istack-commons/maven-plugin/src/test/java/com/sun/istack/maven/ResourceGenMojoITCase.java new file mode 100644 index 0000000..44a6615 --- /dev/null +++ b/istack-commons/maven-plugin/src/test/java/com/sun/istack/maven/ResourceGenMojoITCase.java
@@ -0,0 +1,37 @@ +/* + * 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 Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.maven; + +import java.io.File; + +import org.junit.Assert; +import org.junit.Test; + +/** + * + * @author Lukas Jungmann + */ +public class ResourceGenMojoITCase { + + private static final File PROJECTS_DIR = new File(System.getProperty("it.projects.dir")); + + public ResourceGenMojoITCase() { + } + + @Test + public void testGeneration() { + File project = new File(PROJECTS_DIR, "sample"); + File f = new File(project, "target/generated-sources/resources/org/aaa/ApropMessages.java"); + Assert.assertTrue("Not found " + f.getAbsolutePath(), f.exists()); + f = new File(project, "target/classes/org/aaa/ApropMessages.class"); + Assert.assertTrue("Not found " + f.getAbsolutePath(), f.exists()); + } +}
diff --git a/istack-commons/maven-plugin/src/test/resources/it-settings.xml b/istack-commons/maven-plugin/src/test/resources/it-settings.xml new file mode 100644 index 0000000..d4f5aa2 --- /dev/null +++ b/istack-commons/maven-plugin/src/test/resources/it-settings.xml
@@ -0,0 +1,67 @@ +<?xml version="1.0"?> +<!-- + + Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<settings> + <profiles> + <profile> + <id>it-repo</id> + <activation> + <activeByDefault>true</activeByDefault> + </activation> + <repositories> + <repository> + <id>local.central</id> + <url>@localRepositoryUrl@</url> + <releases> + <enabled>true</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </repository> + <repository> + <id>jakarta-sonatype-nexus</id> + <url>https://jakarta.oss.sonatype.org/service/local/staging/deploy/maven2/</url> + <layout>default</layout> + </repository> + <repository> + <id>jakarta-sonatype-nexus-staging</id> + <url>https://jakarta.oss.sonatype.org/content/repositories/staging/</url> + <layout>default</layout> + </repository> + </repositories> + <pluginRepositories> + <pluginRepository> + <id>local.central</id> + <url>@localRepositoryUrl@</url> + <releases> + <enabled>true</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </pluginRepository> + <pluginRepository> + <id>jakarta-sonatype-nexus-plugins</id> + <url>https://jakarta.oss.sonatype.org/service/local/staging/deploy/maven2/</url> + <layout>default</layout> + </pluginRepository> + <pluginRepository> + <id>jakarta-sonatype-nexus-staging-plugins</id> + <url>https://jakarta.oss.sonatype.org/content/repositories/staging/</url> + <layout>default</layout> + </pluginRepository> + </pluginRepositories> + </profile> + </profiles> +</settings>
diff --git a/istack-commons/maven-plugin/src/test/script/setproxy.groovy b/istack-commons/maven-plugin/src/test/script/setproxy.groovy new file mode 100644 index 0000000..241003e --- /dev/null +++ b/istack-commons/maven-plugin/src/test/script/setproxy.groovy
@@ -0,0 +1,53 @@ +/* + * 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 Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +log.info("Checking proxy...") +def itsettings = new XmlParser().parse(project.build.testResources.directory[0] + "/it-settings.xml") +def itproxy = "" +if (settings?.proxies) { + Node proxies = new Node(itsettings, "proxies") + settings?.proxies?.each { proxy -> + if (proxy.active) { + if ("http".equals(proxy.protocol)) { + itproxy += " -Dhttp.proxyHost=" + proxy.host + if (proxy.port) { + itproxy += " -Dhttp.proxyPort=" + proxy.port + } + } else if ("https".equals(proxy.protocol)) { + itproxy += " -Dhttps.proxyHost=" + proxy.host + if (proxy.port) { + itproxy += " -Dhttps.proxyPort=" + proxy.port + } + } + def p = new Node(proxies, "proxy") + new Node(p, "protocol", proxy.protocol) + new Node(p, "port", proxy.port) + if (proxy.username) {new Node(p, "username", proxy.username)} + if (proxy.password) {new Node(p, "password", proxy.password)} + if (proxy.id) {new Node(p, "id", proxy.id)} else {new Node(p, "id", proxy.protocol)} + new Node(p, "host", proxy.host) + new Node(p, "active", proxy.active) + new Node(p, "nonProxyHosts", proxy.nonProxyHosts) + } + } +} + +if (itproxy.trim().length() > 0) { + log.info("Setting: " + itproxy.trim()) +} else { + log.info("No proxy found") +} + +def writer = new FileWriter(new File(project.build.directory, "it-settings.xml")) +groovy.xml.XmlNodePrinter printer = new groovy.xml.XmlNodePrinter(new PrintWriter(writer)) +printer.setPreserveWhitespace(true) +printer.print(itsettings) + +project.getModel().addProperty("ittest-proxy", itproxy.trim())
diff --git a/istack-commons/pom.xml b/istack-commons/pom.xml new file mode 100644 index 0000000..f875b83 --- /dev/null +++ b/istack-commons/pom.xml
@@ -0,0 +1,624 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.eclipse.ee4j</groupId> + <artifactId>project</artifactId> + <version>1.0.7</version> + <relativePath/> + </parent> + + <groupId>com.sun.istack</groupId> + <artifactId>istack-commons</artifactId> + <version>4.2.0</version> + <packaging>pom</packaging> + <name>iStack Common Utility Code</name> + <description>istack common utility code</description> + + <scm> + <connection>scm:git:ssh://git@github.com/eclipse-ee4j/jaxb-istack-commons.git</connection> + <developerConnection>scm:git:ssh://git@github.com/eclipse-ee4j/jaxb-istack-commons.git</developerConnection> + <url>https://github.com/eclipse-ee4j/jaxb-istack-commons</url> + <tag>HEAD</tag> + </scm> + + <licenses> + <license> + <name>Eclipse Distribution License - v 1.0</name> + <url>http://www.eclipse.org/org/documents/edl-v10.php</url> + <distribution>repo</distribution> + </license> + </licenses> + + <developers> + <developer> + <name>Lukas Jungmann</name> + <email>lukas.jungmann@oracle.com</email> + <organization>Oracle Corporation</organization> + </developer> + </developers> + + <issueManagement> + <system>github</system> + <url>https://github.com/eclipse-ee4j/jaxb-istack-commons/issues</url> + </issueManagement> + + <mailingLists> + <mailingList> + <name>Eclipse Implementation of JAXB mailing list</name> + <post>jaxb-impl-dev@eclipse.org</post> + <subscribe>https://dev.eclipse.org/mailman/listinfo/jaxb-impl-dev</subscribe> + <unsubscribe>https://dev.eclipse.org/mailman/listinfo/jaxb-impl-dev</unsubscribe> + <archive>https://dev.eclipse.org/mhonarc/lists/jaxb-impl-dev</archive> + </mailingList> + </mailingLists> + + <properties> + <project.build.commonResourcesDirectory>${project.build.directory}/common-resources</project.build.commonResourcesDirectory> + <legal.doc.source>${project.build.commonResourcesDirectory}/legal</legal.doc.source> + <config.dir>${project.build.commonResourcesDirectory}/config</config.dir> + <copyright.exclude>${config.dir}/copyright-exclude</copyright.exclude> + <copyright.ignoreyear>false</copyright.ignoreyear> + <copyright.scmonly>true</copyright.scmonly> + <copyright.update>false</copyright.update> + <spotbugs.exclude>${config.dir}/spotbugs-exclude.xml</spotbugs.exclude> + <spotbugs.skip>false</spotbugs.skip> + <spotbugs.threshold>Low</spotbugs.threshold> + <spotbugs.version>4.7.3.4</spotbugs.version> + + <activation.version>2.1.1</activation.version> + <maven.api.version>3.9.1</maven.api.version> + <maven.resolver.version>1.9.7</maven.resolver.version> + <junit.version>4.13.2</junit.version> + <ant.version>1.10.13</ant.version> + <codemodel.version>4.0.2</codemodel.version> + <plexus-utils.version>3.5.1</plexus-utils.version> + <maven-plugin-annotations.version>3.8.1</maven-plugin-annotations.version> + <testng.version>7.7.1</testng.version> + <args4j.version>2.33</args4j.version> + + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.reporting.outputEncoding>${project.build.sourceEncoding}</project.reporting.outputEncoding> + <maven.compiler.release>11</maven.compiler.release> + <maven.compiler.testRelease>${maven.compiler.release}</maven.compiler.testRelease> + <vendor.name>Eclipse Foundation</vendor.name> + </properties> + + <modules> + <module>buildtools</module> + <module>runtime</module> + <module>test</module> + <module>tools</module> + <module>maven-plugin</module> + <module>import-properties-plugin</module> + <module>soimp</module> + </modules> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>jakarta.activation</groupId> + <artifactId>jakarta.activation-api</artifactId> + <version>${activation.version}</version> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>${junit.version}</version> + </dependency> + <dependency> + <groupId>org.apache.ant</groupId> + <artifactId>ant</artifactId> + <version>${ant.version}</version> + </dependency> + <dependency> + <groupId>org.apache.ant</groupId> + <artifactId>ant-junit</artifactId> + <version>${ant.version}</version> + </dependency> + <dependency> + <groupId>org.glassfish.jaxb</groupId> + <artifactId>codemodel</artifactId> + <version>${codemodel.version}</version> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-plugin-api</artifactId> + <version>${maven.api.version}</version> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-core</artifactId> + <version>${maven.api.version}</version> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-artifact</artifactId> + <version>${maven.api.version}</version> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-model</artifactId> + <version>${maven.api.version}</version> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-utils</artifactId> + <version>${plexus-utils.version}</version> + </dependency> + <dependency> + <groupId>org.apache.maven.plugin-tools</groupId> + <artifactId>maven-plugin-annotations</artifactId> + <version>${maven-plugin-annotations.version}</version> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.testng</groupId> + <artifactId>testng</artifactId> + <version>${testng.version}</version> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-settings</artifactId> + <version>${maven.api.version}</version> + </dependency> + <dependency> + <groupId>org.apache.maven.resolver</groupId> + <artifactId>maven-resolver-api</artifactId> + <version>${maven.resolver.version}</version> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.maven.resolver</groupId> + <artifactId>maven-resolver-impl</artifactId> + <version>${maven.resolver.version}</version> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>args4j</groupId> + <artifactId>args4j</artifactId> + <version>${args4j.version}</version> + </dependency> + </dependencies> + </dependencyManagement> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <pluginManagement> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <version>3.3.0</version> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>buildnumber-maven-plugin</artifactId> + <version>3.0.0</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.11.0</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>3.0.0</version> + </plugin> + <plugin> + <groupId>org.glassfish.copyright</groupId> + <artifactId>glassfish-copyright-maven-plugin</artifactId> + <version>2.4</version> + </plugin> + <plugin> + <groupId>com.github.spotbugs</groupId> + <artifactId>spotbugs-maven-plugin</artifactId> + <version>${spotbugs.version}</version> + <configuration> + <skip>${spotbugs.skip}</skip> + <threshold>${spotbugs.threshold}</threshold> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-source-plugin</artifactId> + <version>3.2.1</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>3.3.0</version> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <version>5.1.8</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <version>3.5.0</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-enforcer-plugin</artifactId> + <version>3.3.0</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + <version>3.5.0</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>3.5.0</version> + </plugin> + <plugin> + <groupId>org.codehaus.gmaven</groupId> + <artifactId>gmaven-plugin</artifactId> + <version>1.5</version> + <dependencies> + <dependency> + <groupId>org.apache.groovy</groupId> + <artifactId>groovy</artifactId> + <version>4.0.11</version> + </dependency> + <dependency> + <groupId>org.apache.groovy</groupId> + <artifactId>groovy-xml</artifactId> + <version>4.0.11</version> + </dependency> + </dependencies> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-invoker-plugin</artifactId> + <version>3.5.1</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-failsafe-plugin</artifactId> + <version>3.0.0</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-plugin-plugin</artifactId> + <version>3.8.1</version> + </plugin> + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + <version>0.8.9</version> + </plugin> + </plugins> + </pluginManagement> + + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-enforcer-plugin</artifactId> + <executions> + <execution> + <id>enforce-maven</id> + <goals> + <goal>enforce</goal> + </goals> + <configuration> + <rules> + <requireJavaVersion> + <version>[${maven.compiler.release},)</version> + </requireJavaVersion> + <requireMavenVersion> + <version>[3.6.0,)</version> + </requireMavenVersion> + </rules> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>buildnumber-maven-plugin</artifactId> + <configuration> + <getRevisionOnlyOnce>true</getRevisionOnlyOnce> + <revisionOnScmFailure>false</revisionOnScmFailure> + <shortRevisionLength>7</shortRevisionLength> + </configuration> + <executions> + <execution> + <phase>validate</phase> + <goals> + <goal>create</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.glassfish.copyright</groupId> + <artifactId>glassfish-copyright-maven-plugin</artifactId> + <configuration> + <excludeFile>${copyright.exclude}</excludeFile> + <!-- skip files not under SCM--> + <scmOnly>${copyright.scmonly}</scmOnly> + <!-- for use with repair --> + <update>${copyright.update}</update> + <!-- check that year is correct --> + <ignoreYear>${copyright.ignoreyear}</ignoreYear> + <quiet>false</quiet> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + <executions> + <execution> + <id>common-resources</id> + <phase>generate-resources</phase> + <goals> + <goal>single</goal> + </goals> + <inherited>false</inherited> + <configuration> + <descriptors> + <descriptor>src/main/assembly/resources.xml</descriptor> + </descriptors> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>unpack-resource</id> + <phase>generate-resources</phase> + <goals> + <goal>unpack</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>${project.groupId}</groupId> + <artifactId>istack-commons</artifactId> + <version>${project.version}</version> + <classifier>resources</classifier> + <type>zip</type> + <outputDirectory>${project.build.commonResourcesDirectory}</outputDirectory> + </artifactItem> + </artifactItems> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <compilerArgs> + <arg>-Xlint:all</arg> + <arg>-Xdoclint:all,-missing</arg> + <arg>-Werror</arg> + </compilerArgs> + <showDeprecation>true</showDeprecation> + <createMissingPackageInfoClass>false</createMissingPackageInfoClass> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <configuration> + <archive> + <manifest> + <addDefaultEntries>false</addDefaultEntries> + </manifest> + </archive> + <instructions> + <Implementation-Vendor>${vendor.name}</Implementation-Vendor> + <Implementation-Vendor-Id>${project.groupId}</Implementation-Vendor-Id> + <Implementation-Build-Id>${project.version} - ${buildNumber}</Implementation-Build-Id> + </instructions> + <niceManifest>true</niceManifest> + <noWarningProjectTypes> + <noWarningProjectType>pom</noWarningProjectType> + <noWarningProjectType>maven-plugin</noWarningProjectType> + </noWarningProjectTypes> + </configuration> + <executions> + <execution> + <id>bundle-manifest</id> + <phase>process-classes</phase> + <goals> + <goal>manifest</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <configuration> + <archive> + <manifest> + <addDefaultEntries>false</addDefaultEntries> + </manifest> + </archive> + <excludes> + <exclude>META-INF/jpms.args</exclude> + </excludes> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <configuration> + <notimestamp>true</notimestamp> + <doclint>all,-missing</doclint> + <quiet>true</quiet> + <failOnWarnings>true</failOnWarnings> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-source-plugin</artifactId> + <configuration> + <archive> + <manifest> + <addDefaultEntries>false</addDefaultEntries> + </manifest> + <manifestEntries> + <Implementation-Build-Id>${project.version} - ${buildNumber}</Implementation-Build-Id> + </manifestEntries> + </archive> + </configuration> + </plugin> + <plugin> + <groupId>com.github.spotbugs</groupId> + <artifactId>spotbugs-maven-plugin</artifactId> + <configuration> + <fork>true</fork> + <excludeFilterFile>${spotbugs.exclude}</excludeFilterFile> + <failThreshold>High</failThreshold> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-plugin-plugin</artifactId> + <configuration> + <extractors> + <extractor>java-annotations</extractor> + </extractors> + </configuration> + </plugin> + </plugins> + </build> + + <profiles> + <profile> + <id>coverage</id> + <build> + <plugins> + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + <executions> + <execution> + <id>default-prepare-agent</id> + <goals> + <goal>prepare-agent</goal> + </goals> + </execution> + <execution> + <id>default-report</id> + <goals> + <goal>report</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + <profile> + <id>license-check</id> + <pluginRepositories> + <pluginRepository> + <!-- org.eclipse.dash:license-tool-plugin is nor final nor in central yet --> + <id>dash-licenses-snapshots</id> + <url>https://repo.eclipse.org/content/repositories/dash-licenses-snapshots/</url> + <snapshots> + <enabled>true</enabled> + </snapshots> + </pluginRepository> + </pluginRepositories> + <build> + <pluginManagement> + <plugins> + <plugin> + <groupId>org.eclipse.dash</groupId> + <artifactId>license-tool-plugin</artifactId> + <version>0.0.1-SNAPSHOT</version> + </plugin> + </plugins> + </pluginManagement> + <plugins> + <plugin> + <groupId>org.eclipse.dash</groupId> + <artifactId>license-tool-plugin</artifactId> + <executions> + <execution> + <id>license-check</id> + <phase>validate</phase> + <goals> + <goal>license-check</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> + +</project>
diff --git a/istack-commons/runtime/pom.xml b/istack-commons/runtime/pom.xml new file mode 100644 index 0000000..37f14d8 --- /dev/null +++ b/istack-commons/runtime/pom.xml
@@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.sun.istack</groupId> + <artifactId>istack-commons</artifactId> + <version>4.2.0</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>istack-commons-runtime</artifactId> + + <name>istack common utility code runtime</name> + + <dependencies> + <dependency> + <groupId>jakarta.activation</groupId> + <artifactId>jakarta.activation-api</artifactId> + <scope>provided</scope> + <optional>true</optional> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <artifactId>maven-jar-plugin</artifactId> + <configuration> + <archive> + <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile> + </archive> + </configuration> + </plugin> + </plugins> + </build> + +</project> +
diff --git a/istack-commons/runtime/src/main/java/com/sun/istack/Builder.java b/istack-commons/runtime/src/main/java/com/sun/istack/Builder.java new file mode 100644 index 0000000..fe4b72d --- /dev/null +++ b/istack-commons/runtime/src/main/java/com/sun/istack/Builder.java
@@ -0,0 +1,20 @@ +/* + * Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack; + +/** + * + * @author Martin Grebac + * @param <T> type of the Builder + */ +public interface Builder<T> { + T build(); +}
diff --git a/istack-commons/runtime/src/main/java/com/sun/istack/ByteArrayDataSource.java b/istack-commons/runtime/src/main/java/com/sun/istack/ByteArrayDataSource.java new file mode 100644 index 0000000..11a529d --- /dev/null +++ b/istack-commons/runtime/src/main/java/com/sun/istack/ByteArrayDataSource.java
@@ -0,0 +1,69 @@ +/* + * Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack; + +import jakarta.activation.DataSource; +import java.io.InputStream; +import java.io.ByteArrayInputStream; +import java.io.OutputStream; + +/** + * {@link DataSource} backed by a byte buffer. + * + * @author Kohsuke Kawaguchi + */ +public final class ByteArrayDataSource implements DataSource { + + private final String contentType; + private final byte[] buf; + private final int len; + + /** + * @param buf input buffer - the byte array isn't being copied; used directly + * @param contentType content type + */ + public ByteArrayDataSource(byte[] buf, String contentType) { + this(buf,buf.length,contentType); + } + + /** + * @param buf input buffer - the byte array isn't being copied; used directly + * @param length length + * @param contentType content type + */ + public ByteArrayDataSource(byte[] buf, int length, String contentType) { + this.buf = buf; + this.len = length; + this.contentType = contentType; + } + + @Override + public String getContentType() { + if(contentType==null) + return "application/octet-stream"; + return contentType; + } + + @Override + public InputStream getInputStream() { + return new ByteArrayInputStream(buf,0,len); + } + + @Override + public String getName() { + return null; + } + + @Override + public OutputStream getOutputStream() { + throw new UnsupportedOperationException(); + } +}
diff --git a/istack-commons/runtime/src/main/java/com/sun/istack/FinalArrayList.java b/istack-commons/runtime/src/main/java/com/sun/istack/FinalArrayList.java new file mode 100644 index 0000000..542db9f --- /dev/null +++ b/istack-commons/runtime/src/main/java/com/sun/istack/FinalArrayList.java
@@ -0,0 +1,39 @@ +/* + * Copyright (c) 1997, 2022 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * {@link ArrayList} with the final keyword. + * + * <p> + * This gives HotSpot a better hint that all methods can be inlined. + * + * @author Kohsuke Kawaguchi + * @param <T> element type + */ +public final class FinalArrayList<T> extends ArrayList<T> { + + private static final long serialVersionUID = -540534530037816397L; + + public FinalArrayList(int initialCapacity) { + super(initialCapacity); + } + + public FinalArrayList() { + } + + public FinalArrayList(Collection<? extends T> ts) { + super(ts); + } +}
diff --git a/istack-commons/runtime/src/main/java/com/sun/istack/FragmentContentHandler.java b/istack-commons/runtime/src/main/java/com/sun/istack/FragmentContentHandler.java new file mode 100644 index 0000000..26ab3f7 --- /dev/null +++ b/istack-commons/runtime/src/main/java/com/sun/istack/FragmentContentHandler.java
@@ -0,0 +1,45 @@ +/* + * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack; + +import org.xml.sax.helpers.XMLFilterImpl; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.ContentHandler; + +/** + * {@link XMLFilterImpl} that masks start/end document SAX events. + * @author Kohsuke Kawaguchi + */ +public class FragmentContentHandler extends XMLFilterImpl { + public FragmentContentHandler() { + } + + public FragmentContentHandler(XMLReader parent) { + super(parent); + } + + @SuppressWarnings({"this-escape"}) + public FragmentContentHandler(ContentHandler handler) { + super(); + setContentHandler(handler); + } + + @Override + public void startDocument() throws SAXException { + // noop + } + + @Override + public void endDocument() throws SAXException { + // noop + } +}
diff --git a/istack-commons/runtime/src/main/java/com/sun/istack/Interned.java b/istack-commons/runtime/src/main/java/com/sun/istack/Interned.java new file mode 100644 index 0000000..9c88b42 --- /dev/null +++ b/istack-commons/runtime/src/main/java/com/sun/istack/Interned.java
@@ -0,0 +1,40 @@ +/* + * Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +/** + * Designates that a field, return value, argument, or a variable is supposed + * to be an {@link String#intern() interned} string. + * + * <p> + * In many places in the istack, we assume Strings to be interned for + * the performance reason. Similarly, In many other places, we don't + * make such an assumption for the performance reason (because intern + * isn't free.) + * + * <p> + * Therefore, distinguishing which part is supposed to be interned and + * which part is supposed to be not is important. This annotation + * allows us to capture that in the code. + * + * @author Kohsuke Kawaguchi + */ +@Documented +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.FIELD,ElementType.METHOD,ElementType.PARAMETER,ElementType.LOCAL_VARIABLE}) +public @interface Interned { +}
diff --git a/istack-commons/runtime/src/main/java/com/sun/istack/NotNull.java b/istack-commons/runtime/src/main/java/com/sun/istack/NotNull.java new file mode 100644 index 0000000..e5a3d1a --- /dev/null +++ b/istack-commons/runtime/src/main/java/com/sun/istack/NotNull.java
@@ -0,0 +1,28 @@ +/* + * Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +/** + * Designates that a field, return value, argument, or a variable is guaranteed to be non-null. + * + * @author Kohsuke Kawaguchi + */ +@Documented +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.FIELD,ElementType.METHOD,ElementType.PARAMETER,ElementType.LOCAL_VARIABLE}) +public @interface NotNull { +}
diff --git a/istack-commons/runtime/src/main/java/com/sun/istack/Nullable.java b/istack-commons/runtime/src/main/java/com/sun/istack/Nullable.java new file mode 100644 index 0000000..d52e3b3 --- /dev/null +++ b/istack-commons/runtime/src/main/java/com/sun/istack/Nullable.java
@@ -0,0 +1,28 @@ +/* + * Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +/** + * Designates that a field, return value, argument, or a variable may be null. + * + * @author Kohsuke Kawaguchi + */ +@Documented +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.FIELD,ElementType.METHOD,ElementType.PARAMETER,ElementType.LOCAL_VARIABLE}) +public @interface Nullable { +}
diff --git a/istack-commons/runtime/src/main/java/com/sun/istack/Pool.java b/istack-commons/runtime/src/main/java/com/sun/istack/Pool.java new file mode 100644 index 0000000..525f537 --- /dev/null +++ b/istack-commons/runtime/src/main/java/com/sun/istack/Pool.java
@@ -0,0 +1,115 @@ +/* + * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack; + +import java.util.concurrent.ConcurrentLinkedQueue; +import java.lang.ref.WeakReference; + +/** + * Pool of reusable objects that are indistinguishable from each other, + * such as JAXB marshallers. + * + * @author Kohsuke Kawaguchi + * @param <T> type + */ +public interface Pool<T> { + + /** + * Gets a new object from the pool. + * + * <p> + * If no object is available in the pool, this method creates a new one. + * @return an object from the pool + */ + @NotNull T take(); + + /** + * Returns an object back to the pool. + * @param t object to put back to pool + */ + void recycle(@NotNull T t); + + /** + * Default implementation that uses {@link ConcurrentLinkedQueue} + * as the data store. + * + * <h2>Note for Implementors</h2> + * <p> + * Don't rely on the fact that this class extends from {@link ConcurrentLinkedQueue}. + * @param <T> type + */ + abstract class Impl<T> implements Pool<T> { + + private volatile WeakReference<ConcurrentLinkedQueue<T>> queue; + + /** + * Create new Impl + */ + protected Impl() { + } + + /** + * Gets a new object from the pool. + * + * <p> + * If no object is available in the pool, this method creates a new one. + * + * @return + * always non-null. + */ + @Override + public final @NotNull T take() { + T t = getQueue().poll(); + if(t==null) { + return create(); + } + return t; + } + + /** + * Returns an object back to the pool. + * @param t object to put back to the pool + */ + @Override + public final void recycle(T t) { + getQueue().offer(t); + } + + private ConcurrentLinkedQueue<T> getQueue() { + WeakReference<ConcurrentLinkedQueue<T>> q = queue; + if (q != null) { + ConcurrentLinkedQueue<T> d = q.get(); + if (d != null) { + return d; + } + } + // overwrite the queue + ConcurrentLinkedQueue<T> d = new ConcurrentLinkedQueue<>(); + queue = new WeakReference<>(d); + + return d; + } + + /** + * Creates a new instance of object. + * + * <p> + * This method is used when someone wants to + * {@link #take() take} an object from an empty pool. + * + * <p> + * Also note that multiple threads may call this method + * concurrently. + * @return an object from an empty pool + */ + protected abstract @NotNull T create(); + } +}
diff --git a/istack-commons/runtime/src/main/java/com/sun/istack/SAXException2.java b/istack-commons/runtime/src/main/java/com/sun/istack/SAXException2.java new file mode 100644 index 0000000..7673034 --- /dev/null +++ b/istack-commons/runtime/src/main/java/com/sun/istack/SAXException2.java
@@ -0,0 +1,41 @@ +/* + * Copyright (c) 1997, 2022 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack; + +import org.xml.sax.SAXException; + +/** + * {@link SAXException} that handles exception chaining correctly. + * + * @author Kohsuke Kawaguchi + * @since 2.0 FCS + */ +public class SAXException2 extends SAXException { + + private static final long serialVersionUID = -707119042406163844L; + + public SAXException2(String message) { + super(message); + } + + public SAXException2(Exception e) { + super(e); + } + + public SAXException2(String message, Exception e) { + super(message, e); + } + + @Override + public Throwable getCause() { + return getException(); + } +}
diff --git a/istack-commons/runtime/src/main/java/com/sun/istack/SAXParseException2.java b/istack-commons/runtime/src/main/java/com/sun/istack/SAXParseException2.java new file mode 100644 index 0000000..fb8d743 --- /dev/null +++ b/istack-commons/runtime/src/main/java/com/sun/istack/SAXParseException2.java
@@ -0,0 +1,46 @@ +/* + * Copyright (c) 1997, 2022 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack; + +import org.xml.sax.SAXParseException; +import org.xml.sax.Locator; + +/** + * {@link SAXParseException} that handles exception chaining correctly. + * + * @author Kohsuke Kawaguchi + * @since 2.0 FCS + */ +public class SAXParseException2 extends SAXParseException { + + private static final long serialVersionUID = 1304853690034671001L; + + public SAXParseException2(String message, Locator locator) { + super(message, locator); + } + + public SAXParseException2(String message, Locator locator, Exception e) { + super(message, locator, e); + } + + public SAXParseException2(String message, String publicId, String systemId, int lineNumber, int columnNumber) { + super(message, publicId, systemId, lineNumber, columnNumber); + } + + public SAXParseException2(String message, String publicId, String systemId, int lineNumber, int columnNumber, Exception e) { + super(message, publicId, systemId, lineNumber, columnNumber, e); + } + + @Override + public Throwable getCause() { + return getException(); + } +}
diff --git a/istack-commons/runtime/src/main/java/com/sun/istack/XMLStreamException2.java b/istack-commons/runtime/src/main/java/com/sun/istack/XMLStreamException2.java new file mode 100644 index 0000000..301274f --- /dev/null +++ b/istack-commons/runtime/src/main/java/com/sun/istack/XMLStreamException2.java
@@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997, 2022 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.Location; + +/** + * {@link XMLStreamException} that properly handles exception chaining. + * + * @author Kohsuke Kawaguchi + */ +public class XMLStreamException2 extends XMLStreamException { + + private static final long serialVersionUID = 1409033131880742500L; + + public XMLStreamException2(String msg) { + super(msg); + } + + public XMLStreamException2(Throwable th) { + super(th); + } + + public XMLStreamException2(String msg, Throwable th) { + super(msg, th); + } + + public XMLStreamException2(String msg, Location location) { + super(msg, location); + } + + public XMLStreamException2(String msg, Location location, Throwable th) { + super(msg, location, th); + } + + /** + * {@link XMLStreamException} doesn't return the correct cause. + */ + @Override + public Throwable getCause() { + return getNestedException(); + } +}
diff --git a/istack-commons/runtime/src/main/java/com/sun/istack/XMLStreamReaderToContentHandler.java b/istack-commons/runtime/src/main/java/com/sun/istack/XMLStreamReaderToContentHandler.java new file mode 100644 index 0000000..a4d0fdf --- /dev/null +++ b/istack-commons/runtime/src/main/java/com/sun/istack/XMLStreamReaderToContentHandler.java
@@ -0,0 +1,379 @@ +/* + * Copyright (c) 1997, 2022 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack; + +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.Locator; +import org.xml.sax.Attributes; +import org.xml.sax.helpers.AttributesImpl; + +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.namespace.QName; + +/** + * This is a simple utility class that adapts StAX events from an + * {@link XMLStreamReader} to SAX events on a + * {@link ContentHandler}, bridging between the two + * parser technologies. + * + * @author Ryan.Shoemaker@Sun.COM + * @version 1.0 + */ +public class XMLStreamReaderToContentHandler { + + // StAX event source + private final XMLStreamReader staxStreamReader; + + // SAX event sink + private final ContentHandler saxHandler; + + // if true, when the conversion is completed, leave the cursor to the last + // event that was fired (such as end element) + private final boolean eagerQuit; + + /** + * If true, not start/endDocument event. + */ + private final boolean fragment; + + // array of the even length of the form { prefix0, uri0, prefix1, uri1, ... } + private final String[] inscopeNamespaces; + + /** + * @param staxCore + * StAX event source + * @param saxCore + * SAXevent sink + * @see #XMLStreamReaderToContentHandler(XMLStreamReader, ContentHandler, boolean, boolean, String[]) + */ + public XMLStreamReaderToContentHandler(XMLStreamReader staxCore, ContentHandler saxCore, boolean eagerQuit, boolean fragment) { + this(staxCore, saxCore, eagerQuit, fragment, new String[0]); + } + + /** + * Construct a new StAX to SAX adapter that will convert a StAX event + * stream into a SAX event stream. + * + * @param staxCore + * StAX event source + * @param saxCore + * SAXevent sink + * @param inscopeNamespaces + * array of the even length of the form { prefix0, uri0, prefix1, uri1, ... } + */ + public XMLStreamReaderToContentHandler(XMLStreamReader staxCore, ContentHandler saxCore, + boolean eagerQuit, boolean fragment, String[] inscopeNamespaces) { + this.staxStreamReader = staxCore; + this.saxHandler = saxCore; + this.eagerQuit = eagerQuit; + this.fragment = fragment; + this.inscopeNamespaces = inscopeNamespaces.clone(); + assert inscopeNamespaces.length%2 == 0; + } + + + /* + * @see StAXReaderToContentHandler#bridge() + */ + public void bridge() throws XMLStreamException { + + try { + // remembers the nest level of elements to know when we are done. + int depth=0; + + // if the parser is at the start tag, proceed to the first element + int event = staxStreamReader.getEventType(); + if(event == XMLStreamConstants.START_DOCUMENT) { + // nextTag doesn't correctly handle DTDs + while( !staxStreamReader.isStartElement() ) + event = staxStreamReader.next(); + } + + + if( event!=XMLStreamConstants.START_ELEMENT) + throw new IllegalStateException("The current event is not START_ELEMENT\n but " + event); + + handleStartDocument(); + + for(int i=0; i < inscopeNamespaces.length; i+=2) { + saxHandler.startPrefixMapping(inscopeNamespaces[i], inscopeNamespaces[i+1]); + } + + OUTER: + do { + // These are all of the events listed in the javadoc for + // XMLEvent. + // The spec only really describes 11 of them. + switch (event) { + case XMLStreamConstants.START_ELEMENT : + depth++; + handleStartElement(); + break; + case XMLStreamConstants.END_ELEMENT : + handleEndElement(); + depth--; + if(depth==0 && eagerQuit) + break OUTER; + break; + case XMLStreamConstants.CHARACTERS : + handleCharacters(); + break; + case XMLStreamConstants.ENTITY_REFERENCE : + handleEntityReference(); + break; + case XMLStreamConstants.PROCESSING_INSTRUCTION : + handlePI(); + break; + case XMLStreamConstants.COMMENT : + handleComment(); + break; + case XMLStreamConstants.DTD : + handleDTD(); + break; + case XMLStreamConstants.ATTRIBUTE : + handleAttribute(); + break; + case XMLStreamConstants.NAMESPACE : + handleNamespace(); + break; + case XMLStreamConstants.CDATA : + handleCDATA(); + break; + case XMLStreamConstants.ENTITY_DECLARATION : + handleEntityDecl(); + break; + case XMLStreamConstants.NOTATION_DECLARATION : + handleNotationDecl(); + break; + case XMLStreamConstants.SPACE : + handleSpace(); + break; + default : + throw new InternalError("processing event: " + event); + } + + event=staxStreamReader.next(); + } while (depth!=0); + + for(int i=0; i < inscopeNamespaces.length; i+=2) { + saxHandler.endPrefixMapping(inscopeNamespaces[i]); + } + + handleEndDocument(); + } catch (SAXException e) { + throw new XMLStreamException2(e); + } + } + + private void handleEndDocument() throws SAXException { + if(fragment) + return; + + saxHandler.endDocument(); + } + + private void handleStartDocument() throws SAXException { + if(fragment) + return; + + saxHandler.setDocumentLocator(new Locator() { + @Override + public int getColumnNumber() { + return staxStreamReader.getLocation().getColumnNumber(); + } + @Override + public int getLineNumber() { + return staxStreamReader.getLocation().getLineNumber(); + } + @Override + public String getPublicId() { + return staxStreamReader.getLocation().getPublicId(); + } + @Override + public String getSystemId() { + return staxStreamReader.getLocation().getSystemId(); + } + }); + saxHandler.startDocument(); + } + + private void handlePI() throws XMLStreamException { + try { + saxHandler.processingInstruction( + staxStreamReader.getPITarget(), + staxStreamReader.getPIData()); + } catch (SAXException e) { + throw new XMLStreamException2(e); + } + } + + private void handleCharacters() throws XMLStreamException { + try { + saxHandler.characters( + staxStreamReader.getTextCharacters(), + staxStreamReader.getTextStart(), + staxStreamReader.getTextLength() ); + } catch (SAXException e) { + throw new XMLStreamException2(e); + } + } + + private void handleEndElement() throws XMLStreamException { + QName qName = staxStreamReader.getName(); + + try { + String pfix = qName.getPrefix(); + String rawname = (pfix == null || pfix.length() == 0) + ? qName.getLocalPart() + : pfix + ':' + qName.getLocalPart(); + // fire endElement + saxHandler.endElement( + qName.getNamespaceURI(), + qName.getLocalPart(), + rawname); + + // end namespace bindings + int nsCount = staxStreamReader.getNamespaceCount(); + for (int i = nsCount - 1; i >= 0; i--) { + String prefix = staxStreamReader.getNamespacePrefix(i); + if (prefix == null) { // true for default namespace + prefix = ""; + } + saxHandler.endPrefixMapping(prefix); + } + } catch (SAXException e) { + throw new XMLStreamException2(e); + } + } + + private void handleStartElement() throws XMLStreamException { + + try { + // start namespace bindings + int nsCount = staxStreamReader.getNamespaceCount(); + for (int i = 0; i < nsCount; i++) { + saxHandler.startPrefixMapping( + fixNull(staxStreamReader.getNamespacePrefix(i)), + fixNull(staxStreamReader.getNamespaceURI(i))); + } + + // fire startElement + QName qName = staxStreamReader.getName(); + String prefix = qName.getPrefix(); + String rawname; + if(prefix==null || prefix.length()==0) + rawname = qName.getLocalPart(); + else + rawname = prefix + ':' + qName.getLocalPart(); + Attributes attrs = getAttributes(); + saxHandler.startElement( + qName.getNamespaceURI(), + qName.getLocalPart(), + rawname, + attrs); + } catch (SAXException e) { + throw new XMLStreamException2(e); + } + } + + private static String fixNull(String s) { + if(s==null) return ""; + else return s; + } + + /** + * Get the attributes associated with the given START_ELEMENT or ATTRIBUTE + * StAXevent. + * + * @return the StAX attributes converted to an org.xml.sax.Attributes + */ + private Attributes getAttributes() { + AttributesImpl attrs = new AttributesImpl(); + + int eventType = staxStreamReader.getEventType(); + if (eventType != XMLStreamConstants.ATTRIBUTE + && eventType != XMLStreamConstants.START_ELEMENT) { + throw new InternalError( + "getAttributes() attempting to process: " + eventType); + } + + // in SAX, namespace declarations are not part of attributes by default. + // (there's a property to control that, but as far as we are concerned + // we don't use it.) So don't add xmlns:* to attributes. + + // gather non-namespace attrs + for (int i = 0; i < staxStreamReader.getAttributeCount(); i++) { + String uri = staxStreamReader.getAttributeNamespace(i); + if(uri==null) uri=""; + String localName = staxStreamReader.getAttributeLocalName(i); + String prefix = staxStreamReader.getAttributePrefix(i); + String qName; + if(prefix==null || prefix.length()==0) + qName = localName; + else + qName = prefix + ':' + localName; + String type = staxStreamReader.getAttributeType(i); + String value = staxStreamReader.getAttributeValue(i); + + attrs.addAttribute(uri, localName, qName, type, value); + } + + return attrs; + } + + private void handleNamespace() { + // no-op ??? + // namespace events don't normally occur outside of a startElement + // or endElement + } + + private void handleAttribute() { + // no-op ??? + // attribute events don't normally occur outside of a startElement + // or endElement + } + + private void handleDTD() { + // no-op ??? + // it seems like we need to pass this info along, but how? + } + + private void handleComment() { + // no-op ??? + } + + private void handleEntityReference() { + // no-op ??? + } + + private void handleSpace() { + // no-op ??? + // this event is listed in the javadoc, but not in the spec. + } + + private void handleNotationDecl() { + // no-op ??? + // this event is listed in the javadoc, but not in the spec. + } + + private void handleEntityDecl() { + // no-op ??? + // this event is listed in the javadoc, but not in the spec. + } + + private void handleCDATA() { + // no-op ??? + // this event is listed in the javadoc, but not in the spec. + } +}
diff --git a/istack-commons/runtime/src/main/java/com/sun/istack/localization/Localizable.java b/istack-commons/runtime/src/main/java/com/sun/istack/localization/Localizable.java new file mode 100644 index 0000000..d29f9b3 --- /dev/null +++ b/istack-commons/runtime/src/main/java/com/sun/istack/localization/Localizable.java
@@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.localization; + +import java.util.Locale; +import java.util.ResourceBundle; + +/** + * Localizable message. + * + * @author WS Development Team + */ +public interface Localizable { + /** + * Gets the key in the resource bundle. + * + * @return + * if this method returns {@link #NOT_LOCALIZABLE}, + * that means the message is not localizable, and + * the first item of {@link #getArguments()} array + * holds a String. + */ + String getKey(); + + /** + * Returns the arguments for message formatting. + * + * @return + * can be an array of length 0 but never be null. + */ + Object[] getArguments(); + String getResourceBundleName(); + + ResourceBundle getResourceBundle(Locale locale); + + /** + * Special constant that represents a message that + * is not localizable. + * + * <p> + * Use of "new" is to create an unique instance. + */ + String NOT_LOCALIZABLE = "\u0000"; +}
diff --git a/istack-commons/runtime/src/main/java/com/sun/istack/localization/LocalizableMessage.java b/istack-commons/runtime/src/main/java/com/sun/istack/localization/LocalizableMessage.java new file mode 100644 index 0000000..fa44fa1 --- /dev/null +++ b/istack-commons/runtime/src/main/java/com/sun/istack/localization/LocalizableMessage.java
@@ -0,0 +1,68 @@ +/* + * Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.localization; + +import com.sun.istack.localization.LocalizableMessageFactory.ResourceBundleSupplier; + +import java.util.Arrays; +import java.util.Locale; +import java.util.ResourceBundle; + + +/** + * @author WS Development Team + */ +public final class LocalizableMessage implements Localizable { + + private final String _bundlename; + private final ResourceBundleSupplier _rbSupplier; + + private final String _key; + private final Object[] _args; + + @Deprecated + public LocalizableMessage(String bundlename, String key, Object... args) { + this(bundlename, null, key, args); + } + + public LocalizableMessage(String bundlename, ResourceBundleSupplier rbSupplier, + String key, Object... args) { + _bundlename = bundlename; + _rbSupplier = rbSupplier; + _key = key; + if(args==null) + args = new Object[0]; + _args = args; + } + + @Override + public String getKey() { + return _key; + } + + @Override + public Object[] getArguments() { + return Arrays.copyOf(_args, _args.length); + } + + @Override + public String getResourceBundleName() { + return _bundlename; + } + + @Override + public ResourceBundle getResourceBundle(Locale locale) { + if (_rbSupplier == null) + return null; + + return _rbSupplier.getResourceBundle(locale); + } +}
diff --git a/istack-commons/runtime/src/main/java/com/sun/istack/localization/LocalizableMessageFactory.java b/istack-commons/runtime/src/main/java/com/sun/istack/localization/LocalizableMessageFactory.java new file mode 100644 index 0000000..d40e3ae --- /dev/null +++ b/istack-commons/runtime/src/main/java/com/sun/istack/localization/LocalizableMessageFactory.java
@@ -0,0 +1,48 @@ +/* + * Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.localization; + +import java.util.Locale; +import java.util.ResourceBundle; + +/** + * @author WS Development Team + */ +public class LocalizableMessageFactory { + + private final String _bundlename; + private final ResourceBundleSupplier _rbSupplier; + + @Deprecated + public LocalizableMessageFactory(String bundlename) { + _bundlename = bundlename; + _rbSupplier = null; + } + + public LocalizableMessageFactory(String bundlename, ResourceBundleSupplier rbSupplier) { + _bundlename = bundlename; + _rbSupplier = rbSupplier; + } + + public Localizable getMessage(String key, Object... args) { + return new LocalizableMessage(_bundlename, _rbSupplier, key, args); + } + + public interface ResourceBundleSupplier { + /** + * Gets the ResourceBundle. + * @param locale the requested bundle's locale + * @return ResourceBundle + */ + ResourceBundle getResourceBundle(Locale locale); + } + +}
diff --git a/istack-commons/runtime/src/main/java/com/sun/istack/localization/Localizer.java b/istack-commons/runtime/src/main/java/com/sun/istack/localization/Localizer.java new file mode 100644 index 0000000..07b1edf --- /dev/null +++ b/istack-commons/runtime/src/main/java/com/sun/istack/localization/Localizer.java
@@ -0,0 +1,146 @@ +/* + * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.localization; + +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +/** + * Localizes the {@link Localizable} into a message + * by using a configured {@link Locale}. + * + * @author WS Development Team + */ +public class Localizer { + + private final Locale _locale; + private final HashMap<String, ResourceBundle> _resourceBundles; + + public Localizer() { + this(Locale.getDefault()); + } + + public Localizer(Locale l) { + _locale = l; + _resourceBundles = new HashMap<>(); + } + + public Locale getLocale() { + return _locale; + } + + public String localize(Localizable l) { + String key = l.getKey(); + if (key == Localizable.NOT_LOCALIZABLE) { + // this message is not localizable + return (String) l.getArguments()[0]; + } + + String bundlename = l.getResourceBundleName(); + + try { + ResourceBundle bundle = + _resourceBundles.get(bundlename); + + if (bundle == null) { + bundle = l.getResourceBundle(_locale); + if (bundle != null) { + _resourceBundles.put(bundlename, bundle); + } + } + + if (bundle == null) { + try { + bundle = ResourceBundle.getBundle(bundlename, _locale); + } catch (MissingResourceException e) { + // work around a bug in the com.sun.enterprise.deployment.WebBundleArchivist: + // all files with an extension different from .class (hence all the .properties files) + // get copied to the top level directory instead of being in the package where they + // are defined + // so, since we can't find the bundle under its proper name, we look for it under + // the top-level package + + int i = bundlename.lastIndexOf('.'); + if (i != -1) { + String alternateBundleName = + bundlename.substring(i + 1); + try { + bundle = + ResourceBundle.getBundle( + alternateBundleName, + _locale); + } catch (MissingResourceException e2) { + //try context classloader + try { + bundle = ResourceBundle.getBundle(bundlename, _locale, Thread.currentThread().getContextClassLoader()); + } catch (MissingResourceException e3) { + // give up + return getDefaultMessage(l); + } + + } + } + } + + _resourceBundles.put(bundlename, bundle); + } + + if (bundle == null) { + return getDefaultMessage(l); + } + + if (key == null) + key = "undefined"; + + String msg; + try { + msg = bundle.getString(key); + } catch (MissingResourceException e) { + // notice that this may throw a MissingResourceException of its own (caught below) + msg = bundle.getString("undefined"); + } + + // localize all arguments to the given localizable object + Object[] args = l.getArguments(); + for (int i = 0; i < args.length; ++i) { + if (args[i] instanceof Localizable) + args[i] = localize((Localizable) args[i]); + } + + return MessageFormat.format(msg, args); + + } catch (MissingResourceException e) { + return getDefaultMessage(l); + } + + } + + private String getDefaultMessage(Localizable l) { + String key = l.getKey(); + Object[] args = l.getArguments(); + StringBuilder sb = new StringBuilder(); + sb.append("[failed to localize] "); + sb.append(key); + if (args != null) { + sb.append('('); + for (int i = 0; i < args.length; ++i) { + if (i != 0) + sb.append(", "); + sb.append(String.valueOf(args[i])); + } + sb.append(')'); + } + return sb.toString(); + } +}
diff --git a/istack-commons/runtime/src/main/java/com/sun/istack/localization/NullLocalizable.java b/istack-commons/runtime/src/main/java/com/sun/istack/localization/NullLocalizable.java new file mode 100644 index 0000000..01566cc --- /dev/null +++ b/istack-commons/runtime/src/main/java/com/sun/istack/localization/NullLocalizable.java
@@ -0,0 +1,46 @@ +/* + * Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.localization; + +import java.util.Locale; +import java.util.ResourceBundle; + +/** + * {@link Localizable} that wraps a non-localizable string. + * + * @author WS Development Team + */ +public final class NullLocalizable implements Localizable { + private final String msg; + + public NullLocalizable(String msg) { + if(msg==null) + throw new IllegalArgumentException(); + this.msg = msg; + } + + @Override + public String getKey() { + return Localizable.NOT_LOCALIZABLE; + } + @Override + public Object[] getArguments() { + return new Object[]{msg}; + } + @Override + public String getResourceBundleName() { + return ""; + } + @Override + public ResourceBundle getResourceBundle(Locale locale) { + return null; + } +}
diff --git a/istack-commons/runtime/src/main/java/com/sun/istack/logging/Logger.java b/istack-commons/runtime/src/main/java/com/sun/istack/logging/Logger.java new file mode 100644 index 0000000..7f4aa3c --- /dev/null +++ b/istack-commons/runtime/src/main/java/com/sun/istack/logging/Logger.java
@@ -0,0 +1,486 @@ +/* + * Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.logging; + +import com.sun.istack.NotNull; + +import java.util.StringTokenizer; +import java.util.logging.Level; + +/** + * This is a helper class that provides some convenience methods wrapped around the + * standard {@link java.util.logging.Logger} interface. + * + * The class also makes sure that logger names of each Metro subsystem are consistent + * with each other. + * + * @author Marek Potociar + * @author Fabian Ritzmann + */ +public class Logger { + + private static final String WS_LOGGING_SUBSYSTEM_NAME_ROOT = "com.sun.metro"; + private static final String ROOT_WS_PACKAGE = "com.sun.xml.ws."; + // + private static final Level METHOD_CALL_LEVEL_VALUE = Level.FINEST; + // + private final String componentClassName; + private final java.util.logging.Logger logger; + + /** + * Prevents creation of a new instance of this Logger unless used by a subclass. + * @param systemLoggerName system logger name + * @param componentName component name + */ + protected Logger(final String systemLoggerName, final String componentName) { + this.componentClassName = "[" + componentName + "] "; + this.logger = java.util.logging.Logger.getLogger(systemLoggerName); + } + + /** + * <p> + * The factory method returns preconfigured Logger wrapper for the class. Method calls + * {@link #getSystemLoggerName(java.lang.Class)} to generate default logger name. + * </p> + * <p> + * Since there is no caching implemented, it is advised that the method is called only once + * per a class in order to initialize a final static logger variable, which is then used + * through the class to perform actual logging tasks. + * </p> + * + * @param componentClass class of the component that will use the logger instance. Must not be {@code null}. + * @return logger instance preconfigured for use with the component + * @throws NullPointerException if the componentClass parameter is {@code null}. + */ + public static @NotNull Logger getLogger(final @NotNull Class<?> componentClass) { + return new Logger(getSystemLoggerName(componentClass), componentClass.getName()); + } + + /** + * The factory method returns preconfigured Logger wrapper for the class. Since there is no caching implemented, + * it is advised that the method is called only once per a class in order to initialize a final static logger variable, + * which is then used through the class to perform actual logging tasks. + * + * This method should be only used in a special cases when overriding of a default logger name derived from the + * package of the component class is needed. For all common use cases please use {@link #getLogger(java.lang.Class)} + * method. + * + * @param customLoggerName custom name of the logger. + * @param componentClass class of the component that will use the logger instance. Must not be {@code null}. + * @return logger instance preconfigured for use with the component + * @throws NullPointerException if the componentClass parameter is {@code null}. + * + * @see #getLogger(java.lang.Class) + */ + public static @NotNull Logger getLogger(final @NotNull String customLoggerName, final @NotNull Class<?> componentClass) { + return new Logger(customLoggerName, componentClass.getName()); + } + + /** + * Calculates the subsystem suffix based on the package of the component class + * @param componentClass class of the component that will use the logger instance. Must not be {@code null}. + * @return system logger name for the given {@code componentClass} instance + */ + static final String getSystemLoggerName(@NotNull Class<?> componentClass) { + StringBuilder sb = new StringBuilder(componentClass.getPackage().getName()); + final int lastIndexOfWsPackage = sb.lastIndexOf(ROOT_WS_PACKAGE); + if (lastIndexOfWsPackage > -1) { + sb.replace(0, lastIndexOfWsPackage + ROOT_WS_PACKAGE.length(), ""); + + StringTokenizer st = new StringTokenizer(sb.toString(), "."); + sb = new StringBuilder(WS_LOGGING_SUBSYSTEM_NAME_ROOT).append("."); + if (st.hasMoreTokens()) { + String token = st.nextToken(); + if ("api".equals(token)) { + token = st.nextToken(); + } + sb.append(token); + } + } + + return sb.toString(); + } + + public void log(final Level level, final String message) { + if (!this.logger.isLoggable(level)) { + return; + } + logger.logp(level, componentClassName, StackHelper.getCallerMethodName(), message); + } + + public void log(final Level level, final String message, Object param1) { + if (!this.logger.isLoggable(level)) { + return; + } + logger.logp(level, componentClassName, StackHelper.getCallerMethodName(), message, param1); + } + + public void log(final Level level, final String message, Object[] params) { + if (!this.logger.isLoggable(level)) { + return; + } + logger.logp(level, componentClassName, StackHelper.getCallerMethodName(), message, params); + } + + public void log(final Level level, final String message, final Throwable thrown) { + if (!this.logger.isLoggable(level)) { + return; + } + logger.logp(level, componentClassName, StackHelper.getCallerMethodName(), message, thrown); + } + + public void finest(final String message) { + if (!this.logger.isLoggable(Level.FINEST)) { + return; + } + logger.logp(Level.FINEST, componentClassName, StackHelper.getCallerMethodName(), message); + } + + public void finest(final String message, Object[] params) { + if (!this.logger.isLoggable(Level.FINEST)) { + return; + } + logger.logp(Level.FINEST, componentClassName, StackHelper.getCallerMethodName(), message, params); + } + + public void finest(final String message, final Throwable thrown) { + if (!this.logger.isLoggable(Level.FINEST)) { + return; + } + logger.logp(Level.FINEST, componentClassName, StackHelper.getCallerMethodName(), message, thrown); + } + + public void finer(final String message) { + if (!this.logger.isLoggable(Level.FINER)) { + return; + } + logger.logp(Level.FINER, componentClassName, StackHelper.getCallerMethodName(), message); + } + + public void finer(final String message, Object[] params) { + if (!this.logger.isLoggable(Level.FINER)) { + return; + } + logger.logp(Level.FINER, componentClassName, StackHelper.getCallerMethodName(), message, params); + } + + public void finer(final String message, final Throwable thrown) { + if (!this.logger.isLoggable(Level.FINER)) { + return; + } + logger.logp(Level.FINER, componentClassName, StackHelper.getCallerMethodName(), message, thrown); + } + + public void fine(final String message) { + if (!this.logger.isLoggable(Level.FINE)) { + return; + } + logger.logp(Level.FINE, componentClassName, StackHelper.getCallerMethodName(), message); + } + + public void fine(final String message, final Throwable thrown) { + if (!this.logger.isLoggable(Level.FINE)) { + return; + } + logger.logp(Level.FINE, componentClassName, StackHelper.getCallerMethodName(), message, thrown); + } + + public void info(final String message) { + if (!this.logger.isLoggable(Level.INFO)) { + return; + } + logger.logp(Level.INFO, componentClassName, StackHelper.getCallerMethodName(), message); + } + + public void info(final String message, Object[] params) { + if (!this.logger.isLoggable(Level.INFO)) { + return; + } + logger.logp(Level.INFO, componentClassName, StackHelper.getCallerMethodName(), message, params); + } + + public void info(final String message, final Throwable thrown) { + if (!this.logger.isLoggable(Level.INFO)) { + return; + } + logger.logp(Level.INFO, componentClassName, StackHelper.getCallerMethodName(), message, thrown); + } + + public void config(final String message) { + if (!this.logger.isLoggable(Level.CONFIG)) { + return; + } + logger.logp(Level.CONFIG, componentClassName, StackHelper.getCallerMethodName(), message); + } + + public void config(final String message, Object[] params) { + if (!this.logger.isLoggable(Level.CONFIG)) { + return; + } + logger.logp(Level.CONFIG, componentClassName, StackHelper.getCallerMethodName(), message, params); + } + + public void config(final String message, final Throwable thrown) { + if (!this.logger.isLoggable(Level.CONFIG)) { + return; + } + logger.logp(Level.CONFIG, componentClassName, StackHelper.getCallerMethodName(), message, thrown); + } + + public void warning(final String message) { + if (!this.logger.isLoggable(Level.WARNING)) { + return; + } + logger.logp(Level.WARNING, componentClassName, StackHelper.getCallerMethodName(), message); + } + + public void warning(final String message, Object[] params) { + if (!this.logger.isLoggable(Level.WARNING)) { + return; + } + logger.logp(Level.WARNING, componentClassName, StackHelper.getCallerMethodName(), message, params); + } + + public void warning(final String message, final Throwable thrown) { + if (!this.logger.isLoggable(Level.WARNING)) { + return; + } + logger.logp(Level.WARNING, componentClassName, StackHelper.getCallerMethodName(), message, thrown); + } + + public void severe(final String message) { + if (!this.logger.isLoggable(Level.SEVERE)) { + return; + } + logger.logp(Level.SEVERE, componentClassName, StackHelper.getCallerMethodName(), message); + } + + public void severe(final String message, Object[] params) { + if (!this.logger.isLoggable(Level.SEVERE)) { + return; + } + logger.logp(Level.SEVERE, componentClassName, StackHelper.getCallerMethodName(), message, params); + } + + public void severe(final String message, final Throwable thrown) { + if (!this.logger.isLoggable(Level.SEVERE)) { + return; + } + logger.logp(Level.SEVERE, componentClassName, StackHelper.getCallerMethodName(), message, thrown); + } + + public boolean isMethodCallLoggable() { + return this.logger.isLoggable(METHOD_CALL_LEVEL_VALUE); + } + + public boolean isLoggable(final Level level) { + return this.logger.isLoggable(level); + } + + public void setLevel(final Level level) { + this.logger.setLevel(level); + } + + public void entering() { + if (!this.logger.isLoggable(METHOD_CALL_LEVEL_VALUE)) { + return; + } + + logger.entering(componentClassName, StackHelper.getCallerMethodName()); + } + + public void entering(final Object... parameters) { + if (!this.logger.isLoggable(METHOD_CALL_LEVEL_VALUE)) { + return; + } + + logger.entering(componentClassName, StackHelper.getCallerMethodName(), parameters); + } + + public void exiting() { + if (!this.logger.isLoggable(METHOD_CALL_LEVEL_VALUE)) { + return; + } + logger.exiting(componentClassName, StackHelper.getCallerMethodName()); + } + + public void exiting(final Object result) { + if (!this.logger.isLoggable(METHOD_CALL_LEVEL_VALUE)) { + return; + } + logger.exiting(componentClassName, StackHelper.getCallerMethodName(), result); + } + + /** + * Method logs {@code exception}'s message as a {@code SEVERE} logging level + * message. + * <p> + * If {@code cause} parameter is not {@code null}, it is logged as well and + * {@code exception} original cause is initialized with instance referenced + * by {@code cause} parameter. + * + * @param <T> type + * @param exception exception whose message should be logged. Must not be + * {@code null}. + * @param cause initial cause of the exception that should be logged as well + * and set as {@code exception}'s original cause. May be {@code null}. + * @return the same exception instance that was passed in as the {@code exception} + * parameter. + */ + public <T extends Throwable> T logSevereException(final T exception, final Throwable cause) { + if (this.logger.isLoggable(Level.SEVERE)) { + if (cause == null) { + logger.logp(Level.SEVERE, componentClassName, StackHelper.getCallerMethodName(), exception.getMessage()); + } else { + exception.initCause(cause); + logger.logp(Level.SEVERE, componentClassName, StackHelper.getCallerMethodName(), exception.getMessage(), cause); + } + } + + return exception; + } + + /** + * Method logs {@code exception}'s message as a {@code SEVERE} logging level + * message. + * <p> + * If {@code logCause} parameter is {@code true}, {@code exception}'s original + * cause is logged as well (if exists). This may be used in cases when + * {@code exception}'s class provides constructor to initialize the original + * cause. In such case you do not need to use + * {@link #logSevereException(Throwable, Throwable)} + * method version but you might still want to log the original cause as well. + * + * @param <T> type + * @param exception exception whose message should be logged. Must not be + * {@code null}. + * @param logCause deterimnes whether initial cause of the exception should + * be logged as well + * @return the same exception instance that was passed in as the {@code exception} + * parameter. + */ + public <T extends Throwable> T logSevereException(final T exception, final boolean logCause) { + if (this.logger.isLoggable(Level.SEVERE)) { + if (logCause && exception.getCause() != null) { + logger.logp(Level.SEVERE, componentClassName, StackHelper.getCallerMethodName(), exception.getMessage(), exception.getCause()); + } else { + logger.logp(Level.SEVERE, componentClassName, StackHelper.getCallerMethodName(), exception.getMessage()); + } + } + + return exception; + } + + /** + * Same as {@link #logSevereException(Throwable, boolean) logSevereException(exception, true)}. + * @param <T> type + * @param exception exception whose message should be logged. Must not be + * {@code null}. + * @return the same exception instance that was passed in as the {@code exception} + * parameter. + */ + public <T extends Throwable> T logSevereException(final T exception) { + if (this.logger.isLoggable(Level.SEVERE)) { + if (exception.getCause() == null) { + logger.logp(Level.SEVERE, componentClassName, StackHelper.getCallerMethodName(), exception.getMessage()); + } else { + logger.logp(Level.SEVERE, componentClassName, StackHelper.getCallerMethodName(), exception.getMessage(), exception.getCause()); + } + } + + return exception; + } + + /** + * Method logs {@code exception}'s message at the logging level specified by the + * {@code level} argument. + * <p> + * If {@code cause} parameter is not {@code null}, it is logged as well and + * {@code exception} original cause is initialized with instance referenced + * by {@code cause} parameter. + * + * @param <T> type + * @param exception exception whose message should be logged. Must not be + * {@code null}. + * @param cause initial cause of the exception that should be logged as well + * and set as {@code exception}'s original cause. May be {@code null}. + * @param level loging level which should be used for logging + * @return the same exception instance that was passed in as the {@code exception} + * parameter. + */ + public <T extends Throwable> T logException(final T exception, final Throwable cause, final Level level) { + if (this.logger.isLoggable(level)) { + if (cause == null) { + logger.logp(level, componentClassName, StackHelper.getCallerMethodName(), exception.getMessage()); + } else { + exception.initCause(cause); + logger.logp(level, componentClassName, StackHelper.getCallerMethodName(), exception.getMessage(), cause); + } + } + + return exception; + } + + /** + * Method logs {@code exception}'s message at the logging level specified by the + * {@code level} argument. + * <p> + * If {@code logCause} parameter is {@code true}, {@code exception}'s original + * cause is logged as well (if exists). This may be used in cases when + * {@code exception}'s class provides constructor to initialize the original + * cause. In such case you do not need to use + * {@link #logException(Throwable, Throwable, Level) logException(exception, cause, level)} + * method version but you might still want to log the original cause as well. + * + * @param <T> type + * @param exception exception whose message should be logged. Must not be + * {@code null}. + * @param logCause deterimnes whether initial cause of the exception should + * be logged as well + * @param level loging level which should be used for logging + * @return the same exception instance that was passed in as the {@code exception} + * parameter. + */ + public <T extends Throwable> T logException(final T exception, final boolean logCause, final Level level) { + if (this.logger.isLoggable(level)) { + if (logCause && exception.getCause() != null) { + logger.logp(level, componentClassName, StackHelper.getCallerMethodName(), exception.getMessage(), exception.getCause()); + } else { + logger.logp(level, componentClassName, StackHelper.getCallerMethodName(), exception.getMessage()); + } + } + + return exception; + } + + /** + * Same as {@link #logException(Throwable, Throwable, Level) + * logException(exception, true, level)}. + * @param <T> type + * @param exception exception whose message should be logged. Must not be + * {@code null}. + * @param level loging level which should be used for logging + * @return the same exception instance that was passed in as the {@code exception} + * parameter. + */ + public <T extends Throwable> T logException(final T exception, final Level level) { + if (this.logger.isLoggable(level)) { + if (exception.getCause() == null) { + logger.logp(level, componentClassName, StackHelper.getCallerMethodName(), exception.getMessage()); + } else { + logger.logp(level, componentClassName, StackHelper.getCallerMethodName(), exception.getMessage(), exception.getCause()); + } + } + + return exception; + } + +}
diff --git a/istack-commons/runtime/src/main/java/com/sun/istack/logging/StackHelper.java b/istack-commons/runtime/src/main/java/com/sun/istack/logging/StackHelper.java new file mode 100644 index 0000000..580bfb9 --- /dev/null +++ b/istack-commons/runtime/src/main/java/com/sun/istack/logging/StackHelper.java
@@ -0,0 +1,36 @@ +/* + * Copyright (c) 2019, 2022 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.logging; + +/** + * Utils for stack trace analysis + * + * @author Daniel Kec + */ +class StackHelper { + + /** + * Function returns the name of the caller method for the method executing this + * function. + * + * @return caller method name from the call stack of the current {@link Thread}. + */ + static String getCallerMethodName() { + return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE) + .walk(frames -> frames + //Its a method of first declaring class after istack Logger class + .dropWhile(f -> !Logger.class.equals(f.getDeclaringClass())) + .dropWhile(f -> Logger.class.equals(f.getDeclaringClass())) + .findFirst() + .map(StackWalker.StackFrame::getMethodName) + .orElse("UNKNOWN METHOD")); + } +}
diff --git a/istack-commons/runtime/src/main/java/com/sun/istack/package-info.java b/istack-commons/runtime/src/main/java/com/sun/istack/package-info.java new file mode 100644 index 0000000..3177984 --- /dev/null +++ b/istack-commons/runtime/src/main/java/com/sun/istack/package-info.java
@@ -0,0 +1,14 @@ +/* + * Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * istack-commons runtime utilities. + */ +package com.sun.istack;
diff --git a/istack-commons/runtime/src/main/java/module-info.java b/istack-commons/runtime/src/main/java/module-info.java new file mode 100644 index 0000000..5eff19d --- /dev/null +++ b/istack-commons/runtime/src/main/java/module-info.java
@@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * istack-commons runtime utilities. + */ +module com.sun.istack.runtime { + requires transitive java.logging; + requires transitive java.xml; + requires static transitive jakarta.activation; + + exports com.sun.istack; + exports com.sun.istack.localization; + exports com.sun.istack.logging; +}
diff --git a/istack-commons/runtime/src/test/java/com/sun/istack/logging/LoggerTest.java b/istack-commons/runtime/src/test/java/com/sun/istack/logging/LoggerTest.java new file mode 100644 index 0000000..15e0085 --- /dev/null +++ b/istack-commons/runtime/src/test/java/com/sun/istack/logging/LoggerTest.java
@@ -0,0 +1,75 @@ +/* + * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.logging; + +import org.junit.Assert; +import org.junit.Test; + +import java.io.ByteArrayOutputStream; +import java.nio.charset.StandardCharsets; +import java.util.logging.Formatter; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.StreamHandler; + +/** + * + * @author Marek Potociar + */ +public class LoggerTest { + + public LoggerTest() { + } + + /** + * Test of getLogger method, of class Logger. + */ + @Test + public void testGetLogger() { + Logger result = Logger.getLogger(LoggerTest.class); + Assert.assertNotNull(result); + } + + /** + * Test of getSystemLoggerName method, of class Logger. + */ + @Test + public void testGetSubsystemName() { + String result = Logger.getSystemLoggerName(LoggerTest.class); + Assert.assertEquals("com.sun.istack.logging", result); + } + + /** + * Test source method name resolution + */ + @Test + public void testGetCallerMethodName() { + Logger istackLogger = Logger.getLogger(LoggerTest.class); + java.util.logging.Logger utilLogger = + java.util.logging.Logger.getLogger(Logger.getSystemLoggerName(LoggerTest.class)); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + StreamHandler streamHandler = new StreamHandler(outputStream, new Formatter() { + @Override + public String format(LogRecord record) { + return record.getSourceMethodName(); + } + }); + utilLogger.addHandler(streamHandler); + + istackLogger.logException(new Exception("This LOG entry is part of the test"), Level.INFO); + + streamHandler.flush(); + + String logText = outputStream.toString(StandardCharsets.UTF_8); + Assert.assertEquals("testGetCallerMethodName", logText); + } + +}
diff --git a/istack-commons/soimp/pom.xml b/istack-commons/soimp/pom.xml new file mode 100644 index 0000000..3c2ca00 --- /dev/null +++ b/istack-commons/soimp/pom.xml
@@ -0,0 +1,36 @@ +<!-- + + Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.sun.istack</groupId> + <artifactId>istack-commons</artifactId> + <version>4.2.0</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>istack-commons-soimp</artifactId> + + <name>istack common utility code soimp</name> + + <dependencies> + <dependency> + <groupId>org.apache.ant</groupId> + <artifactId>ant</artifactId> + </dependency> + <dependency> + <groupId>args4j</groupId> + <artifactId>args4j</artifactId> + </dependency> + </dependencies> + +</project>
diff --git a/istack-commons/soimp/src/main/java/com/sun/istack/soimp/Listener.java b/istack-commons/soimp/src/main/java/com/sun/istack/soimp/Listener.java new file mode 100644 index 0000000..d9e19f3 --- /dev/null +++ b/istack-commons/soimp/src/main/java/com/sun/istack/soimp/Listener.java
@@ -0,0 +1,25 @@ +/* + * 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 Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.soimp; + +/** + * @author Kohsuke Kawaguchi + */ +public interface Listener { + void info(String line); + + Listener CONSOLE = new Listener() { + @Override + public void info(String line) { + System.out.println(line); + } + }; +}
diff --git a/istack-commons/soimp/src/main/java/com/sun/istack/soimp/Mode.java b/istack-commons/soimp/src/main/java/com/sun/istack/soimp/Mode.java new file mode 100644 index 0000000..3c6cd3b --- /dev/null +++ b/istack-commons/soimp/src/main/java/com/sun/istack/soimp/Mode.java
@@ -0,0 +1,30 @@ +/* + * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.soimp; + +/** + * @author Kohsuke Kawaguchi + */ +enum Mode { + NEW, DELETED, UPDATED; + + static Mode parse(char ch) { + switch(ch) { + case 'M': + return UPDATED; + case '!': + return DELETED; + case '?': + return NEW; + } + return null; + } +}
diff --git a/istack-commons/soimp/src/main/java/com/sun/istack/soimp/Proc.java b/istack-commons/soimp/src/main/java/com/sun/istack/soimp/Proc.java new file mode 100644 index 0000000..fa54cd3 --- /dev/null +++ b/istack-commons/soimp/src/main/java/com/sun/istack/soimp/Proc.java
@@ -0,0 +1,109 @@ +/* + * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.soimp; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public final class Proc { + private final Process proc; + private final Thread t1,t2; + + public Proc(String cmd,String[] env,OutputStream out, File workDir) throws IOException { + this( Runtime.getRuntime().exec(new String [] {cmd},env,workDir), null, out ); + } + + public Proc(String[] cmd,String[] env,OutputStream out, File workDir) throws IOException { + this( Runtime.getRuntime().exec(cmd,env,workDir), null, out ); + } + + public Proc(String[] cmd,String[] env,InputStream in,OutputStream out) throws IOException { + this( Runtime.getRuntime().exec(cmd,env), in, out ); + } + + private Proc( Process proc, InputStream in, OutputStream out ) throws IOException { + this.proc = proc; + t1 = new Copier(proc.getInputStream(), out); + t1.start(); + t2 = new Copier(proc.getErrorStream(), out); + t2.start(); + if(in!=null) + new ByteCopier(in,proc.getOutputStream()).start(); + else + proc.getOutputStream().close(); + } + + public int join() { + try { + t1.join(); + t2.join(); + return proc.waitFor(); + } catch (InterruptedException e) { + // aborting. kill the process + proc.destroy(); + return -1; + } + } + + private static class Copier extends Thread { + private final InputStream in; + private final OutputStream out; + + public Copier(InputStream in, OutputStream out) { + this.in = in; + this.out = out; + } + + @Override + public void run() { + try { + copyStream(in,out); + in.close(); + } catch (IOException e) { + // TODO: what to do? + } + } + } + + private static class ByteCopier extends Thread { + private final InputStream in; + private final OutputStream out; + + public ByteCopier(InputStream in, OutputStream out) { + this.in = in; + this.out = out; + } + + @Override + public void run() { + try { + while(true) { + int ch = in.read(); + if(ch==-1) break; + out.write(ch); + } + in.close(); + out.close(); + } catch (IOException e) { + // TODO: what to do? + } + } + } + + public static void copyStream(InputStream in,OutputStream out) throws IOException { + byte[] buf = new byte[256]; + int len; + while((len=in.read(buf))>0) + out.write(buf,0,len); + } +}
diff --git a/istack-commons/soimp/src/main/java/com/sun/istack/soimp/ProcessingException.java b/istack-commons/soimp/src/main/java/com/sun/istack/soimp/ProcessingException.java new file mode 100644 index 0000000..4bee1a6 --- /dev/null +++ b/istack-commons/soimp/src/main/java/com/sun/istack/soimp/ProcessingException.java
@@ -0,0 +1,27 @@ +/* + * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.soimp; + +/** + * @author Kohsuke Kawaguchi + */ +public class ProcessingException extends Exception { + + private static final long serialVersionUID = -6214429602282488762L; + + public ProcessingException(String message) { + super(message); + } + + public ProcessingException(String message, Throwable cause) { + super(message, cause); + } +}
diff --git a/istack-commons/soimp/src/main/java/com/sun/istack/soimp/Soimp.java b/istack-commons/soimp/src/main/java/com/sun/istack/soimp/Soimp.java new file mode 100644 index 0000000..8c08cf1 --- /dev/null +++ b/istack-commons/soimp/src/main/java/com/sun/istack/soimp/Soimp.java
@@ -0,0 +1,354 @@ +/* + * 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 Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.soimp; + +import org.kohsuke.args4j.Argument; +import org.kohsuke.args4j.CmdLineException; +import org.kohsuke.args4j.CmdLineParser; +import org.kohsuke.args4j.Option; +import org.apache.tools.ant.types.FileSet; +import org.apache.tools.ant.taskdefs.Copy; +import org.apache.tools.ant.taskdefs.Delete; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.BuildException; + +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; +import java.net.URL; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Subversion overwriting import tool. + * + * @author Kohsuke Kawaguchi + */ +public class Soimp extends Task { + + public static void main(String[] args) throws IOException, ProcessingException { + System.exit(new Soimp().runCLI(args)); + } + + // either this, or ... + @Argument + List<String> pathArgs = new ArrayList<>(); + // these (for Ant) + private File wsDir; + private String remoteURL; + + @Option(name = "-x", usage="specifies the svn command executable to run") + String svn = "svn"; + + @Option(name="-m", usage="specifies the commit message") + String commitMessage = "imported by soimp"; + + @Option(name="-p", usage="create the repository by 'svn mkdir' if necessary") + boolean create = false; + + @Option(name="-u", usage="specify a username") + String username = null; + + @Option(name="-P", usage="specify a password") + String password = null; + + @Option(name="-o", usage="provide additional options for 'svn' command") + String additionalOptions = null; + + private Listener listener = Listener.CONSOLE; + + public void setSvn(String svn) { + this.svn = svn; + } + + public void setCommitMessage(String commitMessage) { + this.commitMessage = commitMessage; + } + + public void setCreate(boolean create) { + this.create = create; + } + + public void setUsername(String userName) { + this.username = userName; + } + + public void setPassword(String password) { + this.password = password; + } + + public void setDir(File dir) { + wsDir = dir; + } + + public void setRepository(String repository) { + this.remoteURL = repository; + } + + public void setAdditionalOptions(String additionalOptions) { + this.additionalOptions = additionalOptions; + } + + /** + * Command line tool entry point. + * + * @return + * 0 if success. Non-zero if failed. + * @throws IOException for errors + * @throws ProcessingException for errors + */ + public int runCLI(String[] args) throws IOException, ProcessingException { + CmdLineParser p = new CmdLineParser(this); + try { + p.parseArgument(args); + } catch (CmdLineException e) { + System.err.println(e.getMessage()); + printUsage(p); + return -1; + } + + if(pathArgs.size()>2 || pathArgs.isEmpty()) { + printUsage(p); + return -1; + } + + File src = new File(pathArgs.get(0)); + if(!src.exists()) { + System.err.println("No such directory "+src); + return -1; + } + + if(pathArgs.size()==1) { + // just one argument. simply update the state of the existing workspace + svnUpdate(src); + } else { + // two arguments + // checkout -> copy -> import -> commit + svnImport(src,pathArgs.get(1)); + } + + return 0; + } + + /** + * Ant entry point. + */ + @Override + public void execute() throws BuildException { + String svnExe = getProject().getProperty("svn.executable"); + if(svnExe!=null) + svn = svnExe; + + listener = new Listener() { + @Override + public void info(String line) { + log(line,Project.MSG_INFO); + } + }; + if(wsDir==null) + throw new BuildException("Required @dir is missing"); + if(!wsDir.exists()) + throw new BuildException("No such directory "+wsDir); + + try { + if(remoteURL==null) + svnUpdate(wsDir); + else + svnImport(wsDir,remoteURL); + } catch (ProcessingException | IOException e) { + throw new BuildException(e); + } + } + + private void svnImport(File src, String repository) throws IOException, ProcessingException { + File tmp = File.createTempFile("soimp","tmp"); + boolean deleted = tmp.delete(); + if (!deleted) { + Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Cannot delete file: {0}", tmp); + } + boolean created = tmp.mkdir(); + if (!created) { + Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Cannot create directory: {0}", tmp); + } + listener.info("Using "+tmp); + + Project p = new Project(); // dummy ant projcet + + try { + // check if the directory exists + if(create) + createRepository(new URL(repository)); + + // check out to tmp + exec(buildSvnWithUsername("co "+repository+" ."),tmp,"failed to check out"); + + FileSet fs = new FileSet(); + fs.setProject(p); + fs.setDir(src); + + // copy all files from src -> tmp + Copy cpTask = new Copy(); + cpTask.setProject(p); + cpTask.setOverwrite(true); + cpTask.setTodir(tmp); + cpTask.addFileset(fs); + cpTask.execute(); + + // update + svnUpdate(tmp); + + // then commit + exec(buildSvnWithUsername("commit -m \""+commitMessage+"\""),tmp,"Failed to commit"); + } finally{ + // clean up + Delete delTask = new Delete(); + delTask.setProject(p); + delTask.setDir(tmp); + delTask.execute(); + } + } + + /** + * Creates directories in the repository if necessary + */ + private void createRepository(URL repository) throws IOException, ProcessingException { + if(repository.getPath().equals("/")) + throw new ProcessingException("Illegal repository name"); + try { + exec(buildSvnWithUsername("proplist "+repository),new File("."),"N/A"); + } catch (ProcessingException e) { + // directory doesn't exist + URL parent; + if(repository.getPath().endsWith("/")) + parent = new URL(repository, ".."); + else + parent = new URL(repository, "."); + createRepository(parent); + + listener.info(repository+" doesn't exist. creating"); + exec(buildSvnWithUsername("mkdir -m \""+commitMessage+"\" "+repository),new File("."),"Failed to create directory"); + } + } + + private void printUsage(CmdLineParser p) { + System.err.println("Usage: soimp [options ...] <PATH> <URL>"); + System.err.println("Works like 'svn import PATH URL', but overwrites remote files by local files."); + p.printUsage(System.err); + } + + public void svnUpdate( File ws ) throws ProcessingException, IOException { + + String log = exec(buildSvnWithUsername("status"), ws, "Failed to stat the workspace"); + + List<String> newFiles = new ArrayList<>(); + List<String> deletedFiles = new ArrayList<>(); + // % svn status + // ? xyz + // M abc + // ! def + BufferedReader in = new BufferedReader(new StringReader(log)); + String line; + while((line=in.readLine())!=null) { + Mode m = Mode.parse(line.charAt(0)); + String file = line.substring(1).trim(); + if(m==null) continue; + + switch(m) { + case NEW: + newFiles.add(file); + break; + case DELETED: + deletedFiles.add(file); + break; + default: + break; + } + } + + // update accordingly + runSvnBatch("add",ws,newFiles); + runSvnBatch("remove",ws,deletedFiles); + } + + /** + * Run svn command in a batch. + */ + private void runSvnBatch(String subCmd, File ws, List<String> files) throws IOException, ProcessingException { + while(!files.isEmpty()) { + // build up command line + StringBuilder cmd = new StringBuilder(buildSvnCommand(subCmd)); + for( int i=0; i<20 && !files.isEmpty(); i++ ) { + cmd.append(' ').append(files.remove(0)); + } + + exec(cmd.toString(),ws,"Failed to "+subCmd); + } + } + + /** + * Concatenate svn executable name with svn global options (username/password) + * and the svn command. + * + * @param subCmd The svn command + * @return The complete executable command + */ + private String buildSvnWithUsername(final String subCmd) { + final StringBuilder command = new StringBuilder(); + if (username != null) { + command.append("--username ").append(username).append(' '); + } + if (password != null) { + command.append("--password ").append(password).append(' '); + } + command.append(subCmd); + return buildSvnCommand(command.toString()); + } + + /** + * Concatenate svn executable name with the svn command. + * + * @param subCmd The svn command + * @return The complete executable command + */ + private String buildSvnCommand(final String subCmd) { + final StringBuilder command = new StringBuilder(svn + ' '); + addAdditionalOptionsToCommand(command); + command.append(subCmd); + return command.toString(); + } + + private void addAdditionalOptionsToCommand(final StringBuilder command) { + if (additionalOptions != null) { + command.append(additionalOptions); + command.append(' '); + } + } + + /** + * Executes subversion and returns its output. + */ + private String exec(String cmd, File ws, String errorMessage) throws IOException, ProcessingException { + listener.info("Executing: "+cmd); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int r = new Proc(cmd, null, baos, ws).join(); + if(r!=0) { + listener.info(baos.toString()); + throw new ProcessingException(errorMessage); + } + return baos.toString(); + } + +}
diff --git a/istack-commons/src/main/assembly/resources.xml b/istack-commons/src/main/assembly/resources.xml new file mode 100644 index 0000000..ecc103e --- /dev/null +++ b/istack-commons/src/main/assembly/resources.xml
@@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 2022 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 + +--> + +<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd"> + <id>resources</id> + <formats> + <format>zip</format> + </formats> + <includeBaseDirectory>false</includeBaseDirectory> + <fileSets> + <fileSet> + <directory>${project.basedir}/..</directory> + <outputDirectory>legal</outputDirectory> + <includes> + <include>LICENSE.md</include> + <include>NOTICE.md</include> + </includes> + </fileSet> + <fileSet> + <directory>${project.basedir}/src/main/resources</directory> + <outputDirectory>config</outputDirectory> + <includes> + <include>*</include> + </includes> + </fileSet> + </fileSets> +</assembly> \ No newline at end of file
diff --git a/istack-commons/src/main/resources/copyright-exclude b/istack-commons/src/main/resources/copyright-exclude new file mode 100644 index 0000000..d9610f8 --- /dev/null +++ b/istack-commons/src/main/resources/copyright-exclude
@@ -0,0 +1,37 @@ +/MANIFEST.MF +/META-INF/services/ +/README +.gif +.jpg +.jpeg +.jpeg1 +.jpeg2 +.png +.svg +.tif +.exe +.ico +.jar +.zip +.war +.sql +.jks +.json +.class +.bin +.iml +.ipr +.envelope +.txt +.bat +.sh +/copyright-exclude +/LICENSE +/copyright.txt +.commented +/.auth +.svnignore +.svn +www +site +.resource
diff --git a/istack-commons/src/main/resources/spotbugs-exclude.xml b/istack-commons/src/main/resources/spotbugs-exclude.xml new file mode 100644 index 0000000..5885564 --- /dev/null +++ b/istack-commons/src/main/resources/spotbugs-exclude.xml
@@ -0,0 +1,49 @@ +<!-- + + 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 Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<FindBugsFilter> + <!-- + As designed + --> + <Match> + <Or> + <Class name="com.sun.istack.maven.ResourceGenMojo$LicenseCodeWriter"/> + <Class name="com.sun.istack.build.ResourceGenTask$LicenseCodeWriter"/> + </Or> + <Bug pattern="OS_OPEN_STREAM"/> + </Match> + + <!-- + As designed - performance + --> + <Match> + <Class name="com.sun.istack.localization.Localizer"/> + <Bug pattern="ES_COMPARING_STRINGS_WITH_EQ"/> + </Match> + + <!-- + Safer for any code changes + --> + <Match> + <Class name="com.sun.istack.tools.ParallelWorldClassLoader"/> + <Bug pattern="RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE"/> + </Match> + + <!-- + Code generated by maven - ignore + --> + <Match> + <Class name="com.sun.istack.maven.HelpMojo"/> + <Bug pattern="UI_INHERITANCE_UNSAFE_GETRESOURCE"/> + </Match> + +</FindBugsFilter>
diff --git a/istack-commons/test/pom.xml b/istack-commons/test/pom.xml new file mode 100644 index 0000000..0793e0c --- /dev/null +++ b/istack-commons/test/pom.xml
@@ -0,0 +1,77 @@ +<!-- + + Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.sun.istack</groupId> + <artifactId>istack-commons</artifactId> + <version>4.2.0</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>istack-commons-test</artifactId> + + <name>istack common utility code test</name> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <executions> + <execution> + <id>default-compile</id> + <configuration> + <compilerArgs> + <arg>--add-reads</arg> + <arg>com.sun.istack.test=ALL-UNNAMED</arg> + </compilerArgs> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <configuration> + <archive> + <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile> + </archive> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <configuration> + <additionalJOptions> + <additionalJOption>--add-reads</additionalJOption> + <additionalJOption>com.sun.istack.test=ALL-UNNAMED</additionalJOption> + </additionalJOptions> + </configuration> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.apache.ant</groupId> + <artifactId>ant-junit</artifactId> + <optional>true</optional> + </dependency> + </dependencies> + +</project>
diff --git a/istack-commons/test/src/main/java/com/sun/istack/test/AntXmlFormatter.java b/istack-commons/test/src/main/java/com/sun/istack/test/AntXmlFormatter.java new file mode 100644 index 0000000..da9c68c --- /dev/null +++ b/istack-commons/test/src/main/java/com/sun/istack/test/AntXmlFormatter.java
@@ -0,0 +1,164 @@ +/* + * Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.test; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestListener; +import org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter; +import org.apache.tools.ant.taskdefs.optional.junit.JUnitTest; +import org.apache.tools.ant.taskdefs.optional.junit.JUnitVersionHelper; + +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * {@link TestListener} that bridges to {@link JUnitResultFormatter}. + * + * @author Kohsuke Kawaguchi + */ +public class AntXmlFormatter implements TestListener,Closeable { + private JUnitResultFormatter antf; + private JUnitTest antTest; // Ant wants this + private final Class<? extends JUnitResultFormatter> formatter; + private long startTime; + + private final File dir; + + FileOutputStream outStream = null; + + /** + * Stdout, stderr that were replaced. Kept so that we can restore them in {@link #close()}. + */ + private final PrintStream out,err; + + private final ByteArrayOutputStream outBuf = new ByteArrayOutputStream(); + private final ByteArrayOutputStream errBuf = new ByteArrayOutputStream(); + + private int id = 0; + + public AntXmlFormatter(Class<? extends JUnitResultFormatter> formatter, File dir) { + this.formatter = formatter; + this.dir = dir; + + out = System.out; + err = System.err; + System.setOut(new PrintStream(new ForkOutputStream(outBuf,out))); + System.setErr(new PrintStream(new ForkOutputStream(errBuf,err))); + } + + @Override + public void close() { + // restore + System.setOut(out); + System.setErr(err); + } + + public void addError(Test test, Throwable t) { + antf.addError(test,t); + antTest.setCounts(1,0,1); + } + + public void addFailure(Test test, AssertionFailedError t) { + antf.addFailure(test,t); + antTest.setCounts(1,1,0); + } + + public void startTest(Test test) { + assert antf==null; + try { + antf = formatter.getConstructor().newInstance(); + } catch (IllegalAccessException e) { + throw new IllegalAccessError(e.getMessage()); + } catch (ReflectiveOperationException e) { + throw new InstantiationError(e.getMessage()); + } + + String testName = getTestName(test); + + antTest = new JUnitTest(testName); + antTest.setCounts(1,0,0); + try { + outStream = new FileOutputStream(new File(dir,getResultFileName(testName))); + antf.setOutput(outStream); + } catch (FileNotFoundException e) { + throw new Error(e); + } + antf.startTestSuite(antTest); + antf.startTest(test); + outBuf.reset(); + errBuf.reset(); + startTime = System.currentTimeMillis(); + } + + private String getTestName(Test test) { + String testName = JUnitVersionHelper.getTestCaseName(test); + if(testName==null) testName="unknown"; + + // if you extend from junit.framework.TestCase where you have public testXXX methods, + // those test names are just the method name, and doesn't include the package name. + // this doesn't work well with our harness, which uses the fully-qualified name as the + // test names. To bridge this gap, detect the plain TestCase classes and fix up + // the package name. + if(testName.indexOf('.')==-1) + testName = test.getClass().getPackage().getName()+"."+testName; + + return testName; + } + + private String getResultFileName(String testName) { + // try to use a test name. + StringBuilder sb = new StringBuilder(testName); + if(sb.length()>70) + sb.delete(0,sb.length()-70); // remove any portion longer than 70 to avoid file names that are too long + + for(int i=0; i<sb.length(); i++ ) { + char ch = sb.charAt(i); + if(!inRange(ch,'0','9') && !inRange(ch,'a','z') && !inRange(ch,'A','Z') && ch!='.') + sb.setCharAt(i,'_'); + } + sb.append('.'); + sb.append(id++); + sb.append(".xml"); + return sb.toString(); + } + + private static boolean inRange(char ch, char start, char end) { + return start<=ch && ch<=end; + } + + public void endTest(Test test) { + antf.endTest(test); + + antf.setSystemOutput(outBuf.toString()); + antf.setSystemError(errBuf.toString()); + antTest.setRunTime(System.currentTimeMillis()-startTime); + antf.endTestSuite(antTest); + + if (out != null) { + try { + outStream.close(); + } catch (IOException ex) { + Logger.getLogger(AntXmlFormatter.class.getName()).log(Level.SEVERE, null, ex); + } + } + antf = null; + antTest = null; + } + +}
diff --git a/istack-commons/test/src/main/java/com/sun/istack/test/ForkOutputStream.java b/istack-commons/test/src/main/java/com/sun/istack/test/ForkOutputStream.java new file mode 100644 index 0000000..72be74d --- /dev/null +++ b/istack-commons/test/src/main/java/com/sun/istack/test/ForkOutputStream.java
@@ -0,0 +1,58 @@ +/* + * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.test; + +import java.io.OutputStream; +import java.io.IOException; + +/** + * {@link OutputStream} splitter. + * + * @author Kohsuke Kawaguchi + */ +public final class ForkOutputStream extends OutputStream { + final OutputStream out1,out2; + + public ForkOutputStream(OutputStream out1,OutputStream out2) { + this.out1 = out1; + this.out2 = out2; + } + + @Override + public void write(int b) throws IOException { + out1.write(b); + out2.write(b); + } + + @Override + public void close() throws IOException { + out1.close(); + out2.close(); + } + + @Override + public void flush() throws IOException { + out1.flush(); + out2.flush(); + } + + @Override + public void write(byte[] b) throws IOException { + out1.write(b); + out2.write(b); + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + out1.write(b,off,len); + out2.write(b,off,len); + } +}
diff --git a/istack-commons/test/src/main/java/com/sun/istack/test/VersionNumber.java b/istack-commons/test/src/main/java/com/sun/istack/test/VersionNumber.java new file mode 100644 index 0000000..83bc842 --- /dev/null +++ b/istack-commons/test/src/main/java/com/sun/istack/test/VersionNumber.java
@@ -0,0 +1,125 @@ +/* + * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.test; + +import java.util.Locale; +import java.util.StringTokenizer; + +/** + * Immutable representation of a dot-separated digits (such as "1.0.1"). + * + * {@link VersionNumber}s are {@link Comparable}. + * + * <p> + * We allow a component to be not just a number, but also "ea", "ea1", "ea2". + * "ea" is treated as "ea0", and {@code eaN < M for any M > 0}. + * + * <p> + * '*' is also allowed as a component, and {@code '*' > M} for any {@code M > 0}. + * + * <pre> + * {@code 2.0.* > 2.0.1 > 2.0.0 > 2.0.ea > 2.0 } + * </pre> + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public class VersionNumber implements Comparable<VersionNumber> { + + public static final VersionNumber v1_0 = new VersionNumber("1.0"); + public static final VersionNumber v1_0_1 = new VersionNumber("1.0.1"); + public static final VersionNumber v1_0_2 = new VersionNumber("1.0.2"); + public static final VersionNumber v1_0_3 = new VersionNumber("1.0.3"); + public static final VersionNumber v2_0 = new VersionNumber("2.0"); + public static final VersionNumber v2_1 = new VersionNumber("2.1"); + + private final int[] digits; + + /** + * Parses a string like "1.0.2" into the version number. + * + * @param num string to parse + * @throws IllegalArgumentException + * if the parsing fails. + */ + public VersionNumber( String num ) { + StringTokenizer tokens = new StringTokenizer(num,"."); + digits = new int[tokens.countTokens()]; + if(digits.length<2) + throw new IllegalArgumentException(); + + int i=0; + while( tokens.hasMoreTokens() ) { + String token = tokens.nextToken().toLowerCase(Locale.ENGLISH); + if(token.equals("*")) { + digits[i++] = 1000; + } else + if(token.startsWith("ea")) { + if(token.length()==2) + digits[i++] = -1000; // just "ea" + else + digits[i++] = -1000 + Integer.parseInt(token.substring(2)); // "eaNNN" + } else { + digits[i++] = Integer.parseInt(token); + } + } + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder(); + for( int i=0; i<digits.length; i++ ) { + if(i!=0) buf.append('.'); + buf.append( Integer.toString(digits[i]) ); + } + return buf.toString(); + } + + public boolean isOlderThan( VersionNumber rhs ) { + return compareTo(rhs)<0; + } + + public boolean isNewerThan( VersionNumber rhs ) { + return compareTo(rhs)>0; + } + + + @Override + public boolean equals( Object o ) { + if (o instanceof VersionNumber) { + return compareTo((VersionNumber)o)==0; + } + return false; + } + + @Override + public int hashCode() { + int x=0; + for (int i : digits) + x = (x << 1) | i; + return x; + } + + @Override + public int compareTo(VersionNumber rhs) { + for( int i=0; ; i++ ) { + if( i==this.digits.length && i==rhs.digits.length ) + return 0; // equals + if( i==this.digits.length ) + return -1; // rhs is larger + if( i==rhs.digits.length ) + return 1; + + int r = this.digits[i] - rhs.digits[i]; + if(r!=0) return r; + } + } +}
diff --git a/istack-commons/test/src/main/java/com/sun/istack/test/VersionProcessor.java b/istack-commons/test/src/main/java/com/sun/istack/test/VersionProcessor.java new file mode 100644 index 0000000..d08c06d --- /dev/null +++ b/istack-commons/test/src/main/java/com/sun/istack/test/VersionProcessor.java
@@ -0,0 +1,115 @@ +/* + * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.test; + +import java.util.HashSet; +import java.util.Set; +import java.util.StringTokenizer; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * Represents a range of versions. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public final class VersionProcessor { + /** + * This test is only applicable to the RI of this version or later. + * can be null. + */ + private final VersionNumber since; + + /** + * This test is only applicable to the RI of this version or younger. + * can be null. + */ + private final VersionNumber until; + + /** + * This test shall be excluded from the RI of versions listed here. + */ + private final Set<Object> excludeVersions; + + /** + * Special version number constant to represent ALL in + * {@link #excludeVersions}. + */ + private static final Object ALL_VERSION = new Object(); + + /** + * Creates a default {@link VersionProcessor} that accepts + * any version. + */ + private VersionProcessor() { + since = null; + until = null; + excludeVersions = null; + } + + public VersionProcessor( String sinceValue, String untilValue, String excludeFromValue ) { + if( sinceValue!=null && !sinceValue.trim().isEmpty()) + since = new VersionNumber( sinceValue ); + else + since = null; + + if( untilValue!=null && !untilValue.trim().isEmpty()) + until = new VersionNumber( untilValue ); + else + until = null; + + if( excludeFromValue!=null && !excludeFromValue.trim().isEmpty()) { + excludeVersions = new HashSet<>(); + String v = excludeFromValue.trim(); + if(v.equals("all")) { + excludeVersions.add(ALL_VERSION); + } else { + StringTokenizer tokens = new StringTokenizer( v ); + while(tokens.hasMoreTokens()) + excludeVersions.add( new VersionNumber( tokens.nextToken() ) ); + } + } else + excludeVersions = null; + } + + public VersionProcessor( Document testSpecMeta ) { + this(testSpecMeta.getDocumentElement()); + } + + public VersionProcessor( Element e ) { + this(e.getAttribute("since"), e.getAttribute("until"), e.getAttribute("excludeFrom")); + } + + /** + * Checks if the test is valid against the JAXB RI of + * the specified version. + * @param v version to check + * @return true if the test is valid + */ + public boolean isApplicable(VersionNumber v) { + if( excludeVersions!=null ) { + if( excludeVersions.contains(ALL_VERSION) + || excludeVersions.contains(v) ) + return false; + } + + if(since!=null && since.isNewerThan(v)) + return false; + + return until == null || !v.isNewerThan(until); + } + + /** + * Default {@link VersionProcessor} that accepts any version. + */ + public static final VersionProcessor DEFAULT = new VersionProcessor(); +}
diff --git a/istack-commons/test/src/main/java/com/sun/istack/test/Which.java b/istack-commons/test/src/main/java/com/sun/istack/test/Which.java new file mode 100644 index 0000000..0fe1525 --- /dev/null +++ b/istack-commons/test/src/main/java/com/sun/istack/test/Which.java
@@ -0,0 +1,49 @@ +/* + * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.test; + +import java.net.URL; + +/** + * Finds out where a class file is loaded from. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public class Which { + + public static String which( Class<?> clazz ) { + return which( clazz.getName(), clazz.getClassLoader()); + } + + /** + * Search the specified classloader for the given classname. + * + * @param classname the fully qualified name of the class to search for + * @param loader the classloader to search + * @return the source location of the resource, or null if it wasn't found + */ + public static String which(String classname, ClassLoader loader) { + + String classnameAsResource = classname.replace('.', '/') + ".class"; + + if(loader == null) { + loader = ClassLoader.getSystemClassLoader(); + } + + URL it = loader.getResource(classnameAsResource); + if (it != null) { + return it.toString(); + } else { + return null; + } + } +}
diff --git a/istack-commons/test/src/main/java/com/sun/istack/test/package-info.java b/istack-commons/test/src/main/java/com/sun/istack/test/package-info.java new file mode 100644 index 0000000..b43349e --- /dev/null +++ b/istack-commons/test/src/main/java/com/sun/istack/test/package-info.java
@@ -0,0 +1,14 @@ +/* + * Copyright (c) 1997, 2019 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * Common test-related utility code for the istack components. + */ +package com.sun.istack.test;
diff --git a/istack-commons/test/src/main/java/module-info.java b/istack-commons/test/src/main/java/module-info.java new file mode 100644 index 0000000..8874d01 --- /dev/null +++ b/istack-commons/test/src/main/java/module-info.java
@@ -0,0 +1,19 @@ +/* + * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * Common test-related utility code for the istack components. + */ +module com.sun.istack.test { + requires java.logging; + requires transitive java.xml; + + exports com.sun.istack.test; +}
diff --git a/istack-commons/tools/pom.xml b/istack-commons/tools/pom.xml new file mode 100644 index 0000000..4775adb --- /dev/null +++ b/istack-commons/tools/pom.xml
@@ -0,0 +1,104 @@ +<!-- + + Copyright (c) 1997, 2022 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.sun.istack</groupId> + <artifactId>istack-commons</artifactId> + <version>4.2.0</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>istack-commons-tools</artifactId> + + <name>istack common utility code tools</name> + + <dependencies> + <dependency> + <groupId>org.apache.ant</groupId> + <artifactId>ant</artifactId> + <optional>true</optional> + </dependency> + <dependency> + <groupId>org.testng</groupId> + <artifactId>testng</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + <properties> + <argLine/> + </properties> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <executions> + <execution> + <id>default-compile</id> + <goals> + <goal>compile</goal> + </goals> + <configuration> + <compilerArgs> + <arg>--add-reads</arg> + <arg>com.sun.istack.tools=ALL-UNNAMED</arg> + </compilerArgs> + </configuration> + </execution> + <execution> + <id>default-testCompile</id> + <goals> + <goal>testCompile</goal> + </goals> + <configuration> + <compilerArgs> + <arg>--add-reads</arg> + <arg>com.sun.istack.tools=ALL-UNNAMED</arg> + </compilerArgs> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <argLine> + @{argLine} --add-opens java.base/java.net=com.sun.istack.tools + </argLine> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <configuration> + <archive> + <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile> + </archive> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <configuration> + <additionalJOptions> + <additionalJOption>--add-reads</additionalJOption> + <additionalJOption>com.sun.istack.tools=ALL-UNNAMED</additionalJOption> + </additionalJOptions> + </configuration> + </plugin> + </plugins> + </build> +</project>
diff --git a/istack-commons/tools/src/main/java/com/sun/istack/tools/DefaultAuthenticator.java b/istack-commons/tools/src/main/java/com/sun/istack/tools/DefaultAuthenticator.java new file mode 100644 index 0000000..6231b83 --- /dev/null +++ b/istack-commons/tools/src/main/java/com/sun/istack/tools/DefaultAuthenticator.java
@@ -0,0 +1,272 @@ +/* + * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.tools; + +import org.xml.sax.Locator; +import org.xml.sax.helpers.LocatorImpl; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.Authenticator; +import java.net.MalformedURLException; +import java.net.PasswordAuthentication; +import java.net.URL; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Pattern; + +/** + * @author Vivek Pandey + * @author Lukas Jungmann + */ +public class DefaultAuthenticator extends Authenticator { + + private static final Logger LOGGER = Logger.getLogger(DefaultAuthenticator.class.getName()); + private static DefaultAuthenticator instance; + private static Authenticator systemAuthenticator = getCurrentAuthenticator(); + private String proxyUser; + private String proxyPasswd; + private final List<AuthInfo> authInfo = new ArrayList<>(); + private static int counter = 0; + + DefaultAuthenticator() { + //try undocumented but often used properties + if (System.getProperty("http.proxyUser") != null) { + proxyUser = System.getProperty("http.proxyUser"); + } else { + proxyUser = System.getProperty("proxyUser"); + } + if (System.getProperty("http.proxyPassword") != null) { + proxyPasswd = System.getProperty("http.proxyPassword"); + } else { + proxyPasswd = System.getProperty("proxyPassword"); + } + } + + public static synchronized DefaultAuthenticator getAuthenticator() { + if (instance == null) { + instance = new DefaultAuthenticator(); + Authenticator.setDefault(instance); + } + counter++; + return instance; + } + + public static synchronized void reset() { + --counter; + if (instance != null && counter == 0) { + Authenticator.setDefault(systemAuthenticator); + } + } + + @Override + protected PasswordAuthentication getPasswordAuthentication() { + //If user sets proxy user and passwd and the RequestType is from proxy server then create + // PasswordAuthentication using proxyUser and proxyPasswd; + if ((getRequestorType() == RequestorType.PROXY) && proxyUser != null && proxyPasswd != null) { + return new PasswordAuthentication(proxyUser, proxyPasswd.toCharArray()); + } + for (AuthInfo auth : authInfo) { + if (auth.matchingHost(getRequestingURL())) { + return new PasswordAuthentication(auth.getUser(), auth.getPassword().toCharArray()); + } + } + return null; + } + + /** + * Proxy authorization string in form of username:password. + * + * @param proxyAuth Proxy authorization string + */ + public void setProxyAuth(String proxyAuth) { + if (proxyAuth == null) { + this.proxyUser = null; + this.proxyPasswd = null; + } else { + int i = proxyAuth.indexOf(':'); + if (i < 0) { + this.proxyUser = proxyAuth; + this.proxyPasswd = ""; + } else if (i == 0) { + this.proxyUser = ""; + this.proxyPasswd = proxyAuth.substring(1); + } else { + this.proxyUser = proxyAuth.substring(0, i); + this.proxyPasswd = proxyAuth.substring(i + 1); + } + } + } + + public void setAuth(File f, Receiver l) { + Receiver listener = l == null ? new DefaultRImpl() : l; + BufferedReader in = null; + FileInputStream fi = null; + InputStreamReader is = null; + try { + String text; + LocatorImpl locator = new LocatorImpl(); + locator.setSystemId(f.getAbsolutePath()); + try { + fi = new FileInputStream(f); + is = new InputStreamReader(fi, StandardCharsets.UTF_8); + in = new BufferedReader(is); + } catch (FileNotFoundException e) { + listener.onError(e, locator); + return; + } + try { + int lineno = 1; + locator.setSystemId(f.getCanonicalPath()); + while ((text = in.readLine()) != null) { + locator.setLineNumber(lineno++); + //ignore empty lines and treat those starting with '#' as comments + if ("".equals(text.trim()) || text.startsWith("#")) { + continue; + } + try { + AuthInfo ai = parseLine(text); + authInfo.add(ai); + } catch (Exception e) { + listener.onParsingError(text, locator); + } + } + } catch (IOException e) { + listener.onError(e, locator); + LOGGER.log(Level.SEVERE, e.getMessage(), e); + } + } finally { + try { + if (in != null) { + in.close(); + } + if (is != null) { + is.close(); + } + if (fi != null) { + fi.close(); + } + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, null, ex); + } + } + } + + private AuthInfo parseLine(String text) throws Exception { + URL url; + try { + url = new URL(text); + } catch (MalformedURLException mue) { + //possible cause of this can be that password contains + //character which has to be encoded in URL, + //such as '@', ')', '#' and few others + //so try to recreate the URL with encoded string + //between 2nd ':' and last '@' + int i = text.indexOf(':', text.indexOf(':') + 1) + 1; + int j = text.lastIndexOf('@'); + String encodedUrl = + text.substring(0, i) + + URLEncoder.encode(text.substring(i, j), StandardCharsets.UTF_8) + + text.substring(j); + url = new URL(encodedUrl); + } + + String authinfo = url.getUserInfo(); + + if (authinfo != null) { + int i = authinfo.indexOf(':'); + + if (i >= 0) { + String user = authinfo.substring(0, i); + String password = authinfo.substring(i + 1); + return new AuthInfo( + new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getFile()), + user, URLDecoder.decode(password, StandardCharsets.UTF_8)); + } + } + throw new Exception(); + } + + static Authenticator getCurrentAuthenticator() { + return Utils.getCurrentAuthenticator(); + } + + public interface Receiver { + + void onParsingError(String line, Locator loc); + + void onError(Exception e, Locator loc); + } + + private static class DefaultRImpl implements Receiver { + + @Override + public void onParsingError(String line, Locator loc) { + System.err.println(getLocationString(loc) + ": " + line); + } + + @Override + public void onError(Exception e, Locator loc) { + System.err.println(getLocationString(loc) + ": " + e.getMessage()); + LOGGER.log(Level.SEVERE, e.getMessage(), e); + } + + private String getLocationString(Locator l) { + return "[" + l.getSystemId() + "#" + l.getLineNumber() + "]"; + } + } + + /** + * Represents authorization information needed by + * {@link DefaultAuthenticator} to authenticate access to remote resources. + * + * @author Vivek Pandey + * @author Lukas Jungmann + */ + final static class AuthInfo { + + private final String user; + private final String password; + private final Pattern urlPattern; + + public AuthInfo(URL url, String user, String password) { + String u = url.toExternalForm().replaceFirst("\\?", "\\\\?"); + this.urlPattern = Pattern.compile(u.replace("*", ".*"), Pattern.CASE_INSENSITIVE); + this.user = user; + this.password = password; + } + + public String getUser() { + return user; + } + + public String getPassword() { + return password; + } + + /** + * Returns if the requesting host and port are associated with this + * {@link AuthInfo} + */ + public boolean matchingHost(URL requestingURL) { + return urlPattern.matcher(requestingURL.toExternalForm()).matches(); + } + } +}
diff --git a/istack-commons/tools/src/main/java/com/sun/istack/tools/MaskingClassLoader.java b/istack-commons/tools/src/main/java/com/sun/istack/tools/MaskingClassLoader.java new file mode 100644 index 0000000..d78c0cf --- /dev/null +++ b/istack-commons/tools/src/main/java/com/sun/istack/tools/MaskingClassLoader.java
@@ -0,0 +1,54 @@ +/* + * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.tools; + +import java.util.Collection; + +/** + * {@link ClassLoader} that masks a specified set of classes + * from its parent class loader. + * + * <p> + * This code is used to create an isolated environment. + * + * @author Kohsuke Kawaguchi + */ +public class MaskingClassLoader extends ClassLoader { + + private final String[] masks; + + public MaskingClassLoader(String... masks) { + this.masks = masks; + } + + public MaskingClassLoader(Collection<String> masks) { + this(masks.toArray(new String[0])); + } + + public MaskingClassLoader(ClassLoader parent, String... masks) { + super(parent); + this.masks = masks; + } + + public MaskingClassLoader(ClassLoader parent, Collection<String> masks) { + this(parent, masks.toArray(new String[0])); + } + + @Override + protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { + for (String mask : masks) { + if(name.startsWith(mask)) + throw new ClassNotFoundException(); + } + + return super.loadClass(name, resolve); + } +}
diff --git a/istack-commons/tools/src/main/java/com/sun/istack/tools/ParallelWorldClassLoader.java b/istack-commons/tools/src/main/java/com/sun/istack/tools/ParallelWorldClassLoader.java new file mode 100644 index 0000000..aedadc8 --- /dev/null +++ b/istack-commons/tools/src/main/java/com/sun/istack/tools/ParallelWorldClassLoader.java
@@ -0,0 +1,204 @@ +/* + * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.tools; + +import java.io.InputStream; +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.net.JarURLConnection; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.MalformedURLException; +import java.net.URLConnection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Set; +import java.util.jar.JarFile; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Load classes/resources from a side folder, so that + * classes of the same package can live in a single jar file. + * + * <p> + * For example, with the following jar file: + * <pre> + * / + * +- foo + * +- X.class + * +- bar + * +- X.class + * </pre> + * <p> + * {@link ParallelWorldClassLoader}("foo/") would load {@code X.class} from + * {@code /foo/X.class} (note that X is defined in the root package, not + * {@code foo.X}. + * + * <p> + * This can be combined with {@link MaskingClassLoader} to mask classes which are loaded by the parent + * class loader so that the child class loader + * classes living in different folders are loaded + * before the parent class loader loads classes living the jar file publicly + * visible + * For example, with the following jar file: + * <pre> + * / + * +- foo + * +- X.class + * +- bar + * +-foo + * +- X.class + * </pre> + * <p> + * {@link ParallelWorldClassLoader}(MaskingClassLoader.class.getClassLoader()) + * would load {@code foo.X.class} from + * {@code /bar/foo.X.class} not the {@code foo.X.class} + * in the publicly visible place in the jar file, thus + * masking the parent classLoader from loading the class from {@code foo.X.class} + * (note that X is defined in the package foo, not + * {@code bar.foo.X}. + * + * @author Kohsuke Kawaguchi + */ +public class ParallelWorldClassLoader extends ClassLoader implements Closeable { + + /** + * Strings like "prefix/", "abc/", or "" to indicate + * classes should be loaded normally. + */ + private final String prefix; + private final Set<JarFile> jars; + + public ParallelWorldClassLoader(ClassLoader parent,String prefix) { + super(parent); + this.prefix = prefix; + jars = Collections.synchronizedSet(new HashSet<>()); + } + + @Override + protected Class<?> findClass(String name) throws ClassNotFoundException { + + StringBuilder sb = new StringBuilder(name.length()+prefix.length()+6); + sb.append(prefix).append(name.replace('.','/')).append(".class"); + + URL u = getParent().getResource(sb.toString()); + if (u == null) { + throw new ClassNotFoundException(name); + } + + InputStream is = null; + URLConnection con = null; + + try { + con = u.openConnection(); + is = con.getInputStream(); + } catch (IOException ioe) { + throw new ClassNotFoundException(name); + } + + if (is==null) + throw new ClassNotFoundException(name); + + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buf = new byte[1024]; + int len; + while((len=is.read(buf))>=0) + baos.write(buf,0,len); + + buf = baos.toByteArray(); + int packIndex = name.lastIndexOf('.'); + if (packIndex != -1) { + String pkgname = name.substring(0, packIndex); + // Check if package already loaded. + Package pkg = getDefinedPackage(pkgname); + if (pkg == null) { + definePackage(pkgname, null, null, null, null, null, null, null); + } + } + return defineClass(name,buf,0,buf.length); + } catch (IOException e) { + throw new ClassNotFoundException(name,e); + } finally { + try { + if (con instanceof JarURLConnection) { + jars.add(((JarURLConnection) con).getJarFile()); + } + } catch (IOException ioe) { + //ignore + } + try { + is.close(); + } catch (IOException ioe) { + //ignore + } + } + } + + @Override + protected URL findResource(String name) { + URL u = getParent().getResource(prefix + name); + if (u != null) { + try { + jars.add(new JarFile(new File(toJarUrl(u).toURI()))); + } catch (URISyntaxException | IOException ex) { + Logger.getLogger(ParallelWorldClassLoader.class.getName()).log(Level.WARNING, null, ex); + } catch (ClassNotFoundException ex) { + //ignore - not a jar + } + } + return u; + } + + @Override + protected Enumeration<URL> findResources(String name) throws IOException { + Enumeration<URL> en = getParent().getResources(prefix + name); + while (en.hasMoreElements()) { + try { + jars.add(new JarFile(new File(toJarUrl(en.nextElement()).toURI()))); + } catch (URISyntaxException | IOException ex) { + //should not happen + Logger.getLogger(ParallelWorldClassLoader.class.getName()).log(Level.WARNING, null, ex); + } catch (ClassNotFoundException ex) { + //ignore - not a jar + } + } + return en; + } + + @Override + public synchronized void close() throws IOException { + for (JarFile jar : jars) { + jar.close(); + } + } + + /** + * Given the URL inside jar, returns the URL to the jar itself. + * @param res Resource in a jar + * @return URL to the conaining jar file + * @throws java.lang.ClassNotFoundException if res does not denote jar URL + * @throws java.net.MalformedURLException if computed URL is invalid + */ + public static URL toJarUrl(URL res) throws ClassNotFoundException, MalformedURLException { + String url = res.toExternalForm(); + if(!url.startsWith("jar:")) + throw new ClassNotFoundException("Loaded outside a jar "+url); + url = url.substring(4); // cut off jar: + url = url.substring(0,url.lastIndexOf('!')); // cut off everything after '!' + url = url.replaceAll(" ", "%20"); // support white spaces in path + return new URL(url); + } +}
diff --git a/istack-commons/tools/src/main/java/com/sun/istack/tools/ProtectedTask.java b/istack-commons/tools/src/main/java/com/sun/istack/tools/ProtectedTask.java new file mode 100644 index 0000000..147ba37 --- /dev/null +++ b/istack-commons/tools/src/main/java/com/sun/istack/tools/ProtectedTask.java
@@ -0,0 +1,175 @@ +/* + * Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package com.sun.istack.tools; + +import java.io.Closeable; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.DynamicConfigurator; +import org.apache.tools.ant.IntrospectionHelper; +import org.apache.tools.ant.Task; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import org.apache.tools.ant.AntClassLoader; + +/** + * Executes a {@link Task} in a special class loader that allows us to control + * where to load particular APIs. + * + * @author Kohsuke Kawaguchi + * @author Bhakti Mehta + */ +public abstract class ProtectedTask extends Task implements DynamicConfigurator { + + private final AntElement root = new AntElement("root"); + + public ProtectedTask() { + super(); + } + + @Override + public void setDynamicAttribute(String name, String value) throws BuildException { + root.setDynamicAttribute(name, value); + } + + @Override + public Object createDynamicElement(String name) throws BuildException { + return root.createDynamicElement(name); + } + + @Override + public void execute() throws BuildException { + //Leave XJC2 in the publicly visible place + // and then isolate XJC1 in a child class loader, + // then use a MaskingClassLoader + // so that the XJC2 classes in the parent class loader + // won't interfere with loading XJC1 classes in a child class loader + ClassLoader ccl = Thread.currentThread().getContextClassLoader(); + try { + ClassLoader cl = createClassLoader(); + @SuppressWarnings("unchecked") + Class<Task> driver = (Class<Task>) cl.loadClass(getCoreClassName()); + + Task t = driver.getDeclaredConstructor().newInstance(); + t.setProject(getProject()); + t.setTaskName(getTaskName()); + root.configure(t); + + Thread.currentThread().setContextClassLoader(cl); + try { + t.execute(); + } finally { + driver = null; + t.setTaskName(null); + t.setProject(null); + t = null; + } + } catch (UnsupportedClassVersionError e) { + throw new BuildException("Requires Java SE 8 or later. Please download it from https://www.oracle.com/java/technologies/javase-download.html"); + } catch (ReflectiveOperationException | IOException e) { + throw new BuildException(e); + } finally { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(ccl); + + //close/cleanup all classloaders but the one which loaded this class + while (cl != null && !ccl.equals(cl)) { + try { + ((Closeable) cl).close(); + } catch (IOException ex) { + throw new BuildException(ex); + } + cl = getParentClassLoader(cl); + } + cl = null; + } + } + + /** + * Returns the name of the class that extends {@link Task}.This class will + * be loaded int the protected classloader. + * @return Task class name + */ + protected abstract String getCoreClassName(); + + /** + * Creates a protective class loader that will host the actual task. + * @return ClassLoader use d for task execution + * @throws java.lang.ClassNotFoundException if required APIs are not found + * @throws java.io.IOException if error happens + */ + protected abstract ClassLoader createClassLoader() throws ClassNotFoundException, IOException; + + private ClassLoader getParentClassLoader(final ClassLoader cl) { + //Calling getParent() on AntClassLoader doesn't return the - expected - + //actual parent classloader but always the SystemClassLoader. + if (cl instanceof AntClassLoader) { + //1.8 added getConfiguredParent() to get correct 'parent' classloader + ClassLoader loader = ((AntClassLoader) cl).getConfiguredParent(); + // we may be called by Gradle, in such case do not close its classloader, + // so Gradle can handle it itself and return null here; + // in other cases return parent or null if not found + return loader == null ? null + : loader.getClass().getName().startsWith("org.gradle.") ? null : loader; + } + return cl.getParent(); + } + + /** + * Captures the elements and attributes. + */ + private class AntElement implements DynamicConfigurator { + + private final String name; + + private final Map<String,String> attributes = new HashMap<>(); + + private final List<AntElement> elements = new ArrayList<>(); + + public AntElement(String name) { + this.name = name; + } + + @Override + public void setDynamicAttribute(String name, String value) throws BuildException { + attributes.put(name, value); + } + + @Override + public Object createDynamicElement(String name) throws BuildException { + AntElement e = new AntElement(name); + elements.add(e); + return e; + } + + /** + * Copies the properties into the Ant task. + */ + public void configure(Object antObject) { + IntrospectionHelper ih = IntrospectionHelper.getHelper(antObject.getClass()); + + // set attributes first + for (Entry<String, String> att : attributes.entrySet()) { + ih.setAttribute(getProject(), antObject, att.getKey(), att.getValue()); + } + + // then nested elements + for (AntElement e : elements) { + Object child = ih.getElementCreator(getProject(), "", antObject, e.name, null).create(); + e.configure(child); + ih.storeElement(getProject(), antObject, child, e.name); + } + } + } +}
diff --git a/istack-commons/tools/src/main/java/com/sun/istack/tools/Utils.java b/istack-commons/tools/src/main/java/com/sun/istack/tools/Utils.java new file mode 100644 index 0000000..0265c90 --- /dev/null +++ b/istack-commons/tools/src/main/java/com/sun/istack/tools/Utils.java
@@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.tools; + +import java.net.Authenticator; + +final class Utils { + + + private Utils() {} + + static Authenticator getCurrentAuthenticator() { + return Authenticator.getDefault(); + } +}
diff --git a/istack-commons/tools/src/main/java/com/sun/istack/tools/package-info.java b/istack-commons/tools/src/main/java/com/sun/istack/tools/package-info.java new file mode 100644 index 0000000..63fc6e3 --- /dev/null +++ b/istack-commons/tools/src/main/java/com/sun/istack/tools/package-info.java
@@ -0,0 +1,17 @@ +/* + * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * istack-commons tool time utilities. + * + * <p> + * This includes code that relies on APT, javac, etc. + */ +package com.sun.istack.tools;
diff --git a/istack-commons/tools/src/main/java/module-info.java b/istack-commons/tools/src/main/java/module-info.java new file mode 100644 index 0000000..12efacb --- /dev/null +++ b/istack-commons/tools/src/main/java/module-info.java
@@ -0,0 +1,19 @@ +/* + * Copyright (c) 2017, 2019 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * istack-commons tool time utilities. + */ +module com.sun.istack.tools { + requires java.logging; + requires transitive java.xml; + + exports com.sun.istack.tools; +}
diff --git a/istack-commons/tools/src/test/java/com/sun/istack/tools/DefaultAuthenticatorTest.java b/istack-commons/tools/src/test/java/com/sun/istack/tools/DefaultAuthenticatorTest.java new file mode 100644 index 0000000..fb154b2 --- /dev/null +++ b/istack-commons/tools/src/test/java/com/sun/istack/tools/DefaultAuthenticatorTest.java
@@ -0,0 +1,198 @@ +/* + * Copyright (c) 2005, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.tools; + +import java.io.File; +import java.lang.reflect.Field; +import java.net.Authenticator; +import java.net.MalformedURLException; +import java.net.PasswordAuthentication; +import java.net.URL; +import java.util.Arrays; +import java.util.logging.Level; +import java.util.logging.Logger; +import static org.testng.Assert.*; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.Test; + +/** + * @author Rama Pulavarthi + * @author Lukas Jungmann + */ +public class DefaultAuthenticatorTest { + + private static final Logger logger = Logger.getLogger(DefaultAuthenticatorTest.class.getName()); + + public DefaultAuthenticatorTest() { + } + + private static class MyAuthenticator extends DefaultAuthenticator { + + private String requestingURL; + + @Override + protected URL getRequestingURL() { + try { + return new URL(requestingURL); + } catch (MalformedURLException e) { + logger.log(Level.SEVERE, null, e); + } + return null; + } + + void setRequestingURL(String url) { + requestingURL = url; + } + } + + @AfterMethod + public void after() { + clearTestAuthenticator(); + } + + @Test + public void testDefaultAuth() throws Exception { + URL url = getResourceAsUrl("com/sun/istack/tools/.auth"); + MyAuthenticator ma = createTestAuthenticator(); + ma.setRequestingURL("http://foo.com/myservice?wsdl"); + assertNull(DefaultAuthenticator.getCurrentAuthenticator()); + assertEquals(0, getCounter()); + try { + DefaultAuthenticator da = DefaultAuthenticator.getAuthenticator(); + assertEquals(ma, da); + assertEquals(1, getCounter()); + da.setAuth(new File(url.toURI()), null); + PasswordAuthentication pa = da.getPasswordAuthentication(); + assertTrue(pa != null && pa.getUserName().equals("duke") && Arrays.equals(pa.getPassword(), "test".toCharArray())); + } finally { + DefaultAuthenticator.reset(); + assertNotEquals(ma, DefaultAuthenticator.getCurrentAuthenticator()); + assertEquals(0, getCounter()); + } + } + + @Test + public void testGetDefaultAuth() { + Authenticator orig = DefaultAuthenticator.getCurrentAuthenticator(); + try { + DefaultAuthenticator da = DefaultAuthenticator.getAuthenticator(); + assertNotEquals(orig, da); + assertEquals(1, getCounter()); + Authenticator auth = DefaultAuthenticator.getCurrentAuthenticator(); + assertNotNull(auth); + assertEquals(da, auth); + } finally { + DefaultAuthenticator.reset(); + assertEquals(orig, DefaultAuthenticator.getCurrentAuthenticator()); + assertEquals(0, getCounter()); + } + } + + @Test + public void testJaxWs_1101() throws Exception { + URL url = getResourceAsUrl("com/sun/istack/tools/auth_test.resource"); + MyAuthenticator ma = createTestAuthenticator(); + + try { + DefaultAuthenticator da = DefaultAuthenticator.getAuthenticator(); + assertEquals(1, getCounter()); + assertEquals(ma, da); + da.setAuth(new File(url.toURI()), null); + + ma.setRequestingURL("http://server1.myserver.com/MyService/Service.svc?wsdl"); + PasswordAuthentication pa = da.getPasswordAuthentication(); + assertEquals("user", pa.getUserName()); + assertEquals(")/_@B8M)gDw", new String(pa.getPassword())); + + ma.setRequestingURL("http://server1.myserver.com/MyService/Service.svc?xsd=xsd0"); + pa = da.getPasswordAuthentication(); + assertEquals("user", pa.getUserName()); + assertEquals(")/_@B8M)gDw", new String(pa.getPassword())); + + ma.setRequestingURL("http://server1.myserver.com/MyService/Service.svc"); + pa = da.getPasswordAuthentication(); + assertEquals("user", pa.getUserName()); + assertEquals(")/_@B8M)gDw", new String(pa.getPassword())); + + ma.setRequestingURL("http://server1.myserver.com/encoded/MyService/Service.svc?wsdl"); + pa = da.getPasswordAuthentication(); + assertEquals("user2", pa.getUserName()); + assertEquals(")/_@B8M)gDw", new String(pa.getPassword())); + } finally { + DefaultAuthenticator.reset(); + assertEquals(0, getCounter()); + } + } + + private static URL getResourceAsUrl(String resourceName) throws RuntimeException { + URL input = Thread.currentThread().getContextClassLoader().getResource(resourceName); + if (input == null) { + throw new RuntimeException("Failed to find resource \"" + resourceName + "\""); + } + return input; + } + + private MyAuthenticator createTestAuthenticator() { + Field f1 = null; + try { + f1 = DefaultAuthenticator.class.getDeclaredField("instance"); + f1.setAccessible(true); + MyAuthenticator auth = new MyAuthenticator(); + f1.set(null, auth); + return auth; + } catch (Exception ex) { + logger.log(Level.SEVERE, null, ex); + } finally { + if (f1 != null) { + f1.setAccessible(false); + } + } + return null; + } + + private void clearTestAuthenticator() { + Field f1, f2 = f1 = null; + try { + f1 = DefaultAuthenticator.class.getDeclaredField("instance"); + f1.setAccessible(true); + MyAuthenticator auth = new MyAuthenticator(); + f1.set(null, null); + f2 = DefaultAuthenticator.class.getDeclaredField("counter"); + f2.setAccessible(true); + f2.setInt(null, 0); + } catch (Exception ex) { + logger.log(Level.SEVERE, null, ex); + } finally { + if (f1 != null) { + f1.setAccessible(false); + } + if (f2 != null) { + f2.setAccessible(false); + } + } + } + + private int getCounter() { + Field f = null; + try { + f = DefaultAuthenticator.class.getDeclaredField("counter"); + f.setAccessible(true); + return f.getInt(null); + } catch (Exception ex) { + logger.log(Level.SEVERE, null, ex); + } finally { + if (f != null) { + f.setAccessible(false); + } + } + return -1; + } +}
diff --git a/istack-commons/tools/src/test/java/com/sun/istack/tools/ParallelWorldClassLoaderTest.java b/istack-commons/tools/src/test/java/com/sun/istack/tools/ParallelWorldClassLoaderTest.java new file mode 100644 index 0000000..f510849 --- /dev/null +++ b/istack-commons/tools/src/test/java/com/sun/istack/tools/ParallelWorldClassLoaderTest.java
@@ -0,0 +1,120 @@ +/* + * 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 Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.istack.tools; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import javax.xml.stream.XMLInputFactory; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** + * + * @author lukas + */ +public class ParallelWorldClassLoaderTest { + + private ClassLoader cl; + private MaskingClassLoader mcl; + private URLClassLoader ucl; + private ParallelWorldClassLoader pwcl; + private ClassLoader orig; + + public ParallelWorldClassLoaderTest() { + } + + @BeforeMethod + public void setUpMethod() throws Exception { + cl = ClassLoader.getSystemClassLoader(); + mcl = new MaskingClassLoader(cl, "javax.xml.ws"); + String dir = System.getProperty("surefire.test.class.path").split(File.pathSeparator)[0]; + ucl = new URLClassLoader(new URL[] {new File(dir).toURI().toURL()}, mcl); + pwcl = new ParallelWorldClassLoader(ucl, ""); + orig = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(pwcl); + } + + @AfterMethod(alwaysRun = true) + public void tearDownMethod() { + Thread.currentThread().setContextClassLoader(orig); + } + + /** + * Test of findClass method, of class ParallelWorldClassLoader. + */ + @Test + public void testFindClass() { + System.out.println("findClass"); + //XXX: why this fails ? +// Class c3 = pwcl.findClass("javax.xml.ws.Service"); +// Assert.assertEquals(c3.getDeclaredMethods().length, 1); + + Class<?> c1,c2; + try { + c1 = Class.forName("javax.xml.ws.Service", false, pwcl); + // jacoco adds method '$jacocoInit' so there can be at most two + Assert.assertTrue(c1.getDeclaredMethods().length < 3); + } catch (ClassNotFoundException cnfe) { + Assert.fail(); + } + try { + c2 = Class.forName("javax.xml.ws.Service", false, Thread.currentThread().getContextClassLoader()); + // jacoco adds method '$jacocoInit' so there can be at most two + Assert.assertTrue(c2.getDeclaredMethods().length < 3); + } catch (ClassNotFoundException cnfe) { + Assert.fail(); + } + } + + /** + * Test of findResource method, of class ParallelWorldClassLoader. + */ + @Test + public void testFindResource() { + if (isJDK9()) return; + URL resource = pwcl.getResource("javax/xml/ws/Service.class"); + URL object = pwcl.getResource("java/lang/Object.class"); + String resJar = resource.getPath().substring(0, resource.getPath().indexOf("!")); + String rtJar = object.getPath().substring(0, object.getPath().indexOf("!")); + Assert.assertEquals(resJar, rtJar); + } + + /** + * Test of findResources method, of class ParallelWorldClassLoader. + */ + @Test + public void testFindResources() throws Exception { + if (isJDK9()) return; + Enumeration<URL> foundURLs = pwcl.getResources("javax/xml/ws/Service.class"); + // TODO - this depends on jdk, maven cp, e.g. + ArrayList<URL> al = Collections.list(foundURLs); + int found = al.size(); + if (!((found == 3) || (found == 4))) { + Assert.fail("Expected 3/4 elements. Verify the urls: \n" + al); + } + } + + @Test + public void testJaxp() { + XMLInputFactory inFactory = XMLInputFactory.newInstance(); + Assert.assertEquals(inFactory.getClass().getClassLoader(), ucl); + } + + private static boolean isJDK9() { + return true; + } +}
diff --git a/istack-commons/tools/src/test/java/javax/xml/ws/Service.java b/istack-commons/tools/src/test/java/javax/xml/ws/Service.java new file mode 100644 index 0000000..32bb45d --- /dev/null +++ b/istack-commons/tools/src/test/java/javax/xml/ws/Service.java
@@ -0,0 +1,20 @@ +/* + * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package javax.xml.ws; + +/** + * + * @author lukas + */ +public final class Service { + + public void test() {} +}
diff --git a/istack-commons/tools/src/test/java/javax/xml/ws/XMLFactory.java b/istack-commons/tools/src/test/java/javax/xml/ws/XMLFactory.java new file mode 100644 index 0000000..e88ee85 --- /dev/null +++ b/istack-commons/tools/src/test/java/javax/xml/ws/XMLFactory.java
@@ -0,0 +1,151 @@ +/* + * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package javax.xml.ws; + +import java.io.InputStream; +import java.io.Reader; +import javax.xml.stream.EventFilter; +import javax.xml.stream.StreamFilter; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLReporter; +import javax.xml.stream.XMLResolver; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.util.XMLEventAllocator; +import javax.xml.transform.Source; + +/** + * + * @author lukas + */ +public class XMLFactory extends XMLInputFactory { + + public void test() { + } + + @Override + public XMLStreamReader createXMLStreamReader(Reader reader) throws XMLStreamException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public XMLStreamReader createXMLStreamReader(Source source) throws XMLStreamException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public XMLStreamReader createXMLStreamReader(InputStream stream) throws XMLStreamException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public XMLStreamReader createXMLStreamReader(InputStream stream, String encoding) throws XMLStreamException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public XMLStreamReader createXMLStreamReader(String systemId, InputStream stream) throws XMLStreamException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public XMLStreamReader createXMLStreamReader(String systemId, Reader reader) throws XMLStreamException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public XMLEventReader createXMLEventReader(Reader reader) throws XMLStreamException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public XMLEventReader createXMLEventReader(String systemId, Reader reader) throws XMLStreamException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public XMLEventReader createXMLEventReader(XMLStreamReader reader) throws XMLStreamException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public XMLEventReader createXMLEventReader(Source source) throws XMLStreamException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public XMLEventReader createXMLEventReader(InputStream stream) throws XMLStreamException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public XMLEventReader createXMLEventReader(InputStream stream, String encoding) throws XMLStreamException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public XMLEventReader createXMLEventReader(String systemId, InputStream stream) throws XMLStreamException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public XMLStreamReader createFilteredReader(XMLStreamReader reader, StreamFilter filter) throws XMLStreamException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public XMLEventReader createFilteredReader(XMLEventReader reader, EventFilter filter) throws XMLStreamException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public XMLResolver getXMLResolver() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setXMLResolver(XMLResolver resolver) { + } + + @Override + public XMLReporter getXMLReporter() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setXMLReporter(XMLReporter reporter) { + } + + @Override + public void setProperty(String name, Object value) throws IllegalArgumentException { + } + + @Override + public Object getProperty(String name) throws IllegalArgumentException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean isPropertySupported(String name) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setEventAllocator(XMLEventAllocator allocator) { + } + + @Override + public XMLEventAllocator getEventAllocator() { + throw new UnsupportedOperationException("Not supported yet."); + } + +}
diff --git a/istack-commons/tools/src/test/resources/META-INF/services/javax.xml.stream.XMLInputFactory b/istack-commons/tools/src/test/resources/META-INF/services/javax.xml.stream.XMLInputFactory new file mode 100644 index 0000000..f9a88b9 --- /dev/null +++ b/istack-commons/tools/src/test/resources/META-INF/services/javax.xml.stream.XMLInputFactory
@@ -0,0 +1 @@ +javax.xml.ws.XMLFactory \ No newline at end of file
diff --git a/istack-commons/tools/src/test/resources/com/sun/istack/tools/.auth b/istack-commons/tools/src/test/resources/com/sun/istack/tools/.auth new file mode 100644 index 0000000..88b04e6 --- /dev/null +++ b/istack-commons/tools/src/test/resources/com/sun/istack/tools/.auth
@@ -0,0 +1 @@ +http://duke:test@foo.com/myservice?wsdl \ No newline at end of file
diff --git a/istack-commons/tools/src/test/resources/com/sun/istack/tools/auth_test.resource b/istack-commons/tools/src/test/resources/com/sun/istack/tools/auth_test.resource new file mode 100644 index 0000000..2282fc2 --- /dev/null +++ b/istack-commons/tools/src/test/resources/com/sun/istack/tools/auth_test.resource
@@ -0,0 +1,5 @@ +#plain password: +http://user:)/_@B8M)gDw@server1.myserver.com/MyService/Service.svc* + +#encoded password: +http://user2:%29%2F_%40B8M%29gDw@server1.myserver.com/encoded/MyService/Service.svc?WSDL