pax_global_header00006660000000000000000000000064147201115200014503gustar00rootroot0000000000000052 comment=5c2199fbe322a317044758e9c5c04155932c5457 jboss-modules-2.1.6.Final/000077500000000000000000000000001472011152000153275ustar00rootroot00000000000000jboss-modules-2.1.6.Final/.github/000077500000000000000000000000001472011152000166675ustar00rootroot00000000000000jboss-modules-2.1.6.Final/.github/dependabot.yml000066400000000000000000000010611472011152000215150ustar00rootroot00000000000000# To get started with Dependabot version updates, you'll need to specify which # package ecosystems to update and where the package manifests are located. # Please see the documentation for all configuration options: # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates version: 2 updates: - package-ecosystem: "maven" directory: "/" schedule: interval: "daily" open-pull-requests-limit: 10 - package-ecosystem: "github-actions" directory: "/" schedule: interval: "daily" jboss-modules-2.1.6.Final/.github/workflows/000077500000000000000000000000001472011152000207245ustar00rootroot00000000000000jboss-modules-2.1.6.Final/.github/workflows/ci.yml000066400000000000000000000035331472011152000220460ustar00rootroot00000000000000# This workflow will build a Java project with Maven # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven name: JBoss Modules CI on: pull_request: types: [opened, synchronize, reopened, ready_for_review] jobs: build-test-matrix: name: ${{ matrix.jdk-distribution }}-${{ matrix.os }} runs-on: ${{ matrix.os }} timeout-minutes: 10 strategy: fail-fast: false matrix: os: [ubuntu-latest, windows-latest] jdk-distribution: [temurin, adopt-openj9] steps: - name: Configure runner - Linux if: contains(matrix.os, 'ubuntu') run: | sudo bash -c "echo '127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4' > /etc/hosts" sudo bash -c "echo '::1 localhost localhost.localdomain localhost6 localhost6.localdomain6' >> /etc/hosts" - name: Configure Runner - Windows if: contains(matrix.os, 'windows') run: | echo '127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4' > %SystemRoot%\System32\drivers\etc\hosts echo '::1 localhost localhost.localdomain localhost6 localhost6.localdomain6' >> %SystemRoot%\System32\drivers\etc\hosts shell: cmd - uses: actions/checkout@v4 - name: Set up JDK ${{ matrix.jdk-distribution }} uses: actions/setup-java@v4 with: distribution: ${{ matrix.jdk-distribution }} java-version: | 11 17 21 - name: Run Tests run: mvn -ntp -U -B -fae clean install "-Djava11.home=${{env.JAVA_HOME_11_X64}}" "-Djava17.home=${{env.JAVA_HOME_17_X64}}" - uses: actions/upload-artifact@v4 if: failure() with: name: surefire-${{ matrix.jdk-distribution }}-${{ matrix.os }} path: '**/surefire-reports/*.txt' jboss-modules-2.1.6.Final/.gitignore000066400000000000000000000002331472011152000173150ustar00rootroot00000000000000# Ignore all dot files .* !.gitignore !.github # Ignore Maven metadata files target pom.xml.versionsBackup # Ignore IDEA files *.iml *.ipr *.iws /.idea jboss-modules-2.1.6.Final/CODEOWNERS000066400000000000000000000000221472011152000167140ustar00rootroot00000000000000@ropalka @dmlloyd jboss-modules-2.1.6.Final/CODE_OF_CONDUCT.md000066400000000000000000000040711472011152000201300ustar00rootroot00000000000000## JBoss Modules Community Code of Conduct v1.0 ### Contributor Code of Conduct As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery * Personal attacks * Trolling or insulting/derogatory comments * Public or private harassment * Publishing other's private information, such as physical or electronic addresses, without explicit permission * Other unethical or unprofessional conduct. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a JBoss Modules project lead, David Lloyd . This Code of Conduct is adapted from the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md) which is adapted from the Contributor Covenant (http://contributor-covenant.org), version 1.2.0, available at http://contributor-covenant.org/version/1/2/0/ jboss-modules-2.1.6.Final/CONTRIBUTING.md000066400000000000000000000115251472011152000175640ustar00rootroot00000000000000First off, thank you for considering contributing to JBoss Modules project. It's people like you that make JBoss Modules such a great library. JBoss Modules is an open source project and contributions from our community are more than welcome! There are many ways to contribute, from writing tutorials or blog posts, improving the documentation, submitting bug reports and feature requests or writing code which can be incorporated into JBoss Modules itself. We expect all contributors and users to follow our [Code of Conduct](CODE_OF_CONDUCT.md) when communicating through project channels. These include, but are not limited to: chat, issues, code. All recent development happens in the branch `main`. There are additional [branches](https://github.com/jboss-modules/jboss-modules/branches) mainly used for maintenance. # One time setup ## Create a GitHub account If you don't have one already, head to https://github.com/ ## Fork JBoss Modules Fork https://github.com/jboss-modules/jboss-modules into your GitHub account. ## Clone your newly forked repository onto your local machine ```bash git clone git@github.com:[your username]/jboss-modules.git cd jboss-modules ``` ## Add a remote reference to upstream This makes it easy to pull down changes in the project over time ```bash git remote add upstream git://github.com/jboss-modules/jboss-modules.git ``` # Development Process This is the typical process you would follow to submit any changes to JBoss Modules. ## Pulling updates from upstream ```bash git pull --rebase upstream main ``` > Note that --rebase will automatically move your local commits, if you have > any, on top of the latest branch you pull from. > If you don't have any commits it is safe to leave off, but for safety it > doesn't hurt to use it each time just in case you have a commit you've > forgotten about! ## Discuss your planned changes (if you want feedback) * JBoss Modules Issue Tracker - https://issues.redhat.com/browse/MODULES * Zulip - https://wildfly.zulipchat.com/#narrow/stream/210170-jboss-modules ## Create a simple topic branch to isolate your work (recommended) ```bash git checkout -b my_cool_feature ``` ## Make the changes Make whatever code changes, including new tests to verify your change, are necessary and ensure that the build and tests pass. ```bash mvn clean install ``` > If you're making non code changes, the above step is not required. ## Commit changes Add whichever files were changed into 'staging' before performing a commit: ```bash git commit ``` ## Rebase changes against main Once all your commits for the issue have been made against your local topic branch, we need to rebase it against branch main in upstream to ensure that your commits are added on top of the current state of main. This will make it easier to incorporate your changes into the main branch, especially if there has been any significant time passed since you rebased at the beginning. ```bash git pull --rebase upstream main ``` ## Push to your repo Now that you've synced your topic branch with upstream, it's time to push it to your GitHub repo. ```bash git push origin my_cool_feature ``` ## Getting your changes merged into upstream, a pull request Now your updates are in your GitHub repo, you will need to notify the project that you have code/docs for inclusion. * Send a pull request, by clicking the pull request link while in your repository fork * After review a maintainer will merge your pull request, update/resolve associated issues, and reply when complete * Lastly, switch back to branch main from your topic branch and pull the updates ```bash git checkout main git pull upstream main ``` * You may also choose to update your origin on GitHub as well ```bash git push origin ``` ## Some tips Here are some tips on increasing the chance that your pull request is accepted: * Write a [good commit message](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) * Include tests that fail without your code, and pass with it # Issues JBoss Modules uses JIRA to manage issues. All issues can be found [here](https://issues.redhat.com/projects/MODULES/issues). To create a new issue, comment on an existing issue, or assign an issue to yourself, you'll need to first [create a JIRA account](https://issues.redhat.com/). ## Good First Issues Want to contribute to JBoss Modules but aren't quite sure where to start? Check out our issues with the `good-first-issue` label. These are a triaged set of issues that are great for getting started on our project. These can be found [here](https://issues.redhat.com/browse/MODULES-1?jql=project%20%3D%20MODULES%20AND%20labels%20%3D%20good-first-issue). Once you have selected an issue you'd like to work on, make sure it's not already assigned to someone else. To assign an issue to yourself, simply click on "Start Progress". This will automatically assign the issue to you. jboss-modules-2.1.6.Final/LICENSE.txt000066400000000000000000000261361472011152000171620ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. jboss-modules-2.1.6.Final/README.md000066400000000000000000000035761472011152000166210ustar00rootroot00000000000000This is the JBoss Modules project. JBoss Modules is a standalone implementation of a modular (non-hierarchical) class loading and execution environment for Java. In other words, rather than a single class loader which loads all JARs into a flat class path, each library becomes a module which only links against the exact modules it depends on, and nothing more. It implements a thread-safe, fast, and highly concurrent delegating class loader model, coupled to an extensible module resolution system, which combine to form a unique, simple and powerful system for application execution and distribution. JBoss Modules is designed to work with any existing library or application without changes, and its simple naming and resolution strategy is what makes that possible. Unlike OSGi, JBoss Modules does not implement a container; rather, it is a thin bootstrap wrapper for executing an application in a modular environment. The moment your application takes control, the modular environment is ready to load and link modules as needed. Furthermore, modules are never loaded (not even for resolution purposes) until required by a dependency, meaning that the performance of a modular application depends only on the number of modules actually used (and when they are used), rather than the total number of modules in the system. And, they may be unloaded by the user at any time. ## Building Prerequisites: * JDK 11 or newer - check `java -version` * Maven 3.6.0 or newer - check `mvn -v` To build with your own Maven installation: mvn install ## Documentation All documentation lives at http://jboss-modules.github.io/jboss-modules/manual/ ## Issue tracker All issues can be reported at https://issues.jboss.org/browse/MODULES ## Code All code can be found at https://github.com/jboss-modules/jboss-modules ## License All code distributed under [ASL 2.0](LICENSE.txt) and [XPP3](XPP3-LICENSE.txt). jboss-modules-2.1.6.Final/SECURITY.md000066400000000000000000000011311472011152000171140ustar00rootroot00000000000000# Security Policy ## Security Contacts and Procedures JBoss Modules community takes security very seriously, and we aim to take immediate action to address serious security-related problems that involve our products or services. Please report any suspected security vulnerability in this project to Red Hat Product Security at secalert@redhat.com. You can use our GPG key to communicate with us securely. To report an issue in any Red Hat branded website or online service, please contact Red Hat Information Security at site-security@redhat.com. https://access.redhat.com/security/team/contact jboss-modules-2.1.6.Final/XPP3-LICENSE.txt000066400000000000000000000042171472011152000177060ustar00rootroot00000000000000Indiana University Extreme! Lab Software License Version 1.1.1 Copyright (c) 2002 Extreme! Lab, Indiana University. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by the Indiana University Extreme! Lab (http://www.extreme.indiana.edu/)." Alternately, this acknowledgment may appear in the software itself, if and wherever such third-party acknowledgments normally appear. 4. The names "Indiana Univeristy" and "Indiana Univeristy Extreme! Lab" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact http://www.extreme.indiana.edu/. 5. Products derived from this software may not use "Indiana Univeristy" name nor may "Indiana Univeristy" appear in their name, without prior written permission of the Indiana University. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED 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 AUTHORS, COPYRIGHT HOLDERS OR ITS 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. jboss-modules-2.1.6.Final/build-release-11000066400000000000000000000000001472011152000201740ustar00rootroot00000000000000jboss-modules-2.1.6.Final/build-test-java11000066400000000000000000000000001472011152000203750ustar00rootroot00000000000000jboss-modules-2.1.6.Final/build-test-java17000066400000000000000000000000001472011152000204030ustar00rootroot00000000000000jboss-modules-2.1.6.Final/build-test-java21000066400000000000000000000000001472011152000203760ustar00rootroot00000000000000jboss-modules-2.1.6.Final/pom.xml000066400000000000000000000225041472011152000166470ustar00rootroot00000000000000 4.0.0 org.jboss.modules jboss-modules 2.1.6.Final JBoss Modules org.jboss jboss-parent 47 Apache License 2.0 http://repository.jboss.org/licenses/apache-2.0.txt repo Indiana University Extreme! Lab Software License 1.1.1 http://www.bearcave.com/software/java/xml/xmlpull_license.html repo 3.4.1 4.13.2 0.8.12 1.2.6 1.0.8.Final 1.6.Final 3.0.0-M7 11 src/main/java true **/*.properties src/main/resources false target/generated-resources false org.apache.maven.plugins maven-checkstyle-plugin ${version.checkstyle.plugin} wildfly-checkstyle/checkstyle.xml true true true **/MXParser.java org.wildfly.checkstyle wildfly-checkstyle-config ${version.org.wildfly.checkstyle-config} check-style compile checkstyle org.apache.maven.plugins maven-compiler-plugin default-compile compile compile 11 org.apache.maven.plugins maven-surefire-plugin true false **/*Test.java false @{argLine} --add-exports=org.jboss.modules/org.jboss.modules.util=ALL-UNNAMED org.apache.maven.plugins maven-jar-plugin org.jboss.modules.Main true ${project.version} ${project.artifactId} org.jboss.modules.ModularAgent org.jboss.modules.ModularAgent true true org.apache.maven.plugins maven-javadoc-plugin false org.jboss.modules._private org.jboss.bridger bridger ${version.org.jboss.bridger} weave process-classes transform org.jacoco jacoco-maven-plugin ${version.org.jacoco} prepare-agent generate-code-coverage-report test report org.jboss.shrinkwrap shrinkwrap-impl-base ${version.org.jboss.shrinkwrap} test junit junit ${version.junit} test jboss-modules-2.1.6.Final/src/000077500000000000000000000000001472011152000161165ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/main/000077500000000000000000000000001472011152000170425ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/main/java/000077500000000000000000000000001472011152000177635ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/main/java/module-info.java000066400000000000000000000026671472011152000230570ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2022 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ module org.jboss.modules { // for consumers of this module requires java.se; requires jdk.unsupported; exports org.jboss.modules; exports org.jboss.modules.filter; exports org.jboss.modules.log; exports org.jboss.modules.management; exports org.jboss.modules.maven; exports org.jboss.modules.ref; exports org.jboss.modules.security; exports org.jboss.modules.xml; uses java.net.URLStreamHandlerFactory; uses java.net.spi.URLStreamHandlerProvider; uses java.util.logging.LogManager; uses java.util.prefs.PreferencesFactory; uses javax.management.MBeanServerBuilder; uses java.lang.SecurityManager; uses java.security.Provider; uses java.security.Policy; uses org.jboss.modules.PreMain; uses System.LoggerFinder; } jboss-modules-2.1.6.Final/src/main/java/org/000077500000000000000000000000001472011152000205525ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/main/java/org/jboss/000077500000000000000000000000001472011152000216725ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/000077500000000000000000000000001472011152000233425ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/AbstractLocalLoader.java000066400000000000000000000041201472011152000300470ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.util.List; /** * An abstract local loader implementation. * * @author David M. Lloyd */ public abstract class AbstractLocalLoader implements LocalLoader { /** * Load a class which is locally defined by this loader. Returns {@code null} by default. * * @param name the class name * @param resolve {@code true} to resolve the class * * @return the class, or {@code null} if there is no local class with this name */ public Class loadClassLocal(final String name, final boolean resolve) { return null; } /** * Load a package which is locally defined by this loader. Returns {@code null} by default. * * @param name the package name * * @return the package, or {@code null} if there is no local package with this name */ public Package loadPackageLocal(final String name) { return null; } /** * Load a resource which is locally defined by this loader. The given name is a path separated by "{@code /}" * characters. Returns {@code null} by default. * * @param name the resource path * * @return the resource or resources, or an empty list if there is no local resource with this name */ public List loadResourceLocal(final String name) { return null; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/AbstractResourceLoader.java000066400000000000000000000072411472011152000306130ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.IOException; import java.net.URL; import java.util.Collection; import java.util.Collections; import java.util.jar.Attributes; import java.util.jar.Manifest; /** * An abstract resource loader implementation. * * @author Carlo de Wolf * @author Richard Opalka */ public abstract class AbstractResourceLoader implements ResourceLoader { /** * Construct a new instance. */ protected AbstractResourceLoader() { } private static String getDefinedAttribute(Attributes.Name name, Attributes entryAttribute, Attributes mainAttribute) { final String value = entryAttribute == null ? null : entryAttribute.getValue(name); return value == null ? mainAttribute == null ? null : mainAttribute.getValue(name) : value; } /** * Convenience method to get a package specification from a {@code Manifest}. * * @param name the (dot-separated) package name * @param manifest the {@code Manifest} instance * @param rootUrl the code source URL * @return the package specification */ protected static PackageSpec getPackageSpec(final String name, final Manifest manifest, final URL rootUrl) { final PackageSpec spec = new PackageSpec(); if (manifest == null) { return null; } final Attributes mainAttribute = manifest.getMainAttributes(); final String path = name.replace('.', '/').concat("/"); final Attributes entryAttribute = manifest.getAttributes(path); spec.setSpecTitle(getDefinedAttribute(Attributes.Name.SPECIFICATION_TITLE, entryAttribute, mainAttribute)); spec.setSpecVersion(getDefinedAttribute(Attributes.Name.SPECIFICATION_VERSION, entryAttribute, mainAttribute)); spec.setSpecVendor(getDefinedAttribute(Attributes.Name.SPECIFICATION_VENDOR, entryAttribute, mainAttribute)); spec.setImplTitle(getDefinedAttribute(Attributes.Name.IMPLEMENTATION_TITLE, entryAttribute, mainAttribute)); spec.setImplVersion(getDefinedAttribute(Attributes.Name.IMPLEMENTATION_VERSION, entryAttribute, mainAttribute)); spec.setImplVendor(getDefinedAttribute(Attributes.Name.IMPLEMENTATION_VENDOR, entryAttribute, mainAttribute)); if (Boolean.parseBoolean(getDefinedAttribute(Attributes.Name.SEALED, entryAttribute, mainAttribute))) { spec.setSealBase(rootUrl); } return spec; } public String getRootName() { return ""; } public ClassSpec getClassSpec(final String fileName) throws IOException { return null; } public PackageSpec getPackageSpec(final String name) throws IOException { return null; } public Resource getResource(final String name) { return null; } public String getLibrary(final String name) { return null; } public Collection getPaths() { return Collections.emptySet(); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/AliasModuleSpec.java000066400000000000000000000030141472011152000272150ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; /** * A module specification for a module alias. * * @author David M. Lloyd */ public final class AliasModuleSpec extends ModuleSpec { private final String aliasName; AliasModuleSpec(final String name, final String aliasName) { super(name); this.aliasName = aliasName; } /** * Get the module alias target. * * @return the module alias target * @deprecated Use {@link #getAliasName()} instead. */ @Deprecated(forRemoval = true) public ModuleIdentifier getAliasTarget() { return ModuleIdentifier.fromString(aliasName); } /** * Get the module alias name. * * @return the module alias name */ public String getAliasName() { return aliasName; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/AssertionSetting.java000066400000000000000000000017001472011152000275100ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; /** * The assertion setting for a package or class. * * @apiviz.exclude * * @author David M. Lloyd */ public enum AssertionSetting { ENABLED, DISABLED, INHERIT, }jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ClassDefiner.java000066400000000000000000000210341472011152000265470ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2018 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.nio.ByteBuffer; import java.security.PrivilegedAction; import java.security.ProtectionDomain; import static java.security.AccessController.doPrivileged; /** * A hook for frameworks which need to define additional classes to a module's class loader. */ public final class ClassDefiner { private static final ClassDefiner instance = new ClassDefiner(); private static final RuntimePermission createClassLoaderPermission = new RuntimePermission("createClassLoader"); private ClassDefiner() {} /** * Define a class using the module and protection domain of an existing class. * * @param originalClass the existing class (must not be {@code null}) * @param className the new class name (must not be {@code null}) * @param classBytes the new class bytes (must not be {@code null}) * @return the defined class (not {@code null}) */ public Class defineClass(Class originalClass, String className, ByteBuffer classBytes) { return defineClass(originalClass, className, getProtectionDomain(originalClass), classBytes); } /** * Define a class using the module and protection domain of an existing class. * * @param originalClass the existing class (must not be {@code null}) * @param className the new class name (must not be {@code null}) * @param classBytes the new class bytes (must not be {@code null}) * @param off the offset into the {@code classBytes} array * @param len the number of bytes to use from the {@code classBytes} array * @return the defined class (not {@code null}) */ public Class defineClass(Class originalClass, String className, byte[] classBytes, int off, int len) { return defineClass(originalClass, className, getProtectionDomain(originalClass), classBytes, off, len); } /** * Define a class using the module and protection domain of an existing class. * * @param originalClass the existing class (must not be {@code null}) * @param className the new class name (must not be {@code null}) * @param classBytes the new class bytes (must not be {@code null}) * @return the defined class (not {@code null}) */ public Class defineClass(Class originalClass, String className, byte[] classBytes) { return defineClass(originalClass, className, getProtectionDomain(originalClass), classBytes, 0, classBytes.length); } /** * Define a class using the module of an existing class. * * @param originalClass the existing class (must not be {@code null}) * @param className the new class name (must not be {@code null}) * @param protectionDomain the protection domain of the new class (must not be {@code null}) * @param classBytes the new class bytes (must not be {@code null}) * @return the defined class (not {@code null}) */ public Class defineClass(Class originalClass, String className, ProtectionDomain protectionDomain, ByteBuffer classBytes) { final Module module = Module.forClass(originalClass); if (module == null) throw new IllegalArgumentException("Original " + originalClass + " does not have a module"); return module.getClassLoaderPrivate().defineClassInternal(className, classBytes, protectionDomain); } /** * Define a class using the module of an existing class. * * @param originalClass the existing class (must not be {@code null}) * @param className the new class name (must not be {@code null}) * @param protectionDomain the protection domain of the new class (must not be {@code null}) * @param classBytes the new class bytes (must not be {@code null}) * @param off the offset into the {@code classBytes} array * @param len the number of bytes to use from the {@code classBytes} array * @return the defined class (not {@code null}) */ public Class defineClass(Class originalClass, String className, ProtectionDomain protectionDomain, byte[] classBytes, int off, int len) { final Module module = Module.forClass(originalClass); if (module == null) throw new IllegalArgumentException("Original " + originalClass + " does not have a module"); return module.getClassLoaderPrivate().defineClassInternal(className, classBytes, off, len, protectionDomain); } /** * Define a class using the module of an existing class. * * @param originalClass the existing class (must not be {@code null}) * @param className the new class name (must not be {@code null}) * @param protectionDomain the protection domain of the new class (must not be {@code null}) * @param classBytes the new class bytes (must not be {@code null}) * @return the defined class (not {@code null}) */ public Class defineClass(Class originalClass, String className, ProtectionDomain protectionDomain, byte[] classBytes) { return defineClass(originalClass, className, protectionDomain, classBytes, 0, classBytes.length); } /** * Define a class. * * @param module the module to define the class to (must not be {@code null}) * @param className the new class name (must not be {@code null}) * @param protectionDomain the protection domain of the new class (must not be {@code null}) * @param classBytes the new class bytes (must not be {@code null}) * @return the defined class (not {@code null}) */ public Class defineClass(Module module, String className, ProtectionDomain protectionDomain, ByteBuffer classBytes) { return module.getClassLoaderPrivate().defineClassInternal(className, classBytes, protectionDomain); } /** * Define a class. * * @param module the module to define the class to (must not be {@code null}) * @param className the new class name (must not be {@code null}) * @param protectionDomain the protection domain of the new class (must not be {@code null}) * @param classBytes the new class bytes (must not be {@code null}) * @param off the offset into the {@code classBytes} array * @param len the number of bytes to use from the {@code classBytes} array * @return the defined class (not {@code null}) */ public Class defineClass(Module module, String className, ProtectionDomain protectionDomain, byte[] classBytes, int off, int len) { return module.getClassLoaderPrivate().defineClassInternal(className, classBytes, off, len, protectionDomain); } /** * Define a class. * * @param module the module to define the class to (must not be {@code null}) * @param className the new class name (must not be {@code null}) * @param protectionDomain the protection domain of the new class (must not be {@code null}) * @param classBytes the new class bytes (must not be {@code null}) * @return the defined class (not {@code null}) */ public Class defineClass(Module module, String className, ProtectionDomain protectionDomain, byte[] classBytes) { return defineClass(module, className, protectionDomain, classBytes, 0, classBytes.length); } /** * Get the class definer instance. The caller must have the {@code createClassLoader} {@link RuntimePermission}. * * @return the singleton class definer instance (not {@code null}) */ public static ClassDefiner getInstance() { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(createClassLoaderPermission); } return instance; } private ProtectionDomain getProtectionDomain(final Class clazz) { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { return doPrivileged((PrivilegedAction) clazz::getProtectionDomain); } else { return clazz.getProtectionDomain(); } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ClassLoaderLocalLoader.java000066400000000000000000000071061472011152000305070ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.IOException; import java.lang.reflect.UndeclaredThrowableException; import java.net.URL; import java.net.URLConnection; import java.security.AccessControlContext; import java.security.PrivilegedActionException; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.List; import static java.security.AccessController.doPrivileged; import static java.security.AccessController.getContext; /** * @author David M. Lloyd */ final class ClassLoaderLocalLoader implements LocalLoader { static final LocalLoader SYSTEM = Utils.getSystemLocalLoader(); private final ClassLoader classLoader; private final AccessControlContext context; /** * Construct a new instance. * * @param classLoader the classloader to which we delegate */ ClassLoaderLocalLoader(final ClassLoader classLoader) { this.classLoader = classLoader; context = getContext(); } // Public members public Class loadClassLocal(final String name, final boolean resolve) { try { return Class.forName(name, resolve, classLoader); } catch (ClassNotFoundException e) { final Throwable cause = e.getCause(); if (cause instanceof Error) { throw (Error) cause; } else if (cause instanceof RuntimeException) { //unlikely throw (RuntimeException) cause; } return null; } } public Package loadPackageLocal(final String name) { return classLoader.getDefinedPackage(name); } public List loadResourceLocal(final String name) { final Enumeration urls; ClassLoader classLoader = this.classLoader; try { if (classLoader == null) { urls = Utils.getSystemResources(name); } else { urls = classLoader.getResources(name); } } catch (IOException e) { return Collections.emptyList(); } final List list = new ArrayList<>(); while (urls.hasMoreElements()) { final URL url = urls.nextElement(); URLConnection connection = null; try { connection = doPrivileged(new GetURLConnectionAction(url), context); } catch (PrivilegedActionException e) { try { throw e.getException(); } catch (IOException e2) { // omit from list } catch (RuntimeException re) { throw re; } catch (Exception e2) { throw new UndeclaredThrowableException(e2); } } list.add(new URLConnectionResource(connection)); } return list; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ClassPathModuleFinder.java000066400000000000000000000111131472011152000303620ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.nio.file.Path; import java.util.function.Supplier; import java.util.jar.Attributes; import org.jboss.modules.filter.PathFilters; /** * The special module finder to handle launching from the actual class path. */ final class ClassPathModuleFinder extends FileSystemClassPathModuleFinder { private final String[] classPath; private final String[] dependencies; private final String mainClass; ClassPathModuleFinder(final Supplier baseModuleLoaderSupplier, final String[] classPath, final String[] dependencies, final String mainClass) { super(baseModuleLoaderSupplier, EMPTY_MODULE_LOADER_SUPPLIER); this.classPath = classPath; this.dependencies = dependencies; this.mainClass = mainClass; } ClassPathModuleFinder(final ModuleLoader baseModuleLoader, final String[] classpath, final String dependencies, final String mainClass) { this(new SimpleSupplier<>(baseModuleLoader), classpath, dependencies == null ? Utils.NO_STRINGS : dependencies.split(","), mainClass); } public ModuleSpec findModule(final String name, final ModuleLoader delegateLoader) throws ModuleLoadException { if (name.equals("")) { // special initial module ModuleSpec.Builder builder = ModuleSpec.build(name); for (String dependency : dependencies) { builder.addDependency(new ModuleDependencySpecBuilder() .setImportFilter(PathFilters.acceptAll()) .setExportFilter(PathFilters.acceptAll()) .setName(dependency) .build()); } for (String item : classPath) { builder.addDependency(new ModuleDependencySpecBuilder() .setImportFilter(PathFilters.acceptAll()) .setExportFilter(PathFilters.acceptAll()) .setName(item) .setOptional(true) .build()); } if (mainClass != null) { builder.setMainClass(mainClass); } addSystemDependencies(builder); return builder.create(); } else { return super.findModule(name, delegateLoader); } } void addExtensionDependencies(final ModuleSpec.Builder builder, final Attributes mainAttributes, final ModuleLoader extensionModuleLoader) { // not supported } void addModuleDependencies(final ModuleSpec.Builder builder, final ModuleLoader fatModuleLoader, final Attributes mainAttributes) { for (String dependency : dependencies) { builder.addDependency(new ModuleDependencySpecBuilder() .setImportFilter(PathFilters.acceptAll()) .setModuleLoader(fatModuleLoader) .setName(dependency) .build()); } super.addModuleDependencies(builder, fatModuleLoader, mainAttributes); } void addClassPathDependencies(final ModuleSpec.Builder builder, final ModuleLoader moduleLoader, final Path path, final Attributes mainAttributes) { // add the class path items in order, just like a real class path would for (String item : classPath) { if (item.equals(builder.getName())) { builder.addDependency(DependencySpec.OWN_DEPENDENCY); } else { builder.addDependency(new ModuleDependencySpecBuilder() .setName(item) .setOptional(true) .build()); } } } void addSelfDependency(final ModuleSpec.Builder builder) { // not supported } void setMainClass(final ModuleSpec.Builder builder, final Attributes mainAttributes) { // every module gets the same main class! if (mainClass != null) { builder.setMainClass(mainClass); } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ClassSpec.java000066400000000000000000000073511472011152000260730ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.nio.ByteBuffer; import java.security.CodeSource; /** * A class definition specification. * * @apiviz.exclude * @author David M. Lloyd */ public final class ClassSpec { private byte[] bytes; private ByteBuffer byteBuffer; private CodeSource codeSource; private AssertionSetting assertionSetting = AssertionSetting.INHERIT; /** * Construct a new instance. */ public ClassSpec() { } /** * Get the class file bytes, if they are set. * * @return the class file bytes, if they are set; {@code null} otherwise */ public byte[] getBytes() { return bytes; } /** * Set the class file bytes. Calling this method will clear any previously set {@code ByteBuffer}. * * @param bytes the class file bytes * @return this class specification */ public ClassSpec setBytes(final byte[] bytes) { this.bytes = bytes; byteBuffer = null; return this; } public void setBytes$$bridge(final byte[] bytes) { setBytes(bytes); } /** * Get the class byte buffer, if one is set. * * @return the class byte buffer, if one is set; {@code null} otherwise */ public ByteBuffer getByteBuffer() { return byteBuffer; } /** * Set the class byte buffer. Calling this method will clear any previously set class {@code byte[]}. * * @param byteBuffer the class byte buffer * @return this class specification */ public ClassSpec setByteBuffer(final ByteBuffer byteBuffer) { this.byteBuffer = byteBuffer; bytes = null; return this; } /** * Get the code source (should not be {@code null}). * * @return the code source */ public CodeSource getCodeSource() { return codeSource; } /** * Set the code source (should not be {@code null}). * * @param codeSource the code source * @return this class specification */ public ClassSpec setCodeSource(final CodeSource codeSource) { this.codeSource = codeSource; return this; } public void setCodeSource$$bridge(final CodeSource codeSource) { setCodeSource(codeSource); } /** * Get the class assertion setting. * * @return the assertion setting */ public AssertionSetting getAssertionSetting() { return assertionSetting; } /** * Set the class assertion setting. * * @param assertionSetting the assertion setting * @return this class specification */ public ClassSpec setAssertionSetting(final AssertionSetting assertionSetting) { if (assertionSetting == null) { throw new IllegalArgumentException("assertionSetting is null"); } this.assertionSetting = assertionSetting; return this; } public void setAssertionSetting$$bridge(final AssertionSetting assertionSetting) { setAssertionSetting(assertionSetting); } }jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ClassTransformer.java000066400000000000000000000111131472011152000274720ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2018 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.nio.ByteBuffer; import java.security.ProtectionDomain; import java.util.Collection; /** * A class file transformer which operates on byte buffers. */ public interface ClassTransformer { /** * Transform the bytes of a class. The position and limit of both the passed-in and returned buffers must mark * the start and end of the class bytes. * * @param loader the class loader of the class being transformed * @param className the internal name of the class being transformed (not {@code null}) * @param protectionDomain the protection domain of the class, if any * @param classBytes the class bytes being transformed (not {@code null}; may be a direct or heap buffer) * @return the transformation result (may be a direct or heap buffer) * @throws IllegalArgumentException if the class could not be transformed for some reason */ ByteBuffer transform(ClassLoader loader, String className, ProtectionDomain protectionDomain, ByteBuffer classBytes) throws IllegalArgumentException; /** * Get a new transformer which applies this transformation followed by another transformation. * * @param other the other transformation (must not be {@code null}) * @return the new transformer (not {@code null}) */ default ClassTransformer andThen(ClassTransformer other) { if (other == null) throw new IllegalArgumentException("other is null"); if (other == IDENTITY) return this; return new ClassTransformer() { public ByteBuffer transform(final ClassLoader loader, final String className, final ProtectionDomain protectionDomain, final ByteBuffer classBytes) throws IllegalArgumentException { ByteBuffer firstStage = ClassTransformer.this.transform(loader, className, protectionDomain, classBytes); if (firstStage == null) firstStage = classBytes; return other.transform(loader, className, protectionDomain, firstStage); } }; } /** * Get a new transformer which applies all the transformations in the given collection. The collection should either be * immutable or safe for concurrent iteration. A synchronized collection is insufficiently thread-safe. * * @param transformers the transformer collection (must not be {@code null}) * @return the new transformer (not {@code null}) */ static ClassTransformer allOf(Collection transformers) { if (transformers == null) throw new IllegalArgumentException("transformers is null"); return new ClassTransformer() { public ByteBuffer transform(final ClassLoader loader, final String className, final ProtectionDomain protectionDomain, ByteBuffer classBytes) throws IllegalArgumentException { ByteBuffer transformed; for (final ClassTransformer transformer : transformers) { if (transformer != null) { transformed = transformer.transform(loader, className, protectionDomain, classBytes); if (transformed != null) { classBytes = transformed; } } } return classBytes; } }; } /** * The identity transformation, which does not modify the class bytes at all. */ ClassTransformer IDENTITY = new ClassTransformer() { public ByteBuffer transform(final ClassLoader loader, final String className, final ProtectionDomain protectionDomain, final ByteBuffer classBytes) throws IllegalArgumentException { return classBytes; } public ClassTransformer andThen(final ClassTransformer other) { if (other == null) throw new IllegalArgumentException("other is null"); return other; } }; } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ClassifyingModuleLoader.java000066400000000000000000000055171472011152000307650ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.util.HashMap; import java.util.Map; /** * A module loader which selects a delegate module loader based upon the prefix of the module name. Longer * names are matched first always. * * @author David M. Lloyd */ public final class ClassifyingModuleLoader extends ModuleLoader { private volatile Map delegates; private final ModuleLoader defaultLoader; private final String name; /** * Construct a new instance. The given delegates map is copied. * * @param delegates the default delegates map to use * @param defaultLoader the default loader to use if no delegate mapping exists */ public ClassifyingModuleLoader(final String name, final Map delegates, final ModuleLoader defaultLoader) { super(true, false); this.defaultLoader = defaultLoader; this.delegates = new HashMap<>(delegates); this.name = name; } /** {@inheritDoc} */ protected Module preloadModule(String name) throws ModuleLoadException { int idx; final Map delegates = this.delegates; for (;;) { final ModuleLoader loader = delegates.get(name); if (loader != null) { return preloadModule(name, loader); } idx = name.lastIndexOf('.'); if (idx == -1) { return preloadModule(name, defaultLoader); } name = name.substring(0, idx); } } /** {@inheritDoc} */ protected ModuleSpec findModule(final String name) throws ModuleLoadException { // We have no modules of our own! return null; } /** * Change the delegates map. A copy is made of the given map. * * @param delegates the new delegates map to use */ public void setDelegates(Map delegates) { this.delegates = new HashMap<>(delegates); } public String toString() { return String.format("Classifying Module Loader @%x \"%s\"", Integer.valueOf(hashCode()), name); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ConcreteModuleSpec.java000066400000000000000000000067071472011152000277420ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.security.PermissionCollection; import java.util.Map; /** * A {@code Module} specification for a concrete module implementation. * * @apiviz.exclude * * @author John Bailey * @author David M. Lloyd */ public final class ConcreteModuleSpec extends ModuleSpec { private final String mainClass; private final AssertionSetting assertionSetting; private final ResourceLoaderSpec[] resourceLoaders; private final DependencySpec[] dependencies; private final LocalLoader fallbackLoader; private final ModuleClassLoaderFactory moduleClassLoaderFactory; private final ClassTransformer classFileTransformer; private final Map properties; private final PermissionCollection permissionCollection; private final Version version; ConcreteModuleSpec(final String name, final String mainClass, final AssertionSetting assertionSetting, final ResourceLoaderSpec[] resourceLoaders, final DependencySpec[] dependencies, final LocalLoader fallbackLoader, final ModuleClassLoaderFactory moduleClassLoaderFactory, final ClassTransformer classFileTransformer, final Map properties, final PermissionCollection permissionCollection, final Version version) { super(name); this.mainClass = mainClass; this.assertionSetting = assertionSetting; this.resourceLoaders = resourceLoaders; this.dependencies = dependencies; this.fallbackLoader = fallbackLoader; this.moduleClassLoaderFactory = moduleClassLoaderFactory; this.classFileTransformer = classFileTransformer; this.properties = properties; this.permissionCollection = permissionCollection; this.version = version; } public String getMainClass() { return mainClass; } AssertionSetting getAssertionSetting() { return assertionSetting; } ResourceLoaderSpec[] getResourceLoaders() { return resourceLoaders; } DependencySpec[] getDependenciesInternal() { return dependencies; } public DependencySpec[] getDependencies() { return dependencies.length == 0 ? dependencies : dependencies.clone(); } LocalLoader getFallbackLoader() { return fallbackLoader; } ModuleClassLoaderFactory getModuleClassLoaderFactory() { return moduleClassLoaderFactory; } ClassTransformer getClassFileTransformer() { return classFileTransformer; } Map getProperties() { return properties; } PermissionCollection getPermissionCollection() { return permissionCollection; } public Version getVersion() { return version; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ConcurrentClassLoader.java000066400000000000000000000477031472011152000304570ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.security.ProtectionDomain; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; import java.util.concurrent.ConcurrentHashMap; /** * A classloader which can delegate to multiple other classloaders without risk of deadlock. A concurrent class loader * should only ever be delegated to by another concurrent class loader; however a concurrent class loader may * delegate to a standard hierarchical class loader. In other words, holding a lock on another class loader while invoking * a method on this class loader may cause an unexpected deadlock. * * @author David M. Lloyd */ public abstract class ConcurrentClassLoader extends NamedClassLoader { private static final ThreadLocal GET_PACKAGE_SUPPRESSOR = new ThreadLocal<>(); static { if (! ClassLoader.registerAsParallelCapable()) { throw new Error("Failed to register " + ConcurrentClassLoader.class.getName() + " as parallel-capable"); } /* This resolves a known deadlock that can occur if one thread is in the process of defining a package as part of defining a class, and another thread is defining the system package that can result in loading a class. One holds the Package.pkgs lock and one holds the Classloader lock. */ Package.getPackages(); } /** * An empty enumeration, for subclasses to use if desired. * * @deprecated Use {@link Collections#emptyEnumeration()} instead. */ @Deprecated protected static final Enumeration EMPTY_ENUMERATION = Collections.emptyEnumeration(); /** * Construct a new instance with the given parent class loader, which must be a concurrent class loader, or {@code null} * to create a root concurrent class loader. * * @param parent the parent class loader */ protected ConcurrentClassLoader(final ConcurrentClassLoader parent) { this(parent, null); } /** * Construct a new instance, using our class loader as the parent. */ protected ConcurrentClassLoader() { this((String) null); } /** * Construct a new instance with the given parent class loader, which must be a concurrent class loader, or {@code null} * to create a root concurrent class loader. * * @param parent the parent class loader * @param name the name of this class loader, or {@code null} if it is unnamed */ protected ConcurrentClassLoader(final ConcurrentClassLoader parent, final String name) { super(parent == null ? Utils.getPlatformClassLoader() : parent, name); if (! isRegisteredAsParallelCapable()) { throw new Error("Cannot instantiate non-parallel subclass"); } } /** * Construct a new instance, using our class loader as the parent. * * @param name the name of this class loader, or {@code null} if it is unnamed */ protected ConcurrentClassLoader(String name) { super(Utils.getPlatformClassLoader(), name); if (! isRegisteredAsParallelCapable()) { throw new Error("Cannot instantiate non-parallel subclass"); } } /** * Loads the class with the specified binary name. Equivalent to calling {@link #loadClass(String, boolean) loadClass(className, false)}. * * @param className The binary name of the class * @return the resulting {@code Class} instance * @throws ClassNotFoundException if the class was not found */ @Override public final Class loadClass(final String className) throws ClassNotFoundException { return performLoadClass(className, false, false); } /** * Loads the class with the specified binary name. * * @param className The binary name of the class * @param resolve {@code true} if the class should be linked after loading * @return the resulting {@code Class} instance */ @Override public final Class loadClass(final String className, boolean resolve) throws ClassNotFoundException { return performLoadClass(className, false, resolve); } /** * Same as {@link #loadClass(String)}, except only exported classes will be considered. * * @param className the class name * @return the class * @throws ClassNotFoundException if the class isn't found */ public final Class loadExportedClass(final String className) throws ClassNotFoundException { return performLoadClass(className, true, false); } /** * Same as {@link #loadClass(String,boolean)}, except only exported classes will be considered. * * @param className the class name * @param resolve {@code true} if the class should be linked after loading * @return the class * @throws ClassNotFoundException if the class isn't found */ public final Class loadExportedClass(final String className, boolean resolve) throws ClassNotFoundException { return performLoadClass(className, true, resolve); } /** * Find a class, possibly delegating to other loader(s). This method should never synchronize across a * delegation method call of any sort. The default implementation always throws {@code ClassNotFoundException}. *

* If a class is to be defined by this method, it should be done via one of the atomic {@code defineOrLoadClass} * methods rather than {@code defineClass()} in order to avoid spurious exceptions. * * @param className the class name * @param exportsOnly {@code true} if only exported classes should be considered * @param resolve {@code true} if the class should be linked after loading * @return the class * @throws ClassNotFoundException if the class is not found */ protected Class findClass(final String className, final boolean exportsOnly, final boolean resolve) throws ClassNotFoundException { throw new ClassNotFoundException(className); } /** * Atomically define or load the named class. If the class is already defined, the existing class is returned. * * @param className the class name to define or load * @param bytes the bytes to use to define the class * @param off the offset into the byte array at which the class bytes begin * @param len the number of bytes in the class * @return the class */ protected final Class defineOrLoadClass(final String className, final byte[] bytes, int off, int len) { try { return defineClass(className, bytes, off, len); } catch (LinkageError e) { final Class loadedClass = findLoadedClass(className); if (loadedClass != null) { return loadedClass; } throw e; } } /** * Atomically define or load the named class. If the class is already defined, the existing class is returned. * * @param className the class name to define or load * @param bytes the bytes to use to define the class * @param off the offset into the byte array at which the class bytes begin * @param len the number of bytes in the class * @param protectionDomain the protection domain for the defined class * @return the class */ protected final Class defineOrLoadClass(final String className, final byte[] bytes, int off, int len, ProtectionDomain protectionDomain) { try { return defineClass(className, bytes, off, len, protectionDomain); } catch (LinkageError e) { final Class loadedClass = findLoadedClass(className); if (loadedClass != null) { return loadedClass; } throw e; } } /** * Implementation of {@link ClassLoader#findClass(String)}. * * @param className the class name * @return the result of {@code findClass(className, false, false)} */ protected final Class findClass(final String className) throws ClassNotFoundException { return findClass(className, false, false); } /** * Implementation of {@link ClassLoader#findClass(String, String)}. * * @param moduleName the Java module name * @param className the class name * @return the result of {@code findClass(className, false, false)} */ protected final Class findClass(final String moduleName, final String className) { try { return findClass(className); } catch (ClassNotFoundException e) { return null; } } /** * Finds the resource with the given name. The name of a resource is a {@code '/'}-separated path name that * identifies the resource. If the resource name starts with {@code "java/"} then the parent class loader is used. * Otherwise, this method delegates to {@link #findResource(String, boolean)}. * * @param name the name of the resource * @return the resource URL, or {@code null} if no such resource exists or the invoker does not have adequate * permission to access it */ public final URL getResource(final String name) { for (String s : Module.systemPaths) { if (name.startsWith(s)) { return Utils.getSystemResource(name); } } return findResource(name, false); } /** * Finds all available resources with the given name. * * @see #getResource(String) * * @param name the resource name * @return an enumeration over all the resource URLs; if no resources could be found, the enumeration will be empty * @throws IOException if an I/O error occurs */ public final Enumeration getResources(final String name) throws IOException { for (String s : Module.systemPaths) { if (name.startsWith(s)) { return Utils.getSystemResources(name); } } return findResources(name, false); } /** * Find the resource with the given name and exported status. * * @see #getResource(String) * * @param name the resource name * @param exportsOnly {@code true} to consider only exported resources or {@code false} to consider all resources * @return the resource URL */ protected URL findResource(final String name, final boolean exportsOnly) { return null; } /** * Never used. {@link ClassLoader#getResource(String)} and related methods can cause a loop condition * when this method is implemented; use {@link #findResource(String, boolean)} instead. * * @param name ignored * @return {@code null} always */ protected final URL findResource(final String name) { // Always return null so that we don't go into a loop from super.getResource*(). return null; } /** * Find the resource with the given name in specified java module. * * @see #getResource(String) * * @param moduleName java module name * @param name the resource name * @return the resource URL */ protected final URL findResource(final String moduleName, final String name) throws IOException { return getResource(name); } /** * Finds the resources with the given name and exported status. * * @see #getResources(String) * * @param name the resource name * @param exportsOnly {@code true} to consider only exported resources or {@code false} to consider all resources * @return the resource enumeration * @throws IOException if an I/O error occurs */ protected Enumeration findResources(final String name, final boolean exportsOnly) throws IOException { return Collections.emptyEnumeration(); } /** * Never used. {@link ClassLoader#getResources(String)} and related methods can cause a loop condition * when this method is implemented; use {@link #findResources(String, boolean)} instead. By default, returns * an empty enumeration. * * @param name ignored * @return an empty enumeration */ protected final Enumeration findResources(final String name) { return Collections.emptyEnumeration(); } /** * Finds the resource with the given name and exported status, returning the resource content as a stream. * * @param name the resource name * @param exportsOnly {@code true} to consider only exported resources or {@code false} to consider all resources * @return the resource stream, or {@code null} if the resource is not found */ protected InputStream findResourceAsStream(final String name, final boolean exportsOnly) { final URL url = findResource(name, exportsOnly); try { return url == null ? null : url.openStream(); } catch (IOException e) { return null; } } /** * Returns an input stream for reading the specified resource. This method delegates to {@link #findResourceAsStream(String, boolean)}. * * @param name the resource name * @return the resource stream, or {@code null} if the resource is not found */ public final InputStream getResourceAsStream(final String name) { for (String s : Module.systemPaths) { if (name.startsWith(s)) { return Utils.getSystemResourceAsStream(name); } } return findResourceAsStream(name, false); } // Private members /** * Perform a class load operation. If the class is in the package or a subpackage of a package in the system packages list, * the parent class loader is used to load the class. Otherwise, this method checks to see if the class loader * object is locked; if so, it unlocks it and submits the request to the class loader thread. Otherwise, it will * load the class itself by delegating to {@link #findClass(String, boolean, boolean)}. * * @param className the class name * @param exportsOnly {@code true} to consider only exported resources or {@code false} to consider all resources * @param resolve {@code true} to resolve the loaded class * @return the class returned by {@link #findClass(String, boolean, boolean)} * @throws ClassNotFoundException if {@link #findClass(String, boolean, boolean)} throws this exception */ private Class performLoadClass(String className, boolean exportsOnly, final boolean resolve) throws ClassNotFoundException { if (className == null) { throw new IllegalArgumentException("name is null"); } if (className.length() == 0) { throw new IllegalArgumentException("name is empty"); } for (String s : Module.systemPackages) { if (className.startsWith(s)) { return Utils.getSystemClass(this, className); } } return performLoadClassUnchecked(className, exportsOnly, resolve); } private Class performLoadClassUnchecked(final String className, final boolean exportsOnly, final boolean resolve) throws ClassNotFoundException { if (className.charAt(0) == '[') { // Use Class.forName to load the array type final Class array = Class.forName(className, false, this); if (resolve) { resolveClass(array); } return array; } return findClass(className, exportsOnly, resolve); } private final ConcurrentHashMap packages = new ConcurrentHashMap<>(); Class findSystemClassInternal(String name) throws ClassNotFoundException { return findSystemClass(name); } /** * Load a package which is visible to this class loader. * * @param name the package name * @return the package, or {@code null} if no such package is visible to this class loader * @deprecated Deprecated in {@link ClassLoader#getPackage(String)}. */ @Deprecated protected final Package getPackage(final String name) { final String packageName = name + "."; for (String s : Module.systemPackages) { if (packageName.startsWith(s)) { return Package.getPackage(name); } } if (GET_PACKAGE_SUPPRESSOR.get() == Boolean.TRUE) { return null; } return getPackageByName(name); } /** * Perform the actual work to load a package which is visible to this class loader. By default, uses a simple * parent-first delegation strategy. * * @param name the package name * @return the package, or {@code null} if no such package is visible to this class loader */ protected Package getPackageByName(final String name) { final Package parentPackage = super.getPackage(name); return parentPackage == null ? findLoadedPackage(name) : parentPackage; } /** * Get all defined packages which are visible to this class loader. * * @return the packages */ protected Package[] getPackages() { ArrayList list = new ArrayList<>(); list.addAll(packages.values()); list.addAll(Arrays.asList(super.getPackages())); return list.toArray(Package[]::new); } /** * Load a package from this class loader only. * * @param name the package name * @return the package or {@code null} if no such package is defined by this class loader */ protected final Package findLoadedPackage(final String name) { return packages.get(name); } /** * Defines a package by name in this ConcurrentClassLoader. If the package was already defined, the * existing package is returned instead. * * @param name the package name * @param specTitle the specification title * @param specVersion the specification version * @param specVendor the specification vendor * @param implTitle the implementation title * @param implVersion the implementation version * @param implVendor the implementation vendor * @param sealBase if not {@code null}, then this package is sealed with respect to the given code source URL * * @return the newly defined package, or the existing one if one was already defined */ protected Package definePackage(final String name, final String specTitle, final String specVersion, final String specVendor, final String implTitle, final String implVersion, final String implVendor, final URL sealBase) throws IllegalArgumentException { ThreadLocal suppressor = GET_PACKAGE_SUPPRESSOR; suppressor.set(Boolean.TRUE); try { Package existing = packages.get(name); if (existing != null) { return existing; } Package pkg; try { pkg = super.definePackage(name, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor, sealBase); } catch (final IllegalArgumentException iae) { pkg = super.getPackage(name); if (pkg == null) throw iae; } existing = packages.putIfAbsent(name, pkg); return existing != null ? existing : pkg; } finally { suppressor.remove(); } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/DataURLStreamHandler.java000066400000000000000000000246341472011152000301240ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2018 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.net.ProtocolException; import java.net.URL; import java.net.URLConnection; import java.net.URLDecoder; import java.net.URLStreamHandler; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.charset.UnsupportedCharsetException; import java.util.Base64; /** */ final class DataURLStreamHandler extends URLStreamHandler { private static final DataURLStreamHandler INSTANCE = new DataURLStreamHandler(); static DataURLStreamHandler getInstance() { return INSTANCE; } private DataURLStreamHandler() { } protected URLConnection openConnection(final URL url) throws IOException { return new DataURLConnection(url); } static final class DataURLConnection extends URLConnection { private static final int ST_INITIAL = 0; private static final int ST_TYPE = 1; private static final int ST_SUBTYPE = 2; private static final int ST_PARAMETER = 3; private static final int ST_PARAMETER_VAL = 4; private final byte[] content; private final String contentString; private final String contentType; DataURLConnection(final URL url) throws IOException { super(url); // We have to use toString() because otherwise URL will eat '?' characters in the content! String urlString = url.toString(); if (! urlString.startsWith("data:")) { // should not happen throw new ProtocolException("Wrong URL scheme"); } String contentType = "text/plain"; StringBuilder contentTypeBuilder = null; int state = ST_INITIAL; final int len = urlString.length(); int cp; int postCt = -1; int content = -1; int paramStart = -1; int paramEnd = -1; boolean base64 = false; String charsetName = null; boolean text = true; Charset charset = StandardCharsets.US_ASCII; for (int i = 5; i < len; i = urlString.offsetByCodePoints(i, 1)) { cp = urlString.codePointAt(i); if (state == ST_INITIAL) { if (isCTToken(cp)) { state = ST_TYPE; contentTypeBuilder = new StringBuilder(); contentTypeBuilder.appendCodePoint(Character.toLowerCase(cp)); } else if (cp == ';') { // default content-type contentTypeBuilder = new StringBuilder(); contentTypeBuilder.append("text/plain"); postCt = contentTypeBuilder.length(); paramStart = urlString.offsetByCodePoints(i, 1); state = ST_PARAMETER; } else if (cp == ',') { content = urlString.offsetByCodePoints(i, 1); // done break; } else { throw invalidChar(i); } } else if (state == ST_TYPE) { if (isCTToken(cp)) { contentTypeBuilder.appendCodePoint(Character.toLowerCase(cp)); } else if (cp == '/') { state = ST_SUBTYPE; contentTypeBuilder.append('/'); } else { throw invalidChar(i); } } else if (state == ST_SUBTYPE) { if (isCTToken(cp)) { contentTypeBuilder.appendCodePoint(Character.toLowerCase(cp)); } else if (cp == ';') { postCt = contentTypeBuilder.length(); paramStart = urlString.offsetByCodePoints(i, 1); state = ST_PARAMETER; } else if (cp == ',') { contentType = contentTypeBuilder.toString(); text = contentType.startsWith("text/"); content = urlString.offsetByCodePoints(i, 1); // done break; } else { throw invalidChar(i); } } else if (state == ST_PARAMETER) { if (isCTToken(cp)) { // OK } else if (cp == ';' || cp == ',') { // no value if (i - paramStart == 6 && urlString.regionMatches(true, paramStart, "base64", 0, 6)) { base64 = true; } else { contentTypeBuilder.append(';').append(urlString.substring(paramStart, i)); } if (cp == ',') { text = contentTypeBuilder.lastIndexOf("text/", 5) != -1; if (text && charsetName != null) { contentTypeBuilder.insert(postCt, ";charset=" + charsetName); } contentType = contentTypeBuilder.toString(); content = urlString.offsetByCodePoints(i, 1); // done break; } paramStart = urlString.offsetByCodePoints(i, 1); // restart ST_PARAMETER } else if (cp == '=') { paramEnd = i; state = ST_PARAMETER_VAL; } else { throw invalidChar(i); } } else if (state == ST_PARAMETER_VAL) { if (isCTToken(cp)) { // OK } else if (cp == ';' || cp == ',') { // there is a value final String value = urlString.substring(paramEnd + 1, i); if (paramEnd - paramStart == 7 && urlString.regionMatches(true, paramStart, "charset", 0, 7)) { try { charset = Charset.forName(value); } catch (UnsupportedCharsetException e) { throw e; } catch (Throwable t) { final UnsupportedCharsetException uce = new UnsupportedCharsetException(value); uce.initCause(t); throw uce; } charsetName = value; } else { contentTypeBuilder.append(urlString.substring(paramStart, i)); } if (cp == ',') { text = contentTypeBuilder.lastIndexOf("text/", 5) != -1; if (text && charsetName != null) { contentTypeBuilder.insert(postCt, ";charset=" + charsetName); } contentType = contentTypeBuilder.toString(); content = urlString.offsetByCodePoints(i, 1); // done break; } state = ST_PARAMETER; } else { throw invalidChar(i); } } else { throw new IllegalStateException(); } } if (content == -1) { throw new ProtocolException("Missing content"); } // now, get the content byte[] bytes; String str; if (base64) { bytes = Base64.getMimeDecoder().decode(urlString.substring(content).replaceAll("\\s+", "")); if (text) { str = new String(bytes, charset); } else { str = null; } } else { if (text) { str = URLDecoder.decode(urlString.substring(content), charset.name()); bytes = str.getBytes(charset); } else { // this is a bit hacky... bytes = URLDecoder.decode(urlString.substring(content), StandardCharsets.ISO_8859_1.name()).getBytes(StandardCharsets.ISO_8859_1); str = null; } } this.content = bytes; this.contentType = contentType; this.contentString = str; } private static ProtocolException invalidChar(int pos) { return new ProtocolException("Invalid character at position " + pos); } private static boolean isCTToken(int cp) { return 0x21 <= cp && cp <= 0x7e && cp != '(' && cp != ')' && cp != '<' && cp != '>' && cp != '@' && cp != ',' && cp != ';' && cp != ':' && cp != '\\' && cp != '"' && cp != '/' && cp != '[' && cp != ']' && cp != '?' && cp != '='; } public void connect() { connected = true; } public int getContentLength() { return content.length; } public String getContentType() { return contentType; } public Object getContent() { return contentString != null ? contentString : content.clone(); } public InputStream getInputStream() { return new ByteArrayInputStream(content); } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/DefaultBootModuleLoaderHolder.java000066400000000000000000000045431472011152000320560ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.lang.reflect.InvocationTargetException; import java.security.AccessController; import java.security.PrivilegedAction; final class DefaultBootModuleLoaderHolder { static final ModuleLoader INSTANCE; private DefaultBootModuleLoaderHolder() { } static { INSTANCE = AccessController.doPrivileged(new PrivilegedAction() { public ModuleLoader run() { final String loaderClass = System.getProperty("boot.module.loader", LocalModuleLoader.class.getName()); try { return Class.forName(loaderClass, true, DefaultBootModuleLoaderHolder.class.getClassLoader()).asSubclass(ModuleLoader.class).getConstructor().newInstance(); } catch (InstantiationException e) { throw new InstantiationError(e.getMessage()); } catch (IllegalAccessException e) { throw new IllegalAccessError(e.getMessage()); } catch (InvocationTargetException e) { try { throw e.getCause(); } catch (RuntimeException cause) { throw cause; } catch (Error cause) { throw cause; } catch (Throwable t) { throw new Error(t); } } catch (NoSuchMethodException e) { throw new NoSuchMethodError(e.getMessage()); } catch (ClassNotFoundException e) { throw new NoClassDefFoundError(e.getMessage()); } } }); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/DelegatingModuleLoader.java000066400000000000000000000045011472011152000305450ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; /** * A module loader which searches its finders first, and then delegates to another loader if the module is not found. */ public class DelegatingModuleLoader extends ModuleLoader { private final ModuleLoader delegate; /** * Construct a new instance. * * @param delegate the delegate module loader, or {@code null} to skip delegation * @param finders the module finders (must not be {@code null}) */ public DelegatingModuleLoader(final ModuleLoader delegate, final ModuleFinder[] finders) { super(finders); this.delegate = delegate; } /** * Construct a new instance. * * @param delegate the delegate module loader, or {@code null} to skip delegation * @param finder the single module finder (must not be {@code null}) */ public DelegatingModuleLoader(final ModuleLoader delegate, final ModuleFinder finder) { super(finder); this.delegate = delegate; } /** * Preload the named module. * * @param name the module name (must not be {@code null}) * @return the loaded module, or {@code null} if it is not found in this loader or the delegate * @throws ModuleLoadException if the module was found but failed to be loaded */ protected Module preloadModule(final String name) throws ModuleLoadException { Module module = loadModuleLocal(name); if (module == null) { final ModuleLoader delegate = this.delegate; if (delegate != null) { module = preloadModule(name, delegate); } } return module; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/Dependency.java000066400000000000000000000075141472011152000262720ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import org.jboss.modules.filter.ClassFilter; import org.jboss.modules.filter.ClassFilters; import org.jboss.modules.filter.PathFilter; import org.jboss.modules.filter.PathFilters; /** * A dependency item. * * @author John Bailey * @author David M. Lloyd */ abstract class Dependency { private final PathFilter exportFilter; private final PathFilter importFilter; private final PathFilter resourceExportFilter; private final PathFilter resourceImportFilter; private final ClassFilter classExportFilter; private final ClassFilter classImportFilter; Dependency(final PathFilter exportFilter, final PathFilter importFilter) { this(exportFilter, importFilter, PathFilters.acceptAll(), PathFilters.acceptAll(), ClassFilters.acceptAll(), ClassFilters.acceptAll()); } protected Dependency(final PathFilter exportFilter, final PathFilter importFilter, final PathFilter resourceExportFilter, final PathFilter resourceImportFilter, final ClassFilter classExportFilter, final ClassFilter classImportFilter) { if (exportFilter == null) { throw new IllegalArgumentException("exportFilter is null"); } if (importFilter == null) { throw new IllegalArgumentException("importFilter is null"); } if (resourceExportFilter == null) { throw new IllegalArgumentException("resourceExportFilter is null"); } if (resourceImportFilter == null) { throw new IllegalArgumentException("resourceImportFilter is null"); } if (classExportFilter == null) { throw new IllegalArgumentException("classExportFilter is null"); } if (classImportFilter == null) { throw new IllegalArgumentException("classImportFilter is null"); } this.exportFilter = exportFilter; this.importFilter = importFilter; this.resourceExportFilter = resourceExportFilter; this.resourceImportFilter = resourceImportFilter; this.classExportFilter = classExportFilter; this.classImportFilter = classImportFilter; } /** * Get the export filter for this dependency. This filter determines what imported paths are re-exported by this * dependency. All exported paths must also satisfy the import filter. * * @return the export filter */ final PathFilter getExportFilter() { return exportFilter; } /** * Get the import filter for this dependency. This filter determines what exported paths are imported from the * dependency to the dependent. * * @return the import filter */ final PathFilter getImportFilter() { return importFilter; } final PathFilter getResourceExportFilter() { return resourceExportFilter; } final PathFilter getResourceImportFilter() { return resourceImportFilter; } final ClassFilter getClassExportFilter() { return classExportFilter; } final ClassFilter getClassImportFilter() { return classImportFilter; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/DependencySpec.java000066400000000000000000000677601472011152000271160ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.util.Set; import org.jboss.modules.filter.ClassFilter; import org.jboss.modules.filter.ClassFilters; import org.jboss.modules.filter.PathFilter; import org.jboss.modules.filter.PathFilters; /** * A dependency specification that represents a single dependency for a module. The dependency can be on a local loader * or another module, or on the target module's local loader. * * @apiviz.exclude * * @author David M. Lloyd * @author John Bailey * @author Jason T. Greene */ public abstract class DependencySpec { static final DependencySpec[] NO_DEPENDENCIES = new DependencySpec[0]; final PathFilter importFilter; final PathFilter exportFilter; final PathFilter resourceImportFilter; final PathFilter resourceExportFilter; final ClassFilter classImportFilter; final ClassFilter classExportFilter; /** * Get the dependency import filter. * * @return the import filter */ public PathFilter getImportFilter() { return importFilter; } /** * Get the dependency export filter. * * @return the export filter */ public PathFilter getExportFilter() { return exportFilter; } /** * Get the dependency resource import filter. * * @return the import filter */ public PathFilter getResourceImportFilter() { return resourceImportFilter; } /** * Get the dependency resource export filter. * * @return the export filter */ public PathFilter getResourceExportFilter() { return resourceExportFilter; } /** * Get the dependency class import filter. * * @return the class import filter */ public ClassFilter getClassImportFilter() { return classImportFilter; } /** * Get the dependency class export filter. * * @return the class export filter */ public ClassFilter getClassExportFilter() { return classExportFilter; } DependencySpec(final PathFilter importFilter, final PathFilter exportFilter, final PathFilter resourceImportFilter, final PathFilter resourceExportFilter, final ClassFilter classImportFilter, final ClassFilter classExportFilter) { this.importFilter = importFilter; this.exportFilter = exportFilter; this.resourceImportFilter = resourceImportFilter; this.resourceExportFilter = resourceExportFilter; this.classImportFilter = classImportFilter; this.classExportFilter = classExportFilter; } abstract Dependency getDependency(final Module module); /** * Create a dependency on the current module's local resources. You should have at least one such dependency * on any module which has its own resources. Always returns {@link #OWN_DEPENDENCY}. * * @return the dependency spec */ public static DependencySpec createLocalDependencySpec() { return OWN_DEPENDENCY; } /** * Create a dependency on the current module's local resources. You should have at least one such dependency * on any module which has its own resources. * * @param importFilter the import filter to apply * @param exportFilter the export filter to apply * @return the dependency spec * * @deprecated Use {@link LocalDependencySpecBuilder} instead. */ @Deprecated public static DependencySpec createLocalDependencySpec(final PathFilter importFilter, final PathFilter exportFilter) { return new LocalDependencySpecBuilder() .setImportFilter(importFilter) .setExportFilter(exportFilter) .build(); } /** * Create a dependency on the current module's local resources. You should have at least one such dependency * on any module which has its own resources. * * @param importFilter the import filter to apply * @param exportFilter the export filter to apply * @param resourceImportFilter the resource import filter to apply * @param resourceExportFilter the resource export filter to apply * @param classImportFilter the class import filter to apply * @param classExportFilter the class export filter to apply * @return the dependency spec * * @deprecated Use {@link LocalDependencySpecBuilder} instead. */ @Deprecated public static DependencySpec createLocalDependencySpec(final PathFilter importFilter, final PathFilter exportFilter, final PathFilter resourceImportFilter, final PathFilter resourceExportFilter, final ClassFilter classImportFilter, final ClassFilter classExportFilter) { return new LocalDependencySpecBuilder() .setImportFilter(importFilter) .setExportFilter(exportFilter) .setResourceImportFilter(resourceImportFilter) .setResourceExportFilter(resourceExportFilter) .setClassImportFilter(classImportFilter) .setClassExportFilter(classExportFilter) .build(); } /** * Create a system dependency. * * @param loaderPaths the set of paths to use from the system class loader * @return the dependency spec */ public static DependencySpec createSystemDependencySpec(final Set loaderPaths) { return new LocalDependencySpecBuilder() .setImportFilter(PathFilters.acceptAll()) .setLocalLoader(ClassLoaderLocalLoader.SYSTEM) .setLoaderPaths(loaderPaths) .build(); } /** * Create a system dependency. * * @param loaderPaths the set of paths to use from the system class loader * @param export {@code true} if this is a fully re-exported dependency, {@code false} if it should not be exported * @return the dependency spec */ public static DependencySpec createSystemDependencySpec(final Set loaderPaths, boolean export) { return new LocalDependencySpecBuilder() .setLocalLoader(ClassLoaderLocalLoader.SYSTEM) .setImportFilter(PathFilters.acceptAll()) .setLoaderPaths(loaderPaths) .setExport(export) .build(); } /** * Create a system dependency. * * @param importFilter the import filter to apply * @param exportFilter the export filter to apply * @param loaderPaths the set of paths to use from the system class loader * @return the dependency spec */ public static DependencySpec createSystemDependencySpec(final PathFilter importFilter, final PathFilter exportFilter, final Set loaderPaths) { return new LocalDependencySpecBuilder() .setImportFilter(importFilter) .setExportFilter(exportFilter) .setLocalLoader(ClassLoaderLocalLoader.SYSTEM) .setLoaderPaths(loaderPaths) .build(); } /** * Create a dependency on the given class loader. * * @param classLoader the class loader * @param loaderPaths the set of paths to use from this class loader * @return the dependency spec * * @deprecated Use {@link LocalDependencySpecBuilder} instead. */ @Deprecated public static DependencySpec createClassLoaderDependencySpec(final ClassLoader classLoader, final Set loaderPaths) { return createLocalDependencySpec(new ClassLoaderLocalLoader(classLoader), loaderPaths); } /** * Create a dependency on the given class loader. * * @param classLoader the class loader * @param loaderPaths the set of paths to use from this class loader * @param export {@code true} if this is a fully re-exported dependency, {@code false} if it should not be exported * @return the dependency spec * * @deprecated Use {@link LocalDependencySpecBuilder} instead. */ @Deprecated public static DependencySpec createClassLoaderDependencySpec(final ClassLoader classLoader, final Set loaderPaths, boolean export) { return createLocalDependencySpec(new ClassLoaderLocalLoader(classLoader), loaderPaths, export); } /** * Create a dependency on the given class loader. * * @param importFilter the import filter to apply * @param exportFilter the export filter to apply * @param classLoader the class loader * @param loaderPaths the set of paths to use from this class loader * @return the dependency spec * * @deprecated Use {@link LocalDependencySpecBuilder} instead. */ @Deprecated public static DependencySpec createClassLoaderDependencySpec(final PathFilter importFilter, final PathFilter exportFilter, final ClassLoader classLoader, final Set loaderPaths) { return createLocalDependencySpec(importFilter, exportFilter, new ClassLoaderLocalLoader(classLoader), loaderPaths); } /** * Create a dependency on the given local loader. * * @param localLoader the local loader * @param loaderPaths the set of paths that is exposed by the local loader * @return the dependency spec * * @deprecated Use {@link LocalDependencySpecBuilder} instead. */ @Deprecated public static DependencySpec createLocalDependencySpec(final LocalLoader localLoader, final Set loaderPaths) { return new LocalDependencySpecBuilder() .setLocalLoader(localLoader) .setLoaderPaths(loaderPaths) .build(); } /** * Create a dependency on the given local loader. * * @param localLoader the local loader * @param loaderPaths the set of paths that is exposed by the local loader * @param export {@code true} if this is a fully re-exported dependency, {@code false} if it should not be exported * @return the dependency spec * * @deprecated Use {@link LocalDependencySpecBuilder} instead. */ @Deprecated public static DependencySpec createLocalDependencySpec(final LocalLoader localLoader, final Set loaderPaths, boolean export) { return new LocalDependencySpecBuilder() .setLocalLoader(localLoader) .setLoaderPaths(loaderPaths) .setExport(export) .build(); } /** * Create a dependency on the given local loader. * * @param importFilter the import filter to apply * @param exportFilter the export filter to apply * @param localLoader the local loader * @param loaderPaths the set of paths that is exposed by the local loader * @return the dependency spec * * @deprecated Use {@link LocalDependencySpecBuilder} instead. */ @Deprecated public static DependencySpec createLocalDependencySpec(final PathFilter importFilter, final PathFilter exportFilter, final LocalLoader localLoader, final Set loaderPaths) { return new LocalDependencySpecBuilder() .setImportFilter(importFilter) .setExportFilter(exportFilter) .setLocalLoader(localLoader) .setLoaderPaths(loaderPaths) .build(); } /** * Create a dependency on the given local loader. * * @param importFilter the import filter to apply * @param exportFilter the export filter to apply * @param resourceImportFilter the resource import filter to apply * @param resourceExportFilter the resource export filter to apply * @param classImportFilter the class import filter to apply * @param classExportFilter the class export filter to apply * @param localLoader the local loader * @param loaderPaths the set of paths that is exposed by the local loader * @return the dependency spec * * @deprecated Use {@link LocalDependencySpecBuilder} instead. */ @Deprecated public static DependencySpec createLocalDependencySpec(final PathFilter importFilter, final PathFilter exportFilter, final PathFilter resourceImportFilter, final PathFilter resourceExportFilter, final ClassFilter classImportFilter, final ClassFilter classExportFilter, final LocalLoader localLoader, final Set loaderPaths) { return new LocalDependencySpecBuilder() .setImportFilter(importFilter) .setExportFilter(exportFilter) .setResourceImportFilter(resourceImportFilter) .setResourceExportFilter(resourceExportFilter) .setClassImportFilter(classImportFilter) .setClassExportFilter(classExportFilter) .setLocalLoader(localLoader) .setLoaderPaths(loaderPaths) .build(); } /** * Create a dependency on the given module. * * @param identifier the module identifier * @return the dependency spec * * @deprecated Use {@link ModuleDependencySpecBuilder} instead. */ @Deprecated(forRemoval = true) public static DependencySpec createModuleDependencySpec(final ModuleIdentifier identifier) { return createModuleDependencySpec(identifier.toString()); } /** * Create a dependency on the given module. * * @param name the module name * @return the dependency spec * * @deprecated Use {@link ModuleDependencySpecBuilder} instead. */ @Deprecated(forRemoval = true) public static DependencySpec createModuleDependencySpec(final String name) { return new ModuleDependencySpecBuilder() .setName(name) .build(); } /** * Create a dependency on the given module. * * @param identifier the module identifier * @param export {@code true} if the dependency should be exported by default * @return the dependency spec * * @deprecated Use {@link ModuleDependencySpecBuilder} instead. */ @Deprecated(forRemoval = true) public static DependencySpec createModuleDependencySpec(final ModuleIdentifier identifier, final boolean export) { return createModuleDependencySpec(identifier.toString(), export); } /** * Create a dependency on the given module. * * @param name the module name * @param export {@code true} if the dependency should be exported by default * @return the dependency spec * * @deprecated Use {@link ModuleDependencySpecBuilder} instead. */ @Deprecated(forRemoval = true) public static DependencySpec createModuleDependencySpec(final String name, final boolean export) { return new ModuleDependencySpecBuilder() .setName(name) .setExport(export) .build(); } /** * Create a dependency on the given module. * * @param identifier the module identifier * @param export {@code true} if this is a fully re-exported dependency, {@code false} if it should not be exported * @param optional {@code true} if the dependency is optional, {@code false} if it is mandatory * @return the dependency spec * * @deprecated Use {@link ModuleDependencySpecBuilder} instead. */ @Deprecated(forRemoval = true) public static DependencySpec createModuleDependencySpec(final ModuleIdentifier identifier, final boolean export, final boolean optional) { return createModuleDependencySpec(identifier.toString(), export, optional); } /** * Create a dependency on the given module. * * @param name the module name * @param export {@code true} if this is a fully re-exported dependency, {@code false} if it should not be exported * @param optional {@code true} if the dependency is optional, {@code false} if it is mandatory * @return the dependency spec * * @deprecated Use {@link ModuleDependencySpecBuilder} instead. */ @Deprecated(forRemoval = true) public static DependencySpec createModuleDependencySpec(final String name, final boolean export, final boolean optional) { return new ModuleDependencySpecBuilder() .setName(name) .setExport(export) .setOptional(optional) .build(); } /** * Create a dependency on the given module. * * @param moduleLoader the specific module loader from which the module should be acquired * @param identifier the module identifier * @param export {@code true} if this is a fully re-exported dependency, {@code false} if it should not be exported * @return the dependency spec * * @deprecated Use {@link ModuleDependencySpecBuilder} instead. */ @Deprecated(forRemoval = true) public static DependencySpec createModuleDependencySpec(final ModuleLoader moduleLoader, final ModuleIdentifier identifier, final boolean export) { return createModuleDependencySpec(moduleLoader, identifier.toString(), export); } /** * Create a dependency on the given module. * * @param moduleLoader the specific module loader from which the module should be acquired * @param name the module name * @param export {@code true} if this is a fully re-exported dependency, {@code false} if it should not be exported * @return the dependency spec * * @deprecated Use {@link ModuleDependencySpecBuilder} instead. */ @Deprecated(forRemoval = true) public static DependencySpec createModuleDependencySpec(final ModuleLoader moduleLoader, final String name, final boolean export) { return new ModuleDependencySpecBuilder() .setModuleLoader(moduleLoader) .setName(name) .setExport(export) .build(); } /** * Create a dependency on the given module. * * @param moduleLoader the specific module loader from which the module should be acquired * @param identifier the module identifier * @param export {@code true} if this is a fully re-exported dependency, {@code false} if it should not be exported * @param optional {@code true} if the dependency is optional, {@code false} if it is mandatory * @return the dependency spec * * @deprecated Use {@link ModuleDependencySpecBuilder} instead. */ @Deprecated(forRemoval = true) public static DependencySpec createModuleDependencySpec(final ModuleLoader moduleLoader, final ModuleIdentifier identifier, final boolean export, final boolean optional) { return createModuleDependencySpec(moduleLoader, identifier.toString(), export, optional); } /** * Create a dependency on the given module. * * @param moduleLoader the specific module loader from which the module should be acquired * @param name the module name * @param export {@code true} if this is a fully re-exported dependency, {@code false} if it should not be exported * @param optional {@code true} if the dependency is optional, {@code false} if it is mandatory * @return the dependency spec * * @deprecated Use {@link ModuleDependencySpecBuilder} instead. */ @Deprecated(forRemoval = true) public static DependencySpec createModuleDependencySpec(final ModuleLoader moduleLoader, final String name, final boolean export, final boolean optional) { return new ModuleDependencySpecBuilder() .setModuleLoader(moduleLoader) .setName(name) .setExport(export) .setOptional(optional) .build(); } /** * Create a dependency on the given module. * * @param exportFilter the export filter to apply * @param identifier the module identifier * @param optional {@code true} if the dependency is optional, {@code false} if it is mandatory * @return the dependency spec * * @deprecated Use {@link ModuleDependencySpecBuilder} instead. */ @Deprecated(forRemoval = true) public static DependencySpec createModuleDependencySpec(final PathFilter exportFilter, final ModuleIdentifier identifier, final boolean optional) { return createModuleDependencySpec(exportFilter, identifier.toString(), optional); } /** * Create a dependency on the given module. * * @param exportFilter the export filter to apply * @param name the module name * @param optional {@code true} if the dependency is optional, {@code false} if it is mandatory * @return the dependency spec * * @deprecated Use {@link ModuleDependencySpecBuilder} instead. */ @Deprecated(forRemoval = true) public static DependencySpec createModuleDependencySpec(final PathFilter exportFilter, final String name, final boolean optional) { return new ModuleDependencySpecBuilder() .setExportFilter(exportFilter) .setName(name) .setOptional(optional) .build(); } /** * Create a dependency on the given module. * * @param exportFilter the export filter to apply * @param moduleLoader the specific module loader from which the module should be acquired * @param identifier the module identifier * @param optional {@code true} if the dependency is optional, {@code false} if it is mandatory * @return the dependency spec * * @deprecated Use {@link ModuleDependencySpecBuilder} instead. */ @Deprecated(forRemoval = true) public static DependencySpec createModuleDependencySpec(final PathFilter exportFilter, final ModuleLoader moduleLoader, final ModuleIdentifier identifier, final boolean optional) { return createModuleDependencySpec(exportFilter, moduleLoader, identifier.toString(), optional); } /** * Create a dependency on the given module. * * @param exportFilter the export filter to apply * @param moduleLoader the specific module loader from which the module should be acquired * @param name the module name * @param optional {@code true} if the dependency is optional, {@code false} if it is mandatory * @return the dependency spec * * @deprecated Use {@link ModuleDependencySpecBuilder} instead. */ @Deprecated(forRemoval = true) public static DependencySpec createModuleDependencySpec(final PathFilter exportFilter, final ModuleLoader moduleLoader, final String name, final boolean optional) { return new ModuleDependencySpecBuilder() .setExportFilter(exportFilter) .setModuleLoader(moduleLoader) .setName(name) .setOptional(optional) .build(); } /** * Create a dependency on the given module. * * @param importFilter the import filter to apply * @param exportFilter the export filter to apply * @param moduleLoader the specific module loader from which the module should be acquired * @param identifier the module identifier * @param optional {@code true} if the dependency is optional, {@code false} if it is mandatory * @return the dependency spec * * @deprecated Use {@link ModuleDependencySpecBuilder} instead. */ @Deprecated(forRemoval = true) public static DependencySpec createModuleDependencySpec(final PathFilter importFilter, final PathFilter exportFilter, final ModuleLoader moduleLoader, final ModuleIdentifier identifier, final boolean optional) { return createModuleDependencySpec(importFilter, exportFilter, PathFilters.acceptAll(), PathFilters.acceptAll(), ClassFilters.acceptAll(), ClassFilters.acceptAll(), moduleLoader, identifier, optional); } /** * Create a dependency on the given module. * * @param importFilter the import filter to apply * @param exportFilter the export filter to apply * @param moduleLoader the specific module loader from which the module should be acquired * @param name the module name * @param optional {@code true} if the dependency is optional, {@code false} if it is mandatory * @return the dependency spec * * @deprecated Use {@link ModuleDependencySpecBuilder} instead. */ @Deprecated(forRemoval = true) public static DependencySpec createModuleDependencySpec(final PathFilter importFilter, final PathFilter exportFilter, final ModuleLoader moduleLoader, final String name, final boolean optional) { return new ModuleDependencySpecBuilder() .setImportFilter(importFilter) .setExportFilter(exportFilter) .setModuleLoader(moduleLoader) .setName(name) .setOptional(optional) .build(); } /** * Create a dependency on the given module. * * @param importFilter the import filter to apply * @param exportFilter the export filter to apply * @param resourceImportFilter the resource import filter to apply * @param resourceExportFilter the resource export filter to apply * @param classImportFilter the class import filter to apply * @param classExportFilter the class export filter to apply * @param moduleLoader the specific module loader from which the module should be acquired * @param identifier the module identifier * @param optional {@code true} if the dependency is optional, {@code false} if it is mandatory * @return the dependency spec * * @deprecated Use {@link ModuleDependencySpecBuilder} instead. */ @Deprecated(forRemoval = true) public static DependencySpec createModuleDependencySpec(final PathFilter importFilter, final PathFilter exportFilter, final PathFilter resourceImportFilter, final PathFilter resourceExportFilter, final ClassFilter classImportFilter, final ClassFilter classExportFilter, final ModuleLoader moduleLoader, final ModuleIdentifier identifier, final boolean optional) { return createModuleDependencySpec(importFilter, exportFilter, resourceImportFilter, resourceExportFilter, classImportFilter, classExportFilter, moduleLoader, identifier.toString(), optional); } /** * Create a dependency on the given module. * * @param importFilter the import filter to apply * @param exportFilter the export filter to apply * @param resourceImportFilter the resource import filter to apply * @param resourceExportFilter the resource export filter to apply * @param classImportFilter the class import filter to apply * @param classExportFilter the class export filter to apply * @param moduleLoader the specific module loader from which the module should be acquired * @param name the module name * @param optional {@code true} if the dependency is optional, {@code false} if it is mandatory * @return the dependency spec * * @deprecated Use {@link ModuleDependencySpecBuilder} instead. */ @Deprecated(forRemoval = true) public static DependencySpec createModuleDependencySpec(final PathFilter importFilter, final PathFilter exportFilter, final PathFilter resourceImportFilter, final PathFilter resourceExportFilter, final ClassFilter classImportFilter, final ClassFilter classExportFilter, final ModuleLoader moduleLoader, final String name, final boolean optional) { return new ModuleDependencySpecBuilder() .setImportFilter(importFilter) .setExportFilter(exportFilter) .setResourceImportFilter(resourceImportFilter) .setResourceExportFilter(resourceExportFilter) .setClassImportFilter(classImportFilter) .setClassExportFilter(classExportFilter) .setModuleLoader(moduleLoader) .setName(name) .setOptional(optional) .build(); } /** * A constant dependency which always represents a module's own content. */ public static final DependencySpec OWN_DEPENDENCY = new LocalDependencySpecBuilder().setExportFilter(PathFilters.acceptAll()).build(); } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/DependencySpecBuilder.java000066400000000000000000000162251472011152000304130ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import org.jboss.modules.filter.ClassFilter; import org.jboss.modules.filter.ClassFilters; import org.jboss.modules.filter.PathFilter; import org.jboss.modules.filter.PathFilters; /** * The base class of dependency specification builders. */ public abstract class DependencySpecBuilder { PathFilter importFilter = PathFilters.getDefaultImportFilter(); PathFilter exportFilter = PathFilters.rejectAll(); PathFilter resourceImportFilter = PathFilters.acceptAll(); PathFilter resourceExportFilter = PathFilters.acceptAll(); ClassFilter classImportFilter = ClassFilters.acceptAll(); ClassFilter classExportFilter = ClassFilters.acceptAll(); /** * Construct a new instance. */ public DependencySpecBuilder() { } /** * Get the import filter to use. The default value is {@link PathFilters#getDefaultImportFilter()}. * * @return the import filter to use */ public PathFilter getImportFilter() { return importFilter; } /** * Set the import filter to use. * * @param importFilter the import filter to use (must not be {@code null}) * @return this builder */ public DependencySpecBuilder setImportFilter(final PathFilter importFilter) { if (importFilter == null) { throw new IllegalArgumentException("importFilter is null"); } this.importFilter = importFilter; return this; } /** * Set a simple import filter, based on a {@code boolean} flag specifying whether services should be * imported. If the flag is {@code true}, the import filter is set to {@link PathFilters#getDefaultImportFilterWithServices()}, * otherwise it is set to {@link PathFilters#getDefaultImportFilter()}. Any previous import filter setting is * overwritten. * * @param services the services flag * @return this builder */ public DependencySpecBuilder setImportServices(final boolean services) { return setImportFilter(services ? PathFilters.getDefaultImportFilterWithServices() : PathFilters.getDefaultImportFilter()); } /** * Get the export filter to use. The default value is {@link PathFilters#rejectAll()}. * * @return the export filter to use */ public PathFilter getExportFilter() { return exportFilter; } /** * Set the export filter to use. * * @param exportFilter the export filter to use (must not be {@code null}) * @return this builder */ public DependencySpecBuilder setExportFilter(final PathFilter exportFilter) { if (exportFilter == null) { throw new IllegalArgumentException("exportFilter is null"); } this.exportFilter = exportFilter; return this; } /** * Set a simple export filter, based on a {@code boolean} flag. If the flag is {@code true}, the * export filter is set to {@link PathFilters#acceptAll()}, otherwise it is set to {@link PathFilters#rejectAll()}. * Any previous export filter setting is overwritten. * * @param export the export flag * @return this builder */ public DependencySpecBuilder setExport(final boolean export) { return setExportFilter(export ? PathFilters.acceptAll() : PathFilters.rejectAll()); } /** * Get the resource import filter to use. The default value is {@link PathFilters#acceptAll()}. * * @return the resource import filter to use */ public PathFilter getResourceImportFilter() { return resourceImportFilter; } /** * Set the resource import filter to use. * * @param resourceImportFilter the resource import filter to use (must not be {@code null}) * @return this builder */ public DependencySpecBuilder setResourceImportFilter(final PathFilter resourceImportFilter) { if (resourceImportFilter == null) { throw new IllegalArgumentException("resourceImportFilter is null"); } this.resourceImportFilter = resourceImportFilter; return this; } /** * Get the resource export filter to use. The default value is {@link PathFilters#acceptAll()}. * * @return the resource export filter to use */ public PathFilter getResourceExportFilter() { return resourceExportFilter; } /** * Set the resource export filter to use. The default value is {@link PathFilters#acceptAll()}. * * @param resourceExportFilter the resource export filter to use (must not be {@code null}) * @return this builder */ public DependencySpecBuilder setResourceExportFilter(final PathFilter resourceExportFilter) { if (resourceExportFilter == null) { throw new IllegalArgumentException("resourceExportFilter is null"); } this.resourceExportFilter = resourceExportFilter; return this; } /** * Get the class import filter to use. The default value is {@link ClassFilters#acceptAll()}. * * @return the class import filter to use */ public ClassFilter getClassImportFilter() { return classImportFilter; } /** * Set the class import filter to use. * * @param classImportFilter the class import filter to use (must not be {@code null}) * @return this builder */ public DependencySpecBuilder setClassImportFilter(final ClassFilter classImportFilter) { if (classImportFilter == null) { throw new IllegalArgumentException("classImportFilter is null"); } this.classImportFilter = classImportFilter; return this; } /** * Get the class export filter to use. The default value is {@link ClassFilters#acceptAll()}. * * @return the class export filter to use */ public ClassFilter getClassExportFilter() { return classExportFilter; } /** * Set the class export filter to use. * * @param classExportFilter the class export filter to use (must not be {@code null}) * @return this builder */ public DependencySpecBuilder setClassExportFilter(final ClassFilter classExportFilter) { if (classExportFilter == null) { throw new IllegalArgumentException("classExportFilter is null"); } this.classExportFilter = classExportFilter; return this; } /** * Construct the dependency specification. * * @return the dependency specification */ public abstract DependencySpec build(); } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/DependencyTreeViewer.java000066400000000000000000000130241472011152000302650ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.util.Arrays; import org.jboss.modules.filter.PathFilter; import org.jboss.modules.filter.PathFilters; /** * A dependency tree viewer utility. Prints out the dependency tree for a module. */ public final class DependencyTreeViewer { private static DependencySpec[] filtered(Class oType, DependencySpec... inputs) { final DependencySpec[] newArray = Arrays.copyOf(inputs, inputs.length); int o = 0; for (int i = 0; i < inputs.length; i ++) { if (oType.getComponentType().isInstance(inputs[i])) { newArray[o++] = inputs[i]; } } return Arrays.copyOf(newArray, o, oType); } private static void print(PrintWriter out, String prefix, ModuleSpec spec, FastCopyHashSet visited, File... roots) { if (spec instanceof AliasModuleSpec) { final AliasModuleSpec aliasModuleSpec = (AliasModuleSpec) spec; out.print(" -> "); final String aliasTarget = aliasModuleSpec.getAliasName(); out.println(aliasTarget); if (visited.add(aliasTarget)) { try { final ModuleSpec moduleSpec = LocalModuleFinder.parseModuleXmlFile(aliasTarget, null, roots); print(out, prefix, moduleSpec, visited); } catch (IOException e) { out.println(e); } catch (ModuleLoadException e) { out.println(e); } } } else if (spec instanceof ConcreteModuleSpec) { out.println(); final ConcreteModuleSpec concreteModuleSpec = (ConcreteModuleSpec) spec; final DependencySpec[] dependencies = filtered(ModuleDependencySpec[].class, concreteModuleSpec.getDependencies()); for (int i = 0, dependenciesLength = dependencies.length; i < dependenciesLength; i++) { print(out, prefix, dependencies[i], visited, i == dependenciesLength - 1, roots); } } else { out.println(); } } private static void print(PrintWriter out, String prefix, DependencySpec spec, FastCopyHashSet visited, final boolean last, final File... roots) { if (spec instanceof ModuleDependencySpec) { final ModuleDependencySpec moduleDependencySpec = (ModuleDependencySpec) spec; final String name = moduleDependencySpec.getName(); out.print(prefix); out.print(last ? '└' : '├'); out.print('─'); out.print(' '); out.print(name); if (moduleDependencySpec.isOptional()) { out.print(" (optional)"); } final PathFilter exportFilter = moduleDependencySpec.getExportFilter(); if (! exportFilter.equals(PathFilters.rejectAll())) { out.print(" (exported)"); } if (visited.add(name)) { print(out, prefix + (last ? " " : "│ "), name, visited, roots); } else { out.println(); } } } private static void print(PrintWriter out, String prefix, String name, FastCopyHashSet visited, final File... roots) { final ModuleSpec moduleSpec; try { moduleSpec = LocalModuleFinder.parseModuleXmlFile(name, null, roots); if (moduleSpec == null) { out.println(" (not found)"); } else { print(out, prefix, moduleSpec, visited, roots); } } catch (IOException e) { out.print(" ("); out.print(e); out.println(")"); } catch (ModuleLoadException e) { out.print(" ("); out.print(e); out.println(")"); } } /** * Print the dependency tree for the given module with the given module root list. * * @param out the output stream to use * @param identifier the identifier of the module to examine * @param roots the module roots to search * @deprecated Use {@link #print(PrintWriter, String, File...)} instead. */ @Deprecated(forRemoval = true) public static void print(PrintWriter out, ModuleIdentifier identifier, final File... roots) { print(out, identifier.toString(), roots); } /** * Print the dependency tree for the given module with the given module root list. * * @param out the output stream to use * @param name the name of the module to examine * @param roots the module roots to search */ public static void print(PrintWriter out, String name, final File... roots) { out.print(name); print(out, "", name, new FastCopyHashSet<>(), roots); out.flush(); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/FastCopyHashSet.java000066400000000000000000000372571472011152000272330ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.IOException; import java.io.Serializable; import java.util.AbstractSet; import java.util.Arrays; import java.util.Collection; import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Set; /** * A HashSet that is optimized for fast shallow copies. If the copy-ctor is * passed another FastCopyHashSet, or clone is called on this set, the shallow * copy can be performed using little more than a single array copy. In order to * accomplish this, immutable objects must be used internally, so update * operations result in slightly more object churn than HashSet. *

* Note: It is very important to use a smaller load factor than you normally * would for HashSet, since the implementation is open-addressed with linear * probing. With a 50% load-factor a get is expected to return in only 2 probes. * However, a 90% load-factor is expected to return in around 50 probes. * * @author Jason T. Greene * @author David M. Lloyd */ class FastCopyHashSet extends AbstractSet implements Set, Cloneable, Serializable { /** * Serialization ID */ private static final long serialVersionUID = 10929568968762L; /** * Same default as HashMap, must be a power of 2 */ private static final int DEFAULT_CAPACITY = 64; /** * MAX_INT - 1 */ private static final int MAXIMUM_CAPACITY = 1 << 30; /** * 50% */ private static final float DEFAULT_LOAD_FACTOR = 0x0.5p0f; /** * The open-addressed table */ private transient E[] table; /** * The current number of key-value pairs */ private transient int size; /** * The next resize */ private transient int threshold; /** * The user defined load factor which defines when to resize */ private final float loadFactor; /** * Counter used to detect changes made outside of an iterator */ private transient int modCount; /** * Accumulated hash code */ private transient int hashCode; FastCopyHashSet(int initialCapacity, float loadFactor) { if (initialCapacity < 0) throw new IllegalArgumentException("Can not have a negative size table!"); if (initialCapacity > MAXIMUM_CAPACITY) initialCapacity = MAXIMUM_CAPACITY; if (!(loadFactor > 0F && loadFactor <= 1F)) throw new IllegalArgumentException("Load factor must be greater than 0 and less than or equal to 1"); this.loadFactor = loadFactor; init(initialCapacity, loadFactor); } FastCopyHashSet(Set set) { if (set instanceof FastCopyHashSet) { FastCopyHashSet fast = (FastCopyHashSet) set; table = fast.table.clone(); loadFactor = fast.loadFactor; size = fast.size; threshold = fast.threshold; hashCode = fast.hashCode; } else { loadFactor = DEFAULT_LOAD_FACTOR; init(set.size(), loadFactor); addAll(set); } } @SuppressWarnings("unchecked") private void init(int initialCapacity, float loadFactor) { int c = 1; while (c < initialCapacity) c <<= 1; threshold = (int) (c * loadFactor); // Include the load factor when sizing the table for the first time if (initialCapacity > threshold && c < MAXIMUM_CAPACITY) { c <<= 1; threshold = (int) (c * loadFactor); } table = (E[]) new Object[c]; } FastCopyHashSet(int initialCapacity) { this(initialCapacity, DEFAULT_LOAD_FACTOR); } FastCopyHashSet() { this(DEFAULT_CAPACITY); } private int nextIndex(int index, int length) { index = (index >= length - 1) ? 0 : index + 1; return index; } private static int index(int hashCode, int length) { return hashCode & (length - 1); } public int size() { return size; } public boolean isEmpty() { return size == 0; } public boolean contains(Object key) { if (key == null) { return false; } int hash = key.hashCode(); int length = table.length; int index = index(hash, length); for (int start = index; ;) { E e = table[index]; if (e == null) return false; if (key.equals(e)) return true; index = nextIndex(index, length); if (index == start) // Full table return false; } } public boolean add(E key) { if (key == null) { throw new IllegalArgumentException("key is null"); } E[] table = this.table; int hash = key.hashCode(); int length = table.length; int index = index(hash, length); boolean f = false; for (int start = index; ;) { E e = table[index]; if (e == null) break; if (! f) { f= true; } if (key.equals(e)) { return false; } index = nextIndex(index, length); if (index == start) throw new IllegalStateException("Table is full!"); } modCount++; table[index] = key; hashCode += key.hashCode(); if (++size >= threshold) resize(length); return true; } @SuppressWarnings("unchecked") private void resize(int from) { int newLength = from << 1; // Can't get any bigger if (newLength > MAXIMUM_CAPACITY || newLength <= from) return; E[] newTable = (E[]) new Object[newLength]; E[] old = table; for (E e : old) { if (e == null) continue; int index = index(e.hashCode(), newLength); while (newTable[index] != null) index = nextIndex(index, newLength); newTable[index] = e; } threshold = (int) (loadFactor * newLength); table = newTable; } public boolean addAll(Collection set) { int size = set.size(); if (size == 0) return false; boolean changed = false; for (E e : set) { if (add(e)) { changed = true; } } return changed; } public boolean remove(Object key) { E[] table = this.table; int length = table.length; int hash = key.hashCode(); int start = index(hash, length); for (int index = start; ;) { E e = table[index]; if (e == null) return false; if (key.equals(e)) { table[index] = null; hashCode -= hash; relocate(index); modCount++; size--; return true; } index = nextIndex(index, length); if (index == start) return false; } } private void relocate(int start) { E[] table = this.table; int length = table.length; int current = nextIndex(start, length); for (; ;) { E e = table[current]; if (e == null) return; // A Doug Lea variant of Knuth's Section 6.4 Algorithm R. // This provides a non-recursive method of relocating // entries to their optimal positions once a gap is created. int prefer = index(e.hashCode(), length); if ((current < prefer && (prefer <= start || start <= current)) || (prefer <= start && start <= current)) { table[start] = e; table[current] = null; start = current; } current = nextIndex(current, length); } } public void clear() { modCount++; E[] table = this.table; for (int i = 0; i < table.length; i++) table[i] = null; size = hashCode = 0; } @SuppressWarnings("unchecked") public FastCopyHashSet clone() { try { FastCopyHashSet clone = (FastCopyHashSet) super.clone(); clone.table = table.clone(); return clone; } catch (CloneNotSupportedException e) { // should never happen throw new IllegalStateException(e); } } public Iterator iterator() { return new KeyIterator(); } public void printDebugStats() { int optimal = 0; int total = 0; int totalSkew = 0; int maxSkew = 0; for (int i = 0; i < table.length; i++) { E e = table[i]; if (e != null) { total++; int target = index(e.hashCode(), table.length); if (i == target) optimal++; else { int skew = Math.abs(i - target); if (skew > maxSkew) maxSkew = skew; totalSkew += skew; } } } System.out.println(" Size: " + size); System.out.println(" Real Size: " + total); System.out.println(" Optimal: " + optimal + " (" + (float) optimal * 100 / total + "%)"); System.out.println(" Average Distance: " + ((float) totalSkew / (total - optimal))); System.out.println(" Max Distance: " + maxSkew); } @SuppressWarnings("unchecked") private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); int size = s.readInt(); init(size, loadFactor); for (int i = 0; i < size; i++) { E key = (E) s.readObject(); putForCreate(key); } this.size = size; } @SuppressWarnings("unchecked") private void putForCreate(E key) { E[] table = this.table; int hash = key.hashCode(); int length = table.length; int index = index(hash, length); E e = table[index]; while (e != null) { index = nextIndex(index, length); e = table[index]; } table[index] = key; } private void writeObject(java.io.ObjectOutputStream s) throws IOException { s.defaultWriteObject(); s.writeInt(size); for (E e : table) { if (e != null) { s.writeObject(e); } } } public boolean containsAll(final Collection c) { final E[] table = this.table; for (E e : table) { if (e != null) { if (! c.contains(e)) { return false; } } } return true; } @SuppressWarnings("NonFinalFieldReferenceInEquals") public boolean equals(final Object o) { if (o == this) return true; if (! (o instanceof Set)) return false; if (o instanceof FastCopyHashSet) { final FastCopyHashSet set = (FastCopyHashSet) o; if (hashCode != set.hashCode) { return false; } if (table.length == set.table.length) { return Arrays.equals(table, set.table); } } Set set = (Set) o; if (set.size() != size()) return false; try { return containsAll(set); } catch (ClassCastException unused) { return false; } catch (NullPointerException unused) { return false; } } @SuppressWarnings("NonFinalFieldReferencedInHashCode") public int hashCode() { return hashCode; } public Object[] getRawArray() { return table; } private class KeyIterator implements Iterator { private int next = 0; private int expectedCount = modCount; private int current = -1; private boolean hasNext; private E[] table = FastCopyHashSet.this.table; public E next() { if (modCount != expectedCount) throw new ConcurrentModificationException(); if (!hasNext && !hasNext()) throw new NoSuchElementException(); current = next++; hasNext = false; return table[current]; } public boolean hasNext() { if (hasNext == true) return true; E[] table = this.table; for (int i = next; i < table.length; i++) { if (table[i] != null) { next = i; return hasNext = true; } } next = table.length; return false; } @SuppressWarnings("unchecked") public void remove() { if (modCount != expectedCount) throw new ConcurrentModificationException(); int current = this.current; int delete = current; if (current == -1) throw new IllegalStateException(); // Invalidate current (prevents multiple remove) this.current = -1; // Start were we relocate next = delete; E[] table = this.table; if (table != FastCopyHashSet.this.table) { FastCopyHashSet.this.remove(table[delete]); table[delete] = null; expectedCount = modCount; return; } int length = table.length; int i = delete; table[delete] = null; size--; for (; ;) { i = nextIndex(i, length); E e = table[i]; if (e == null) break; int prefer = index(e.hashCode(), length); if ((i < prefer && (prefer <= delete || delete <= i)) || (prefer <= delete && delete <= i)) { // Snapshot the unseen portion of the table if we have // to relocate an entry that was already seen by this iterator if (i < current && current <= delete && table == FastCopyHashSet.this.table) { int remaining = length - current; E[] newTable = (E[]) new Object[remaining]; System.arraycopy(table, current, newTable, 0, remaining); // Replace iterator's table. // Leave table local var pointing to the real table this.table = newTable; next = 0; } // Do the swap on the real table table[delete] = e; table[i] = null; delete = i; } } } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/FileSystemClassPathModuleFinder.java000077500000000000000000000335571472011152000324120ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import static org.jboss.modules.Utils.DEPENDENCIES; import static org.jboss.modules.Utils.EXPORT; import static org.jboss.modules.Utils.MODULES_DIR; import static org.jboss.modules.Utils.MODULE_VERSION; import static org.jboss.modules.Utils.OPTIONAL; import static org.jboss.modules.Utils.SERVICES; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.security.AccessControlContext; import java.security.AccessController; import java.util.function.Supplier; import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.jar.Manifest; import org.jboss.modules.filter.MultiplePathFilterBuilder; import org.jboss.modules.filter.PathFilter; import org.jboss.modules.filter.PathFilters; import org.jboss.modules.xml.PermissionsXmlParser; import org.jboss.modules.xml.XmlPullParserException; /** * A module finder which loads modules from individual JARs or directories on the file system, supporting the JAR specification headers * as well as the extended {@code MANIFEST} headers supported by JBoss Modules. The JAR files or modules may in turn contain * nested module repositories inside of their {@code modules} subdirectories. Modules in nested repositories are only visible * to the module that contains them. * * @author David M. Lloyd * @author Richard Opalka */ public class FileSystemClassPathModuleFinder implements ModuleFinder { static final ModuleLoader EMPTY_MODULE_LOADER = new ModuleLoader(); static final SimpleSupplier EMPTY_MODULE_LOADER_SUPPLIER = new SimpleSupplier<>(EMPTY_MODULE_LOADER); private final AccessControlContext context; private final Supplier baseModuleLoaderSupplier; private final Supplier extensionModuleLoaderSupplier; private static final PathFilter NO_MODULES_DIR; static { final MultiplePathFilterBuilder builder = PathFilters.multiplePathFilterBuilder(true); builder.addFilter(PathFilters.is(MODULES_DIR), false); builder.addFilter(PathFilters.isChildOf(MODULES_DIR), false); NO_MODULES_DIR = builder.create(); } /** * Construct a new instance. * * @param baseModuleLoader the module loader to use to load module dependencies from (must not be {@code null}) */ public FileSystemClassPathModuleFinder(final ModuleLoader baseModuleLoader) { this(baseModuleLoader, EMPTY_MODULE_LOADER_SUPPLIER); } /** * Construct a new instance. * * @param baseModuleLoader the module loader to use to load module dependencies from (must not be {@code null}) * @param extensionModuleLoaderSupplier a supplier which yields a module loader for loading extensions (must not be {@code null}) */ public FileSystemClassPathModuleFinder(final ModuleLoader baseModuleLoader, final Supplier extensionModuleLoaderSupplier) { this(new SimpleSupplier<>(baseModuleLoader), extensionModuleLoaderSupplier); if (baseModuleLoader == null) throw new IllegalArgumentException("baseModuleLoader is null"); } /** * Construct a new instance. * * @param baseModuleLoaderSupplier the supplier to supply a module loader for loading dependencies (must not be {@code null}) * @param extensionModuleLoaderSupplier a supplier which yields a module loader for loading extensions (must not be {@code null}) */ public FileSystemClassPathModuleFinder(final Supplier baseModuleLoaderSupplier, final Supplier extensionModuleLoaderSupplier) { if (baseModuleLoaderSupplier == null) throw new IllegalArgumentException("baseModuleLoaderSupplier is null"); this.baseModuleLoaderSupplier = baseModuleLoaderSupplier; if (extensionModuleLoaderSupplier == null) throw new IllegalArgumentException("extensionModuleLoaderSupplier is null"); this.extensionModuleLoaderSupplier = extensionModuleLoaderSupplier; context = AccessController.getContext(); } public ModuleSpec findModule(final String name, final ModuleLoader delegateLoader) throws ModuleLoadException { final Path path = Paths.get(name); if (! path.isAbsolute()) { return null; } final Path normalizedPath = path.normalize(); if (! path.equals(normalizedPath)) { return null; } try { final Manifest manifest; final String fileName = path.toString(); final ModuleSpec.Builder builder = ModuleSpec.build(fileName); final ResourceLoader resourceLoader; final ModuleLoader fatModuleLoader; final ModuleLoader baseModuleLoader = baseModuleLoaderSupplier.get(); if (Files.isDirectory(path)) { manifest = new Manifest(); final Path manifestPath = path.resolve("META-INF/MANIFEST.MF"); if (Files.exists(manifestPath)) try { try (InputStream stream = Files.newInputStream(manifestPath, StandardOpenOption.READ)) { manifest.read(stream); } } catch (NoSuchFileException | FileNotFoundException ignored) { } catch (IOException e) { throw new ModuleLoadException("Failed to load MANIFEST from " + path, e); } resourceLoader = new PathResourceLoader(fileName, path, context); fatModuleLoader = new DelegatingModuleLoader(baseModuleLoader, new LocalModuleFinder(new File[]{ path.resolve(MODULES_DIR).toFile() })); } else { // assume some kind of JAR file final JarFile jarFile = new JarFile(path.toFile(), true, JarFile.OPEN_READ, JarFile.runtimeVersion()); try { try { manifest = jarFile.getManifest(); } catch (IOException e) { throw new ModuleLoadException("Failed to load MANIFEST from " + path, e); } resourceLoader = new JarFileResourceLoader(fileName, jarFile); } catch (Throwable t) { try { jarFile.close(); } catch (Throwable e2) { e2.addSuppressed(t); throw e2; } throw t; } fatModuleLoader = new DelegatingModuleLoader(baseModuleLoader, new ResourceLoaderModuleFinder(resourceLoader)); } // now build the module specification from the manifest information try { addSelfContent(builder, resourceLoader); addSelfDependency(builder); final Attributes mainAttributes = manifest.getMainAttributes(); setMainClass(builder, mainAttributes); addClassPathDependencies(builder, delegateLoader, path, mainAttributes); final ModuleLoader extensionModuleLoader = extensionModuleLoaderSupplier.get(); addExtensionDependencies(builder, mainAttributes, extensionModuleLoader); addModuleDependencies(builder, fatModuleLoader, mainAttributes); setModuleVersion(builder, mainAttributes); addSystemDependencies(builder); addPermissions(builder, resourceLoader, delegateLoader); } catch (Throwable t) { resourceLoader.close(); throw t; } return builder.create(); } catch (IOException e) { throw new ModuleLoadException(e); } } void addPermissions(final ModuleSpec.Builder builder, final ResourceLoader resourceLoader, final ModuleLoader moduleLoader) { final Resource resource = resourceLoader.getResource("META-INF/permissions.xml"); if (resource != null) { try { try (InputStream stream = resource.openStream()) { builder.setPermissionCollection(PermissionsXmlParser.parsePermissionsXml(stream, moduleLoader, builder.getName())); } } catch (XmlPullParserException | IOException ignored) { } } } void addSystemDependencies(final ModuleSpec.Builder builder) { builder.addDependency(new LocalDependencySpecBuilder() .setLocalLoader(ClassLoaderLocalLoader.SYSTEM) .setLoaderPaths(JDKPaths.JDK) .build()); } void addModuleDependencies(final ModuleSpec.Builder builder, final ModuleLoader fatModuleLoader, final Attributes mainAttributes) { final String dependencies = mainAttributes.getValue(DEPENDENCIES); final String[] dependencyEntries = dependencies == null ? Utils.NO_STRINGS : dependencies.split("\\s*,\\s*"); for (String dependencyEntry : dependencyEntries) { boolean optional = false; boolean export = false; boolean services = false; dependencyEntry = dependencyEntry.trim(); if (! dependencyEntry.isEmpty()) { String[] fields = dependencyEntry.split("\\s+"); if (fields.length < 1) { continue; } String moduleName = fields[0]; for (int i = 1; i < fields.length; i++) { String field = fields[i]; if (field.equals(OPTIONAL)) { optional = true; } else if (field.equals(EXPORT)) { export = true; } else if (field.equals(SERVICES)) { services = true; } // else ignored } builder.addDependency(new ModuleDependencySpecBuilder() .setImportServices(services) .setExport(export) .setModuleLoader(fatModuleLoader) .setName(moduleName) .setOptional(optional) .build()); } } } void setModuleVersion(final ModuleSpec.Builder builder, final Attributes mainAttributes) { final String versionString = mainAttributes.getValue(MODULE_VERSION); if (versionString != null) { builder.setVersion(Version.parse(versionString)); } } void addExtensionDependencies(final ModuleSpec.Builder builder, final Attributes mainAttributes, final ModuleLoader extensionModuleLoader) { final String extensionList = mainAttributes.getValue(Attributes.Name.EXTENSION_LIST); final String[] extensionListEntries = extensionList == null ? Utils.NO_STRINGS : extensionList.split("\\s+"); for (String entry : extensionListEntries) { if (! entry.isEmpty()) { builder.addDependency(new ModuleDependencySpecBuilder() .setImportFilter(PathFilters.acceptAll()) .setModuleLoader(extensionModuleLoader) .setName(entry) .setOptional(true) .build()); } } } void addClassPathDependencies(final ModuleSpec.Builder builder, final ModuleLoader moduleLoader, final Path path, final Attributes mainAttributes) { final String classPath = mainAttributes.getValue(Attributes.Name.CLASS_PATH); final String[] classPathEntries = classPath == null ? Utils.NO_STRINGS : classPath.split("\\s+"); for (String entry : classPathEntries) { if (! entry.isEmpty()) { final URI uri; try { uri = new URI(entry); } catch (URISyntaxException e) { // ignore invalid class path entries continue; } final Path depPath = path.resolveSibling(Paths.get(uri)).normalize(); // simple dependency; class path deps are always optional builder.addDependency(new ModuleDependencySpecBuilder() .setImportFilter(PathFilters.acceptAll()) .setModuleLoader(moduleLoader) .setName(depPath.toString()) .setOptional(true) .build()); } } } void setMainClass(final ModuleSpec.Builder builder, final Attributes mainAttributes) { final String mainClass = mainAttributes.getValue(Attributes.Name.MAIN_CLASS); if (mainClass != null) { builder.setMainClass(mainClass); } } void addSelfDependency(final ModuleSpec.Builder builder) { // add our own dependency builder.addDependency(DependencySpec.OWN_DEPENDENCY); } void addSelfContent(final ModuleSpec.Builder builder, final ResourceLoader resourceLoader) { // add our own content builder.addResourceRoot(ResourceLoaderSpec.createResourceLoaderSpec(resourceLoader, NO_MODULES_DIR)); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/FilteredIterableLocalLoader.java000066400000000000000000000043071472011152000315210ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.jboss.modules.filter.ClassFilter; import org.jboss.modules.filter.PathFilter; import org.jboss.modules.filter.PathFilters; /** * @author David M. Lloyd */ class FilteredIterableLocalLoader implements IterableLocalLoader { private final ClassFilter classFilter; private final IterableLocalLoader originalLoader; private final PathFilter resourcePathFilter; FilteredIterableLocalLoader(final ClassFilter classFilter, final PathFilter resourcePathFilter, final IterableLocalLoader originalLoader) { this.classFilter = classFilter; this.originalLoader = originalLoader; this.resourcePathFilter = resourcePathFilter; } public Class loadClassLocal(final String name, final boolean resolve) { return classFilter.accept(name) ? originalLoader.loadClassLocal(name, resolve) : null; } public Package loadPackageLocal(final String name) { return originalLoader.loadPackageLocal(name); } public List loadResourceLocal(final String name) { return resourcePathFilter.accept(name) ? originalLoader.loadResourceLocal(name) : Collections.emptyList(); } public Iterator iterateResources(final String startPath, final boolean recursive) { return PathFilters.filtered(resourcePathFilter, originalLoader.iterateResources(startPath, recursive)); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/FilteredIterableResourceLoader.java000066400000000000000000000051501472011152000322530ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.IOException; import java.net.URI; import java.util.Collection; import java.util.Iterator; import org.jboss.modules.filter.PathFilter; import org.jboss.modules.filter.PathFilters; final class FilteredIterableResourceLoader implements IterableResourceLoader { private final PathFilter filter; private final IterableResourceLoader loader; FilteredIterableResourceLoader(final PathFilter filter, final IterableResourceLoader loader) { this.filter = filter; this.loader = loader; } @Deprecated public String getRootName() { return loader.getRootName(); } public ClassSpec getClassSpec(final String fileName) throws IOException { final String canonicalFileName = PathUtils.canonicalize(PathUtils.relativize(fileName)); return filter.accept(canonicalFileName) ? loader.getClassSpec(canonicalFileName) : null; } public PackageSpec getPackageSpec(final String name) throws IOException { return loader.getPackageSpec(PathUtils.canonicalize(PathUtils.relativize(name))); } public Resource getResource(final String name) { final String canonicalFileName = PathUtils.canonicalize(PathUtils.relativize(name)); return filter.accept(canonicalFileName) ? loader.getResource(canonicalFileName) : null; } public String getLibrary(final String name) { return loader.getLibrary(PathUtils.canonicalize(PathUtils.relativize(name))); } public Collection getPaths() { return loader.getPaths(); } public Iterator iterateResources(final String startPath, final boolean recursive) { return PathFilters.filtered(filter, loader.iterateResources(PathUtils.relativize(PathUtils.canonicalize(startPath)), recursive)); } public void close() { loader.close(); } public URI getLocation() { return loader.getLocation(); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/FilteredLocalLoader.java000066400000000000000000000035761472011152000300600ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.util.Collections; import java.util.List; import org.jboss.modules.filter.ClassFilter; import org.jboss.modules.filter.PathFilter; /** * @author David M. Lloyd */ class FilteredLocalLoader implements LocalLoader { private final ClassFilter classFilter; private final LocalLoader originalLoader; private final PathFilter resourcePathFilter; FilteredLocalLoader(final ClassFilter classFilter, final PathFilter resourcePathFilter, final LocalLoader originalLoader) { this.classFilter = classFilter; this.originalLoader = originalLoader; this.resourcePathFilter = resourcePathFilter; } public Class loadClassLocal(final String name, final boolean resolve) { return classFilter.accept(name) ? originalLoader.loadClassLocal(name, resolve) : null; } public Package loadPackageLocal(final String name) { return originalLoader.loadPackageLocal(name); } public List loadResourceLocal(final String name) { return resourcePathFilter.accept(name) ? originalLoader.loadResourceLocal(name) : Collections.emptyList(); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/FilteredResourceLoader.java000066400000000000000000000046251472011152000306110ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.IOException; import java.net.URI; import java.util.Collection; import org.jboss.modules.filter.PathFilter; /** * @author David M. Lloyd * @author Richard Opalka */ final class FilteredResourceLoader implements ResourceLoader { private final PathFilter filter; private final ResourceLoader loader; FilteredResourceLoader(final PathFilter filter, final ResourceLoader loader) { this.filter = filter; this.loader = loader; } @Deprecated public String getRootName() { return loader.getRootName(); } public ClassSpec getClassSpec(final String fileName) throws IOException { final String canonicalFileName = PathUtils.canonicalize(PathUtils.relativize(fileName)); return filter.accept(canonicalFileName) ? loader.getClassSpec(canonicalFileName) : null; } public PackageSpec getPackageSpec(final String name) throws IOException { return loader.getPackageSpec(PathUtils.canonicalize(PathUtils.relativize(name))); } public Resource getResource(final String name) { final String canonicalFileName = PathUtils.canonicalize(PathUtils.relativize(name)); return filter.accept(canonicalFileName) ? loader.getResource(canonicalFileName) : null; } public String getLibrary(final String name) { return loader.getLibrary(PathUtils.canonicalize(PathUtils.relativize(name))); } public Collection getPaths() { return loader.getPaths(); } public void close() { loader.close(); } public URI getLocation() { return loader.getLocation(); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/GetURLConnectionAction.java000066400000000000000000000023021472011152000304620ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2018 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.IOException; import java.net.URL; import java.net.URLConnection; import java.security.PrivilegedExceptionAction; /** */ final class GetURLConnectionAction implements PrivilegedExceptionAction { private final URL url; GetURLConnectionAction(final URL url) { this.url = url; } public URLConnection run() throws IOException { final URLConnection c = url.openConnection(); c.connect(); return c; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/IterableLocalLoader.java000066400000000000000000000031011472011152000300310ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.util.Iterator; /** * A local loader which can enumerate its contents. * * @author David M. Lloyd */ public interface IterableLocalLoader extends LocalLoader { /** * Enumerate all the resources under the given path. The given path name is relative to the root * of the resource loader. If the path "escapes" the root via {@code ..}, such segments will be consumed. * If the path is absolute, it will be converted to a relative path by dropping the leading {@code /}. * * @param startPath the path to search under * @param recursive {@code true} to recursively descend into subdirectories, {@code false} to only read this path * @return the resource iterator (possibly empty) */ Iterator iterateResources(String startPath, boolean recursive); } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/IterableModuleFinder.java000066400000000000000000000052661472011152000302430ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.util.Collections; import java.util.Iterator; /** * A module finder which is iterable. * * @author David M. Lloyd */ public interface IterableModuleFinder extends ModuleFinder { /** * This method returns an empty iterator and should not be used by new code. * * @param baseIdentifier the identifier to start with, or {@code null} to iterate all modules * @param recursive {@code true} to find recursively nested modules, {@code false} to only find immediately nested * modules * @return an iterator for the modules in this module finder * @deprecated Use {@link #iterateModules(String, boolean, ModuleLoader)} instead. */ @Deprecated(forRemoval = true) default Iterator iterateModules(ModuleIdentifier baseIdentifier, boolean recursive) { return Collections.emptyIterator(); } /** * Iterate the modules which can be located via this module finder. * * @param baseName the identifier to start with, or {@code null} to iterate all modules; ignored if this module * loader does not have a concept of nested modules * @param recursive {@code true} to find recursively nested modules, {@code false} to only find immediately nested * modules; ignored if this module finder does not have a concept of nested modules * @return an iterator for the modules in this module finder * @deprecated Use {@link #iterateModules(String, boolean, ModuleLoader)} instead. */ @Deprecated default Iterator iterateModules(String baseName, boolean recursive) { return iterateModules(baseName, recursive, null); } default Iterator iterateModules(String baseName, boolean recursive, final ModuleLoader delegateLoader) { return IteratorUtils.transformingIterator(iterateModules(baseName == null ? null : ModuleIdentifier.fromString(baseName), recursive), ModuleIdentifier::toString); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/IterableResourceLoader.java000066400000000000000000000031311472011152000305710ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.util.Iterator; /** * A resource loader which has the ability to enumerate its contents. * * @author David M. Lloyd */ public interface IterableResourceLoader extends ResourceLoader { /** * Enumerate all the resources under the given path. The given path name is relative to the root * of the resource loader. If the path "escapes" the root via {@code ..}, such segments will be consumed. * If the path is absolute, it will be converted to a relative path by dropping the leading {@code /}. * * @param startPath the path to search under * @param recursive {@code true} to recursively descend into subdirectories, {@code false} to only read this path * @return the resource iterator (possibly empty) */ Iterator iterateResources(String startPath, boolean recursive); } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/IteratorUtils.java000066400000000000000000000024301472011152000270160ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2016 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.util.Iterator; import java.util.function.Function; /** * @author David M. Lloyd */ final class IteratorUtils { private IteratorUtils() { } public static Iterator transformingIterator(Iterator original, Function translator) { return new Iterator<>() { public boolean hasNext() { return original.hasNext(); } public U next() { return translator.apply(original.next()); } }; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/JDKModuleFinder.java000066400000000000000000000207661472011152000271260ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import static java.security.AccessController.doPrivileged; import java.io.IOException; import java.lang.Module; import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleFinder; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Optional; import java.util.Set; /** */ public final class JDKModuleFinder implements IterableModuleFinder { private final ModuleLayer layer; private static final JDKModuleFinder INSTANCE = new JDKModuleFinder(); private JDKModuleFinder() { ModuleLayer layer; if (JDKModuleFinder.class.getModule().isNamed()) { layer = JDKModuleFinder.class.getModule().getLayer(); if (layer == null) { layer = ModuleLayer.boot(); } } else { layer = ModuleLayer.boot(); } this.layer = layer; } public static JDKModuleFinder getInstance() { return INSTANCE; } public ModuleSpec findModule(final String name, final ModuleLoader delegateLoader) { if ("java.se".equals(name)) { // The `java.se` aggregator module is not included in JDK boot layer by default. // It becomes available when the JVM starts with the `--add-modules java.se` command line parameter. // By defining it here, we ensure its availability even if the JVM was not started with this parameter. final ModuleSpec.Builder builder = ModuleSpec.build(name, false); final ModuleDescriptor javaSeDescriptor = ModuleFinder.ofSystem().find(name).get().descriptor(); DependencySpec dependencySpec; for (final ModuleDescriptor.Requires dep : javaSeDescriptor.requires()) { dependencySpec = new ModuleDependencySpecBuilder().setName(dep.name()).setExport(true).build(); builder.addDependency(dependencySpec); } return builder.create(); } final Set packages; final Module module; final Optional moduleOptional = layer.findModule(name); if (moduleOptional.isEmpty()) { if ("org.jboss.modules".equals(name)) { module = getClass().getModule(); if (module.isNamed()) { packages = module.getPackages(); } else { packages = Utils.MODULES_PACKAGES; } } else { return null; } } else { module = moduleOptional.get(); packages = module.getPackages(); } final ModuleSpec.Builder builder = ModuleSpec.build(name); final ModuleDescriptor descriptor = module.getDescriptor(); if (descriptor != null) { final Optional version = descriptor.rawVersion(); if (version.isPresent()) builder.setVersion(Version.parse(version.get())); for (ModuleDescriptor.Requires require : descriptor.requires()) { final Set modifiers = require.modifiers(); builder.addDependency( new ModuleDependencySpecBuilder() .setName(require.name()) .setExport(modifiers.contains(ModuleDescriptor.Requires.Modifier.TRANSITIVE)) .setOptional(modifiers.contains(ModuleDescriptor.Requires.Modifier.STATIC)) .build() ); } } final Set paths = new HashSet<>(packages.size()); for (String pkg : packages) { paths.add(pkg.replace('.', '/')); } final LocalDependencySpecBuilder depBuilder = new LocalDependencySpecBuilder(); depBuilder.setLoaderPaths(paths); depBuilder.setExport(true); depBuilder.setLocalLoader(new JDKModuleLoader(module, packages)); builder.addDependency(depBuilder.build()); return builder.create(); } public String toString() { return "JDK Module Finder"; } public Iterator iterateModules(final String baseName, final boolean recursive, final ModuleLoader delegate) { final Set moduleSet = layer.modules(); final ArrayList nameList = new ArrayList<>(moduleSet.size() + 1); final Module ourModule = getClass().getModule(); boolean foundUs = false; for (Module module : moduleSet) { if (module == ourModule) { foundUs = true; } nameList.add(module.getName()); } if (!foundUs) { nameList.add("org.jboss.modules"); } return nameList.iterator(); } static class JDKModuleLoader implements LocalLoader { private final Module module; private final ClassLoader classLoader; private final Set packages; JDKModuleLoader(final Module module, final Set packages) { this.module = module; JDKModuleLoader.class.getModule().addReads(module); classLoader = doPrivileged(new ModuleClassLoaderAction(module)); this.packages = packages; } public Class loadClassLocal(String name, final boolean resolve) { final String nameDots = name.replace('/', '.'); final int idx = nameDots.lastIndexOf('.'); if (idx == -1) { // no empty package allowed return null; } if (packages.contains(nameDots.substring(0, idx))) { try { final Class clazz = classLoader.loadClass(nameDots); if (clazz.getModule() != module) { return null; } else { return clazz; } } catch (ClassNotFoundException e) { // unlikely return null; } } return null; } public Package loadPackageLocal(final String name) { return packages.contains(name) ? classLoader.getDefinedPackage(name) : null; } public List loadResourceLocal(final String name) { final URL url; try { url = new URL("jrt:/" + module.getName() + "/" + name); } catch (MalformedURLException e) { return Collections.emptyList(); } try { final URLConnection connection = url.openConnection(); connection.connect(); return Collections.singletonList(new URLConnectionResource(connection)); } catch (IOException e) { // connect failed; try the class loader final int idx = name.lastIndexOf('/'); if (idx != -1) { final String nameDots = name.substring(0, idx).replace('/', '.'); if (packages.contains(nameDots)) { final URL resource = classLoader.getResource(name); if (resource != null) { try { final URLConnection connection = resource.openConnection(); connection.connect(); return Collections.singletonList(new URLConnectionResource(connection)); } catch (IOException e2) { return Collections.emptyList(); } } } } return Collections.emptyList(); } } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/JDKPaths.java000066400000000000000000000101321472011152000256120ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.Enumeration; import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; /** * A utility class which maintains the set of JDK paths. Makes certain assumptions about the disposition of the * class loader used to load JBoss Modules; thus this class should only be used when booted up via the "-jar" or "-cp" * switches. * * @author David M. Lloyd * @author Richard Opalka */ final class JDKPaths { static final Set JDK; static { final Set pathSet = Utils.getJDKPaths(); if (pathSet.size() == 0) throw new IllegalStateException("Something went wrong with system paths set up"); JDK = Collections.unmodifiableSet(pathSet); } private JDKPaths() { } static void processJar(final Set pathSet, final File file) throws IOException { try (final ZipFile zipFile = new ZipFile(file)) { final Enumeration entries = zipFile.entries(); while (entries.hasMoreElements()) { final ZipEntry entry = entries.nextElement(); final String name = entry.getName(); final int lastSlash = name.lastIndexOf('/'); if (lastSlash != -1) { pathSet.add(name.substring(0, lastSlash)); } } } } static void processClassPathItem(final String classPath, final Set jarSet, final Set pathSet) { if (classPath == null) return; int s = 0, e; do { e = classPath.indexOf(File.pathSeparatorChar, s); String item = e == -1 ? classPath.substring(s) : classPath.substring(s, e); if (! jarSet.contains(item)) { final File file = new File(item); if (file.isDirectory()) { processDirectory(pathSet, file); } else { try { processJar(pathSet, file); } catch (IOException ex) { // ignore } } } s = e + 1; } while (e != -1); } static void processDirectory(final Set pathSet, final File file) { for (File entry : file.listFiles()) { if (entry.isDirectory()) { processDirectory1(pathSet, entry, file.getPath()); } else { final String parent = entry.getParent(); if (parent != null) pathSet.add(parent); } } } private static void processDirectory1(final Set pathSet, final File file, final String pathBase) { for (File entry : file.listFiles()) { if (entry.isDirectory()) { processDirectory1(pathSet, entry, pathBase); } else { String packagePath = entry.getParent(); if (packagePath != null) { packagePath = packagePath.substring(pathBase.length()).replace('\\', '/'); if(packagePath.startsWith("/")) { packagePath = packagePath.substring(1); } pathSet.add(packagePath); } } } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/JLIClassTransformer.java000066400000000000000000000045521472011152000300420ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2018 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; import java.nio.ByteBuffer; import java.security.ProtectionDomain; /** * A wrapper around a {@link ClassFileTransformer}. */ public final class JLIClassTransformer implements ClassTransformer { private final ClassFileTransformer transformer; /** * Construct a new instance. * * @param transformer the delegate transformer (must not be {@code null}) */ public JLIClassTransformer(final ClassFileTransformer transformer) { if (transformer == null) throw new IllegalArgumentException("transformer is null"); this.transformer = transformer; } public ByteBuffer transform(final ClassLoader loader, final String className, final ProtectionDomain protectionDomain, final ByteBuffer classBytes) throws IllegalArgumentException { final int position = classBytes.position(); final int limit = classBytes.limit(); final byte[] bytes; final byte[] result; if (classBytes.hasArray() && classBytes.arrayOffset() == 0 && position == 0 && limit == classBytes.capacity()) { bytes = classBytes.array(); } else { bytes = new byte[limit - position]; classBytes.get(bytes); classBytes.position(position); } try { result = transformer.transform(loader, className, null, protectionDomain, bytes); } catch (IllegalClassFormatException e) { throw new IllegalArgumentException(e); } return result == null || result == bytes ? classBytes : ByteBuffer.wrap(result); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/JarEntryResource.java000066400000000000000000000041151472011152000274540ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.jar.JarFile; import java.util.zip.ZipEntry; /** * @author David M. Lloyd * @author Richard Opalka */ final class JarEntryResource implements Resource { private final JarFile jarFile; private final String relativePath; private final String entryName; private final URL resourceURL; JarEntryResource(final JarFile jarFile, final String name, final String relativePath, final URL resourceURL) { this.jarFile = jarFile; this.relativePath = relativePath; this.entryName = relativePath == null ? name : name.substring(relativePath.length() + 1); this.resourceURL = resourceURL; } public String getName() { return entryName; } public URL getURL() { return resourceURL; } public InputStream openStream() throws IOException { return jarFile.getInputStream(getEntry()); } public long getSize() { final long size = getEntry().getSize(); return size == -1 ? 0 : size; } private ZipEntry getEntry() { final String relativePath = this.relativePath; return relativePath == null ? jarFile.getEntry(entryName) : jarFile.getEntry(relativePath + "/" + entryName); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/JarFileResourceLoader.java000066400000000000000000000346101472011152000303640ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLStreamHandler; import java.security.CodeSigner; import java.security.CodeSource; import java.security.PrivilegedActionException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.Manifest; import static java.security.AccessController.doPrivileged; import org.jboss.modules.log.ModuleLogger; /** * * @author David M. Lloyd * @author Thomas.Diesler@jboss.com * @author Richard Opalka */ final class JarFileResourceLoader extends AbstractResourceLoader implements IterableResourceLoader { private final JarFile jarFile; private final String rootName; private final URL rootUrl; private final String relativePath; private final File fileOfJar; private volatile List directory; // protected by {@code this} private final Map codeSources = new HashMap<>(); JarFileResourceLoader(final String rootName, final JarFile jarFile) { this(rootName, jarFile, null); } JarFileResourceLoader(final String rootName, final JarFile jarFile, final String relativePath) { if (jarFile == null) { throw new IllegalArgumentException("jarFile is null"); } if (rootName == null) { throw new IllegalArgumentException("rootName is null"); } fileOfJar = new File(jarFile.getName()); this.jarFile = jarFile; this.rootName = rootName; String realPath = relativePath == null ? null : PathUtils.canonicalize(relativePath); if (realPath != null && realPath.endsWith("/")) realPath = realPath.substring(0, realPath.length() - 1); this.relativePath = realPath; try { rootUrl = getJarURI(fileOfJar.toURI(), realPath).toURL(); } catch (URISyntaxException e) { throw new IllegalArgumentException("Invalid root file specified", e); } catch (MalformedURLException e) { throw new IllegalArgumentException("Invalid root file specified", e); } } private static URI getJarURI(final URI original, final String nestedPath) throws URISyntaxException { final StringBuilder b = new StringBuilder(); b.append("file:"); assert original.getScheme().equals("file"); final String path = original.getPath(); assert path != null; final String host = original.getHost(); if (host != null) { final String userInfo = original.getRawUserInfo(); b.append("//"); if (userInfo != null) { b.append(userInfo).append('@'); } b.append(host); } b.append(path).append("!/"); if (nestedPath != null) { b.append(nestedPath); } return new URI("jar", b.toString(), null); } public String getRootName() { return rootName; } public synchronized ClassSpec getClassSpec(final String fileName) throws IOException { final ClassSpec spec = new ClassSpec(); final JarEntry entry = getJarEntry(fileName); if (entry == null) { // no such entry return null; } final long size = entry.getSize(); try (final InputStream is = jarFile.getInputStream(entry)) { if (size == -1) { // size unknown final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final byte[] buf = new byte[16384]; int res; while ((res = is.read(buf)) > 0) { baos.write(buf, 0, res); } // done CodeSource codeSource = createCodeSource(entry); baos.close(); is.close(); spec.setBytes(baos.toByteArray()); spec.setCodeSource(codeSource); return spec; } else if (size <= (long) Integer.MAX_VALUE) { final int castSize = (int) size; byte[] bytes = new byte[castSize]; int a = 0, res; while ((res = is.read(bytes, a, castSize - a)) > 0) { a += res; } // consume remainder so that cert check doesn't fail in case of wonky JARs while (is.read() != -1) { // } // done CodeSource codeSource = createCodeSource(entry); is.close(); spec.setBytes(bytes); spec.setCodeSource(codeSource); return spec; } else { throw new IOException("Resource is too large to be a valid class file"); } } } // this MUST only be called after the input stream is fully read (see MODULES-201) private CodeSource createCodeSource(final JarEntry entry) { final CodeSigner[] entryCodeSigners = entry.getCodeSigners(); final CodeSigners codeSigners = entryCodeSigners == null || entryCodeSigners.length == 0 ? EMPTY_CODE_SIGNERS : new CodeSigners(entryCodeSigners); CodeSource codeSource = codeSources.get(codeSigners); if (codeSource == null) { codeSources.put(codeSigners, codeSource = new CodeSource(rootUrl, entryCodeSigners)); } return codeSource; } private JarEntry getJarEntry(final String fileName) { return relativePath == null ? jarFile.getJarEntry(fileName) : jarFile.getJarEntry(relativePath + "/" + fileName); } public PackageSpec getPackageSpec(final String name) throws IOException { final Manifest manifest; if (relativePath == null) { manifest = jarFile.getManifest(); } else { JarEntry jarEntry = getJarEntry("META-INF/MANIFEST.MF"); if (jarEntry == null) { manifest = null; } else { try (final InputStream inputStream = jarFile.getInputStream(jarEntry)) { manifest = new Manifest(inputStream); } } } return getPackageSpec(name, manifest, rootUrl); } public String getLibrary(final String name) { // JARs cannot have libraries in them return null; } public Resource getResource(String name) { try { final JarFile jarFile = this.jarFile; name = PathUtils.canonicalize(PathUtils.relativize(name)); final JarEntry entry = getJarEntry(name); if (entry == null) { return null; } final URI uri; try { File absoluteFile = new File(jarFile.getName()).getAbsoluteFile(); String path = absoluteFile.getPath(); path = PathUtils.canonicalize(path); if (File.separatorChar != '/') { // optimizes away on platforms with / path = path.replace(File.separatorChar, '/'); } if (PathUtils.isRelative(path)) { // should not be possible, but the JDK thinks this might happen sometimes..? path = "/" + path; } if (path.startsWith("//")) { // UNC path URIs have loads of leading slashes path = "//" + path; } uri = new URI("file", null, path, null); } catch (URISyntaxException x) { throw new IllegalStateException(x); } final URL url = new URL(null, getJarURI(uri, entry.getName()).toString(), (URLStreamHandler) null); try { doPrivileged(new GetURLConnectionAction(url)); } catch (PrivilegedActionException e) { // ignored; the user might not even ask for the URL } return new JarEntryResource(jarFile, entry.getName(), relativePath, url); } catch (MalformedURLException e) { // must be invalid...? (todo: check this out) return null; } catch (URISyntaxException e) { // must be invalid...? (todo: check this out) return null; } } public Iterator iterateResources(String startPath, final boolean recursive) { if (relativePath != null) startPath = startPath.equals("") ? relativePath : relativePath + "/" + startPath; final String startName = PathUtils.canonicalize(PathUtils.relativize(startPath)); List directory = this.directory; if (directory == null) { synchronized (jarFile) { directory = this.directory; if (directory == null) { directory = new ArrayList<>(); final Enumeration entries = jarFile.entries(); while (entries.hasMoreElements()) { final JarEntry jarEntry = entries.nextElement(); if (! jarEntry.isDirectory()) { directory.add(jarEntry.getName()); } } this.directory = directory; } } } final Iterator iterator = directory.iterator(); return new Iterator<>() { private Resource next; public boolean hasNext() { while (next == null) { if (! iterator.hasNext()) { return false; } final String name = iterator.next(); if ((recursive ? PathUtils.isChild(startName, name) : PathUtils.isDirectChild(startName, name))) { try { next = new JarEntryResource(jarFile, name, relativePath, getJarURI(new File(jarFile.getName()).toURI(), name).toURL()); } catch (Exception ignored) { } } } return true; } public Resource next() { if (! hasNext()) { throw new NoSuchElementException(); } try { return next; } finally { next = null; } } public void remove() { throw new UnsupportedOperationException(); } }; } public Collection getPaths() { final Collection index = new HashSet<>(); index.add(""); extractJarPaths(jarFile, relativePath, index); return index; } @Override public void close() { try { super.close(); } finally { try { jarFile.close(); } catch (IOException e) { // ignored } } } public URI getLocation() { try { return getJarURI(fileOfJar.toURI(), ""); } catch (URISyntaxException e) { return null; } } public ResourceLoader createSubloader(final String relativePath, final String rootName) { final String ourRelativePath = this.relativePath; final String fixedPath = PathUtils.relativize(PathUtils.canonicalize(relativePath)); return new JarFileResourceLoader(rootName, jarFile, ourRelativePath == null ? fixedPath : ourRelativePath + "/" + fixedPath); } static void extractJarPaths(final JarFile jarFile, String relativePath, final Collection index) { index.add(""); final Enumeration entries = jarFile.entries(); if (! entries.hasMoreElements()) { ModuleLogger log = Module.getModuleLogger(); log.trace("No JAR paths were found in the JAR file path %s", relativePath); } else do { final JarEntry jarEntry = entries.nextElement(); final String name = jarEntry.getName(); final int idx = name.lastIndexOf('/'); if (idx == -1) continue; final String path = name.substring(0, idx); if (path.isEmpty() || path.endsWith("/")) { // invalid name, just skip... continue; } if (relativePath == null) { index.add(path); } else { if (path.startsWith(relativePath + "/")) { index.add(path.substring(relativePath.length() + 1)); } } } while (entries.hasMoreElements()); } private static final CodeSigners EMPTY_CODE_SIGNERS = new CodeSigners(new CodeSigner[0]); static final class CodeSigners { private final CodeSigner[] codeSigners; private final int hashCode; CodeSigners(final CodeSigner[] codeSigners) { this.codeSigners = codeSigners; hashCode = Arrays.hashCode(codeSigners); } public boolean equals(final Object obj) { return obj instanceof CodeSigners && equals((CodeSigners) obj); } private boolean equals(final CodeSigners other) { return Arrays.equals(codeSigners, other.codeSigners); } public int hashCode() { return hashCode; } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/JarModuleFinder.java000077500000000000000000000204101472011152000272170ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; import java.security.AccessControlContext; import java.security.AccessController; import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.Manifest; import org.jboss.modules.filter.MultiplePathFilterBuilder; import org.jboss.modules.filter.PathFilters; import org.jboss.modules.xml.ModuleXmlParser; import static org.jboss.modules.Utils.DEPENDENCIES; import static org.jboss.modules.Utils.EXPORT; import static org.jboss.modules.Utils.OPTIONAL; import static org.jboss.modules.Utils.MODULES_DIR; import static org.jboss.modules.Utils.MODULE_FILE; /** * A module finder which uses a JAR file as a module repository. * * @author David M. Lloyd * @author Richard Opalka * @deprecated {@link FileSystemClassPathModuleFinder} and/or {@link ResourceLoaderModuleFinder} should be used instead for more * complete functionality. */ @Deprecated public final class JarModuleFinder implements ModuleFinder { private final String myName; private final JarFile jarFile; private final AccessControlContext context; /** * Construct a new instance. * * @param myIdentifier the identifier to use for the JAR itself * @param jarFile the JAR file to encapsulate * @deprecated Use {@link #JarModuleFinder(String,JarFile)} instead. */ @Deprecated(forRemoval = true) public JarModuleFinder(final ModuleIdentifier myIdentifier, final JarFile jarFile) { this(myIdentifier.toString(), jarFile); } /** * Construct a new instance. * * @param myName the name to use for the JAR itself * @param jarFile the JAR file to encapsulate */ public JarModuleFinder(final String myName, final JarFile jarFile) { this.myName = myName; this.jarFile = jarFile; context = AccessController.getContext(); } public ModuleSpec findModule(final String name, final ModuleLoader delegateLoader) throws ModuleLoadException { if (name.equals(myName)) { // special root JAR module Manifest manifest; try { manifest = jarFile.getManifest(); } catch (IOException e) { throw new ModuleLoadException("Failed to load MANIFEST from JAR", e); } ModuleSpec.Builder builder = ModuleSpec.build(name); Attributes mainAttributes = manifest.getMainAttributes(); String mainClass = mainAttributes.getValue(Attributes.Name.MAIN_CLASS); if (mainClass != null) { builder.setMainClass(mainClass); } String classPath = mainAttributes.getValue(Attributes.Name.CLASS_PATH); String dependencies = mainAttributes.getValue(DEPENDENCIES); MultiplePathFilterBuilder pathFilterBuilder = PathFilters.multiplePathFilterBuilder(true); pathFilterBuilder.addFilter(PathFilters.is(MODULES_DIR), false); pathFilterBuilder.addFilter(PathFilters.isChildOf(MODULES_DIR), false); builder.addResourceRoot(ResourceLoaderSpec.createResourceLoaderSpec(new JarFileResourceLoader("", jarFile), pathFilterBuilder.create())); String[] classPathEntries = classPath == null ? Utils.NO_STRINGS : classPath.split("\\s+"); for (String entry : classPathEntries) { if (! entry.isEmpty()) { if (entry.startsWith("../") || entry.startsWith("./") || entry.startsWith("/") || entry.contains("/../")) { // invalid continue; } File root; try { File path = new File(new URI(entry)); if (path.isAbsolute()) { root = path; } else { root = new File(jarFile.getName(), path.getPath()); } } catch (URISyntaxException e) { // invalid, will probably fail anyway root = new File(jarFile.getName(), entry); } if (entry.endsWith("/")) { // directory reference builder.addResourceRoot(ResourceLoaderSpec.createResourceLoaderSpec(new PathResourceLoader(entry, root.toPath(), context))); } else { // assume a JAR JarFile childJarFile; try { childJarFile = new JarFile(root, true, JarFile.OPEN_READ, JarFile.runtimeVersion()); } catch (IOException e) { // ignore and continue continue; } builder.addResourceRoot(ResourceLoaderSpec.createResourceLoaderSpec(new JarFileResourceLoader(entry, childJarFile))); } } } String[] dependencyEntries = dependencies == null ? Utils.NO_STRINGS : dependencies.split("\\s*,\\s*"); for (String dependencyEntry : dependencyEntries) { boolean optional = false; boolean export = false; dependencyEntry = dependencyEntry.trim(); if (! dependencyEntry.isEmpty()) { String[] fields = dependencyEntry.split("\\s+"); if (fields.length < 1) { continue; } String moduleName = fields[0]; for (int i = 1; i < fields.length; i++) { String field = fields[i]; if (field.equals(OPTIONAL)) { optional = true; } else if (field.equals(EXPORT)) { export = true; } // else ignored } builder.addDependency(new ModuleDependencySpecBuilder() .setName(moduleName) .setExport(export) .setOptional(optional) .build()); } } builder.addDependency(DependencySpec.createSystemDependencySpec(JDKPaths.JDK)); builder.addDependency(DependencySpec.createLocalDependencySpec()); return builder.create(); } else { final String path = PathUtils.basicModuleNameToPath(name); if (path == null) { return null; // not valid, so not found } String basePath = MODULES_DIR + "/" + path; JarEntry moduleXmlEntry = jarFile.getJarEntry(basePath + "/" + MODULE_FILE); if (moduleXmlEntry == null) { return null; } ModuleSpec moduleSpec; try { try (final InputStream inputStream = jarFile.getInputStream(moduleXmlEntry)) { moduleSpec = ModuleXmlParser.parseModuleXml((rootPath, loaderPath, loaderName) -> new JarFileResourceLoader(loaderName, jarFile, loaderPath), basePath, inputStream, moduleXmlEntry.getName(), delegateLoader, name); } } catch (IOException e) { throw new ModuleLoadException("Failed to read " + MODULE_FILE + " file", e); } return moduleSpec; } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/LayeredModulePathFactory.java000066400000000000000000000231421472011152000311070ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Properties; /** * Provides a module path that includes entries for any "layer" and "add-on" directory structures found * within the regular items in the provided module path. * * @author Brian Stansberry (c) 2012 Red Hat Inc. */ class LayeredModulePathFactory { /** * Inspects each element in the given {@code modulePath} to see if it includes a {@code layers.conf} file * and/or a standard directory structure with child directories {@code system/layers} and, optionally, * {@code system/add-ons}. If so, the layers identified in {@code layers.conf} are added to the module path * * @param modulePath the filesystem locations that make up the standard module path, each of which is to be * checked for the presence of layers and add-ons * * @return a new module path, including any layers and add-ons, if found */ static File[] resolveLayeredModulePath(File... modulePath) { boolean foundLayers = false; List layeredPath = new ArrayList<>(); for (File file : modulePath) { // Always add the root, as the user may place modules directly in it layeredPath.add(file); LayersConfig layersConfig = getLayersConfig(file); File layersDir = new File(file, layersConfig.getLayersPath()); if (!layersDir.exists()) { if (layersConfig.isConfigured()) { // Bad config from user throw new IllegalStateException("No layers directory found at " + layersDir); } // else this isn't a root that has layers and add-ons continue; } boolean validLayers = true; List layerFiles = new ArrayList<>(); for (String layerName : layersConfig.getLayers()) { File layer = new File(layersDir, layerName); if (!layer.exists()) { if (layersConfig.isConfigured()) { // Bad config from user throw new IllegalStateException(String.format("Cannot find layer %s under directory %s", layerName, layersDir)); } // else this isn't a standard layers and add-ons structure validLayers = false; break; } loadOverlays(layer, layerFiles); } if (validLayers) { foundLayers = true; layeredPath.addAll(layerFiles); // Now add-ons File[] addOns = new File(file, layersConfig.getAddOnsPath()).listFiles(); if (addOns != null) { for (File addOn : addOns) { if (addOn.isDirectory()) { loadOverlays(addOn, layeredPath); } } } } } return foundLayers ? layeredPath.toArray(File[]::new) : modulePath; } private static LayersConfig getLayersConfig(File repoRoot) { File layersList = new File(repoRoot, "layers.conf"); if (!layersList.exists()) { return new LayersConfig(); } try (final Reader reader = new InputStreamReader(new FileInputStream(layersList), StandardCharsets.UTF_8)) { Properties props = new Properties(); props.load(reader); return new LayersConfig(props); } catch (IOException e) { throw new RuntimeException(e); } } private static class LayersConfig { private static final String DEFAULT_LAYERS_PATH = "system/layers"; private static final String DEFAULT_ADD_ONS_PATH = "system/add-ons"; private final boolean configured; private final String layersPath; private final String addOnsPath; private final List layers; private LayersConfig() { configured = false; layersPath = DEFAULT_LAYERS_PATH; addOnsPath = DEFAULT_ADD_ONS_PATH; layers = Collections.singletonList("base"); } private LayersConfig(Properties properties) { configured = true; // Possible future enhancement; probably better to use an xml file // layersPath = properties.getProperty("layers.path", DEFAULT_LAYERS_PATH); // addOnsPath = properties.getProperty("add-ons.path", DEFAULT_ADD_ONS_PATH); // boolean excludeBase = Boolean.valueOf(properties.getProperty("exclude.base.layer", "false")); layersPath = DEFAULT_LAYERS_PATH; addOnsPath = DEFAULT_ADD_ONS_PATH; boolean excludeBase = false; String layersProp = (String) properties.get("layers"); if (layersProp == null || (layersProp = layersProp.trim()).length() == 0) { if (excludeBase) { layers = Collections.emptyList(); } else { layers = Collections.singletonList("base"); } } else { String[] layerNames = layersProp.split(","); layers = new ArrayList<>(); boolean hasBase = false; for (String layerName : layerNames) { if ("base".equals(layerName)) { hasBase = true; } layers.add(layerName); } if (!hasBase && !excludeBase) { layers.add("base"); } } } boolean isConfigured() { return configured; } String getLayersPath() { return layersPath; } String getAddOnsPath() { return addOnsPath; } List getLayers() { return layers; } } private static final String OVERLAYS = ".overlays"; /** * Load the overlays for each layer. * * @param layeringRoot the layer root * @param path the module path */ static void loadOverlays(final File layeringRoot, final List path) { final File overlays = new File(layeringRoot, OVERLAYS); if (overlays.exists()) { if (!overlays.canRead()) { throw new IllegalStateException("Overlays directory exists but is not readable: " + overlays.getPath()); } final File refs = new File(overlays, OVERLAYS); if (refs.exists()) { if (!refs.canRead()) { throw new IllegalStateException("Overlays metadata file exists but is not readable: " + refs.getPath()); } try { for (final String overlay : readRefs(refs)) { final File root = new File(overlays, overlay); if (!root.exists() || !root.canRead()) { throw new IllegalStateException("Overlay root directory doesn't exists or is not readable: " + root.getPath()); } path.add(root); } } catch (IOException e) { throw new RuntimeException(e); } } } path.add(layeringRoot); } public static List readRefs(final File file) throws IOException { if(! file.exists()) { return Collections.emptyList(); } final InputStream is = new FileInputStream(file); try { return readRefs(is); } finally { if (is != null) try { is.close(); } catch (Exception e) { throw new RuntimeException(e); } } } static List readRefs(final InputStream is) throws IOException { final List refs = new ArrayList<>(); final StringBuffer buffer = new StringBuffer(); do { if(buffer.length() > 0) { final String ref = buffer.toString().trim(); if(ref.length() > 0) { refs.add(ref); } } } while(readLine(is, buffer)); return refs; } static boolean readLine(InputStream is, StringBuffer buffer) throws IOException { buffer.setLength(0); int c; for(;;) { c = is.read(); switch(c) { case '\t': case '\r': break; case -1: return false; case '\n': return true; default: buffer.append((char) c); } } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/Linkage.java000066400000000000000000000046241472011152000255650ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.util.Collections; import java.util.List; import java.util.Map; /** * The linkage state of a module. * * @author David M. Lloyd */ final class Linkage { private static final Dependency[] NO_DEPENDENCIES = new Dependency[0]; private static final DependencySpec[] NO_DEPENDENCY_SPECS = new DependencySpec[0]; enum State { NEW, UNLINKED, LINKING, LINKED, ; } private final DependencySpec[] dependencySpecs; private final Dependency[] dependencies; private final State state; private final Map> allPaths; Linkage(final State state) { this(NO_DEPENDENCY_SPECS, NO_DEPENDENCIES, state, Collections.>emptyMap()); } Linkage(final DependencySpec[] dependencySpecs, final Dependency[] dependencies, final State state) { this(dependencySpecs, dependencies, state, Collections.>emptyMap()); } Linkage(final DependencySpec[] dependencySpecs, final Dependency[] dependencies, final State state, final Map> allPaths) { this.dependencySpecs = dependencySpecs; this.dependencies = dependencies; this.state = state; this.allPaths = PathUtils.deduplicateLists(allPaths); } Map> getPaths() { return allPaths; } State getState() { return state; } Dependency[] getDependencies() { return dependencies; } DependencySpec[] getDependencySpecs() { return dependencySpecs; } static final Linkage NONE = new Linkage(State.NEW); } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/LocalDependency.java000066400000000000000000000033401472011152000272360ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.util.Set; import org.jboss.modules.filter.ClassFilter; import org.jboss.modules.filter.PathFilter; /** * @author David M. Lloyd */ final class LocalDependency extends Dependency { private final LocalLoader localLoader; private final Set paths; LocalDependency(final PathFilter exportFilter, final PathFilter importFilter, final PathFilter resourceExportFilter, final PathFilter resourceImportFilter, final ClassFilter classExportFilter, final ClassFilter classImportFilter, final LocalLoader localLoader, final Set paths) { super(exportFilter, importFilter, resourceExportFilter, resourceImportFilter, classExportFilter, classImportFilter); this.localLoader = localLoader; this.paths = paths; } LocalLoader getLocalLoader() { return localLoader; } Set getPaths() { return paths; } public String toString() { return "dependency on " + localLoader; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/LocalDependencySpec.java000066400000000000000000000035131472011152000300530ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2018 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.util.Set; import org.jboss.modules.filter.ClassFilter; import org.jboss.modules.filter.PathFilter; final class LocalDependencySpec extends DependencySpec { private final LocalLoader localLoader; private final Set loaderPaths; LocalDependencySpec(final PathFilter importFilter, final PathFilter exportFilter, final PathFilter resourceImportFilter, final PathFilter resourceExportFilter, final ClassFilter classImportFilter, final ClassFilter classExportFilter, final LocalLoader localLoader, final Set loaderPaths) { super(importFilter, exportFilter, resourceImportFilter, resourceExportFilter, classImportFilter, classExportFilter); this.localLoader = localLoader; this.loaderPaths = loaderPaths; } Dependency getDependency(final Module module) { return new LocalDependency(getExportFilter(), getImportFilter(), getResourceExportFilter(), getResourceImportFilter(), getClassExportFilter(), getClassImportFilter(), localLoader, loaderPaths); } public String toString() { return "dependency on local loader " + localLoader; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/LocalDependencySpecBuilder.java000066400000000000000000000120111472011152000313530ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.util.Collections; import java.util.Set; import org.jboss.modules.filter.ClassFilter; import org.jboss.modules.filter.PathFilter; import org.jboss.modules.filter.PathFilters; /** * A local dependency specification builder, which includes a module's own content or some other, external content. */ public final class LocalDependencySpecBuilder extends DependencySpecBuilder { private LocalLoader localLoader; private Set loaderPaths = Collections.emptySet(); /** * Construct a new instance. */ public LocalDependencySpecBuilder() { // different default import filter setImportFilter(PathFilters.acceptAll()); } // covariant overrides /** * Get the import filter to use. The default value is {@link PathFilters#acceptAll()}. * * @return the import filter to use */ public PathFilter getImportFilter() { return super.getImportFilter(); } public LocalDependencySpecBuilder setImportFilter(final PathFilter importFilter) { super.setImportFilter(importFilter); return this; } public LocalDependencySpecBuilder setImportServices(final boolean services) { super.setImportServices(services); return this; } public LocalDependencySpecBuilder setExportFilter(final PathFilter exportFilter) { super.setExportFilter(exportFilter); return this; } public LocalDependencySpecBuilder setExport(final boolean export) { super.setExport(export); return this; } public LocalDependencySpecBuilder setResourceImportFilter(final PathFilter resourceImportFilter) { super.setResourceImportFilter(resourceImportFilter); return this; } public LocalDependencySpecBuilder setResourceExportFilter(final PathFilter resourceExportFilter) { super.setResourceExportFilter(resourceExportFilter); return this; } public LocalDependencySpecBuilder setClassImportFilter(final ClassFilter classImportFilter) { super.setClassImportFilter(classImportFilter); return this; } public LocalDependencySpecBuilder setClassExportFilter(final ClassFilter classExportFilter) { super.setClassExportFilter(classExportFilter); return this; } /** * Get the local loader to use. The default value is {@code null}, indicating that the content should come from * the module being defined. * * @return the local loader to use, or {@code null} to use the module's own content */ public LocalLoader getLocalLoader() { return localLoader; } /** * Set the local loader to use. * * @param localLoader the local loader to use, or {@code null} to use the module's own content * @return this builder */ public LocalDependencySpecBuilder setLocalLoader(final LocalLoader localLoader) { if (localLoader == null) { throw new IllegalArgumentException("localLoader is null"); } this.localLoader = localLoader; return this; } /** * Get the loader paths set. The default is the empty set. This value is ignored if the dependency specification * refers to the module's own content. * * @return the loader paths set */ public Set getLoaderPaths() { return loaderPaths; } /** * Set the loader paths set. * * @param loaderPaths the loader paths set (must not be {@code null}) * @return this builder */ public LocalDependencySpecBuilder setLoaderPaths(final Set loaderPaths) { if (loaderPaths == null) { throw new IllegalArgumentException("loaderPaths is null"); } this.loaderPaths = loaderPaths; return this; } public DependencySpec build() { final LocalLoader localLoader = this.localLoader; final Set loaderPaths = this.loaderPaths; if (localLoader == null) { return new ModuleClassLoaderDependencySpec(importFilter, exportFilter, resourceImportFilter, resourceExportFilter, classImportFilter, classExportFilter); } else { return new LocalDependencySpec(importFilter, exportFilter, resourceImportFilter, resourceExportFilter, classImportFilter, classExportFilter, localLoader, loaderPaths); } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/LocalLoader.java000066400000000000000000000041121472011152000263640ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.util.List; /** * A loader which implements the local part of a module. *

* Thread safety warning! The loader must never call into a class loader (or any other object) which may * take locks and subsequently delegate to a module class loader. This will cause deadlocks and other hard-to-debug * concurrency problems. * * @author David M. Lloyd */ public interface LocalLoader { /** * Load a class which is locally defined by this loader. * * @param name the class name * @param resolve {@code true} to resolve the class * @return the class, or {@code null} if there is no local class with this name */ Class loadClassLocal(String name, boolean resolve); /** * Load a package which is locally defined by this loader. * * @param name the package name * @return the package, or {@code null} if there is no local package with this name */ Package loadPackageLocal(String name); /** * Load a resource which is locally defined by this loader. The given name is a path separated * by "{@code /}" characters. * * @param name the resource path * @return the resource or resources, or an empty list if there is no local resource with this name */ List loadResourceLocal(String name); } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/LocalLoaders.java000066400000000000000000000077441472011152000265650ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import org.jboss.modules.filter.ClassFilter; import org.jboss.modules.filter.ClassFilters; import org.jboss.modules.filter.PathFilter; import org.jboss.modules.filter.PathFilters; /** * Static factory methods for various types of local loaders. * * @apiviz.exclude * * @author David M. Lloyd */ public final class LocalLoaders { private LocalLoaders() { } /** * Create a filtered local loader. * * @param pathFilter the path filter to apply to resources * @param originalLoader the original loader * @return the filtered loader */ public static LocalLoader createPathFilteredLocalLoader(final PathFilter pathFilter, final LocalLoader originalLoader) { return new FilteredLocalLoader(ClassFilters.acceptAll(), pathFilter, originalLoader); } /** * Create a filtered local loader. * * @param pathFilter the path filter to apply to resources * @param originalLoader the original loader * @return the filtered loader */ public static IterableLocalLoader createIterablePathFilteredLocalLoader(final PathFilter pathFilter, final IterableLocalLoader originalLoader) { return new FilteredIterableLocalLoader(ClassFilters.acceptAll(), pathFilter, originalLoader); } /** * Create a filtered local loader. * * @param classFilter the class filter to apply to classes * @param originalLoader the original loader * @return the filtered loader */ public static LocalLoader createClassFilteredLocalLoader(final ClassFilter classFilter, final LocalLoader originalLoader) { return new FilteredLocalLoader(classFilter, PathFilters.acceptAll(), originalLoader); } /** * Create a filtered local loader. * * @param classFilter the class filter to apply to classes * @param originalLoader the original loader * @return the filtered loader */ public static IterableLocalLoader createIterableClassFilteredLocalLoader(final ClassFilter classFilter, final IterableLocalLoader originalLoader) { return new FilteredIterableLocalLoader(classFilter, PathFilters.acceptAll(), originalLoader); } /** * Create a filtered local loader. * * @param classFilter the class filter to apply to classes * @param resourcePathFilter the path filter to apply to resources * @param originalLoader the original loader * @return the filtered loader */ public static LocalLoader createFilteredLocalLoader(final ClassFilter classFilter, final PathFilter resourcePathFilter, final LocalLoader originalLoader) { return new FilteredLocalLoader(classFilter, resourcePathFilter, originalLoader); } /** * Create a filtered local loader. * * @param classFilter the class filter to apply to classes * @param resourcePathFilter the path filter to apply to resources * @param originalLoader the original loader * @return the filtered loader */ public static IterableLocalLoader createIterableFilteredLocalLoader(final ClassFilter classFilter, final PathFilter resourcePathFilter, final IterableLocalLoader originalLoader) { return new FilteredIterableLocalLoader(classFilter, resourcePathFilter, originalLoader); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/LocalModuleFinder.java000066400000000000000000000362401472011152000275420ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.File; import java.io.FilePermission; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.UndeclaredThrowableException; import java.nio.file.Files; import java.nio.file.Path; import java.security.AccessControlContext; import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.Set; import java.util.function.Predicate; import org.jboss.modules.filter.PathFilter; import org.jboss.modules.filter.PathFilters; import org.jboss.modules.xml.ModuleXmlParser; import static java.security.AccessController.doPrivileged; import static org.jboss.modules.Utils.MODULE_FILE; /** * A module finder which locates module specifications which are stored in a local module * repository on the filesystem, which uses {@code module.xml} descriptors. * * @author David M. Lloyd * @author Richard Opalka */ public final class LocalModuleFinder implements IterableModuleFinder, AutoCloseable { private static final File[] NO_FILES = new File[0]; private final File[] repoRoots; private final PathFilter pathFilter; private final AccessControlContext accessControlContext; private final List resourceLoaderList = new ArrayList<>(64); private final ModuleXmlParser.ResourceRootFactory resourceRootFactory; private static final ResourceLoader TERMINATED_MARKER = new ResourceLoader() { public String getRootName() { return null; } public ClassSpec getClassSpec(final String fileName) throws IOException { return null; } public PackageSpec getPackageSpec(final String name) throws IOException { return null; } public Resource getResource(final String name) { return null; } public String getLibrary(final String name) { return null; } public Collection getPaths() { return null; } }; private LocalModuleFinder(final File[] repoRoots, final PathFilter pathFilter, final boolean cloneRoots) { this.repoRoots = cloneRoots && repoRoots.length > 0 ? repoRoots.clone() : repoRoots; final SecurityManager sm = System.getSecurityManager(); if (sm != null) { for (File repoRoot : this.repoRoots) { if (repoRoot != null) sm.checkPermission(new FilePermission(new File(repoRoot, "-").getPath(), "read")); } } this.pathFilter = pathFilter; this.accessControlContext = AccessController.getContext(); resourceRootFactory = (rootPath, loaderPath, loaderName) -> { final ResourceLoader loader = ModuleXmlParser.ResourceRootFactory.getDefault().createResourceLoader(rootPath, loaderPath, loaderName); final List list = this.resourceLoaderList; synchronized (list) { if (list.size() == 1 && list.get(0) == TERMINATED_MARKER) { safeClose(loader); throw new IllegalStateException("Module finder is closed"); } list.add(loader); } return loader; }; } /** * Construct a new instance. * * @param repoRoots the repository roots to use * @param pathFilter the path filter to use */ public LocalModuleFinder(final File[] repoRoots, final PathFilter pathFilter) { this(repoRoots, pathFilter, true); } /** * Construct a new instance. * * @param repoRoots the repository roots to use */ public LocalModuleFinder(final File[] repoRoots) { this(repoRoots, PathFilters.acceptAll()); } /** * Construct a new instance, using the {@code module.path} system property or the {@code JAVA_MODULEPATH} environment variable * to get the list of module repository roots. *

* This is equivalent to a call to {@link LocalModuleFinder#LocalModuleFinder(boolean) LocalModuleFinder(true)}. *

*/ public LocalModuleFinder() { this(true); } /** * Construct a new instance, using the {@code module.path} system property or the {@code JAVA_MODULEPATH} environment variable * to get the list of module repository roots. * * @param supportLayersAndAddOns {@code true} if the identified module repository roots should be checked for * an internal structure of child "layer" and "add-on" directories that may also * be treated as module roots lower in precedence than the parent root. Any "layers" * subdirectories whose names are specified in a {@code layers.conf} file found in * the module repository root will be added in the precedence of order specified * in the {@code layers.conf} file; all "add-on" subdirectories will be added at * a lower precedence than all "layers" and with no guaranteed precedence order * between them. If {@code false} no check for "layer" and "add-on" directories * will be performed. * */ public LocalModuleFinder(boolean supportLayersAndAddOns) { this(getRepoRoots(supportLayersAndAddOns), PathFilters.acceptAll(), false); } static File[] getRepoRoots(final boolean supportLayersAndAddOns) { return supportLayersAndAddOns ? LayeredModulePathFactory.resolveLayeredModulePath(getModulePathFiles()) : getModulePathFiles(); } private static File[] getModulePathFiles() { return getFiles(System.getProperty("module.path", System.getenv("JAVA_MODULEPATH")), 0, 0); } private static File[] getFiles(final String modulePath, final int stringIdx, final int arrayIdx) { if (modulePath == null) return NO_FILES; final int i = modulePath.indexOf(File.pathSeparatorChar, stringIdx); final File[] files; if (i == -1) { files = new File[arrayIdx + 1]; files[arrayIdx] = new File(modulePath.substring(stringIdx)).getAbsoluteFile(); } else { files = getFiles(modulePath, i + 1, arrayIdx + 1); files[arrayIdx] = new File(modulePath.substring(stringIdx, i)).getAbsoluteFile(); } return files; } public ModuleSpec findModule(final String name, final ModuleLoader delegateLoader) throws ModuleLoadException { final String child = PathUtils.basicModuleNameToPath(name); if (child == null) { return null; // not valid, so not found } final PathFilter pathFilter = this.pathFilter; if (pathFilter.accept(child + "/")) { try { return doPrivileged((PrivilegedExceptionAction) () -> parseModuleXmlFile(resourceRootFactory, name, delegateLoader, repoRoots), accessControlContext); } catch (PrivilegedActionException e) { try { throw e.getCause(); } catch (IOException e1) { throw new ModuleLoadException(e1); } catch (RuntimeException | Error | ModuleLoadException e1) { throw e1; } catch (Throwable t) { throw new UndeclaredThrowableException(t); } } } return null; } /** * Parse a {@code module.xml} file and return the corresponding module specification. * * @param identifier the identifier to load * @param delegateLoader the delegate module loader to use for module specifications * @param roots the repository root paths to search * @return the module specification * @throws IOException if reading the module file failed * @throws ModuleLoadException if creating the module specification failed (e.g. due to a parse error) * @deprecated Use {@link #parseModuleXmlFile(String, ModuleLoader, File...)} instead. */ @Deprecated(forRemoval = true) public static ModuleSpec parseModuleXmlFile(final ModuleIdentifier identifier, final ModuleLoader delegateLoader, final File... roots) throws IOException, ModuleLoadException { return parseModuleXmlFile(identifier.toString(), delegateLoader, roots); } /** * Parse a {@code module.xml} file and return the corresponding module specification. * * @param name the name of the module to load * @param delegateLoader the delegate module loader to use for module specifications * @param roots the repository root paths to search * @return the module specification * @throws IOException if reading the module file failed * @throws ModuleLoadException if creating the module specification failed (e.g. due to a parse error) */ public static ModuleSpec parseModuleXmlFile(final String name, final ModuleLoader delegateLoader, final File... roots) throws IOException, ModuleLoadException { return parseModuleXmlFile(ModuleXmlParser.ResourceRootFactory.getDefault(), name, delegateLoader, roots); } static ModuleSpec parseModuleXmlFile(final ModuleXmlParser.ResourceRootFactory factory, final String name, final ModuleLoader delegateLoader, final File... roots) throws IOException, ModuleLoadException { final String child = PathUtils.basicModuleNameToPath(name); if (child == null) { return null; // not valid, so not found } for (File root : roots) { File file = new File(root, child); File moduleXml = new File(file, MODULE_FILE); if (moduleXml.exists()) { final ModuleSpec spec = ModuleXmlParser.parseModuleXml(factory, delegateLoader, name, file, moduleXml); if (spec == null) break; return spec; } } return null; } private static final Path MODULE_FILE_PATH = new File(MODULE_FILE).toPath(); private static final Predicate ITER_FILTER = new Predicate() { public boolean test(final Path path) { final Path fileName = path.getFileName(); return fileName != null && fileName.equals(MODULE_FILE_PATH); } }; public Iterator iterateModules(final String baseName, final boolean recursive, final ModuleLoader delegateLoader) { return new Iterator<>() { private final Iterator rootIter = Arrays.asList(repoRoots).iterator(); private final Set found = new HashSet<>(); private Iterator pathIter; private String next; public boolean hasNext() { while (next == null) { while (pathIter == null) { if (! rootIter.hasNext()) { return false; } Path path = rootIter.next().toPath(); if (baseName != null && ! baseName.isEmpty()) { path = path.resolve(PathUtils.basicModuleNameToPath(baseName)); } try { pathIter = Files.walk(path, recursive ? Integer.MAX_VALUE : 1).filter(ITER_FILTER).iterator(); } catch (IOException ignored) { pathIter = null; continue; } } if (pathIter.hasNext()) { final Path nextPath = pathIter.next(); if (nextPath.getParent() == null) { continue; } try (InputStream stream = Files.newInputStream(nextPath)) { final ModuleSpec moduleSpec = ModuleXmlParser.parseModuleXml(ModuleXmlParser.ResourceRootFactory.getDefault(), nextPath.getParent().toString(), stream, nextPath.toString(), delegateLoader, (String)null); if (moduleSpec != null) { this.next = moduleSpec.getName(); if (found.add(this.next)) { return true; } this.next = null; } } catch (IOException | ModuleLoadException e) { // ignore } } else { pathIter = null; } } return true; } public String next() { if (! hasNext()) throw new NoSuchElementException(); try { return next; } finally { next = null; } } }; } public String toString() { final StringBuilder b = new StringBuilder(); b.append("local module finder @").append(Integer.toHexString(hashCode())).append(" (roots: "); final int repoRootsLength = repoRoots.length; for (int i = 0; i < repoRootsLength; i++) { final File root = repoRoots[i]; b.append(root); if (i != repoRootsLength - 1) { b.append(','); } } b.append(')'); return b.toString(); } /** * Close this module loader and release all backing files. Note that subsequent load attempts will fail with an * error after this method is called. */ public void close() { final List list = this.resourceLoaderList; final ArrayList toClose; synchronized (list) { if (list.size() == 1 && list.get(0) == TERMINATED_MARKER) { return; } toClose = new ArrayList<>(list); list.clear(); list.add(TERMINATED_MARKER); } for (ResourceLoader resourceLoader : toClose) { safeClose(resourceLoader); } } private static void safeClose(AutoCloseable closeable) { if (closeable != null) try { closeable.close(); } catch (Throwable ignored) {} } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/LocalModuleLoader.java000066400000000000000000000052611472011152000275400ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.File; import org.jboss.modules.filter.PathFilter; import org.jboss.modules.filter.PathFilters; /** * A local filesystem-backed module loader. * * @author John Bailey * @author David M. Lloyd */ public final class LocalModuleLoader extends DelegatingModuleLoader implements AutoCloseable { /** * Construct a new instance. * * @param repoRoots the array of repository roots to look for modules */ public LocalModuleLoader(final File[] repoRoots) { this(repoRoots, PathFilters.acceptAll()); } /** * Construct a new instance. * * @param repoRoots the array of repository roots to look for modules * @param pathFilter the path filter to apply to roots */ public LocalModuleLoader(final File[] repoRoots, final PathFilter pathFilter) { super(Utils.JDK_MODULE_LOADER, new ModuleFinder[] { new LocalModuleFinder(repoRoots, pathFilter)}); } /** * Construct a new instance, using the {@code module.path} system property or the {@code JAVA_MODULEPATH} environment variable * to get the list of module repository roots. */ public LocalModuleLoader() { super(Utils.JDK_MODULE_LOADER, new ModuleFinder[] { new LocalModuleFinder() }); } public String toString() { final StringBuilder b = new StringBuilder(); b.append("local module loader @").append(Integer.toHexString(hashCode())).append(" (finder: ").append(getFinders()[0]).append(')'); return b.toString(); } /** * Close this module loader and release all backing files. Note that subsequent load attempts will fail with an * error after this method is called. */ public void close() { final ModuleFinder[] finders = getFinders(); assert finders.length == 1 && finders[0] instanceof LocalModuleFinder; ((LocalModuleFinder)finders[0]).close(); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/Main.java000066400000000000000000000765061472011152000251070ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; 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.lang.instrument.Instrumentation; import java.lang.management.ManagementFactory; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; import java.security.AccessControlContext; import java.security.AccessController; import java.security.Policy; import java.security.PrivilegedAction; import java.security.ProtectionDomain; import java.security.Provider; import java.security.Security; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import java.util.logging.LogManager; import java.util.jar.Attributes; import java.util.jar.Manifest; import java.util.prefs.Preferences; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.jboss.modules.log.JDKModuleLogger; import org.jboss.modules.log.StreamModuleLogger; import static java.security.AccessController.doPrivileged; import static org.jboss.modules.SecurityActions.setContextClassLoader; /** * The main entry point of JBoss Modules when run as a JAR on the command line. * * @author David M. Lloyd * @author Richard Opalka * @author Jason T. Greene * @apiviz.exclude */ public final class Main { static { // Force initialization at the earliest possible point @SuppressWarnings("unused") long start = StartTimeHolder.START_TIME; } private static final String[] NO_STRINGS = new String[0]; static volatile Instrumentation instrumentation; private Main() { } private static void usage() { System.out.println("Usage: java [-jvmoptions...] -jar " + getJarName() + ".jar [-options...] [args...]"); System.out.println(" java [-jvmoptions...] -jar " + getJarName() + ".jar [-options...] -jar [args...]"); System.out.println(" java [-jvmoptions...] -jar " + getJarName() + ".jar [-options...] -cp [args...]"); System.out.println(" java [-jvmoptions...] -jar " + getJarName() + ".jar [-options...] -class [args...]"); System.out.println("where is a valid module specification string"); System.out.println("and options include:"); System.out.println(" -help Display this message"); System.out.println(" -mp, -modulepath "); System.out.println(" A list of directories, separated by '" + File.pathSeparator + "', where modules may be located"); System.out.println(" If not specified, the value of the \"module.path\" system property is used"); System.out.println(" -class Specify that the final argument is a"); System.out.println(" class to load from the class path; not compatible with -jar"); System.out.println(" -cp,-classpath "); System.out.println(" A search path for class files; implies -class"); System.out.println(" -dep,-dependencies [,,...]"); System.out.println(" A list of module dependencies to add to the class path;"); System.out.println(" requires -class or -cp"); System.out.println(" -deptree Print the dependency tree of the given module instead of running it"); System.out.println(" -debuglog Enable debug mode output to System.out during bootstrap before any logging manager is installed"); System.out.println(" -jar Specify that the final argument is the name of a"); System.out.println(" JAR file to run as a module; not compatible with -class"); System.out.println(" -javaagent:agent.jar"); System.out.println(" Add a Java agent that can load modules"); System.out.println(" -secmgr Run with a security manager installed; not compatible with -secmgrmodule"); System.out.println(" -secmgrmodule "); System.out.println(" Run with a security manager module; not compatible with -secmgr"); System.out.println(" -add-provider [/]"); System.out.println(" Add a security provider of the given module and class (can be given more than once)"); System.out.println(" -version Print version and exit\n"); } /** * Run JBoss Modules. * * @param args the command-line arguments * * @throws Throwable if an error occurs */ public static void main(String[] args) throws Throwable { final int argsLen = args.length; String deps = null; String[] moduleArgs = NO_STRINGS; String modulePath = null; String classpath = null; boolean jar = false; boolean classpathDefined = false; boolean classDefined = false; boolean depTree = false; String nameArgument = null; boolean defaultSecMgr = false; String secMgrModule = null; boolean debuglog = false; final List agentJars = new ArrayList<>(); final List addedProviders = new ArrayList<>(); for (int i = 0; i < argsLen; i++) { final String arg = args[i]; try { if (arg.charAt(0) == '-') { // it's an option if ("-version".equals(arg)) { System.out.println("JBoss Modules version " + getVersionString()); return; } else if ("-help".equals(arg)) { usage(); return; } else if ("-modulepath".equals(arg) || "-mp".equals(arg)) { if (modulePath != null) { System.err.println("Module path may only be specified once"); System.exit(1); } modulePath = args[++i]; System.setProperty("module.path", modulePath); } else if ("-deptree".equals(arg)) { if (depTree) { System.err.println("-deptree may only be specified once"); System.exit(1); } if (jar) { System.err.println("-deptree may not be specified with -jar"); System.exit(1); } if (classDefined) { System.err.println("-deptree may not be specified with -class"); System.exit(1); } if (classpathDefined) { System.err.println("-deptree may not be specified with -classpath"); System.exit(1); } depTree = true; } else if ("-debuglog".equals(arg)) { debuglog = true; } else if ("-jar".equals(arg)) { if (jar) { System.err.println("-jar flag may only be specified once"); System.exit(1); } if (classpathDefined) { System.err.println("-cp/-classpath may not be specified with -jar"); System.exit(1); } if (classDefined) { System.err.println("-class may not be specified with -jar"); System.exit(1); } if (depTree) { System.err.println("-deptree may not be specified with -jar"); System.exit(1); } jar = true; } else if ("-cp".equals(arg) || "-classpath".equals(arg)) { if (classpathDefined) { System.err.println("-cp or -classpath may only be specified once."); System.exit(1); } if (classDefined) { System.err.println("-class may not be specified with -cp/classpath"); System.exit(1); } if (jar) { System.err.println("-cp/-classpath may not be specified with -jar"); System.exit(1); } if (depTree) { System.err.println("-deptree may not be specified with -classpath"); System.exit(1); } classpathDefined = true; classpath = args[++i]; doPrivileged(new PropertyWriteAction("java.class.path", classpath)); } else if ("-dep".equals(arg) || "-dependencies".equals(arg)) { if (deps != null) { System.err.println("-dep or -dependencies may only be specified once."); System.exit(1); } deps = args[++i]; } else if ("-class".equals(arg)) { if (classDefined) { System.err.println("-class flag may only be specified once"); System.exit(1); } if (classpathDefined) { System.err.println("-class may not be specified with -cp/classpath"); System.exit(1); } if (jar) { System.err.println("-class may not be specified with -jar"); System.exit(1); } if (depTree) { System.err.println("-deptree may not be specified with -class"); System.exit(1); } classDefined = true; } else if ("-secmgr".equals(arg)) { if (defaultSecMgr) { System.err.println("-secmgr may only be specified once"); System.exit(1); } if (secMgrModule != null) { System.err.println("-secmgr may not be specified when -secmgrmodule is given"); System.exit(1); } defaultSecMgr = true; } else if ("-secmgrmodule".equals(arg)) { if (secMgrModule != null) { System.err.println("-secmgrmodule may only be specified once"); System.exit(1); } if (defaultSecMgr) { System.err.println("-secmgrmodule may not be specified when -secmgr is given"); System.exit(1); } secMgrModule = args[++ i]; } else if ("-add-provider".equals(arg)) { addedProviders.add(args[++i]); } else if (arg.startsWith("-javaagent:")) { agentJars.add(arg.substring(11)); } else { System.err.printf("Invalid option '%s'%n", arg); usage(); System.exit(1); } } else { // it's the module specification nameArgument = arg; int cnt = argsLen - i - 1; moduleArgs = new String[cnt]; System.arraycopy(args, i + 1, moduleArgs, 0, cnt); break; } } catch (IndexOutOfBoundsException e) { System.err.printf("Argument expected for option '%s'%n", arg); usage(); System.exit(1); } } int actualVersion = Runtime.version().feature(); if (actualVersion >= 24 && (secMgrModule != null || defaultSecMgr)) { System.err.printf("The security manager is not supported in Java %d.", Runtime.version().feature()); System.exit(1); } if (deps != null && ! classDefined && ! classpathDefined) { System.err.println("-deps may only be specified when -cp/-classpath or -class is in use"); System.exit(1); } // run the module if (nameArgument == null) { if (classDefined || classpathDefined) { System.err.println("No class name specified"); } else if (jar) { System.err.println("No JAR specified"); } else { System.err.println("No module specified"); } usage(); System.exit(1); } final ModuleLoader loader; final ModuleLoader environmentLoader; environmentLoader = DefaultBootModuleLoaderHolder.INSTANCE; final Path rootPath = Paths.get("").toAbsolutePath(); final String moduleName; final String className; if (jar) { loader = new ModuleLoader(new FileSystemClassPathModuleFinder(environmentLoader)); moduleName = rootPath.resolve(nameArgument).normalize().toString(); className = null; } else if (classpathDefined || classDefined) { final String[] items; if (classpath != null) { AccessController.doPrivileged(new PropertyWriteAction("java.class.path", classpath)); items = classpath.split(Pattern.quote(File.pathSeparator)); } else { items = NO_STRINGS; } for (int i = 0; i < items.length; i++) { items[i] = rootPath.resolve(items[i]).normalize().toString(); } loader = new DelegatingModuleLoader(environmentLoader, new ClassPathModuleFinder(environmentLoader, items, deps, nameArgument)); moduleName = ""; className = null; } else { loader = environmentLoader; final int idx = nameArgument.lastIndexOf('/'); if (idx != -1) { moduleName = nameArgument.substring(0, idx); className = nameArgument.substring(idx + 1); } else { moduleName = nameArgument; className = null; } } Module.initBootModuleLoader(environmentLoader); if (depTree) { DependencyTreeViewer.print(new PrintWriter(System.out), nameArgument, LocalModuleFinder.getRepoRoots(true)); System.exit(0); } if(debuglog) { // Install the StreamModuleLogger on System.out to capture bootstrap messages Module.setModuleLogger(new StreamModuleLogger(System.out)); } if (moduleName == null) { return; } final Module module; try { module = loader.loadModule(moduleName); } catch (ModuleNotFoundException e) { e.printStackTrace(System.err); System.exit(1); return; } final String requireJavaVersion = module.getProperty("jboss.require-java-version", Integer.toString(actualVersion)); final Pattern versionPattern = Pattern.compile("(?:1\\.)?(\\d+)"); final Matcher requireMatcher = versionPattern.matcher(requireJavaVersion); if (requireMatcher.matches() && Integer.parseInt(requireMatcher.group(1)) > actualVersion) { System.err.printf("This application requires Java specification version %s or later to run (this Java virtual machine implements specification version %s)%n", requireJavaVersion, Integer.valueOf(actualVersion)); System.exit(1); } ModularURLStreamHandlerProvider.addHandlerModule(module); ModularContentHandlerFactory.addHandlerModule(module); if (actualVersion < 24) { // at this point, having a security manager already installed will prevent correct operation. final SecurityManager existingSecMgr = System.getSecurityManager(); if (existingSecMgr != null) { System.err.println("An existing security manager was detected. You must use the -secmgr switch to start with a security manager."); System.exit(1); return; // not reached } try { final Iterator iterator = module.loadService(Policy.class).iterator(); if (iterator.hasNext()) { Policy.setPolicy(iterator.next()); } } catch (Exception ignored) { } // configure policy so that if SM is enabled, modules can still function final ModulesPolicy policy = new ModulesPolicy(Policy.getPolicy()); Policy.setPolicy(policy); if (secMgrModule != null) { final Module loadedModule; try { loadedModule = environmentLoader.loadModule(secMgrModule); } catch (ModuleNotFoundException e) { e.printStackTrace(System.err); System.exit(1); return; } final Iterator iterator = ServiceLoader.load(SecurityManager.class, loadedModule.getClassLoaderPrivate()) .iterator(); if (iterator.hasNext()) { System.setSecurityManager(iterator.next()); } else { System.err.println("No security manager found in module " + secMgrModule); System.exit(1); } } if (defaultSecMgr) { final Iterator iterator = module.loadService(SecurityManager.class).iterator(); if (iterator.hasNext()) { System.setSecurityManager(iterator.next()); } else { System.setSecurityManager(new SecurityManager()); } } } final ModuleClassLoader bootClassLoader = module.getClassLoaderPrivate(); setContextClassLoader(bootClassLoader); final String serviceName = getServiceName(bootClassLoader, "java.util.prefs.PreferencesFactory"); if (serviceName != null) { final String old = System.setProperty("java.util.prefs.PreferencesFactory", serviceName); try { Preferences.systemRoot(); } finally { if (old == null) { System.clearProperty("java.util.prefs.PreferencesFactory"); } else { System.setProperty("java.util.prefs.PreferencesFactory", old); } } } final String logManagerName = getServiceName(bootClassLoader, "java.util.logging.LogManager"); if (logManagerName != null) { System.setProperty("java.util.logging.manager", logManagerName); if (LogManager.getLogManager().getClass() == LogManager.class) { System.err.println("WARNING: Failed to load the specified log manager class " + logManagerName); } else { Module.setModuleLogger(new JDKModuleLogger()); } } // Activated the module finder ModuleLoggerFinder.activate(bootClassLoader); if (! agentJars.isEmpty()) { final Instrumentation instrumentation = Main.instrumentation; if (instrumentation == null) { // we have to self-attach (todo later) System.err.println("Not started in agent mode (self-attach not supported yet)"); usage(); System.exit(1); } final ModuleLoader agentLoader = new ModuleLoader(new FileSystemClassPathModuleFinder(loader)); for (String agentJarArg : agentJars) { final String agentJar; final String agentArgs; final int i = agentJarArg.indexOf('='); if (i > 0) { agentJar = agentJarArg.substring(0, i); if (agentJarArg.length() > (i + 1)) { agentArgs = agentJarArg.substring(i + 1); } else { agentArgs = ""; } } else { agentJar = agentJarArg; agentArgs = ""; } final Module agentModule; try { agentModule = agentLoader.loadModule(new File(agentJar).getAbsolutePath()); } catch (ModuleLoadException ex) { System.err.printf("Cannot load agent JAR %s: %s", agentJar, ex); System.exit(1); throw new IllegalStateException(); } final ModuleClassLoader classLoader = agentModule.getClassLoaderPrivate(); final InputStream is = classLoader.getResourceAsStream("META-INF/MANIFEST.MF"); final Manifest manifest; if (is == null) { System.err.printf("Agent JAR %s has no manifest", agentJar); System.exit(1); throw new IllegalStateException(); } try { manifest = new Manifest(); manifest.read(is); is.close(); } catch (IOException e) { try { is.close(); } catch (IOException e2) { e2.addSuppressed(e); throw e2; } throw e; } // Note that this does not implement agent invocation as defined on // https://docs.oracle.com/javase/8/docs/api/java/lang/instrument/package-summary.html. This is also not // done on the system class path which means some agents that rely on that may not work well here. final Attributes attributes = manifest.getMainAttributes(); final String preMainClassName = attributes.getValue("Premain-Class"); if (preMainClassName != null) { final Class preMainClass = Class.forName(preMainClassName, true, classLoader); Object[] premainArgs; Method premain; try { premain = preMainClass.getDeclaredMethod("premain", String.class, Instrumentation.class); premainArgs = new Object[] {agentArgs, instrumentation}; } catch (NoSuchMethodException ignore) { // If the method is not found we should check for the string only method premain = preMainClass.getDeclaredMethod("premain", String.class); premainArgs = new Object[] {agentArgs}; } catch (Exception e) { System.out.printf("Failed to find premain method: %s", e); System.exit(1); throw new IllegalStateException(); } try { premain.invoke(null, premainArgs); } catch (InvocationTargetException e) { System.out.printf("Execution of premain method failed: %s", e.getCause()); System.exit(1); throw new IllegalStateException(); } } else { System.out.printf("Agent JAR %s has no premain method", agentJar); System.exit(1); throw new IllegalStateException(); } } } final String mbeanServerBuilderName = getServiceName(bootClassLoader, "javax.management.MBeanServerBuilder"); if (mbeanServerBuilderName != null) { System.setProperty("javax.management.builder.initial", mbeanServerBuilderName); // Initialize the platform mbean server ManagementFactory.getPlatformMBeanServer(); } for (String addedProvider : addedProviders) { final int idx = addedProvider.indexOf('/'); if (idx != -1) { final String provModule = addedProvider.substring(0, idx); final String provClazz = addedProvider.substring(idx + 1); final Class providerClass; try { providerClass = Class.forName(provClazz, false, environmentLoader.loadModule(provModule).getClassLoaderPrivate()).asSubclass(Provider.class); // each provider needs permission to install itself doPrivileged(new AddProviderAction(providerClass.getConstructor().newInstance()), getProviderContext(providerClass)); } catch (Exception e) { Module.getModuleLogger().trace(e, "Failed to initialize a security provider"); } } else { final ModuleClassLoader classLoader = environmentLoader.loadModule(addedProvider).getClassLoaderPrivate(); final ServiceLoader providerServiceLoader = ServiceLoader.load(Provider.class, classLoader); final Iterator iterator = providerServiceLoader.iterator(); for (;;) try { if (! (iterator.hasNext())) { Module.getModuleLogger().trace("Module \"%s\" did not contain a security provider service", addedProvider); break; } final Provider provider = iterator.next(); final Class providerClass = provider.getClass(); // each provider needs permission to install itself doPrivileged(new AddProviderAction(provider), getProviderContext(providerClass)); } catch (ServiceConfigurationError | RuntimeException e) { Module.getModuleLogger().trace(e, "Failed to initialize a security provider"); } } } final ServiceLoader providerServiceLoader = ServiceLoader.load(Provider.class, bootClassLoader); Iterator iterator = providerServiceLoader.iterator(); for (;;) try { if (! (iterator.hasNext())) break; final Provider provider = iterator.next(); final Class providerClass = provider.getClass(); // each provider needs permission to install itself doPrivileged(new AddProviderAction(provider), getProviderContext(providerClass)); } catch (ServiceConfigurationError | RuntimeException e) { Module.getModuleLogger().trace(e, "Failed to initialize a security provider"); } ModuleLoader.installMBeanServer(); final ArrayList argsList = new ArrayList<>(moduleArgs.length); Collections.addAll(argsList, moduleArgs); final ServiceLoader preMainServiceLoader = ServiceLoader.load(PreMain.class, bootClassLoader); for (PreMain preMain : preMainServiceLoader) { preMain.run(argsList); } try { final String[] argsArray = argsList.toArray(NO_STRINGS); if (className != null) module.run(className, argsArray); else module.run(argsArray); } catch (InvocationTargetException e) { throw e.getCause(); } return; } private static AccessControlContext getProviderContext(final Class providerClass) { return new AccessControlContext(new ProtectionDomain[] { providerClass.getProtectionDomain() }); } private static String getServiceName(ClassLoader classLoader, String className) throws IOException { try (final InputStream stream = classLoader.getResourceAsStream("META-INF/services/" + className)) { if ( stream == null ) return null; final BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); String line; while ((line = reader.readLine()) != null) { final int i = line.indexOf('#'); if (i != -1) { line = line.substring(0, i); } line = line.trim(); if (line.length() == 0) continue; return line; } return null; } } private static final String JAR_NAME; private static final String VERSION_STRING; static { Properties versionProps = new Properties(); String jarName = "(unknown)"; String versionString = "(unknown)"; try (InputStream stream = Main.class.getResourceAsStream("version.properties")) { if (stream != null) try (InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) { versionProps.load(reader); jarName = versionProps.getProperty("jarName", jarName); versionString = versionProps.getProperty("version", versionString); } } catch (IOException ignored) { } JAR_NAME = jarName; VERSION_STRING = versionString; } /** * Get the name of the JBoss Modules JAR. * * @return the name */ public static String getJarName() { return JAR_NAME; } /** * Get the version string of JBoss Modules. * * @return the version string */ public static String getVersionString() { return VERSION_STRING; } static final class AddProviderAction implements PrivilegedAction { private final Provider provider; AddProviderAction(final Provider provider) { this.provider = provider; } public Void run() { Security.addProvider(provider); return null; } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/Metrics.java000066400000000000000000000022421472011152000256130ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.security.AccessController; /** * @author David M. Lloyd */ final class Metrics { static final boolean ENABLED; private Metrics() { } static long getCurrentCPUTime() { return ENABLED ? System.nanoTime() : 0L; } static { ENABLED = Boolean.parseBoolean(AccessController.doPrivileged(new PropertyReadAction("jboss.modules.metrics", "false"))); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ModularAgent.java000066400000000000000000000021621472011152000265700ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2019 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.lang.instrument.Instrumentation; /** * The modular agent entry point. */ public final class ModularAgent { public static void premain(String agentArgs, Instrumentation instrumentation) { agentmain(agentArgs, instrumentation); } public static void agentmain(String agentArgs, Instrumentation instrumentation) { Main.instrumentation = instrumentation; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ModularContentHandlerFactory.java000066400000000000000000000064201472011152000317730ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.net.ContentHandler; import java.net.ContentHandlerFactory; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.List; import java.util.ServiceLoader; import java.util.concurrent.CopyOnWriteArrayList; /** * @author David M. Lloyd */ final class ModularContentHandlerFactory implements ContentHandlerFactory { private static final PrivilegedAction CONTENT_MODULES_LIST_ACTION = new PropertyReadAction("jboss.content.handler.modules"); private static final List modules; static { CopyOnWriteArrayList list = new CopyOnWriteArrayList<>(); final SecurityManager sm = System.getSecurityManager(); final String urlModulesList; if (sm != null) { urlModulesList = AccessController.doPrivileged(CONTENT_MODULES_LIST_ACTION); } else { urlModulesList = CONTENT_MODULES_LIST_ACTION.run(); } if (urlModulesList != null) { final List moduleList = new ArrayList<>(); int f = 0; int i; do { i = urlModulesList.indexOf('|', f); final String moduleId = (i == -1 ? urlModulesList.substring(f) : urlModulesList.substring(f, i)).trim(); if (! moduleId.isEmpty()) { try { Module module = Module.getBootModuleLoader().loadModule(moduleId); moduleList.add(module); } catch (RuntimeException | ModuleLoadException e) { // skip it } } f = i + 1; } while (i != -1); list.addAll(moduleList); } modules = list; } static final ModularContentHandlerFactory INSTANCE = new ModularContentHandlerFactory(); static void addHandlerModule(Module module) { modules.add(module); } public ContentHandler createContentHandler(final String mimeType) { for (Module module : modules) { ServiceLoader loader = module.loadService(ContentHandlerFactory.class); for (ContentHandlerFactory factory : loader) try { final ContentHandler handler = factory.createContentHandler(mimeType); if (handler != null) { return handler; } } catch (RuntimeException e) { // ignored } } return null; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ModularURLStreamHandlerProvider.java000066400000000000000000000114271472011152000323650ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.net.URLStreamHandler; import java.net.URLStreamHandlerFactory; import java.net.spi.URLStreamHandlerProvider; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.List; import java.util.ServiceLoader; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; /** * The root URL stream handler factory for the module system. * * @author David M. Lloyd */ final class ModularURLStreamHandlerProvider extends URLStreamHandlerProvider { private static final PrivilegedAction URL_MODULES_LIST_ACTION = new PropertyReadAction("jboss.protocol.handler.modules"); private static final List modules; private static final ThreadLocal> reentered = ThreadLocal.withInitial(FastCopyHashSet::new); static { CopyOnWriteArrayList list = new CopyOnWriteArrayList<>(); final SecurityManager sm = System.getSecurityManager(); final String urlModulesList; if (sm != null) { urlModulesList = AccessController.doPrivileged(URL_MODULES_LIST_ACTION); } else { urlModulesList = URL_MODULES_LIST_ACTION.run(); } if (urlModulesList != null) { final List moduleList = new ArrayList<>(); int f = 0; int i; do { i = urlModulesList.indexOf('|', f); final String moduleId = (i == -1 ? urlModulesList.substring(f) : urlModulesList.substring(f, i)).trim(); if (! moduleId.isEmpty()) { try { Module module = Module.getBootModuleLoader().loadModule(moduleId); moduleList.add(module); } catch (RuntimeException | ModuleLoadException e) { // skip it } } f = i + 1; } while (i != -1); list.addAll(moduleList); } modules = list; } static final ModularURLStreamHandlerProvider INSTANCE = new ModularURLStreamHandlerProvider(); static void addHandlerModule(Module module) { modules.add(module); } private ModularURLStreamHandlerProvider() { } private URLStreamHandler locateHandler(final String protocol) { URLStreamHandler handler; for (Module module : modules) { handler = loadService(protocol, module, URLStreamHandlerProvider.class); if (handler != null) return handler; // backward compatibility handler = loadService(protocol, module, URLStreamHandlerFactory.class); if (handler != null) return handler; } return "data".equals(protocol) ? DataURLStreamHandler.getInstance() : null; } private static URLStreamHandler loadService(final String protocol, final Module module, final Class providerType) { final ServiceLoader loader = module.loadService(providerType); for (URLStreamHandlerFactory factory : loader) { try { final URLStreamHandler handler = factory.createURLStreamHandler(protocol); if (handler != null) { return handler; } } catch (RuntimeException e) { // ignored } } return null; } public URLStreamHandler createURLStreamHandler(final String protocol) { final Set set = reentered.get(); if (set.add(protocol)) { try { if (System.getSecurityManager() == null) { return locateHandler(protocol); } return AccessController.doPrivileged(new PrivilegedAction() { public URLStreamHandler run() { return locateHandler(protocol); } }); } finally { set.remove(protocol); } } return null; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/Module.java000066400000000000000000002222641472011152000254420ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import static java.security.AccessController.doPrivileged; import java.io.IOException; import java.io.InputStream; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.net.URLConnection; import java.security.AccessController; import java.security.Permission; import java.security.PermissionCollection; import java.security.Permissions; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.ServiceLoader; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Predicate; import org.jboss.modules._private.ModulesPrivateAccess; import org.jboss.modules.filter.ClassFilter; import org.jboss.modules.filter.ClassFilters; import org.jboss.modules.filter.PathFilter; import org.jboss.modules.filter.PathFilters; import org.jboss.modules.log.ModuleLogger; import org.jboss.modules.log.NoopModuleLogger; import org.jboss.modules.security.ModularPermissionFactory; /** * A module is a unit of classes and other resources, along with the specification of what is imported and exported * by this module from and to other modules. Modules are created by {@link ModuleLoader}s which build modules from * various configuration information and resource roots. * * @author David M. Lloyd * @author John Bailey * @author Flavia Rainone * @author Jason T. Greene * @author thomas.diesler@jboss.com * * @apiviz.landmark */ public final class Module { private static final AtomicReference BOOT_MODULE_LOADER; private static final MethodType MAIN_METHOD_TYPE = MethodType.methodType(void.class, String[].class); static { log = NoopModuleLogger.getInstance(); BOOT_MODULE_LOADER = new AtomicReference<>(); EMPTY_CLASS_FILTERS = new FastCopyHashSet<>(0); EMPTY_PATH_FILTERS = new FastCopyHashSet<>(0); GET_DEPENDENCIES = new RuntimePermission("getDependencies"); GET_CLASS_LOADER = new RuntimePermission("getClassLoader"); GET_BOOT_MODULE_LOADER = new RuntimePermission("getBootModuleLoader"); ACCESS_MODULE_LOGGER = new RuntimePermission("accessModuleLogger"); ADD_CONTENT_HANDLER_FACTORY = new RuntimePermission("addContentHandlerFactory"); ADD_URL_STREAM_HANDLER_FACTORY = new RuntimePermission("addURLStreamHandlerFactory"); final String pkgsString = AccessController.doPrivileged(new PropertyReadAction("jboss.modules.system.pkgs")); final List list = new ArrayList<>(); if (pkgsString != null) { int i; int nc = -1; do { i = nc + 1; nc = pkgsString.indexOf(',', i); String part; if (nc == -1) { part = pkgsString.substring(i).trim(); } else { part = pkgsString.substring(i, nc).trim(); } if (! part.isEmpty()) { list.add((part + ".").intern()); } } while (nc != -1); } systemPackages = list.toArray(String[]::new); systemPaths = list.stream().map(i -> i.replace('.', '/')).toArray(String[]::new); AccessController.doPrivileged(new PrivilegedAction() { public Void run() { try { URL.setURLStreamHandlerFactory(ModularURLStreamHandlerProvider.INSTANCE); } catch (Throwable t) { // todo log a warning or something } try { URLConnection.setContentHandlerFactory(ModularContentHandlerFactory.INSTANCE); } catch (Throwable t) { // todo log a warning or something } return null; } }); } // static properties static final String[] systemPackages; static final String[] systemPaths; static final ModulesPrivateAccess PRIVATE_ACCESS = new ModulesPrivateAccess() { public ModuleClassLoader getClassLoaderOf(final Module module) { return module.getClassLoaderPrivate(); } }; /** * Private access for module internal code. Throws {@link SecurityException} for user code. * * @throws SecurityException always */ public static ModulesPrivateAccess getPrivateAccess() { if (STACK_WALKER.getCallerClass() == ModularPermissionFactory.class) { return PRIVATE_ACCESS; } throw new SecurityException(); } /** * The system-wide module logger, which may be changed via {@link #setModuleLogger(org.jboss.modules.log.ModuleLogger)}. */ static volatile ModuleLogger log; private static final FastCopyHashSet EMPTY_CLASS_FILTERS; private static final FastCopyHashSet EMPTY_PATH_FILTERS; // immutable properties /** * The name of this module. */ private final String name; /** * The name of the main class, if any (may be {@code null}). */ private final String mainClassName; /** * The module class loader for this module. */ private final ModuleClassLoader moduleClassLoader; /** * The module loader which created this module. */ private final ModuleLoader moduleLoader; /** * The fallback local loader, if any is defined. */ private final LocalLoader fallbackLoader; /** * The properties map specified when this module was defined. */ private final Map properties; /** * The assigned permission collection. */ private final PermissionCollection permissionCollection; /** * The (optional) module version. */ private final Version version; // mutable properties /** * Module aliases */ volatile Set aliases = new HashSet<>(); /** * The linkage state. */ private volatile Linkage linkage = Linkage.NONE; // private constants private static final RuntimePermission GET_DEPENDENCIES; private static final RuntimePermission GET_CLASS_LOADER; private static final RuntimePermission GET_BOOT_MODULE_LOADER; private static final RuntimePermission ACCESS_MODULE_LOGGER; private static final RuntimePermission ADD_CONTENT_HANDLER_FACTORY; private static final RuntimePermission ADD_URL_STREAM_HANDLER_FACTORY; private static final PermissionCollection NO_PERMISSIONS = noPermissions(); /** * Construct a new instance from a module specification. * * @param spec the module specification * @param moduleLoader the module loader */ Module(final ConcreteModuleSpec spec, final ModuleLoader moduleLoader) { this.moduleLoader = moduleLoader; // Initialize state from the spec. name = spec.getName(); mainClassName = spec.getMainClass(); fallbackLoader = spec.getFallbackLoader(); final PermissionCollection permissionCollection = spec.getPermissionCollection(); this.permissionCollection = permissionCollection == null ? NO_PERMISSIONS : permissionCollection.isReadOnly() ? permissionCollection : copyPermissions(permissionCollection); //noinspection ThisEscapedInObjectConstruction final ModuleClassLoader.Configuration configuration = new ModuleClassLoader.Configuration(this, spec.getAssertionSetting(), spec.getResourceLoaders(), spec.getClassFileTransformer()); final ModuleClassLoaderFactory factory = spec.getModuleClassLoaderFactory(); final Map properties = spec.getProperties(); this.properties = properties.isEmpty() ? Collections.emptyMap() : new LinkedHashMap<>(properties); this.version = spec.getVersion(); ModuleClassLoader moduleClassLoader = null; if (factory != null) moduleClassLoader = factory.create(configuration); if (moduleClassLoader == null) moduleClassLoader = new ModuleClassLoader(configuration); this.moduleClassLoader = moduleClassLoader; } private static PermissionCollection noPermissions() { final Permissions permissions = new Permissions(); permissions.setReadOnly(); return permissions; } private static PermissionCollection copyPermissions(PermissionCollection permissionCollection) { final Permissions permissions = new Permissions(); final Enumeration elements = permissionCollection.elements(); while (elements.hasMoreElements()) { permissions.add(elements.nextElement()); } permissions.setReadOnly(); return permissions; } LocalLoader getFallbackLoader() { return fallbackLoader; } Dependency[] getDependenciesInternal() { return linkage.getDependencies(); } DependencySpec[] getDependencySpecsInternal() { return linkage.getDependencySpecs(); } ModuleClassLoader getClassLoaderPrivate() { return moduleClassLoader; } /** * Get the current dependencies of this module. * * @return the current dependencies of this module * @throws SecurityException if a security manager is enabled and the caller does not have the {@code getDependencies} * {@link RuntimePermission} */ public DependencySpec[] getDependencies() throws SecurityException { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(GET_DEPENDENCIES); } return getDependencySpecsInternal().clone(); } /** * Get an exported resource from a specific root in this module. * * @param rootPath the module root to search * @param resourcePath the path of the resource * @return the resource * @deprecated Resource root names are deprecated. */ @Deprecated public Resource getExportedResource(final String rootPath, final String resourcePath) { return moduleClassLoader.loadResourceLocal(rootPath, resourcePath); } /** * Run a module's main class, if any. * * @param args the arguments to pass * @throws NoSuchMethodException if there is no main method * @throws InvocationTargetException if the main method failed * @throws ClassNotFoundException if the main class is not found */ public void run(final String[] args) throws NoSuchMethodException, InvocationTargetException, ClassNotFoundException { run(mainClassName, args); } /** * Run the given main class in this module. * * @param className the class name to run (must not be {@code null}) * @param args the arguments to pass * @throws NoSuchMethodException if there is no main method * @throws InvocationTargetException if the main method failed * @throws ClassNotFoundException if the main class is not found */ public void run(final String className, final String[] args) throws NoSuchMethodException, InvocationTargetException, ClassNotFoundException { if (className == null) { throw new NoSuchMethodException("No main class defined for " + this); } final ClassLoader oldClassLoader = SecurityActions.setContextClassLoader(moduleClassLoader); try { final Class mainClass = Class.forName(className, false, moduleClassLoader); try { Class.forName(className, true, moduleClassLoader); } catch (Throwable t) { throw new InvocationTargetException(t, "Failed to initialize main class '" + className + "'"); } final MethodHandles.Lookup lookup = MethodHandles.publicLookup(); final MethodHandle methodHandle; try { methodHandle = lookup.findStatic(mainClass, "main", MAIN_METHOD_TYPE); } catch (IllegalAccessException e) { throw new NoSuchMethodException("The main method is not public"); } try { methodHandle.invokeExact(args); } catch (Throwable throwable) { throw new InvocationTargetException(throwable); } } finally { SecurityActions.setContextClassLoader(oldClassLoader); } } /** * Get this module's identifier. * * @return the identifier * @deprecated Use {@link #getName()} instead. */ @Deprecated(forRemoval = true) public ModuleIdentifier getIdentifier() { return ModuleIdentifier.fromString(getName()); } /** * Get this module's name. * * @return this module's name */ public String getName() { return name; } /** * Get the module loader which created this module. * * @return the module loader of this module */ public ModuleLoader getModuleLoader() { return moduleLoader; } /** * Load a service loader from this module. * * @param serviceType the service type class * @param the service type * @return the service loader */ public ServiceLoader loadService(Class serviceType) { getClass().getModule().addUses(serviceType); return ServiceLoader.load(serviceType, moduleClassLoader); } /** * Load a service loader from this module, without looking at dependencies. * * @param serviceType the service type class * @param the service type * @return the service loader */ public ServiceLoader loadServiceDirectly(Class serviceType) { getClass().getModule().addUses(serviceType); return ServiceLoader.load(serviceType, new ClassLoader(null) { public Enumeration getResources(final String name) throws IOException { final Enumeration resourceEnumeration = Collections.enumeration(getClassLoader().getLocalLoader().loadResourceLocal(name)); return new Enumeration<>() { public boolean hasMoreElements() { return resourceEnumeration.hasMoreElements(); } public URL nextElement() { return resourceEnumeration.nextElement().getURL(); } }; } }); } /** * Load a service loader from a module in the caller's module loader. The caller's * module loader refers to the loader of the module of the class that calls this method. * Note that {@link #loadService(Class)} is more efficient since it does not need to crawl * the stack. * * @param the service type * @param identifier the module identifier containing the service loader * @param serviceType the service type class * @return the loaded service from the caller's module * @throws ModuleLoadException if the named module failed to load * @deprecated Use {@link #loadServiceFromCallerModuleLoader(String, Class)} instead. */ @Deprecated(forRemoval = true) public static ServiceLoader loadServiceFromCallerModuleLoader(ModuleIdentifier identifier, Class serviceType) throws ModuleLoadException { Class caller = STACK_WALKER.getCallerClass(); assert ! caller.getPackageName().equals(Module.class.getPackageName()); String name = identifier.toString(); Module callerModule = forClass(caller); if (callerModule != null) { ModuleLoader ml = callerModule.getModuleLoader(); if (ml != null) { return ml.loadModule(name).loadService(serviceType); } } throw new ModuleLoadException(name); } /** * Load a service loader from a module in the caller's module loader. The caller's * module loader refers to the loader of the module of the class that calls this method. * Note that {@link #loadService(Class)} is more efficient since it does not need to crawl * the stack. * * @param the service type * @param name the module name containing the service loader * @param serviceType the service type class * @return the loaded service from the caller's module * @throws ModuleLoadException if the named module failed to load */ public static ServiceLoader loadServiceFromCallerModuleLoader(String name, Class serviceType) throws ModuleLoadException { Class caller = STACK_WALKER.getCallerClass(); assert ! caller.getPackageName().equals(Module.class.getPackageName()); Module callerModule = forClass(caller); if (callerModule != null) { ModuleLoader ml = callerModule.getModuleLoader(); if (ml != null) { return ml.loadModule(name).loadService(serviceType); } } throw new ModuleLoadException(name); } /** * Get the class loader for a module. The class loader can be used to access non-exported classes and * resources of the module. *

* If a security manager is present, then this method invokes the security manager's {@code checkPermission} method * with a RuntimePermission("getClassLoader") permission to verify access to the class loader. If * access is not granted, a {@code SecurityException} will be thrown. * * @return the module class loader */ public ModuleClassLoader getClassLoader() { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(GET_CLASS_LOADER); } return moduleClassLoader; } /** * Get all the paths exported by this module. * * @return the paths that are exported by this module */ public Set getExportedPaths() { return Collections.unmodifiableSet(getPathsUnchecked().keySet()); } /** * Get the module for a loaded class, or {@code null} if the class did not come from any module. * * @param clazz the class * @return the module it came from */ public static Module forClass(Class clazz) { final ClassLoader cl = clazz.getClassLoader(); return forClassLoader(cl, false); } /** * Get the module for a class loader, or {@code null} if the class loader is not associated with any module. If * the class loader is unknown, it is possible to check the parent class loader up the chain, and so on until a module is found. * * @param cl the class loader * @param search {@code true} to search up the delegation chain * @return the associated module */ public static Module forClassLoader(ClassLoader cl, boolean search) { if (cl instanceof ModuleClassLoader) { return ((ModuleClassLoader) cl).getModule(); } else if (search && cl != null) { return forClassLoader(cl.getParent(), true); } else { return null; } } /** * Gets the boot module loader. The boot module loader is the * initial loader that is established by the module framework. It typically * is based off of the environmental module path unless it is overridden by * specifying a different class name for the {@code boot.module.loader} system * property. * * @return the boot module loader */ public static ModuleLoader getBootModuleLoader() { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(GET_BOOT_MODULE_LOADER); } ModuleLoader loader; while ((loader = BOOT_MODULE_LOADER.get()) == null) { loader = DefaultBootModuleLoaderHolder.INSTANCE; if (BOOT_MODULE_LOADER.compareAndSet(null, loader)) { break; } // get it again } return loader; } /** * Get the system module loader. This is the module loader which contains the Java platform modules, plus * a module for JBoss Modules itself, called {@code org.jboss.modules}. * * @return the system module loader */ public static ModuleLoader getSystemModuleLoader() { return Utils.JDK_MODULE_LOADER; } /** * Returns an iterable of available and filtered providers of given type. * * @param type service provider type * @param filter to specify which providers to load * @param loader to be used for providers lookup * @return An iterable of available and filtered providers of given type */ public static Iterable findServices(final Class type, final Predicate> filter, final ClassLoader loader) { if (type == null) { throw new IllegalArgumentException("type is null"); } if (filter == null) { throw new IllegalArgumentException("filter is null"); } if (loader == null) { throw new IllegalArgumentException("loader is null"); } return Utils.findServices(type, filter, loader); } static void initBootModuleLoader(ModuleLoader loader) { BOOT_MODULE_LOADER.set(loader); } /** * Gets the current module loader. The current module loader is the * loader of the module from the calling class. Note that this method * must crawl the stack to determine this, so other mechanisms are more * efficient. * * @return the current module loader, or {@code null} if this method is called outside of a module */ public static ModuleLoader getCallerModuleLoader() { return ModuleLoader.forClass(STACK_WALKER.getCallerClass()); } /** * Get the current thread's context module loader. This loader is the one which defined the module * whose class loader is, or is a parent of, the thread's current context class loader. If there is none, * then {@code null} is returned. * * @return the module loader, or {@code null} if none is set */ public static ModuleLoader getContextModuleLoader() { Module module = Module.forClassLoader(Thread.currentThread().getContextClassLoader(), true); if (module != null) { return module.getModuleLoader(); } return null; } static final StackWalker STACK_WALKER = doPrivileged((PrivilegedAction) () -> StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)); /** * Get a module from the current module loader. Note that this must crawl the * stack to determine this, so other mechanisms are more efficient. * @see #getCallerModuleLoader() * * @param identifier the module identifier * @return the module * @throws ModuleLoadException if the module could not be loaded * @deprecated Use {@link #getModuleFromCallerModuleLoader(String)} instead. */ @Deprecated(forRemoval = true) public static Module getModuleFromCallerModuleLoader(final ModuleIdentifier identifier) throws ModuleLoadException { final String name = identifier.toString(); Class caller = STACK_WALKER.getCallerClass(); assert ! caller.getPackageName().equals(Module.class.getPackageName()); ModuleLoader ml = ModuleLoader.forClass(caller); if (ml != null) { return ml.loadModule(name); } throw new ModuleLoadException(name); } /** * Get a module from the current module loader. Note that this must crawl the * stack to determine this, so other mechanisms are more efficient. * @see #getCallerModuleLoader() * * @param name the module name * @return the module * @throws ModuleLoadException if the module could not be loaded */ public static Module getModuleFromCallerModuleLoader(final String name) throws ModuleLoadException { Class caller = STACK_WALKER.getCallerClass(); assert ! caller.getPackageName().equals(Module.class.getPackageName()); ModuleLoader ml = ModuleLoader.forClass(caller); if (ml != null) { return ml.loadModule(name); } throw new ModuleLoadException(name); } /** * Get the caller's module. The caller's module is the module containing the method that calls this * method. Note that this method crawls the stack so other ways of obtaining the * module are more efficient. * * @return the current module */ public static Module getCallerModule() { return forClass(STACK_WALKER.getCallerClass()); } /** * Get the module with the given identifier from the module loader used by this module. * * @param identifier the module identifier * @return the module * @throws ModuleLoadException if an error occurs * @deprecated Use {@link #getModule(String)} instead. */ @Deprecated(forRemoval = true) public Module getModule(final ModuleIdentifier identifier) throws ModuleLoadException { return getModule(identifier.toString()); } /** * Get the module with the given identifier from the module loader used by this module. * * @param name the module name * @return the module * @throws ModuleLoadException if an error occurs */ public Module getModule(final String name) throws ModuleLoadException { return moduleLoader.loadModule(name); } /** * Load a class from a module in the system module loader. * * @see #getBootModuleLoader() * * @param moduleIdentifier the identifier of the module from which the class * should be loaded * @param className the class name to load * @return the class * @throws ModuleLoadException if the module could not be loaded * @throws ClassNotFoundException if the class could not be loaded * @deprecated Use {@link #loadClassFromBootModuleLoader(String, String)} instead. */ @Deprecated(forRemoval = true) public static Class loadClassFromBootModuleLoader(final ModuleIdentifier moduleIdentifier, final String className) throws ModuleLoadException, ClassNotFoundException { return loadClassFromBootModuleLoader(moduleIdentifier.toString(), className); } /** * Load a class from a module in the system module loader. * * @see #getBootModuleLoader() * * @param name the name of the module from which the class * should be loaded * @param className the class name to load * @return the class * @throws ModuleLoadException if the module could not be loaded * @throws ClassNotFoundException if the class could not be loaded */ public static Class loadClassFromBootModuleLoader(final String name, final String className) throws ModuleLoadException, ClassNotFoundException { return Class.forName(className, true, getBootModuleLoader().loadModule(name).getClassLoaderPrivate()); } /** * Load a class from a module in the caller's module loader. * * @see #getCallerModuleLoader() * * @param moduleIdentifier the identifier of the module from which the class * should be loaded * @param className the class name to load * @return the class * @throws ModuleLoadException if the module could not be loaded * @throws ClassNotFoundException if the class could not be loaded * @deprecated Use {@link #loadClassFromCallerModuleLoader(String, String)} instead. */ @Deprecated(forRemoval = true) public static Class loadClassFromCallerModuleLoader(final ModuleIdentifier moduleIdentifier, final String className) throws ModuleLoadException, ClassNotFoundException { Class caller = STACK_WALKER.getCallerClass(); assert ! caller.getPackageName().equals(Module.class.getPackageName()); ModuleLoader ml = ModuleLoader.forClass(caller); String name = moduleIdentifier.toString(); if (ml != null) { return Class.forName(className, true, ml.loadModule(name).getClassLoaderPrivate()); } throw new ModuleLoadException(name); } /** * Load a class from a module in the caller's module loader. * * @see #getCallerModuleLoader() * * @param name the name of the module from which the class * should be loaded * @param className the class name to load * @return the class * @throws ModuleLoadException if the module could not be loaded * @throws ClassNotFoundException if the class could not be loaded */ public static Class loadClassFromCallerModuleLoader(final String name, final String className) throws ModuleLoadException, ClassNotFoundException { Class caller = STACK_WALKER.getCallerClass(); assert ! caller.getPackageName().equals(Module.class.getPackageName()); ModuleLoader ml = ModuleLoader.forClass(caller); if (ml != null) { return Class.forName(className, true, ml.loadModule(name).getClassLoaderPrivate()); } throw new ModuleLoadException(name); } /** * Load a class from a local loader. * * @param className the class name * @param resolve {@code true} to resolve the class after definition * @return the class */ Class loadModuleClass(final String className, final boolean resolve) throws ClassNotFoundException { for (String s : systemPackages) { if (className.startsWith(s)) { return moduleClassLoader.loadClass(className, resolve); } } final String path = pathOfClass(className); final Map> paths = getPathsUnchecked(); final List loaders = paths.get(path); if (loaders != null) { Class clazz; for (LocalLoader loader : loaders) { clazz = loader.loadClassLocal(className, resolve); if (clazz != null) { return clazz; } } } final LocalLoader fallbackLoader = this.fallbackLoader; if (fallbackLoader != null) { return fallbackLoader.loadClassLocal(className, resolve); } return null; } /** * Load a resource from a local loader. * * @param name the resource name * @return the resource URL, or {@code null} if not found */ URL getResource(final String name) { final String canonPath = PathUtils.canonicalize(name); for (String s : Module.systemPaths) { if (canonPath.startsWith(s)) { return moduleClassLoader.getResource(canonPath); } } log.trace("Attempting to find resource %s in %s", canonPath, this); final String path = pathOf(canonPath); final Map> paths = getPathsUnchecked(); final List loaders = paths.get(path); if (loaders != null) { for (LocalLoader loader : loaders) { final Iterator iterator = loader.loadResourceLocal(canonPath).iterator(); if (iterator.hasNext()) { return iterator.next().getURL(); } } } final LocalLoader fallbackLoader = this.fallbackLoader; if (fallbackLoader != null) { final Iterator iterator = fallbackLoader.loadResourceLocal(canonPath).iterator(); if (iterator.hasNext()) { return iterator.next().getURL(); } } return null; } /** * Load a resource from a local loader. * * @param name the resource name * @return the resource stream, or {@code null} if not found */ InputStream getResourceAsStream(final String name) throws IOException { final String canonPath = PathUtils.canonicalize(name); for (String s : Module.systemPaths) { if (canonPath.startsWith(s)) { return moduleClassLoader.getResourceAsStream(canonPath); } } log.trace("Attempting to find resource %s in %s", canonPath, this); final String path = pathOf(canonPath); final Map> paths = getPathsUnchecked(); final List loaders = paths.get(path); if (loaders != null) { for (LocalLoader loader : loaders) { final List resourceList = loader.loadResourceLocal(canonPath); final Iterator iterator = resourceList.iterator(); if (iterator.hasNext()) { return iterator.next().openStream(); } } } final LocalLoader fallbackLoader = this.fallbackLoader; if (fallbackLoader != null) { final List resourceList = fallbackLoader.loadResourceLocal(canonPath); final Iterator iterator = resourceList.iterator(); if (iterator.hasNext()) { return iterator.next().openStream(); } } return null; } /** * Load all resources of a given name from a local loader. * * @param name the resource name * @return the enumeration of all the matching resource URLs (may be empty) */ Enumeration getResources(final String name) { final String canonPath = PathUtils.canonicalize(PathUtils.relativize(name)); for (String s : Module.systemPaths) { if (canonPath.startsWith(s)) { try { return moduleClassLoader.getResources(canonPath); } catch (IOException e) { return Collections.emptyEnumeration(); } } } log.trace("Attempting to find all resources %s in %s", canonPath, this); final String path = pathOf(canonPath); final Map> paths = getPathsUnchecked(); final List loaders = paths.get(path); final List list = new ArrayList<>(); if (loaders != null) { for (LocalLoader loader : loaders) { final List resourceList = loader.loadResourceLocal(canonPath); for (Resource resource : resourceList) { list.add(resource.getURL()); } } } final LocalLoader fallbackLoader = this.fallbackLoader; if (fallbackLoader != null) { final List resourceList = fallbackLoader.loadResourceLocal(canonPath); for (Resource resource : resourceList) { list.add(resource.getURL()); } } return Collections.enumeration(list); } /** * Get an exported resource URL. * * @param name the resource name * @return the resource, or {@code null} if it was not found */ public URL getExportedResource(final String name) { return getResource(name); } /** * Get all exported resource URLs for a resource name. * * @param name the resource name * @return the resource URLs */ public Enumeration getExportedResources(final String name) { return getResources(name); } /** * Enumerate all the imported resources in this module, subject to a path filter. The filter applies to * the containing path of each resource. * * @param filter the filter to apply to the search * @return the resource iterator (possibly empty) * @throws ModuleLoadException if linking a dependency module fails for some reason */ public Iterator iterateResources(final PathFilter filter) throws ModuleLoadException { final Map> paths = getPaths(); final Iterator>> iterator = paths.entrySet().iterator(); return new Iterator<>() { private String path; private Iterator resourceIterator; private Iterator loaderIterator; private Resource next; public boolean hasNext() { while (next == null) { if (resourceIterator != null) { assert path != null; if (resourceIterator.hasNext()) { next = resourceIterator.next(); return true; } resourceIterator = null; } if (loaderIterator != null) { assert path != null; if (loaderIterator.hasNext()) { final LocalLoader loader = loaderIterator.next(); if (loader instanceof IterableLocalLoader) { resourceIterator = ((IterableLocalLoader)loader).iterateResources(path, false); continue; } } loaderIterator = null; } if (! iterator.hasNext()) { return false; } final Map.Entry> entry = iterator.next(); path = entry.getKey(); if (filter.accept(path)) { loaderIterator = entry.getValue().iterator(); } } return true; } public Resource next() { if (! hasNext()) throw new NoSuchElementException(); try { return next; } finally { next = null; } } public void remove() { throw new UnsupportedOperationException(); } }; } /** * Enumerate all imported resources in this module which match the given glob expression. The glob applies to * the whole resource name. * * @param glob the glob to apply * @return the iterator * @throws ModuleLoadException if linking a dependency module fails for some reason */ public Iterator globResources(final String glob) throws ModuleLoadException { String safeGlob = PathUtils.canonicalize(PathUtils.relativize(glob)); final int i = safeGlob.lastIndexOf('/'); if (i == -1) { return PathFilters.filtered(PathFilters.match(glob), iterateResources(PathFilters.acceptAll())); } else { return PathFilters.filtered(PathFilters.match(glob.substring(i + 1)), iterateResources(PathFilters.match(glob.substring(0, i)))); } } /** * Get the (unmodifiable) set of paths which are imported into this module class loader, including local paths. The * set will include all paths defined by the module's resource loaders, minus any paths excluded by filters. The * set will generally always contain an empty entry (""). The set is unordered and unsorted, and is iterable in * O(n) time and accessible in O(1) time. * * @return the set of paths * @throws ModuleLoadException if the module was previously unlinked, and there was an exception while linking */ public Set getImportedPaths() throws ModuleLoadException { return Collections.unmodifiableSet(getPaths().keySet()); } /** * Get the path name of a class. * * @param className the binary name of the class * @return the parent path */ static String pathOfClass(final String className) { final String resourceName = className.replace('.', '/'); final String path; final int idx = resourceName.lastIndexOf('/'); if (idx > -1) { path = resourceName.substring(0, idx); } else { path = ""; } return path; } /** * Get the path name of a resource. * * @param resourceName the resource name * @return the parent path */ static String pathOf(final String resourceName) { final String path; if (resourceName.indexOf('/') == 0) { return pathOf(resourceName.substring(1)); } final int idx = resourceName.lastIndexOf('/'); if (idx > -1) { path = resourceName.substring(0, idx); } else { path = ""; } return path; } /** * Get the file name of a class. * * @param className the class name * @return the name of the corresponding class file */ static String fileNameOfClass(final String className) { return className.replace('.', '/') + ".class"; } /** * Get the property with the given name, or {@code null} if none was defined. * * @param name the property name * @return the property value */ public String getProperty(String name) { return properties.get(name); } /** * Get the property with the given name, or a default value if none was defined. * * @param name the property name * @param defaultVal the default value * @return the property value */ public String getProperty(String name, String defaultVal) { return properties.getOrDefault(name, defaultVal); } /** * Get a copy of the list of property names. * * @return the property names list */ public List getPropertyNames() { return new ArrayList<>(properties.keySet()); } /** * Get the module version. * * @return the module version, or {@code null} if none was set */ public Version getVersion() { return version; } /** * Get the string representation of this module. * * @return the string representation */ @Override public String toString() { StringBuilder b = new StringBuilder(); b.append("Module \""); b.append(getName()); b.append("\""); if (version != null) { b.append(" version ").append(version); } b.append(" from ").append(moduleLoader); return b.toString(); } /** * Get the logger used by the module system. *

* If a security manager is present, then this method invokes the security manager's {@code checkPermission} method * with a RuntimePermission("accessModuleLogger") permission to verify access to the module logger. If * access is not granted, a {@code SecurityException} will be thrown. * * @return the module logger */ public static ModuleLogger getModuleLogger() { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(ACCESS_MODULE_LOGGER); } return log; } /** * Change the logger used by the module system. *

* If a security manager is present, then this method invokes the security manager's {@code checkPermission} method * with a RuntimePermission("accessModuleLogger") permission to verify access to the module logger. If * access is not granted, a {@code SecurityException} will be thrown. * * @param logger the new logger, must not be {@code null} */ public static void setModuleLogger(final ModuleLogger logger) { if (logger == null) { throw new IllegalArgumentException("logger is null"); } final SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(ACCESS_MODULE_LOGGER); } logger.greeting(); log = logger; } /** * Return the start time in millis when Module.class was loaded. * * @return start time of Module.class load */ public static long getStartTime() { return StartTimeHolder.START_TIME; } /** * Register an additional module which contains content handlers. *

* If a security manager is present, then this method invokes the security manager's {@code checkPermission} method * with a RuntimePermission("addContentHandlerFactory") permission to verify access. If * access is not granted, a {@code SecurityException} will be thrown. * * @param module the module to add */ public static void registerContentHandlerFactoryModule(Module module) { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(ADD_CONTENT_HANDLER_FACTORY); } ModularContentHandlerFactory.addHandlerModule(module); } /** * Register an additional module which contains URL handlers. *

* If a security manager is present, then this method invokes the security manager's {@code checkPermission} method * with a RuntimePermission("addURLStreamHandlerFactory") permission to verify access. If * access is not granted, a {@code SecurityException} will be thrown. * * @param module the module to add */ public static void registerURLStreamHandlerFactoryModule(Module module) { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(ADD_URL_STREAM_HANDLER_FACTORY); } ModularURLStreamHandlerProvider.addHandlerModule(module); } /** * Get the platform identifier. This is the string that uniquely identifies the hardware and OS combination for * the current running system. * * @return the platform identifier */ public static String getPlatformIdentifier() { return NativeLibraryResourceLoader.getArchName(); } /** * Get the module's configured permission collection. * * @return the module permission collection */ public PermissionCollection getPermissionCollection() { return permissionCollection; } // Linking and resolution static final class Visited { private final Module module; private final FastCopyHashSet filters; private final FastCopyHashSet classFilters; private final FastCopyHashSet resourceFilters; private final int hashCode; Visited(final Module module, final FastCopyHashSet filters, final FastCopyHashSet classFilters, final FastCopyHashSet resourceFilters) { this.module = module; this.filters = filters; this.classFilters = classFilters; this.resourceFilters = resourceFilters; hashCode = ((resourceFilters.hashCode() * 13 + classFilters.hashCode()) * 13 + filters.hashCode()) * 13 + module.hashCode(); } public int hashCode() { return hashCode; } public boolean equals(Object other) { return other instanceof Visited && equals((Visited)other); } public boolean equals(Visited other) { return this == other || other != null && module == other.module && filters.equals(other.filters) && classFilters.equals(other.classFilters) && resourceFilters.equals(other.resourceFilters); } } private long addPaths(Dependency[] dependencies, Map> map, FastCopyHashSet filterStack, FastCopyHashSet classFilterStack, final FastCopyHashSet resourceFilterStack, Set visited) throws ModuleLoadException { long subtract = 0L; moduleLoader.incScanCount(); for (Dependency dependency : dependencies) { if (dependency instanceof ModuleDependency) { final ModuleDependency moduleDependency = (ModuleDependency) dependency; final ModuleLoader moduleLoader = moduleDependency.getModuleLoader(); final String name = moduleDependency.getName(); final Module module; try { long pauseStart = Metrics.getCurrentCPUTime(); try { module = moduleLoader.preloadModule(name); } finally { subtract += Metrics.getCurrentCPUTime() - pauseStart; } } catch (ModuleLoadException ex) { if (moduleDependency.isOptional()) { continue; } else { log.trace("Module %s, dependency %s preload failed: %s", getName(), moduleDependency.getName(), ex); throw ex; } } if (module == null) { if (!moduleDependency.isOptional()) { throw new ModuleNotFoundException(name); } continue; } final PathFilter importFilter = dependency.getImportFilter(); final FastCopyHashSet nestedFilters; final FastCopyHashSet nestedClassFilters; final FastCopyHashSet nestedResourceFilters; if (filterStack.contains(importFilter)) { nestedFilters = filterStack; } else { nestedFilters = filterStack.clone(); nestedFilters.add(importFilter); } final ClassFilter classImportFilter = dependency.getClassImportFilter(); if (classImportFilter == ClassFilters.acceptAll() || classFilterStack.contains(classImportFilter)) { nestedClassFilters = classFilterStack; } else { nestedClassFilters = classFilterStack.clone(); if (classImportFilter != ClassFilters.acceptAll()) nestedClassFilters.add(classImportFilter); } final PathFilter resourceImportFilter = dependency.getResourceImportFilter(); if (resourceImportFilter == PathFilters.acceptAll() || resourceFilterStack.contains(resourceImportFilter)) { nestedResourceFilters = resourceFilterStack; } else { nestedResourceFilters = resourceFilterStack.clone(); if (resourceImportFilter != PathFilters.acceptAll()) nestedResourceFilters.add(resourceImportFilter); } subtract += module.addExportedPaths(module.getDependenciesInternal(), map, nestedFilters, nestedClassFilters, nestedResourceFilters, visited); } else if (dependency instanceof ModuleClassLoaderDependency) { final ModuleClassLoaderDependency classLoaderDependency = (ModuleClassLoaderDependency) dependency; LocalLoader localLoader = classLoaderDependency.getLocalLoader(); for (Object filter : classFilterStack.getRawArray()) { if (filter != null && filter != ClassFilters.acceptAll()) { localLoader = createClassFilteredLocalLoader((ClassFilter) filter, localLoader); } } for (Object filter : resourceFilterStack.getRawArray()) { if (filter != null && filter != PathFilters.acceptAll()) { localLoader = createPathFilteredLocalLoader((PathFilter) filter, localLoader); } } ClassFilter classFilter = classLoaderDependency.getClassImportFilter(); if (classFilter != ClassFilters.acceptAll()) { localLoader = createClassFilteredLocalLoader(classFilter, localLoader); } PathFilter resourceFilter = classLoaderDependency.getResourceImportFilter(); if (resourceFilter != PathFilters.acceptAll()) { localLoader = createPathFilteredLocalLoader(resourceFilter, localLoader); } final PathFilter importFilter = classLoaderDependency.getImportFilter(); final Set paths = classLoaderDependency.getPaths(); for (String path : paths) { if (importFilter.accept(path)) { List list = map.get(path); if (list == null) { map.put(path, list = new ArrayList<>()); list.add(localLoader); } else if (! list.contains(localLoader)) { list.add(localLoader); } } } } else if (dependency instanceof LocalDependency) { final LocalDependency localDependency = (LocalDependency) dependency; LocalLoader localLoader = localDependency.getLocalLoader(); for (Object filter : classFilterStack.getRawArray()) { if (filter != null && filter != ClassFilters.acceptAll()) { localLoader = createClassFilteredLocalLoader((ClassFilter) filter, localLoader); } } for (Object filter : resourceFilterStack.getRawArray()) { if (filter != null && filter != PathFilters.acceptAll()) { localLoader = createPathFilteredLocalLoader((PathFilter) filter, localLoader); } } final ClassFilter classFilter = localDependency.getClassImportFilter(); if (classFilter != ClassFilters.acceptAll()) { localLoader = createClassFilteredLocalLoader(classFilter, localLoader); } final PathFilter resourceFilter = localDependency.getResourceImportFilter(); if (resourceFilter != PathFilters.acceptAll()) { localLoader = createPathFilteredLocalLoader(resourceFilter, localLoader); } final PathFilter importFilter = localDependency.getImportFilter(); final Set paths = localDependency.getPaths(); for (String path : paths) { if (importFilter.accept(path)) { List list = map.get(path); if (list == null) { map.put(path, list = new ArrayList<>()); list.add(localLoader); } else if (! list.contains(localLoader)) { list.add(localLoader); } } } } // else unknown dep type so just skip } return subtract; } private LocalLoader createPathFilteredLocalLoader(PathFilter filter, LocalLoader localLoader) { if (localLoader instanceof IterableLocalLoader) return LocalLoaders.createIterablePathFilteredLocalLoader(filter, (IterableLocalLoader) localLoader); else return LocalLoaders.createPathFilteredLocalLoader(filter, localLoader); } private LocalLoader createClassFilteredLocalLoader(ClassFilter filter, LocalLoader localLoader) { if (localLoader instanceof IterableLocalLoader) return LocalLoaders.createIterableClassFilteredLocalLoader(filter, (IterableLocalLoader) localLoader); else return LocalLoaders.createClassFilteredLocalLoader(filter, localLoader); } private long addExportedPaths(Dependency[] dependencies, Map> map, FastCopyHashSet filterStack, FastCopyHashSet classFilterStack, final FastCopyHashSet resourceFilterStack, Set visited) throws ModuleLoadException { if (!visited.add(new Visited(this, filterStack, classFilterStack, resourceFilterStack))) { return 0L; } long subtract = 0L; moduleLoader.incScanCount(); for (Dependency dependency : dependencies) { final PathFilter exportFilter = dependency.getExportFilter(); // skip non-exported dependencies altogether if (exportFilter != PathFilters.rejectAll()) { if (dependency instanceof ModuleDependency) { final ModuleDependency moduleDependency = (ModuleDependency) dependency; final ModuleLoader moduleLoader = moduleDependency.getModuleLoader(); final String name = moduleDependency.getName(); final Module module; try { long pauseStart = Metrics.getCurrentCPUTime(); try { module = moduleLoader.preloadModule(name); } finally { subtract += Metrics.getCurrentCPUTime() - pauseStart; } } catch (ModuleLoadException ex) { if (moduleDependency.isOptional()) { continue; } else { log.trace("Module %s, dependency %s preload failed: %s", getName(), moduleDependency.getName(), ex); throw ex; } } if (module == null) { if (!moduleDependency.isOptional()) { throw new ModuleNotFoundException(name); } continue; } final PathFilter importFilter = dependency.getImportFilter(); final FastCopyHashSet nestedFilters; final FastCopyHashSet nestedClassFilters; final FastCopyHashSet nestedResourceFilters; if (filterStack.contains(importFilter) && filterStack.contains(exportFilter)) { nestedFilters = filterStack; } else { nestedFilters = filterStack.clone(); nestedFilters.add(importFilter); nestedFilters.add(exportFilter); } final ClassFilter classImportFilter = dependency.getClassImportFilter(); final ClassFilter classExportFilter = dependency.getClassExportFilter(); if ((classImportFilter == ClassFilters.acceptAll() || classFilterStack.contains(classImportFilter)) && (classExportFilter == ClassFilters.acceptAll() || classFilterStack.contains(classExportFilter))) { nestedClassFilters = classFilterStack; } else { nestedClassFilters = classFilterStack.clone(); if (classImportFilter != ClassFilters.acceptAll()) nestedClassFilters.add(classImportFilter); if (classExportFilter != ClassFilters.acceptAll()) nestedClassFilters.add(classExportFilter); } final PathFilter resourceImportFilter = dependency.getResourceImportFilter(); final PathFilter resourceExportFilter = dependency.getResourceExportFilter(); if ((resourceImportFilter == PathFilters.acceptAll() || resourceFilterStack.contains(resourceImportFilter)) && (resourceExportFilter == PathFilters.acceptAll() || resourceFilterStack.contains(resourceExportFilter))) { nestedResourceFilters = resourceFilterStack; } else { nestedResourceFilters = resourceFilterStack.clone(); if (resourceImportFilter != PathFilters.acceptAll()) nestedResourceFilters.add(resourceImportFilter); if (resourceExportFilter != PathFilters.acceptAll()) nestedResourceFilters.add(resourceExportFilter); } subtract += module.addExportedPaths(module.getDependenciesInternal(), map, nestedFilters, nestedClassFilters, nestedResourceFilters, visited); } else if (dependency instanceof ModuleClassLoaderDependency) { final ModuleClassLoaderDependency classLoaderDependency = (ModuleClassLoaderDependency) dependency; LocalLoader localLoader = classLoaderDependency.getLocalLoader(); for (Object filter : classFilterStack.getRawArray()) { if (filter != null && filter != ClassFilters.acceptAll()) { localLoader = createClassFilteredLocalLoader((ClassFilter) filter, localLoader); } } for (Object filter : resourceFilterStack.getRawArray()) { if (filter != null && filter != PathFilters.acceptAll()) { localLoader = createPathFilteredLocalLoader((PathFilter) filter, localLoader); } } ClassFilter classImportFilter = classLoaderDependency.getClassImportFilter(); if (classImportFilter != ClassFilters.acceptAll()) { localLoader = createClassFilteredLocalLoader(classImportFilter, localLoader); } ClassFilter classExportFilter = classLoaderDependency.getClassExportFilter(); if (classExportFilter != ClassFilters.acceptAll()) { localLoader = createClassFilteredLocalLoader(classExportFilter, localLoader); } PathFilter resourceImportFilter = classLoaderDependency.getResourceImportFilter(); if (resourceImportFilter != PathFilters.acceptAll()) { localLoader = createPathFilteredLocalLoader(resourceImportFilter, localLoader); } PathFilter resourceExportFilter = classLoaderDependency.getResourceExportFilter(); if (resourceExportFilter != PathFilters.acceptAll()) { localLoader = createPathFilteredLocalLoader(resourceExportFilter, localLoader); } final PathFilter importFilter = classLoaderDependency.getImportFilter(); final Set paths = classLoaderDependency.getPaths(); for (String path : paths) { boolean accept = ! "_private".equals(path); if (accept) for (Object filter : filterStack.getRawArray()) { if (filter != null && ! ((PathFilter)filter).accept(path)) { accept = false; break; } } if (accept && importFilter.accept(path) && exportFilter.accept(path)) { List list = map.get(path); if (list == null) { map.put(path, list = new ArrayList<>(1)); list.add(localLoader); } else if (! list.contains(localLoader)) { list.add(localLoader); } } } } else if (dependency instanceof LocalDependency) { final LocalDependency localDependency = (LocalDependency) dependency; LocalLoader localLoader = localDependency.getLocalLoader(); for (Object filter : classFilterStack.getRawArray()) { if (filter != null && filter != ClassFilters.acceptAll()) { localLoader = createClassFilteredLocalLoader((ClassFilter) filter, localLoader); } } for (Object filter : resourceFilterStack.getRawArray()) { if (filter != null && filter != PathFilters.acceptAll()) { localLoader = createPathFilteredLocalLoader((PathFilter) filter, localLoader); } } ClassFilter classFilter = localDependency.getClassExportFilter(); if (classFilter != ClassFilters.acceptAll()) { localLoader = createClassFilteredLocalLoader(classFilter, localLoader); } classFilter = localDependency.getClassImportFilter(); if (classFilter != ClassFilters.acceptAll()) { localLoader = createClassFilteredLocalLoader(classFilter, localLoader); } PathFilter resourceFilter = localDependency.getResourceExportFilter(); if (resourceFilter != PathFilters.acceptAll()) { localLoader = createPathFilteredLocalLoader(resourceFilter, localLoader); } resourceFilter = localDependency.getResourceImportFilter(); if (resourceFilter != PathFilters.acceptAll()) { localLoader = createPathFilteredLocalLoader(resourceFilter, localLoader); } final Set paths = localDependency.getPaths(); for (String path : paths) { boolean accept = true; for (Object filter : filterStack.getRawArray()) { if (filter != null && ! ((PathFilter)filter).accept(path)) { accept = false; break; } } if (accept && localDependency.getImportFilter().accept(path) && localDependency.getExportFilter().accept(path)) { List list = map.get(path); if (list == null) { map.put(path, list = new ArrayList<>(1)); list.add(localLoader); } else if (! list.contains(localLoader)) { list.add(localLoader); } } } } // else unknown dep type so just skip } } return subtract; } Map> getPaths() throws ModuleLoadException { Linkage oldLinkage = this.linkage; Linkage linkage; Linkage.State state = oldLinkage.getState(); if (state == Linkage.State.LINKED) { return oldLinkage.getPaths(); } // slow path loop boolean intr = false; try { for (;;) { synchronized (this) { oldLinkage = this.linkage; state = oldLinkage.getState(); while (state == Linkage.State.LINKING || state == Linkage.State.NEW) try { wait(); oldLinkage = this.linkage; state = oldLinkage.getState(); } catch (InterruptedException e) { intr = true; } if (state == Linkage.State.LINKED) { return oldLinkage.getPaths(); } this.linkage = linkage = new Linkage(oldLinkage.getDependencySpecs(), oldLinkage.getDependencies(), Linkage.State.LINKING); // fall out and link } boolean ok = false; try { link(linkage); ok = true; } finally { if (! ok) { // restore original (lack of) linkage synchronized (this) { if (this.linkage == linkage) { this.linkage = oldLinkage; notifyAll(); } } } } } } finally { if (intr) { Thread.currentThread().interrupt(); } } } Map> getPathsUnchecked() { try { return getPaths(); } catch (ModuleLoadException e) { throw e.toError(); } } void link(final Linkage linkage) throws ModuleLoadException { final HashMap> importsMap = new HashMap<>(); final Dependency[] dependencies = linkage.getDependencies(); final long start = Metrics.getCurrentCPUTime(); long subtractTime = 0L; try { final Set visited = new FastCopyHashSet<>(16); final FastCopyHashSet filterStack = new FastCopyHashSet<>(8); final FastCopyHashSet classFilterStack = EMPTY_CLASS_FILTERS; final FastCopyHashSet resourceFilterStack = EMPTY_PATH_FILTERS; subtractTime += addPaths(dependencies, importsMap, filterStack, classFilterStack, resourceFilterStack, visited); synchronized (this) { if (this.linkage == linkage) { this.linkage = new Linkage(linkage.getDependencySpecs(), linkage.getDependencies(), Linkage.State.LINKED, importsMap); notifyAll(); } // else all our efforts were just wasted since someone changed the deps in the meantime } } finally { moduleLoader.addLinkTime(Metrics.getCurrentCPUTime() - start - subtractTime); } } void relinkIfNecessary() throws ModuleLoadException { Linkage oldLinkage = this.linkage; Linkage linkage; if (oldLinkage.getState() != Linkage.State.UNLINKED) { return; } synchronized (this) { oldLinkage = this.linkage; if (oldLinkage.getState() != Linkage.State.UNLINKED) { return; } this.linkage = linkage = new Linkage(oldLinkage.getDependencySpecs(), oldLinkage.getDependencies(), Linkage.State.LINKING); } boolean ok = false; try { link(linkage); ok = true; } finally { if (! ok) { // restore original (lack of) linkage synchronized (this) { if (this.linkage == linkage) { this.linkage = oldLinkage; notifyAll(); } } } } } void relink() throws ModuleLoadException { link(linkage); } void setDependencies(final List dependencySpecs) { if (dependencySpecs == null) { throw new IllegalArgumentException("dependencySpecs is null"); } final DependencySpec[] specs = dependencySpecs.toArray(DependencySpec[]::new); for (DependencySpec spec : specs) { if (spec == null) { throw new IllegalArgumentException("dependencySpecs contains a null dependency specification"); } } setDependencies(specs); } void setDependencies(final DependencySpec[] dependencySpecs) { synchronized (this) { linkage = new Linkage(dependencySpecs, calculateDependencies(dependencySpecs), Linkage.State.UNLINKED, null); notifyAll(); } } private Dependency[] calculateDependencies(final DependencySpec[] dependencySpecs) { final Dependency[] dependencies = new Dependency[dependencySpecs.length]; int i = 0; for (DependencySpec spec : dependencySpecs) { final Dependency dependency = spec.getDependency(this); dependencies[i++] = dependency; } return dependencies; } String getMainClass() { return mainClassName; } Package getPackage(final String name) { List loaders = getPathsUnchecked().get(name.replace('.', '/')); if (loaders != null) for (LocalLoader localLoader : loaders) { Package pkg = localLoader.loadPackageLocal(name); if (pkg != null) return pkg; } return null; } Package[] getPackages() { final ArrayList packages = new ArrayList<>(); final Map> allPaths = getPathsUnchecked(); next: for (String path : allPaths.keySet()) { String packageName = path.replace('/', '.'); for (LocalLoader loader : allPaths.get(path)) { Package pkg = loader.loadPackageLocal(packageName); if (pkg != null) { packages.add(pkg); } continue next; } } return packages.toArray(Package[]::new); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ModuleClassLoader.java000066400000000000000000000776551472011152000275730ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.lang.reflect.InvocationTargetException; import java.nio.ByteBuffer; import java.security.PermissionCollection; import java.security.ProtectionDomain; import java.util.IdentityHashMap; import java.util.Iterator; import java.util.NoSuchElementException; import org.jboss.modules.filter.PathFilter; import org.jboss.modules.filter.PathFilters; import org.jboss.modules.log.ModuleLogger; import org.jboss.modules.security.ModularProtectionDomain; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.security.CodeSource; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; /** * A module classloader. Instances of this class implement the complete view of classes and resources available in a * module. Contrast with {@link Module}, which has API methods to access the exported view of classes and resources. * * @author John Bailey * @author David M. Lloyd * @author Richard Opalka * @author thomas.diesler@jboss.com * * @apiviz.landmark */ public class ModuleClassLoader extends ConcurrentClassLoader { static { boolean parallelOk = true; try { parallelOk = ClassLoader.registerAsParallelCapable(); } catch (Throwable ignored) { } if (! parallelOk) { throw new Error("Failed to register " + ModuleClassLoader.class.getName() + " as parallel-capable"); } } private final Module module; private final ClassTransformer transformer; private final AtomicReference> paths = new AtomicReference<>(Paths.none()); private final LocalLoader localLoader = new IterableLocalLoader() { public Class loadClassLocal(final String name, final boolean resolve) { try { return ModuleClassLoader.this.loadClassLocal(name, resolve); } catch (ClassNotFoundException e) { final Throwable cause = e.getCause(); if (cause instanceof Error) { throw (Error) cause; } else if (cause instanceof RuntimeException) { //unlikely throw (RuntimeException) cause; } return null; } } public Package loadPackageLocal(final String name) { return findLoadedPackage(name); } public List loadResourceLocal(final String name) { return ModuleClassLoader.this.loadResourceLocal(name); } public Iterator iterateResources(final String startPath, final boolean recursive) { return ModuleClassLoader.this.iterateResources(startPath, recursive); } public String toString() { return "local loader for " + ModuleClassLoader.this; } }; /** * Construct a new instance. * * @param configuration the module class loader configuration to use */ protected ModuleClassLoader(final Configuration configuration) { super(configuration.getModule().getModuleLoader().getModuleDescription(configuration.getModule())); module = configuration.getModule(); paths.lazySet(new Paths<>(configuration.getResourceLoaders(), Collections.emptyMap())); final AssertionSetting setting = configuration.getAssertionSetting(); if (setting != AssertionSetting.INHERIT) { setDefaultAssertionStatus(setting == AssertionSetting.ENABLED); } transformer = configuration.getTransformer(); } /** * Recalculate the path maps for this module class loader. * * @return {@code true} if the paths were recalculated, or {@code false} if another thread finished recalculating * before the calling thread */ boolean recalculate() { final Paths paths = this.paths.get(); return setResourceLoaders(paths, paths.getSourceList(ResourceLoaderSpec.NO_RESOURCE_LOADERS)); } /** * Change the set of resource loaders for this module class loader, and recalculate the path maps. * * @param resourceLoaders the new resource loaders * @return {@code true} if the paths were recalculated, or {@code false} if another thread finished recalculating * before the calling thread */ boolean setResourceLoaders(final ResourceLoaderSpec[] resourceLoaders) { return setResourceLoaders(paths.get(), resourceLoaders); } private boolean setResourceLoaders(final Paths paths, final ResourceLoaderSpec[] resourceLoaders) { final Map> allPaths = new HashMap<>(); for (ResourceLoaderSpec loaderSpec : resourceLoaders) { final ResourceLoader loader = loaderSpec.getResourceLoader(); final PathFilter filter = loaderSpec.getPathFilter(); for (String path : loader.getPaths()) { if (filter.accept(path)) { final List allLoaders = allPaths.get(path); if (allLoaders == null) { ArrayList newList = new ArrayList<>(16); newList.add(loader); allPaths.put(path, newList); } else { allLoaders.add(loader); } } } } return this.paths.compareAndSet(paths, new Paths<>(resourceLoaders, allPaths)); } /** * Get the local loader which refers to this module class loader. * * @return the local loader */ LocalLoader getLocalLoader() { return localLoader; } /** {@inheritDoc} */ @Override protected final Class findClass(String className, boolean exportsOnly, final boolean resolve) throws ClassNotFoundException { className = className.replace('/', '.'); // Check if we have already loaded it.. Class loadedClass = findLoadedClass(className); if (loadedClass != null) { if (resolve) { resolveClass(loadedClass); } return loadedClass; } final ModuleLogger log = Module.log; final Module module = this.module; log.trace("Finding class %s from %s", className, module); final Class clazz = module.loadModuleClass(className, resolve); if (clazz != null) { return clazz; } log.trace("Class %s not found from %s", className, module); throw new ClassNotFoundException(getClassNotFoundExceptionMessage(className, module)); } /** * Returns an exception message used when producing instances of ClassNotFoundException. This can be overridden * by subclasses to customise the error message. * * @param className the name of the class which is missing * @param fromModule the module from which the class could not be found * @return an exception message used when producing instances of ClassNotFoundException */ protected String getClassNotFoundExceptionMessage(String className, Module fromModule){ return className + " from [" + fromModule + "]"; } /** * Load a class from this class loader. * * @param className the class name to load * @return the loaded class or {@code null} if it was not found * @throws ClassNotFoundException if an exception occurs while loading the class or its dependencies */ public Class loadClassLocal(String className) throws ClassNotFoundException { return loadClassLocal(className, false); } /** * Load a local class from this class loader. * * @param className the class name * @param resolve {@code true} to resolve the loaded class * @return the loaded class or {@code null} if it was not found * @throws ClassNotFoundException if an error occurs while loading the class */ public Class loadClassLocal(final String className, final boolean resolve) throws ClassNotFoundException { final ModuleLogger log = Module.log; final Module module = this.module; log.trace("Finding local class %s from %s", className, module); // Check if we have already loaded it.. Class loadedClass = findLoadedClass(className); if (loadedClass != null) { log.trace("Found previously loaded %s from %s", loadedClass, module); if (resolve) { resolveClass(loadedClass); } return loadedClass; } final Map> paths = this.paths.get().getAllPaths(); log.trace("Loading class %s locally from %s", className, module); String pathOfClass = Module.pathOfClass(className); final List loaders = paths.get(pathOfClass); if (loaders == null) { // no loaders for this path return null; } // Check to see if we can define it locally it ClassSpec classSpec; ResourceLoader resourceLoader; try { if (loaders.size() > 0) { String fileName = Module.fileNameOfClass(className); for (ResourceLoader loader : loaders) { classSpec = loader.getClassSpec(fileName); if (classSpec != null) { resourceLoader = loader; try { preDefine(classSpec, className); } catch (Throwable th) { throw new ClassNotFoundException("Failed to preDefine class: " + className, th); } final Class clazz = defineClass(className, classSpec, resourceLoader); try { postDefine(classSpec, clazz); } catch (Throwable th) { throw new ClassNotFoundException("Failed to postDefine class: " + className, th); } if (resolve) { resolveClass(clazz); } return clazz; } } } } catch (IOException e) { throw new ClassNotFoundException(className, e); } catch (RuntimeException e) { log.trace(e, "Unexpected runtime exception in module loader"); throw new ClassNotFoundException(className, e); } catch (Error e) { log.trace(e, "Unexpected error in module loader"); throw e; } log.trace("No local specification found for class %s in %s", className, module); return null; } /** * Load a local exported resource from a specific root from this module class loader. * * @param root the root name * @param name the resource name * @return the resource, or {@code null} if it was not found */ @Deprecated Resource loadResourceLocal(final String root, final String name) { final Map> paths = this.paths.get().getAllPaths(); final String path = Module.pathOf(name); final List loaders = paths.get(path); if (loaders != null) { for (ResourceLoader loader : loaders) { if (root.equals(loader.getRootName())) { return loader.getResource(name); } } } return null; } /** * Load a local exported resource from this class loader. * * @param name the resource name * @return the list of resources */ public List loadResourceLocal(final String name) { final Map> paths = this.paths.get().getAllPaths(); final String path = Module.pathOf(name); final List loaders = paths.get(path); final List list = new ArrayList<>(loaders == null ? 1 : loaders.size()); if (loaders != null) { for (ResourceLoader loader : loaders) { final Resource resource = loader.getResource(name); if (resource != null) { list.add(resource); } } } return list.isEmpty() ? Collections.emptyList() : list; } private Class doDefineOrLoadClass(final String className, final byte[] bytes, final ByteBuffer byteBuffer, ProtectionDomain protectionDomain) { try { final Class definedClass = bytes != null ? defineClass(className, bytes, 0, bytes.length, protectionDomain) : defineClass(className, byteBuffer, protectionDomain); module.getModuleLoader().incClassCount(); return definedClass; } catch (LinkageError e) { final Class loadedClass = findLoadedClass(className); if (loadedClass != null) { module.getModuleLoader().incRaceCount(); return loadedClass; } throw e; } } private final IdentityHashMap protectionDomains = new IdentityHashMap<>(); private ProtectionDomain getProtectionDomain(CodeSource codeSource) { final IdentityHashMap map = protectionDomains; synchronized (map) { ProtectionDomain protectionDomain = map.get(codeSource); if (protectionDomain == null) { final PermissionCollection permissions = module.getPermissionCollection(); protectionDomain = new ModularProtectionDomain(codeSource, permissions, this); map.put(codeSource, protectionDomain); } return protectionDomain; } } Class defineClassInternal(final String className, ByteBuffer byteBuffer, final ProtectionDomain protectionDomain) { if (transformer != null) { int pos = byteBuffer.position(); int lim = byteBuffer.limit(); ByteBuffer transformed; try { transformed = transformer.transform(this, className.replace('.', '/'), protectionDomain, byteBuffer); } catch (Exception e) { ClassFormatError error = new ClassFormatError(e.getMessage()); error.initCause(e); throw error; } if (transformed != null) { byteBuffer = transformed; } else { byteBuffer.position(0); byteBuffer.limit(lim); byteBuffer.position(pos); } } final long start = Metrics.getCurrentCPUTime(); final Class defined = defineClass(className, byteBuffer, protectionDomain); module.getModuleLoader().addClassLoadTime(Metrics.getCurrentCPUTime() - start); return defined; } Class defineClassInternal(final String className, byte[] bytes, int off, int len, final ProtectionDomain protectionDomain) { if (transformer != null) { return defineClassInternal(className, ByteBuffer.wrap(bytes, off, len), protectionDomain); } final long start = Metrics.getCurrentCPUTime(); final Class defined = defineClass(className, bytes, off, len, protectionDomain); module.getModuleLoader().addClassLoadTime(Metrics.getCurrentCPUTime() - start); return defined; } /** * Define a class from a class name and class spec. Also defines any enclosing {@link Package} instances, * and performs any sealed-package checks. * * @param name the class name * @param classSpec the class spec * @param resourceLoader the resource loader of the class spec * @return the new class */ private Class defineClass(final String name, final ClassSpec classSpec, final ResourceLoader resourceLoader) { final ModuleLogger log = Module.log; final Module module = this.module; log.trace("Attempting to define class %s in %s", name, module); // Ensure that the package is loaded final int lastIdx = name.lastIndexOf('.'); if (lastIdx != -1) { // there's a package name; get the Package for it final String packageName = name.substring(0, lastIdx); synchronized (this) { Package pkg = findLoadedPackage(packageName); if (pkg == null) { try { pkg = definePackage(packageName, resourceLoader.getPackageSpec(packageName)); } catch (IOException e) { pkg = definePackage(packageName, null); } } // Check sealing if (pkg.isSealed() && ! pkg.isSealed(classSpec.getCodeSource().getLocation())) { log.trace("Detected a sealing violation (attempt to define class %s in sealed package %s in %s)", name, packageName, module); // use the same message as the JDK throw new SecurityException("sealing violation: package " + packageName + " is sealed"); } } } final Class newClass; try { byte[] bytes = classSpec.getBytes(); ByteBuffer byteBuffer = classSpec.getByteBuffer(); try { final ProtectionDomain protectionDomain = getProtectionDomain(classSpec.getCodeSource()); if (transformer != null) { ByteBuffer buffer = byteBuffer; if (buffer == null) { buffer = ByteBuffer.wrap(bytes); } int pos = buffer.position(); int lim = buffer.limit(); ByteBuffer transformed; try { transformed = transformer.transform(this, name.replace('.', '/'), protectionDomain, buffer); } catch (Exception e) { ClassFormatError error = new ClassFormatError(e.getMessage()); error.initCause(e); throw error; } if (transformed != null) { byteBuffer = transformed; bytes = null; } else if (byteBuffer != null) { byteBuffer.position(0); byteBuffer.limit(lim); byteBuffer.position(pos); } } final long start = Metrics.getCurrentCPUTime(); newClass = doDefineOrLoadClass(name, bytes, byteBuffer, protectionDomain); module.getModuleLoader().addClassLoadTime(Metrics.getCurrentCPUTime() - start); log.classDefined(name, module); } catch (LinkageError e) { // Prepend the current class name, so that transitive class definition issues are clearly expressed Error ne; try { final String oldMsg = e.getMessage(); final String newMsg = "Failed to link " + name.replace('.', '/') + " (" + module + ")"; ne = e.getClass().getConstructor(String.class).newInstance(oldMsg == null || oldMsg.isEmpty() ? newMsg : newMsg + ": " + oldMsg); ne.initCause(e.getCause()); ne.setStackTrace(e.getStackTrace()); } catch (InstantiationException | NoSuchMethodException | InvocationTargetException | IllegalAccessException ignored) { // just throw the original throw e; } throw ne; } } catch (Error | RuntimeException e) { log.classDefineFailed(e, name, module); throw e; } final AssertionSetting setting = classSpec.getAssertionSetting(); if (setting != AssertionSetting.INHERIT) { setClassAssertionStatus(name, setting == AssertionSetting.ENABLED); } return newClass; } /** * A hook which is invoked before a class is defined. * * @param classSpec the class spec of the defined class * @param className the class to be defined */ @SuppressWarnings("unused") protected void preDefine(ClassSpec classSpec, String className) { } /** * A hook which is invoked after a class is defined. * * @param classSpec the class spec of the defined class * @param definedClass the class that was defined */ @SuppressWarnings("unused") protected void postDefine(ClassSpec classSpec, Class definedClass) { } /** * Define a package from a package spec. * * @param name the package name * @param spec the package specification * @return the new package */ private Package definePackage(final String name, final PackageSpec spec) { final Module module = this.module; final ModuleLogger log = Module.log; log.trace("Attempting to define package %s in %s", name, module); final Package pkg; if (spec == null) { pkg = definePackage(name, null, null, null, null, null, null, null); } else { pkg = definePackage(name, spec.getSpecTitle(), spec.getSpecVersion(), spec.getSpecVendor(), spec.getImplTitle(), spec.getImplVersion(), spec.getImplVendor(), spec.getSealBase()); final AssertionSetting setting = spec.getAssertionSetting(); if (setting != AssertionSetting.INHERIT) { setPackageAssertionStatus(name, setting == AssertionSetting.ENABLED); } } log.trace("Defined package %s in %s", name, module); return pkg; } /** * Find a library from one of the resource loaders. * * @param libname the library name * @return the full absolute path to the library */ @Override protected final String findLibrary(final String libname) { final ModuleLogger log = Module.log; log.trace("Attempting to load native library %s from %s", libname, module); for (ResourceLoaderSpec loader : paths.get().getSourceList(ResourceLoaderSpec.NO_RESOURCE_LOADERS)) { final String library = loader.getResourceLoader().getLibrary(libname); if (library != null) { return library; } } return null; } /** {@inheritDoc} */ @Override public final URL findResource(final String name, final boolean exportsOnly) { return module.getResource(name); } /** {@inheritDoc} */ @Override public final Enumeration findResources(final String name, final boolean exportsOnly) { return module.getResources(name); } /** {@inheritDoc} */ @Override public final InputStream findResourceAsStream(final String name, boolean exportsOnly) { try { return module.getResourceAsStream(name); } catch (IOException e) { return null; } } /** * Get the module for this class loader. * * @return the module */ public final Module getModule() { return module; } /** * Get the name of this module. This method is used by Java 9 in debug output. * * @return the name of this module */ public final String getName() { return super.getName(); } /** * Get a string representation of this class loader. * * @return the string */ @Override public final String toString() { return getClass().getSimpleName() + " for " + module; } Set getPaths() { return paths.get().getAllPaths().keySet(); } /** {@inheritDoc} */ @Override protected final Package definePackage(final String name, final String specTitle, final String specVersion, final String specVendor, final String implTitle, final String implVersion, final String implVendor, final URL sealBase) throws IllegalArgumentException { return super.definePackage(name, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor, sealBase); } /** {@inheritDoc} */ @Override protected final Package getPackageByName(final String name) { Package loaded = findLoadedPackage(name); if (loaded != null) { return loaded; } return module.getPackage(name); } /** {@inheritDoc} */ @Override protected final Package[] getPackages() { return module.getPackages(); } /** {@inheritDoc} */ @Override public final void setDefaultAssertionStatus(final boolean enabled) { super.setDefaultAssertionStatus(enabled); } /** {@inheritDoc} */ @Override public final void setPackageAssertionStatus(final String packageName, final boolean enabled) { super.setPackageAssertionStatus(packageName, enabled); } /** {@inheritDoc} */ @Override public final void setClassAssertionStatus(final String className, final boolean enabled) { super.setClassAssertionStatus(className, enabled); } /** {@inheritDoc} */ @Override public final void clearAssertionStatus() { super.clearAssertionStatus(); } /** {@inheritDoc} */ @Override public final int hashCode() { return super.hashCode(); } /** {@inheritDoc} */ @Override public final boolean equals(final Object obj) { return super.equals(obj); } /** {@inheritDoc} */ @Override protected final Object clone() throws CloneNotSupportedException { return super.clone(); } /** {@inheritDoc} */ @Override protected final void finalize() throws Throwable { super.finalize(); } ResourceLoader[] getResourceLoaders() { final ResourceLoaderSpec[] specs = paths.get().getSourceList(ResourceLoaderSpec.NO_RESOURCE_LOADERS); final int length = specs.length; final ResourceLoader[] loaders = new ResourceLoader[length]; for (int i = 0; i < length; i++) { loaders[i] = specs[i].getResourceLoader(); } return loaders; } /** * Iterate the resources within this module class loader. Only resource roots which are inherently iterable will * be checked, thus the result of this method may only be a subset of the actual loadable resources. The returned * resources are not sorted or grouped in any particular way. * * @param startName the directory name to search * @param recurse {@code true} to recurse into subdirectories, {@code false} otherwise * @return the resource iterator */ public final Iterator iterateResources(final String startName, final boolean recurse) { final String realStartName = PathUtils.canonicalize(PathUtils.relativize(startName)); final PathFilter filter; if (recurse) { if (realStartName.isEmpty()) { filter = PathFilters.acceptAll(); } else { filter = PathFilters.any(PathFilters.is(realStartName), PathFilters.isChildOf(realStartName)); } } else { filter = PathFilters.is(realStartName); } final Map> paths = this.paths.get().getAllPaths(); final Iterator>> iterator = paths.entrySet().iterator(); return new Iterator<>() { private String path; private Iterator resourceIterator; private Iterator loaderIterator; private Resource next; public boolean hasNext() { while (next == null) { if (resourceIterator != null) { assert path != null; if (resourceIterator.hasNext()) { next = resourceIterator.next(); return true; } resourceIterator = null; } if (loaderIterator != null) { assert path != null; if (loaderIterator.hasNext()) { final ResourceLoader loader = loaderIterator.next(); if (loader instanceof IterableResourceLoader) { resourceIterator = ((IterableResourceLoader)loader).iterateResources(path, false); continue; } } loaderIterator = null; } if (! iterator.hasNext()) { return false; } final Map.Entry> entry = iterator.next(); path = entry.getKey(); if (filter.accept(path)) { loaderIterator = entry.getValue().iterator(); } } return true; } public Resource next() { if (! hasNext()) throw new NoSuchElementException(); try { return next; } finally { next = null; } } public void remove() { throw new UnsupportedOperationException(); } }; } /** * Get the (unmodifiable) set of paths which are locally available in this module class loader. The set will * include all paths defined by the module's resource loaders, minus any paths excluded by filters. The set will * generally always contain an empty entry (""). The set is unordered and unsorted, and is iterable in O(n) time * and accessible in O(1) time. * * @return the set of local paths */ public final Set getLocalPaths() { return Collections.unmodifiableSet(paths.get().getAllPaths().keySet()); } /** * An opaque configuration used internally to create a module class loader. * * @apiviz.exclude */ public static final class Configuration { private final Module module; private final AssertionSetting assertionSetting; private final ResourceLoaderSpec[] resourceLoaders; private final ClassTransformer transformer; Configuration(final Module module, final AssertionSetting assertionSetting, final ResourceLoaderSpec[] resourceLoaders, final ClassTransformer transformer) { this.module = module; this.assertionSetting = assertionSetting; this.resourceLoaders = resourceLoaders; this.transformer = transformer; } Module getModule() { return module; } AssertionSetting getAssertionSetting() { return assertionSetting; } ResourceLoaderSpec[] getResourceLoaders() { return resourceLoaders; } ClassTransformer getTransformer() { return transformer; } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ModuleClassLoaderAction.java000066400000000000000000000030571472011152000307120ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2018 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.lang.Module; import java.security.PrivilegedAction; /** */ final class ModuleClassLoaderAction implements PrivilegedAction { static final ClassLoader SAFE_CL; static { ClassLoader safeClassLoader = ModuleClassLoaderAction.class.getClassLoader(); if (safeClassLoader == null) { safeClassLoader = ClassLoader.getSystemClassLoader(); } if (safeClassLoader == null) { safeClassLoader = new ClassLoader() { }; } SAFE_CL = safeClassLoader; } private final Module module; ModuleClassLoaderAction(final Module module) { this.module = module; } public ClassLoader run() { final ClassLoader classLoader = module.getClassLoader(); return classLoader == null ? SAFE_CL : classLoader; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ModuleClassLoaderDependency.java000066400000000000000000000033661472011152000315560ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.util.Set; import org.jboss.modules.filter.ClassFilter; import org.jboss.modules.filter.PathFilter; /** * @author David M. Lloyd */ final class ModuleClassLoaderDependency extends Dependency { private final ModuleClassLoader moduleClassLoader; ModuleClassLoaderDependency(final PathFilter exportFilter, final PathFilter importFilter, final PathFilter resourceExportFilter, final PathFilter resourceImportFilter, final ClassFilter classExportFilter, final ClassFilter classImportFilter, final ModuleClassLoader moduleClassLoader) { super(exportFilter, importFilter, resourceExportFilter, resourceImportFilter, classExportFilter, classImportFilter); this.moduleClassLoader = moduleClassLoader; } LocalLoader getLocalLoader() { return moduleClassLoader.getLocalLoader(); } Set getPaths() { return moduleClassLoader.getPaths(); } public String toString() { return "dependency on " + moduleClassLoader; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ModuleClassLoaderDependencySpec.java000066400000000000000000000031551472011152000323650ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2018 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import org.jboss.modules.filter.ClassFilter; import org.jboss.modules.filter.PathFilter; final class ModuleClassLoaderDependencySpec extends DependencySpec { ModuleClassLoaderDependencySpec(final PathFilter importFilter, final PathFilter exportFilter, final PathFilter resourceImportFilter, final PathFilter resourceExportFilter, final ClassFilter classImportFilter, final ClassFilter classExportFilter) { super(importFilter, exportFilter, resourceImportFilter, resourceExportFilter, classImportFilter, classExportFilter); } Dependency getDependency(final Module module) { return new ModuleClassLoaderDependency(getExportFilter(), getImportFilter(), getResourceExportFilter(), getResourceImportFilter(), getClassExportFilter(), getClassImportFilter(), module.getClassLoaderPrivate()); } public String toString() { return "dependency on local resources"; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ModuleClassLoaderFactory.java000066400000000000000000000023401472011152000310760ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; /** * A producer for Module class loaders. * * @author David M. Lloyd */ public interface ModuleClassLoaderFactory { /** * Create the module class loader. If this method returns {@code null}, then a default implementation is used. * * @param configuration the configuration to use * @return the module class loader, or {@code null} to use the default */ ModuleClassLoader create(ModuleClassLoader.Configuration configuration); } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ModuleDependency.java000066400000000000000000000043121472011152000274310ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import org.jboss.modules.filter.ClassFilter; import org.jboss.modules.filter.PathFilter; /** * @author David M. Lloyd */ final class ModuleDependency extends Dependency { private final ModuleLoader moduleLoader; private final String name; private final boolean optional; ModuleDependency(final PathFilter exportFilter, final PathFilter importFilter, final ModuleLoader moduleLoader, final String name, final boolean optional) { super(exportFilter, importFilter); this.moduleLoader = moduleLoader; this.name = name; this.optional = optional; } ModuleDependency(final PathFilter exportFilter, final PathFilter importFilter, final PathFilter resourceExportFilter, final PathFilter resourceImportFilter, final ClassFilter classExportFilter, final ClassFilter classImportFilter, final ModuleLoader moduleLoader, final String name, final boolean optional) { super(exportFilter, importFilter, resourceExportFilter, resourceImportFilter, classExportFilter, classImportFilter); this.moduleLoader = moduleLoader; this.name = name; this.optional = optional; } String getName() { return name; } boolean isOptional() { return optional; } ModuleLoader getModuleLoader() { return moduleLoader; } public String toString() { return (optional ? "optional " : "" ) + "dependency on " + name + " (" + moduleLoader + ")"; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ModuleDependencySpec.java000066400000000000000000000065361472011152000302560ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import org.jboss.modules.filter.ClassFilter; import org.jboss.modules.filter.PathFilter; /** * A dependency specification on a module. */ public final class ModuleDependencySpec extends DependencySpec { /** * A simple dependency on the {@code java.base} module. */ public static final ModuleDependencySpec JAVA_BASE = new ModuleDependencySpecBuilder().setModuleLoader(Utils.JDK_MODULE_LOADER).setName("java.base").build(); /** * A simple dependency on the {@code java.se} module. */ public static final ModuleDependencySpec JAVA_SE = new ModuleDependencySpecBuilder().setModuleLoader(Utils.JDK_MODULE_LOADER).setName("java.se").build(); private final ModuleLoader moduleLoader; private final String name; private final boolean optional; ModuleDependencySpec(final PathFilter importFilter, final PathFilter exportFilter, final PathFilter resourceImportFilter, final PathFilter resourceExportFilter, final ClassFilter classImportFilter, final ClassFilter classExportFilter, final ModuleLoader moduleLoader, final String name, final boolean optional) { super(importFilter, exportFilter, resourceImportFilter, resourceExportFilter, classImportFilter, classExportFilter); this.moduleLoader = moduleLoader; this.name = name; this.optional = optional; } Dependency getDependency(final Module module) { final ModuleLoader loader = moduleLoader; return new ModuleDependency(exportFilter, importFilter, resourceExportFilter, resourceImportFilter, classExportFilter, classImportFilter, loader == null ? module.getModuleLoader() : loader, name, optional); } /** * Get the module loader of this dependency, or {@code null} if the defined module's loader is to be used. * * @return the module loader */ public ModuleLoader getModuleLoader() { return moduleLoader; } /** * Get the module identifier of the dependency. * * @return the module identifier * @deprecated Use {@code #getName()} instead. */ @Deprecated(forRemoval = true) public ModuleIdentifier getIdentifier() { return ModuleIdentifier.fromString(name); } /** * Get the module name of the dependency. * * @return the module name */ public String getName() { return name; } /** * Determine whether this dependency is optional. * * @return {@code true} if the dependency is optional, {@code false} if it is required */ public boolean isOptional() { return optional; } public String toString() { return "dependency on " + name; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ModuleDependencySpecBuilder.java000066400000000000000000000113741472011152000315610ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import org.jboss.modules.filter.ClassFilter; import org.jboss.modules.filter.PathFilter; /** * A builder for dependency specifications that refer to other modules. */ public final class ModuleDependencySpecBuilder extends DependencySpecBuilder { ModuleLoader moduleLoader; String name; boolean optional; /** * Construct a new instance. */ public ModuleDependencySpecBuilder() { } // covariant overrides public ModuleDependencySpecBuilder setImportFilter(final PathFilter importFilter) { super.setImportFilter(importFilter); return this; } public ModuleDependencySpecBuilder setImportServices(final boolean services) { super.setImportServices(services); return this; } public ModuleDependencySpecBuilder setExportFilter(final PathFilter exportFilter) { super.setExportFilter(exportFilter); return this; } public ModuleDependencySpecBuilder setExport(final boolean export) { super.setExport(export); return this; } public ModuleDependencySpecBuilder setResourceImportFilter(final PathFilter resourceImportFilter) { super.setResourceImportFilter(resourceImportFilter); return this; } public ModuleDependencySpecBuilder setResourceExportFilter(final PathFilter resourceExportFilter) { super.setResourceExportFilter(resourceExportFilter); return this; } public ModuleDependencySpecBuilder setClassImportFilter(final ClassFilter classImportFilter) { super.setClassImportFilter(classImportFilter); return this; } public ModuleDependencySpecBuilder setClassExportFilter(final ClassFilter classExportFilter) { super.setClassExportFilter(classExportFilter); return this; } /** * Get the module loader of the dependency. Defaults to {@code null}, indicating that the module loader * to use should be the loader of the module being defined. * * @return the module loader of the dependency, or {@code null} to use the module's own module loader */ public ModuleLoader getModuleLoader() { return moduleLoader; } /** * Set the module loader of the dependency. * * @param moduleLoader the module loader of the dependency, or {@code null} to use the module's own module loader * @return this builder */ public ModuleDependencySpecBuilder setModuleLoader(final ModuleLoader moduleLoader) { this.moduleLoader = moduleLoader; return this; } /** * Get the module name. * * @return the module name, or {@code null} if was not yet set */ public String getName() { return name; } /** * Set the module name. * * @param name the module name (must not be {@code null}) * @return this builder */ public ModuleDependencySpecBuilder setName(final String name) { if (name == null) { throw new IllegalArgumentException("name is null"); } this.name = name; return this; } /** * Determine whether this dependency will be optional. The default value is {@code false}. * * @return {@code true} if the dependency will be optional, {@code false} if it will be required */ public boolean isOptional() { return optional; } /** * Establish whether this dependency will be optional. * * @param optional {@code true} if the dependency will be optional, {@code false} if it will be required * @return this builder */ public ModuleDependencySpecBuilder setOptional(final boolean optional) { this.optional = optional; return this; } public ModuleDependencySpec build() { final String name = this.name; if (name == null) { throw new IllegalArgumentException("name is null"); } return new ModuleDependencySpec(importFilter, exportFilter, resourceImportFilter, resourceExportFilter, classImportFilter, classExportFilter, moduleLoader, name, optional); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ModuleFinder.java000066400000000000000000000045051472011152000265660ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; /** * A locator for module definitions. * * @author David M. Lloyd */ public interface ModuleFinder { /** * Find a module specification for the given name. The default implementation delegates to the legacy * {@link #findModule(ModuleIdentifier, ModuleLoader)} method for now, however this behavior will be * discontinued in the future. * * @param name the module name * @param delegateLoader the module loader from which dependencies should be resolved * @return the module specification, or {@code null} if no specification is found for this identifier */ default ModuleSpec findModule(String name, ModuleLoader delegateLoader) throws ModuleLoadException { return findModule(ModuleIdentifier.fromString(name), delegateLoader); } /** * Find a module specification for the given identifier. The default implementation returns {@code null}. This * method will never be called by the module system unless {@link #findModule(String, ModuleLoader)} is left * unimplemented. * * @param moduleIdentifier the module identifier * @param delegateLoader the module loader from which dependencies should be resolved * @return the module specification, or {@code null} if no specification is found for this identifier * @deprecated Implement {@link #findModule(String, ModuleLoader)} instead. */ @Deprecated(forRemoval = true) default ModuleSpec findModule(ModuleIdentifier moduleIdentifier, ModuleLoader delegateLoader) throws ModuleLoadException { return null; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ModuleIdentifier.java000066400000000000000000000201211472011152000274310ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.IOException; import java.io.ObjectInputStream; import java.io.Serializable; /** * A unique identifier for a module within a module loader. * * @author John Bailey * @author David M. Lloyd * @author Jason T. Greene * * @deprecated This class has been deprecated in favor of name strings; however, programs using identifiers will * continue to function correctly. * @apiviz.landmark */ @Deprecated public final class ModuleIdentifier implements Serializable { private static final long serialVersionUID = 118533026624827995L; private static final String DEFAULT_SLOT = "main"; private final String name; private final String slot; private transient volatile int hashCode; /** * The class path module (only present if booted from a class path). */ public static final ModuleIdentifier CLASSPATH = new ModuleIdentifier("Classpath", DEFAULT_SLOT); private ModuleIdentifier(final String name, final String slot) { this.name = name; this.slot = slot; hashCode = calculateHashCode(name, slot); } private static int calculateHashCode(final String name, final String slot) { int h = 17; h = 37 * h + name.hashCode(); h = 37 * h + slot.hashCode(); return h; } /** * Get the module name. * * @return the module name */ public String getName() { return name; } /** * Get the module version slot. * * @return the version slot */ public String getSlot() { return slot; } /** * Determine whether this object is equal to another. * * @param other the other object * @return {@code true} if they are equal, {@code false} otherwise */ public boolean equals(Object other) { return other instanceof ModuleIdentifier && equals((ModuleIdentifier)other); } /** * Determine whether this object is equal to another. * * @param other the other object * @return {@code true} if they are equal, {@code false} otherwise */ public boolean equals(ModuleIdentifier other) { return this == other || other != null && name.equals(other.name) && slot.equals(other.slot); } /** * Determine the hash code of this module identifier. * * @return the hash code */ @Override public int hashCode() { return hashCode; } /** * Get the string representation of this module identifier. * * @return the string representation */ @Override public String toString() { final String escapeName = escapeName(name); return slot.equals(DEFAULT_SLOT) ? escapeName : escapeName + ":" + escapeSlot(slot); } private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { ois.defaultReadObject(); hashCode = calculateHashCode(name, slot); } private static String escapeName(String name) { final StringBuilder b = new StringBuilder(); boolean escaped = false; int c; for (int i = 0; i < name.length(); i = name.offsetByCodePoints(i, 1)) { c = name.codePointAt(i); switch (c) { case '\\': case ':': escaped = true; b.append('\\'); // fall thru default: b.appendCodePoint(c); } } return escaped ? b.toString() : name; } private static String escapeSlot(String slot) { final StringBuilder b = new StringBuilder(); boolean escaped = false; int c; for (int i = 0; i < slot.length(); i = slot.offsetByCodePoints(i, 1)) { c = slot.codePointAt(i); switch (c) { case '\\': escaped = true; b.append('\\'); // fall thru default: b.appendCodePoint(c); } } return escaped ? b.toString() : slot; } /** * Parse a module specification from a string. * * @param moduleSpec the specification string * @return the module identifier * @throws IllegalArgumentException if the format of the module specification is invalid or it is {@code null} */ public static ModuleIdentifier fromString(String moduleSpec) throws IllegalArgumentException { if (moduleSpec == null) { throw new IllegalArgumentException("Module specification is null"); } if (moduleSpec.length() == 0) { throw new IllegalArgumentException("Empty module specification"); } int c; final StringBuilder b = new StringBuilder(); int i = 0; while (i < moduleSpec.length()) { c = moduleSpec.codePointAt(i); if (c == '\\') { b.appendCodePoint(c); i = moduleSpec.offsetByCodePoints(i, 1); if (i < moduleSpec.length()) { c = moduleSpec.codePointAt(i); b.appendCodePoint(c); } else { throw new IllegalArgumentException("Name has an unterminated escape"); } } else if (c == ':') { i = moduleSpec.offsetByCodePoints(i, 1); if (i == moduleSpec.length()) { throw new IllegalArgumentException("Slot is empty"); } // end of name, now comes the slot break; } else { b.appendCodePoint(c); } i = moduleSpec.offsetByCodePoints(i, 1); } final String name = b.toString(); b.setLength(0); if (i < moduleSpec.length()) do { c = moduleSpec.codePointAt(i); b.appendCodePoint(c); i = moduleSpec.offsetByCodePoints(i, 1); } while (i < moduleSpec.length()); else { return new ModuleIdentifier(name, DEFAULT_SLOT); } return new ModuleIdentifier(name, b.toString()); } /** * Creates a new module identifier using the specified name and slot. * A slot allows for multiple modules to exist with the same name. * The main usage pattern for this is to differentiate between * two incompatible release streams of a module. * * Normally all module definitions wind up in the "main" slot. * An unspecified or null slot will result in placement in the "main" * slot. * * Unless you have a true need for a slot, it should not be specified. * When in doubt use the {{@link #create(String)} method instead. * * @param name the name of the module * @param slot the slot this module belongs in * @return the identifier */ public static ModuleIdentifier create(final String name, String slot) { if (name == null) throw new IllegalArgumentException("Name can not be null"); if (slot == null) slot = DEFAULT_SLOT; return new ModuleIdentifier(name, slot); } /** * Creates a new module identifier using the specified name. * * @param name the name of the module * @return the identifier */ public static ModuleIdentifier create(String name) { return create(name, null); } }jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ModuleLoadError.java000066400000000000000000000051361472011152000272510ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; /** * Module load error, thrown when there is some problem loading a module during runtime. * * @author David M. Lloyd */ public class ModuleLoadError extends Error { private static final long serialVersionUID = 3286005346300416890L; /** * Constructs a {@code ModuleLoadException} with no detail message. The cause is not initialized, and may subsequently * be initialized by a call to {@link #initCause(Throwable) initCause}. */ public ModuleLoadError() { } /** * Constructs a {@code ModuleLoadException} with the specified detail message. The cause is not initialized, and may * subsequently be initialized by a call to {@link #initCause(Throwable) initCause}. * * @param msg the detail message */ public ModuleLoadError(final String msg) { super(msg); } /** * Constructs a {@code ModuleLoadException} with the specified cause. The detail message is set to: *

(cause == null ? null : cause.toString())
* (which typically contains the class and detail message of {@code cause}). * * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method) */ public ModuleLoadError(final Throwable cause) { super(cause); } /** * Constructs a {@code ModuleLoadException} with the specified detail message and cause. * * @param msg the detail message * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method) */ public ModuleLoadError(final String msg, final Throwable cause) { super(msg, cause); } /** * Convert to a checked exception type. * * @return the checked exception */ public ModuleLoadException toException() { return new ModuleLoadException(getMessage(), getCause()); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ModuleLoadException.java000066400000000000000000000052671472011152000301230ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; /** * Module load exception, thrown when there is some problem loading a module. * * @author David M. Lloyd */ public class ModuleLoadException extends Exception { private static final long serialVersionUID = 3286005346300416890L; /** * Constructs a {@code ModuleLoadException} with no detail message. The cause is not initialized, and may subsequently * be initialized by a call to {@link #initCause(Throwable) initCause}. */ public ModuleLoadException() { } /** * Constructs a {@code ModuleLoadException} with the specified detail message. The cause is not initialized, and may * subsequently be initialized by a call to {@link #initCause(Throwable) initCause}. * * @param msg the detail message */ public ModuleLoadException(final String msg) { super(msg); } /** * Constructs a {@code ModuleLoadException} with the specified cause. The detail message is set to: *
(cause == null ? null : cause.toString())
* (which typically contains the class and detail message of {@code cause}). * * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method) */ public ModuleLoadException(final Throwable cause) { super(cause); } /** * Constructs a {@code ModuleLoadException} with the specified detail message and cause. * * @param msg the detail message * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method) */ public ModuleLoadException(final String msg, final Throwable cause) { super(msg, cause); } /** * Convert to an unchecked error type. * * @return the unchecked error */ public ModuleLoadError toError() { final ModuleLoadError error = new ModuleLoadError(getMessage(), getCause()); error.setStackTrace(getStackTrace()); return error; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ModuleLoader.java000066400000000000000000001524011472011152000265640ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import static java.security.AccessController.doPrivileged; import static org.jboss.modules.management.ObjectProperties.property; import java.lang.management.ManagementFactory; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.UndeclaredThrowableException; import java.net.URL; import java.security.CodeSource; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.security.ProtectionDomain; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import org.jboss.modules.log.ModuleLogger; import org.jboss.modules.management.DependencyInfo; import org.jboss.modules.management.ModuleInfo; import org.jboss.modules.management.ModuleLoaderMXBean; import org.jboss.modules.management.ObjectProperties; import org.jboss.modules.management.ResourceLoaderInfo; import org.jboss.modules.ref.Reaper; import org.jboss.modules.ref.Reference; import org.jboss.modules.ref.WeakReference; import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; /** * A repository for modules, from which a module may be loaded by identifier. Module loaders may additionally * delegate to one or more other module loaders. * * @author David M. Lloyd * @author John Bailey * @author Richard Opalka * @author Jason T. Greene * * @apiviz.landmark */ public class ModuleLoader { private static final RuntimePermission ML_PERM = new RuntimePermission("canCreateModuleLoader"); private static final RuntimePermission MODULE_REDEFINE_PERM = new RuntimePermission("canRedefineModule"); private static final RuntimePermission MODULE_REDEFINE_ANY_PERM = new RuntimePermission("canRedefineAnyModule"); private static final RuntimePermission MODULE_UNLOAD_ANY_PERM = new RuntimePermission("canUnloadAnyModule"); private static final RuntimePermission MODULE_ITERATE_PERM = new RuntimePermission("canIterateModules"); private static final AtomicInteger SEQ = new AtomicInteger(1); private static final Class[] JUST_MODULE_IDENTIFIER = { ModuleIdentifier.class }; private static volatile MBeanReg REG_REF = new TempMBeanReg(); /** * A constant representing zero module finders. */ public static final ModuleFinder[] NO_FINDERS = new ModuleFinder[0]; private final ConcurrentMap moduleMap = new ConcurrentHashMap<>(); private final ModuleFinder[] finders; private final boolean canRedefine; private final ModuleLoaderMXBean mxBean; private final AtomicLong linkTime = new AtomicLong(); private final AtomicLong loadTime = new AtomicLong(); private final AtomicLong classLoadTime = new AtomicLong(); private final AtomicInteger scanCount = new AtomicInteger(); private final AtomicInteger raceCount = new AtomicInteger(); private final AtomicInteger classCount = new AtomicInteger(); private final boolean overridesFindModuleByIdentifier; private final boolean overridesPreloadModuleByIdentifier; ModuleLoader(boolean canRedefine, boolean skipRegister) { this(canRedefine, skipRegister, NO_FINDERS); } // Bypass security check for classes in this package ModuleLoader(boolean canRedefine, boolean skipRegister, ModuleFinder[] finders) { this.canRedefine = canRedefine; this.finders = finders; mxBean = skipRegister ? null : doPrivileged(new PrivilegedAction() { public ModuleLoaderMXBean run() { ObjectName objectName; try { objectName = new ObjectName("jboss.modules", ObjectProperties.properties(property("type", "ModuleLoader"), property("name", ModuleLoader.this.getClass().getSimpleName() + "-" + SEQ.incrementAndGet()))); } catch (MalformedObjectNameException e) { return null; } try { MXBeanImpl mxBean = new MXBeanImpl(ModuleLoader.this, objectName); REG_REF.addMBean(objectName, mxBean); return mxBean; } catch (Throwable ignored) { } return null; } }); // determine if the subclass overrides the crusty old find-module-by-identifier method boolean foundFindModule = false; boolean foundPreloadModule = false; for (Class clazz = getClass(); clazz != ModuleLoader.class; clazz = clazz.getSuperclass().asSubclass(ModuleLoader.class)) { for (Method method : clazz.getDeclaredMethods()) { if ((method.getModifiers() & (Modifier.STATIC | Modifier.PRIVATE)) == 0) { if (method.getName().equals("findModule")) { if (ModuleSpec.class.isAssignableFrom(method.getReturnType())) { if (Arrays.equals(method.getParameterTypes(), JUST_MODULE_IDENTIFIER)) { foundFindModule = true; if (foundPreloadModule) break; } } } else if (method.getName().equals("preloadModule")) { if (Module.class.isAssignableFrom(method.getReturnType())) { if (Arrays.equals(method.getParameterTypes(), JUST_MODULE_IDENTIFIER)) { foundPreloadModule = true; if (foundFindModule) break; } } } } } } overridesFindModuleByIdentifier = foundFindModule; overridesPreloadModuleByIdentifier = foundPreloadModule; } /** * Construct a new instance. */ protected ModuleLoader() { this(NO_FINDERS); } /** * Construct a new instance. * * @param finders the module finders to search, in order */ public ModuleLoader(final ModuleFinder[] finders) { this(checkPermissions(), false, safeClone(finders)); } /** * Construct a new instance. * * @param finder the single module finder to search (must not be {@code null}) */ public ModuleLoader(final ModuleFinder finder) { this(new ModuleFinder[] { finder }); } private static ModuleFinder[] safeClone(ModuleFinder[] finders) { if (finders == null || finders.length == 0) { return NO_FINDERS; } finders = finders.clone(); for (ModuleFinder finder : finders) { if (finder == null) { throw new IllegalArgumentException("Module finder cannot be null"); } } return finders; } private static boolean checkPermissions() { SecurityManager manager = System.getSecurityManager(); if (manager == null) { return true; } manager.checkPermission(ML_PERM); try { manager.checkPermission(MODULE_REDEFINE_PERM); return true; } catch (SecurityException e) { return false; } } /** * Get the module loader for a class. * * @param clazz the class * * @return the module loader or {@code null} if the class's class loader does not belong to a module loader. */ public static ModuleLoader forClass(Class clazz) { final Module module = Module.forClass(clazz); if (module == null) { return null; } return module.getModuleLoader(); } /** * Get the module loader for a class loader. * * @param classLoader the class loader * * @return the module loader or {@code null} if the class loader does not belong to a module loader. */ public static ModuleLoader forClassLoader(ClassLoader classLoader) { final Module module = Module.forClassLoader(classLoader, true); if (module == null) { return null; } return module.getModuleLoader(); } /** * Get the string representation of this module loader. * * @return the string representation */ public String toString() { return String.format("%s@%x for finders %s", getClass().getSimpleName(), hashCode(), Arrays.toString(finders)); } /** * Get a string representation of the given module, used in debug output and stack traces. This method may be * overridden to provide a more detailed description. By default it returns a string consisting of the module's * name and version (if any). * * @param module the module to describe * @return the description string */ public String getModuleDescription(final Module module) { final Version version = module.getVersion(); return version == null ? module.getName() : module.getName() + "@" + version; } /** * Install JBoss Modules MBeans. WARNING: This method is not intended to be * called by application code. */ public static void installMBeanServer() { REG_REF.installReal(); } /** * Load a module based on an identifier. This method delegates to {@link #preloadModule(String)} and then * links the returned module if necessary. * * @param identifier The module identifier * @return The loaded Module * @throws ModuleLoadException if the Module can not be loaded * @deprecated Use {@link #loadModule(String)} instead. */ @Deprecated(forRemoval = true) public final Module loadModule(ModuleIdentifier identifier) throws ModuleLoadException { return loadModule(identifier.toString()); } /** * Load a module based on an identifier. This method delegates to {@link #preloadModule(String)} and then * links the returned module if necessary. * * @param name The module name * @return The loaded Module * @throws ModuleLoadException if the Module can not be loaded */ public final Module loadModule(String name) throws ModuleLoadException { final Module module = preloadModule(name); if (module == null) { throw new ModuleNotFoundException(name); } module.relinkIfNecessary(); return module; } /** * Iterate the modules which can be located via this module loader. * * @param baseIdentifier the identifier to start with, or {@code null} to iterate all modules * @param recursive {@code true} to find recursively nested modules, {@code false} to only find immediately nested modules * @return an iterator for the modules in this module finder * @throws SecurityException if the caller does not have permission to iterate module loaders * @deprecated Use {@link #iterateModules(String, boolean)} instead. */ @Deprecated(forRemoval = true) public final Iterator iterateModules(final ModuleIdentifier baseIdentifier, final boolean recursive) { return IteratorUtils.transformingIterator(iterateModules(baseIdentifier == null ? null : baseIdentifier.toString(), recursive), ModuleIdentifier::fromString); } /** * Iterate the modules which can be located via this module loader. * * @param baseName the identifier to start with, or {@code null} to iterate all modules; ignored if this module * loader does not have a concept of nested modules * @param recursive {@code true} to find recursively nested modules, {@code false} to only find immediately nested * modules; ignored if this module finder does not have a concept of nested modules * @return an iterator for the modules in this module finder * @throws SecurityException if the caller does not have permission to iterate module loaders */ public final Iterator iterateModules(final String baseName, final boolean recursive) { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(MODULE_ITERATE_PERM); } return new Iterator<>() { int idx; Iterator nested; public boolean hasNext() { for (;;) { while (nested == null) { if (idx == finders.length) { return false; } final ModuleFinder finder = finders[idx++]; if (finder instanceof IterableModuleFinder) { nested = ((IterableModuleFinder) finder).iterateModules(baseName, recursive, ModuleLoader.this); } } if (! nested.hasNext()) { nested = null; } else { return true; } } } public String next() { if (! hasNext()) { throw new NoSuchElementException(); } return nested.next(); } public void remove() { throw new UnsupportedOperationException(); } }; } /** * This compatibility method just calls {@code preloadModule(methodIdentifier.toString())} and is usually not used; * if however a legacy subclass overrides this method, then it will be called instead of {@link #preloadModule(String)}, * and that method will redirect to this one. * * @deprecated Use {@link #preloadModule(String)} instead. * * @param identifier the module identifier (must not be {@code null}) * @return the load result, or {@code null} if the module is not found * @throws ModuleLoadException if an error occurs */ @Deprecated(forRemoval = true) protected Module preloadModule(ModuleIdentifier identifier) throws ModuleLoadException { if (overridesPreloadModuleByIdentifier) { return loadModuleLocal(identifier); } else { return preloadModule(identifier.toString()); } } /** * Preload a module based on an identifier. By default, delegation is only done for system and this method otherwise simply invokes * {@link #loadModuleLocal(String)}. A delegating module loader may delegate to the appropriate module * loader based on loader-specific criteria (via the {@link #preloadModule(String, ModuleLoader)} method). * * @param name the module identifier * @return the load result, or {@code null} if the module is not found * @throws ModuleLoadException if an error occurs */ protected Module preloadModule(String name) throws ModuleLoadException { if (overridesPreloadModuleByIdentifier) { return preloadModule(ModuleIdentifier.fromString(name)); } else { return loadModuleLocal(name); } } /** * Preload an "exported" module based on an identifier. By default this simply delegates to {@link #preloadModule(String)}. * * @param name the module name * @return the load result, or {@code null} if the module is not found * @throws ModuleLoadException if an error occurs */ protected Module preloadExportedModule(String name) throws ModuleLoadException { return preloadModule(name); } /** * Preload an "exported" module based on an identifier. By default this simply delegates to {@link #preloadModule(String)}. * * @param identifier the module identifier * @return the load result, or {@code null} if the module is not found * @throws ModuleLoadException if an error occurs * @deprecated Use {@link #preloadModule(String)} instead. */ @Deprecated(forRemoval = true) protected Module preloadExportedModule(ModuleIdentifier identifier) throws ModuleLoadException { return preloadModule(identifier.getName()); } /** * Utility method to delegate to another module loader, accessible from subclasses. The delegate module loader * will be queried for exported modules only. * * @param name the module name * @param moduleLoader the module loader to delegate to * @return the delegation result * @throws ModuleLoadException if an error occurs */ protected static Module preloadModule(String name, ModuleLoader moduleLoader) throws ModuleLoadException { return moduleLoader.preloadExportedModule(name); } /** * Utility method to delegate to another module loader, accessible from subclasses. The delegate module loader * will be queried for exported modules only. * * @param identifier the module identifier * @param moduleLoader the module loader to delegate to * @return the delegation result * @throws ModuleLoadException if an error occurs * @deprecated Use {@link #preloadModule(String, ModuleLoader)} instead. */ @Deprecated(forRemoval = true) protected static Module preloadModule(ModuleIdentifier identifier, ModuleLoader moduleLoader) throws ModuleLoadException { return moduleLoader.preloadExportedModule(identifier.toString()); } /** * Try to load a module from this module loader. Returns {@code null} if the module is not found. The returned * module may not yet be resolved. The returned module may have a different name than the given identifier if * the identifier is an alias for another module. * * @param moduleIdentifier the module identifier * @return the module * @throws ModuleLoadException if an error occurs while loading the module * @deprecated Use {@link #loadModuleLocal(String)} instead. */ @Deprecated(forRemoval = true) protected final Module loadModuleLocal(ModuleIdentifier moduleIdentifier) throws ModuleLoadException { return loadModuleLocal(moduleIdentifier.toString()); } /** * Try to load a module from this module loader. Returns {@code null} if the module is not found. The returned * module may not yet be resolved. The returned module may have a different name than the given identifier if * the identifier is an alias for another module. * * @param name the module name * @return the module * @throws ModuleLoadException if an error occurs while loading the module */ protected final Module loadModuleLocal(String name) throws ModuleLoadException { FutureModule futureModule = moduleMap.get(name); if (futureModule != null) { return futureModule.getModule(); } FutureModule newFuture = new FutureModule(name); futureModule = moduleMap.putIfAbsent(name, newFuture); if (futureModule != null) { return futureModule.getModule(); } boolean ok = false; try { final ModuleLogger log = Module.log; log.trace("Locally loading module %s from %s", name, this); final long startTime = Metrics.getCurrentCPUTime(); final ModuleSpec moduleSpec = findModule(name); loadTime.addAndGet(Metrics.getCurrentCPUTime() - startTime); if (moduleSpec == null) { log.trace("Module %s not found from %s", name, this); return null; } if (! moduleSpec.getName().equals(name)) { throw new ModuleLoadException("Module loader found a module with the wrong name"); } final Module module; if (moduleSpec instanceof AliasModuleSpec) { final AliasModuleSpec aliasModuleSpec = (AliasModuleSpec) moduleSpec; Module aliasedModule; while (true) { aliasedModule = loadModuleLocal(aliasModuleSpec.getAliasName()); if (aliasedModule == null) { throw new ModuleLoadException("Alias module " + name + " is referencing not existing module"); } final Set aliases = aliasedModule.aliases; if (aliases == null) continue; // race condition detected, retry synchronized (aliases) { if (aliases == aliasedModule.aliases) { // no race-condition with removal, go ahead aliases.add(moduleSpec.getName()); newFuture.setModule(module = aliasedModule); log.trace("Added module %s as alias of %s from %s", moduleSpec.getName(), aliasModuleSpec.getAliasName(), this); ok = true; break; } } } } else { module = defineModule((ConcreteModuleSpec) moduleSpec, newFuture); log.trace("Loaded module %s from %s", name, this); ok = true; } return module; } finally { if (! ok) { newFuture.setModule(null); moduleMap.remove(name, newFuture); } } } /** * Find an already-loaded module, returning {@code null} if the module isn't currently loaded. May block * while the loaded state of the module is in question (if the module is being concurrently loaded from another * thread, for example). * * @param identifier the module identifier * @return the module, or {@code null} if it wasn't found * @deprecated Use {@link #findLoadedModuleLocal(String)} instead. */ @Deprecated(forRemoval = true) protected final Module findLoadedModuleLocal(ModuleIdentifier identifier) { return findLoadedModuleLocal(identifier.toString()); } /** * Find an already-loaded module, returning {@code null} if the module isn't currently loaded. May block * while the loaded state of the module is in question (if the module is being concurrently loaded from another * thread, for example). * * @param name the module identifier * @return the module, or {@code null} if it wasn't found */ protected final Module findLoadedModuleLocal(String name) { FutureModule futureModule = moduleMap.get(name); if (futureModule != null) { try { return futureModule.getModule(); } catch (ModuleNotFoundException e) { return null; } } else { return null; } } /** * Unload a module from this module loader. Note that this has no effect on existing modules which refer to the * module being unloaded. Also, only modules from the current module loader can be unloaded. Unloading the same * module more than once has no additional effect. This method only removes the mapping for the module; any running * threads which are currently accessing or linked to the module will continue to function, however attempts to load * this module will fail until a new module is loaded with the same name. Once this happens, if all references to * the previous module are not cleared, the same module may be loaded more than once, causing possible class duplication * and class cast exceptions if proper care is not taken. * * @param module the module to unload * @throws SecurityException if an attempt is made to unload a module which does not belong to this module loader * @throws SecurityException if the module was not defined by this module loader * @deprecated use {@link #unloadModuleLocal(String,Module)} instead */ @Deprecated protected final void unloadModuleLocal(Module module) throws SecurityException { if (module == null) { throw new NullPointerException("Module parameter cannot be null"); } unloadModuleLocal(module.getName(), module); } /** * Unload a module from this module loader. Note that this has no effect on existing modules which refer to the * module being unloaded. Also, only modules from the current module loader can be unloaded. Unloading the same * module more than once has no additional effect. This method only removes the mapping for the module; any running * threads which are currently accessing or linked to the module will continue to function, however attempts to load * this module will fail until a new module is loaded with the same name. Once this happens, if all references to * the previous module are not cleared, the same module may be loaded more than once, causing possible class duplication * and class cast exceptions if proper care is not taken. *

* If the given {@code moduleName} is an alias of the given {@code module} * then only alias mapping to {@code module} is removed. Aliased {@code module} * with its canonical name and other aliases mapping is left intact. *

* If the given {@code moduleName} is the canonical {@code module} name * then all its alias plus canonical {@code moduleName} association mappings are removed. * * @param moduleId the module identifier * @param module the module to unload * @return true iff module was unloaded * @throws SecurityException if an attempt is made to unload a module which does not belong to this module loader * @throws SecurityException if the module was not defined by this module loader */ protected final boolean unloadModuleLocal(final String moduleId, final Module module) throws SecurityException { if (moduleId == null || module == null) { throw new NullPointerException("Method parameters cannot be null"); } final ModuleLoader moduleLoader = module.getModuleLoader(); if (moduleLoader != this) { throw new SecurityException("Attempted to unload " + module + " from a different module loader"); } final FutureModule futureModule = moduleMap.get(moduleId); if (futureModule != null && futureModule.module == module) { final Set aliases = module.aliases; if (aliases != null) { synchronized (aliases) { if (aliases.remove(moduleId)) { // unregistered alias from aliased module } else { // cleaning aliased module and all its aliases module.aliases = null; for (String alias : aliases) { moduleMap.remove(alias); } } } } return moduleMap.remove(moduleId, futureModule); } return false; } /** * This compatibility method just calls {@code findModule(methodIdentifier.toString())} and is usually not used; * if however a legacy subclass overrides this method, then it will be called instead of {@link #findModule(String)}, * and that method will redirect to this one. * * @deprecated Use {@link #findModule(String)} instead. * * @param moduleIdentifier the module identifier * @return the module specification * @throws ModuleLoadException */ @Deprecated(forRemoval = true) protected ModuleSpec findModule(final ModuleIdentifier moduleIdentifier) throws ModuleLoadException { if (overridesFindModuleByIdentifier) { return findModule0(moduleIdentifier.toString()); } else { return findModule(moduleIdentifier.toString()); } } /** * Find a Module's specification in this ModuleLoader by its name. This can be overriden by sub-classes to * implement the Module loading strategy for this loader. The default implementation iterates the module finders * provided during construction. *

* If no module is found in this module loader with the given identifier, then this method should return {@code * null}. If the module is found but some problem occurred (for example, a transitive dependency failed to load) * then this method should throw a {@link ModuleLoadException} of the relevant type. * * @param name the module name * @return the module specification, or {@code null} if no module is found with the given identifier * @throws ModuleLoadException if any problems occur finding the module */ protected ModuleSpec findModule(final String name) throws ModuleLoadException { if (overridesFindModuleByIdentifier) { return findModule(ModuleIdentifier.fromString(name)); } else { return findModule0(name); } } private ModuleSpec findModule0(final String name) throws ModuleLoadException { for (ModuleFinder finder : finders) { if (finder != null) { final ModuleSpec spec = finder.findModule(name, this); if (spec != null) { return spec; } } } return null; } /** * Get the module finders configured for this module loader. * * @return the module finders */ protected final ModuleFinder[] getFinders() { return finders.length > 0 ? finders.clone() : NO_FINDERS; } /** * Defines a Module based on a specification. May only be called from {@link #loadModuleLocal(String)}. * * @param moduleSpec The module specification to create the Module from * @param futureModule the future module to populate * @return The defined Module * @throws ModuleLoadException If any dependent modules can not be loaded */ private Module defineModule(final ConcreteModuleSpec moduleSpec, final FutureModule futureModule) throws ModuleLoadException { try { return doPrivileged(new PrivilegedExceptionAction() { public Module run() { final ModuleLogger log = Module.log; final String name = moduleSpec.getName(); final Module module = new Module(moduleSpec, ModuleLoader.this); module.getClassLoaderPrivate().recalculate(); module.setDependencies(moduleSpec.getDependenciesInternal()); log.moduleDefined(name, ModuleLoader.this); try { futureModule.setModule(module); return module; } catch (RuntimeException | Error e) { log.trace(e, "Failed to load module %s", name); throw e; } } }); } catch (PrivilegedActionException pe) { try { throw pe.getException(); } catch (RuntimeException | ModuleLoadException e) { throw e; } catch (Exception e) { throw new UndeclaredThrowableException(e); } } } /** * Refreshes the paths provided by resource loaders associated with the * specified Module. This is an advanced method that is intended to be * called on modules that have a resource loader implementation that has * changed and is returning different paths. * * @param module the module to refresh * @throws SecurityException if the module was not defined by this module loader, or if the module loader does not * have the required permissions associated with it */ protected void refreshResourceLoaders(Module module) { if (! canRedefine) { throw new SecurityException("Module redefinition requires canRedefineModule permission"); } if (module.getModuleLoader() != this) { throw new SecurityException("Module is not defined by this module loader"); } module.getClassLoaderPrivate().recalculate(); } /** * Replaces the resources loaders for the specified module and refreshes the * internal path list that is derived from the loaders. This is an advanced * method that should be used carefully, since it alters a live module. * Modules that import resources from the specified module will not * automatically be updated to reflect the change. For this to occur * {@link #relink(Module)} must be called on all of them. * * @param module the module to update and refresh * @param loaders the new collection of loaders the module should use * @throws SecurityException if the module was not defined by this module loader, or if the module loader does not * have the required permissions associated with it */ protected void setAndRefreshResourceLoaders(Module module, Collection loaders) { if (! canRedefine) { throw new SecurityException("Module redefinition requires canRedefineModule permission"); } if (module.getModuleLoader() != this) { throw new SecurityException("Module is not defined by this module loader"); } module.getClassLoaderPrivate().setResourceLoaders(loaders.toArray(ResourceLoaderSpec[]::new)); } /** * Relinks the dependencies associated with the specified Module. This is an * advanced method that is intended to be called on all modules that * directly or indirectly import dependencies that are re-exported by a module * that has recently been updated and relinked via * {@link #setAndRelinkDependencies(Module, java.util.List)}. * * @param module the module to relink * @throws ModuleLoadException if relinking failed * @throws SecurityException if the module was not defined by this module loader, or if the module loader does not * have the required permissions associated with it */ protected void relink(Module module) throws ModuleLoadException { if (! canRedefine) { throw new SecurityException("Module redefinition requires canRedefineModule permission"); } if (module.getModuleLoader() != this) { throw new SecurityException("Module is not defined by this module loader"); } module.relink(); } /** * Replaces the dependencies for the specified module and relinks against * the new modules This is an advanced method that should be used carefully, * since it alters a live module. Modules that import dependencies that are * re-exported from the specified module will not automatically be updated * to reflect the change. For this to occur {@link #relink(Module)} must be * called on all of them. * * @param module the module to update and relink * @param dependencies the new dependency list * @throws ModuleLoadException if relinking failed * @throws SecurityException if the module was not defined by this module loader, or if the module loader does not * have the required permissions associated with it */ protected void setAndRelinkDependencies(Module module, List dependencies) throws ModuleLoadException { if (! canRedefine) { throw new SecurityException("Module redefinition requires canRedefineModule permission"); } if (module.getModuleLoader() != this) { throw new SecurityException("Module is not defined by this module loader"); } module.setDependencies(dependencies); module.relinkIfNecessary(); } /** * Get the current dependency list for a module which was defined by this module loader, without any access checks. * * @return the current dependency list for the module * @throws SecurityException if the module was not defined by this module loader */ protected DependencySpec[] getDependencies(Module module) { if (module.getModuleLoader() != this) { throw new SecurityException("Module is not defined by this module loader"); } return module.getDependencySpecsInternal().clone(); } void addLinkTime(long amount) { if (amount != 0L) linkTime.addAndGet(amount); } void addClassLoadTime(final long time) { if (time != 0L) classLoadTime.addAndGet(time); } void incScanCount() { if (Metrics.ENABLED) scanCount.getAndIncrement(); } void incRaceCount() { if (Metrics.ENABLED) raceCount.getAndIncrement(); } void incClassCount() { if (Metrics.ENABLED) classCount.getAndIncrement(); } static final Object NOT_FOUND = new Object(); static final class FutureModule { final String name; volatile Object module; FutureModule(final String name) { this.name = name; } Module getModule() throws ModuleNotFoundException { boolean intr = false; try { Object module = this.module; if (module == null) synchronized (this) { while ((module = this.module) == null) { try { wait(); } catch (InterruptedException e) { intr = true; } } } if (module == NOT_FOUND) return null; return (Module) module; } finally { if (intr) Thread.currentThread().interrupt(); } } void setModule(Module m) { synchronized (this) { module = m == null ? NOT_FOUND : m; notifyAll(); } } } private static final Reaper reaper = new Reaper<>() { public void reap(final Reference reference) { REG_REF.removeMBean(reference.getAttachment()); } }; static final class MXBeanImpl implements ModuleLoaderMXBean { private final Reference reference; MXBeanImpl(final ModuleLoader moduleLoader, final ObjectName objectName) { reference = new WeakReference<>(moduleLoader, objectName, reaper); } public String getDescription() { return getModuleLoader().toString(); } public long getLinkTime() { return getModuleLoader().linkTime.get(); } public long getLoadTime() { return getModuleLoader().loadTime.get(); } public long getClassDefineTime() { return getModuleLoader().classLoadTime.get(); } public int getScanCount() { return getModuleLoader().scanCount.get(); } public int getLoadedModuleCount() { return getModuleLoader().moduleMap.size(); } public int getRaceCount() { return getModuleLoader().raceCount.get(); } public int getClassCount() { return getModuleLoader().classCount.get(); } public List queryLoadedModuleNames() { final ModuleLoader loader = getModuleLoader(); final Set names = loader.moduleMap.keySet(); final ArrayList list = new ArrayList<>(names); list.sort(Comparator.naturalOrder()); return list; } public String dumpAllModuleInformation() { final StringBuilder b = new StringBuilder(); for (String name : queryLoadedModuleNames()) { doDumpModuleInformation(name, b); } return b.toString(); } public String dumpModuleInformation(final String name) { final StringBuilder b = new StringBuilder(); doDumpModuleInformation(name, b); return b.toString(); } private void doDumpModuleInformation(final String name, final StringBuilder b) { ModuleInfo description = getModuleDescription(name); b.append("Module ").append(name).append('\n'); b.append(" Class loader: ").append(description.getClassLoader()).append('\n'); String fallbackLoader = description.getFallbackLoader(); if (fallbackLoader != null) b.append(" Fallback loader: ").append(fallbackLoader).append('\n'); String mainClass = description.getMainClass(); if (mainClass != null) b.append(" Main Class: ").append(mainClass).append('\n'); List loaders = description.getResourceLoaders(); b.append(" Resource Loaders:\n"); for (ResourceLoaderInfo loader : loaders) { b.append(" Loader Type: ").append(loader.getType()).append('\n'); b.append(" Paths:\n"); for (String path : loader.getPaths()) { b.append(" ").append(path).append('\n'); } } b.append(" Dependencies:\n"); for (DependencyInfo dependencyInfo : description.getDependencies()) { b.append(" Type: ").append(dependencyInfo.getDependencyType()).append('\n'); String moduleName = dependencyInfo.getModuleName(); if (moduleName != null) { b.append(" Module Name: ").append(moduleName).append('\n'); } if (dependencyInfo.isOptional()) b.append(" (optional)\n"); b.append(" Export Filter: ").append(dependencyInfo.getExportFilter()).append('\n'); b.append(" Import Filter: ").append(dependencyInfo.getImportFilter()).append('\n'); String localLoader = dependencyInfo.getLocalLoader(); if (localLoader != null) { b.append(" Local Loader: ").append(localLoader).append('\n'); b.append(" Paths:\n"); for (String path : dependencyInfo.getLocalLoaderPaths()) { b.append(" ").append(path).append('\n'); } } } } public boolean unloadModule(final String name) { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(MODULE_UNLOAD_ANY_PERM); } final ModuleLoader loader = getModuleLoader(); final Module module = loader.findLoadedModuleLocal(name); if (module == null) { return false; } else { loader.unloadModuleLocal(name, module); return true; } } public void refreshResourceLoaders(final String name) { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(MODULE_REDEFINE_ANY_PERM); } final ModuleLoader loader = getModuleLoader(); final Module module = loadModule(name, loader); loader.refreshResourceLoaders(module); } public void relink(final String name) { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(MODULE_REDEFINE_ANY_PERM); } final ModuleLoader loader = getModuleLoader(); final Module module = loadModule(name, loader); try { loader.relink(module); } catch (ModuleLoadException e) { throw new IllegalStateException("Module load failure for module " + name + ": " + e); } } public List getDependencies(final String name) { final ModuleLoader loader = getModuleLoader(); final Module module = loadModule(name, loader); return doGetDependencies(module); } private List doGetDependencies(final Module module) { Dependency[] dependencies = module.getDependenciesInternal(); if (dependencies == null) { return Collections.emptyList(); } ArrayList list = new ArrayList<>(dependencies.length); for (Dependency dependency : dependencies) { final String dependencyType = dependency.getClass().getSimpleName(); final String exportFilter = dependency.getExportFilter().toString(); final String importFilter = dependency.getImportFilter().toString(); final DependencyInfo info; if (dependency instanceof LocalDependency) { final LocalDependency localDependency = (LocalDependency) dependency; ArrayList pathList = new ArrayList<>(localDependency.getPaths()); Collections.sort(pathList); info = new DependencyInfo(dependencyType, exportFilter, importFilter, null, null, false, localDependency.getLocalLoader().toString(), pathList); } else if (dependency instanceof ModuleDependency) { final ModuleDependency moduleDependency = (ModuleDependency) dependency; info = new DependencyInfo(dependencyType, exportFilter, importFilter, moduleDependency.getModuleLoader().mxBean, moduleDependency.getName(), moduleDependency.isOptional(), null, null); } else { info = new DependencyInfo(dependencyType, exportFilter, importFilter, null, null, false, null, null); } list.add(info); } return list; } public List getResourceLoaders(final String name) { ModuleLoader loader = getModuleLoader(); final Module module = loadModule(name, loader); return doGetResourceLoaders(module); } private List doGetResourceLoaders(final Module module) { final ModuleClassLoader classLoader = module.getClassLoaderPrivate(); final ResourceLoader[] loaders = classLoader.getResourceLoaders(); final ArrayList list = new ArrayList<>(loaders.length); for (ResourceLoader resourceLoader : loaders) { list.add(new ResourceLoaderInfo(resourceLoader.getClass().getName(), String.valueOf(resourceLoader.getLocation()), new ArrayList<>(resourceLoader.getPaths()))); } return list; } public ModuleInfo getModuleDescription(final String name) { ModuleLoader loader = getModuleLoader(); final Module module = loadModule(name, loader); final List dependencies = doGetDependencies(module); final List resourceLoaders = doGetResourceLoaders(module); final LocalLoader fallbackLoader = module.getFallbackLoader(); final String fallbackLoaderString = fallbackLoader == null ? null : fallbackLoader.toString(); return new ModuleInfo(module.getName(), module.getModuleLoader().mxBean, dependencies, resourceLoaders, module.getMainClass(), module.getClassLoaderPrivate().toString(), fallbackLoaderString); } public SortedMap> getModulePathsInfo(final String name, final boolean exports) { ModuleLoader loader = getModuleLoader(); final Module module = loadModule(name, loader); final Map> paths; try { paths = module.getPathsUnchecked(); } catch (ModuleLoadError e) { throw new IllegalArgumentException("Error loading module " + name + ": " + e); } final TreeMap> result = new TreeMap<>(); for (Map.Entry> entry : paths.entrySet()) { final String path = entry.getKey(); final List loaders = entry.getValue(); if (loaders.isEmpty()) { result.put(path, Collections.emptyList()); } else if (loaders.size() == 1) { result.put(path, Collections.singletonList(loaders.get(0).toString())); } else { final ArrayList list = new ArrayList<>(); for (LocalLoader localLoader : loaders) { list.add(localLoader.toString()); } result.put(path, list); } } return result; } public String getClassLocation(final String moduleName, final String className) { final ModuleLoader loader = getModuleLoader(); final Module module = loadModule(moduleName, loader); final Class clazz; try { clazz = Class.forName(className, false, module.getClassLoaderPrivate()); } catch (ClassNotFoundException e) { return null; } final ProtectionDomain pd = clazz.getProtectionDomain(); if (pd == null) { return null; } final CodeSource cs = pd.getCodeSource(); if (cs == null) { return null; } final URL url = cs.getLocation(); if (url == null) { return null; } return url.toString(); } private Module loadModule(final String name, final ModuleLoader loader) { try { final Module module = loader.findLoadedModuleLocal(name); if (module == null) { throw new IllegalArgumentException("Module " + name + " not found"); } return module; } catch (ModuleLoadError e) { throw new IllegalArgumentException("Error loading module " + name + ": " + e); } } private ModuleLoader getModuleLoader() { final ModuleLoader loader = reference.get(); if (loader == null) { throw new IllegalStateException("Module Loader is gone"); } return loader; } } private interface MBeanReg { boolean addMBean(ObjectName name, Object bean); void removeMBean(ObjectName name); void installReal(); } private static final class TempMBeanReg implements MBeanReg { private final Map mappings = new LinkedHashMap<>(); public boolean addMBean(final ObjectName name, final Object bean) { if (bean == null) { throw new IllegalArgumentException("bean is null"); } synchronized (ModuleLoader.class) { if (REG_REF == this) { return mappings.put(name, bean) == null; } else { return REG_REF.addMBean(name, bean); } } } public void removeMBean(final ObjectName name) { synchronized (ModuleLoader.class) { if (REG_REF == this) { mappings.remove(name); } else { REG_REF.removeMBean(name); } } } public void installReal() { synchronized (ModuleLoader.class) { RealMBeanReg real = new RealMBeanReg(); if (REG_REF == this) { REG_REF = real; for (Map.Entry entry : mappings.entrySet()) { real.addMBean(entry.getKey(), entry.getValue()); } mappings.clear(); } } } } private static final class RealMBeanReg implements MBeanReg { private final MBeanServer server; RealMBeanReg() { server = doPrivileged((PrivilegedAction) ManagementFactory::getPlatformMBeanServer); } public boolean addMBean(final ObjectName name, final Object bean) { try { server.registerMBean(bean, name); return true; } catch (Throwable e) { } return false; } public void removeMBean(final ObjectName name) { try { server.unregisterMBean(name); } catch (Throwable e) { } } public void installReal() { // ignore } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ModuleLoggerFinder.java000066400000000000000000000315341472011152000277300ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2023 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.lang.System.LoggerFinder; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Arrays; import java.util.Deque; import java.util.EnumMap; import java.util.Iterator; import java.util.Map; import java.util.ResourceBundle; import java.util.ServiceLoader; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Supplier; import java.util.logging.Logger; /** * A logger finder which attempts to locate a {@link LoggerFinder} on the * {@linkplain java.util.logging.LogManager log managers} class path. If not found a default finder will be used. * * @author James R. Perkins */ public final class ModuleLoggerFinder extends LoggerFinder { private static final LoggerFinder queueingFinder = new LoggerFinder() { @Override public System.Logger getLogger(final String name, final java.lang.Module module) { return new DelegatingSystemLogger(new QueueingSystemLogger(name, module)); } }; private static final Supplier defaultFinder = () -> new LoggerFinder() { @Override public System.Logger getLogger(final String name, final java.lang.Module module) { return new JulSystemLogger(Logger.getLogger(name)); } }; private static final Map loggers = new ConcurrentHashMap<>(); private static final ReentrantLock lock = new ReentrantLock(); private static final Deque messages = new LinkedBlockingDeque<>(); private static volatile boolean activated = false; // Guarded by lock private static volatile LoggerFinder finder; @Override public System.Logger getLogger(final String name, final java.lang.Module module) { if (activated) { return finder.getLogger(name, module); } lock.lock(); try { // Check if we're activated at this point, if so we need to return a logger from the resolved finder if (activated) { // This should be set at this point return finder.getLogger(name, module); } return loggers.computeIfAbsent(name, s -> queueingFinder.getLogger(name, module)); } finally { lock.unlock(); } } /** * Activates the module logger and replaces any old delegating {@link System.Logger system loggers} with a logger * from the new finder. * * @param cl the class loader to use */ static void activate(final ClassLoader cl) { // To keep order, we must observe the lock lock.lock(); try { if (!activated) { try { final ServiceLoader loader = ServiceLoader.load(LoggerFinder.class, cl == null ? ClassLoader.getSystemClassLoader() : cl); for (LoggerFinder lf : loader) { if (!ModuleLoggerFinder.class.equals(lf.getClass())) { finder = lf; break; } } if (finder == null) { finder = defaultFinder.get(); } } catch (Throwable ignore) { finder = defaultFinder.get(); } // Process the queued loggers and drain the contents to new loggers from the finder found final Iterator> iter = loggers.entrySet().iterator(); while (iter.hasNext()) { final Map.Entry entry = iter.next(); final System.Logger currentLogger = entry.getValue(); // The current should be a delegating logger final DelegatingSystemLogger delegatingSystemLogger = (DelegatingSystemLogger) currentLogger; final System.Logger currentDelegate = delegatingSystemLogger.getDelegate(); final QueueingSystemLogger queueingSystemLogger = (QueueingSystemLogger) currentDelegate; // Replace the queueing logger with a logger from the finder delegatingSystemLogger.delegate.compareAndSet(currentDelegate, finder.getLogger(queueingSystemLogger.name, queueingSystemLogger.module)); iter.remove(); } } // Drain the queue SystemLogRecord record; while ((record = messages.pollFirst()) != null) { final System.Logger logger = finder.getLogger(record.name, record.module); try { if (record.cause == null) { logger.log(record.level, record.bundle, record.msg, record.params); } else { logger.log(record.level, record.bundle, record.msg, record.cause); } } catch (Exception e) { System.err.printf("Failed to log message: %s%n", record); e.printStackTrace(System.err); } } } finally { activated = true; lock.unlock(); } } private static class DelegatingSystemLogger implements System.Logger { private final AtomicReference delegate; private DelegatingSystemLogger(final System.Logger delegate) { this.delegate = new AtomicReference<>(delegate); } @Override public String getName() { return getDelegate().getName(); } @Override public boolean isLoggable(final Level level) { return getDelegate().isLoggable(level); } @Override public void log(final Level level, final String msg) { getDelegate().log(level, msg); } @Override public void log(final Level level, final Supplier msgSupplier) { getDelegate().log(level, msgSupplier); } @Override public void log(final Level level, final Object obj) { getDelegate().log(level, obj); } @Override public void log(final Level level, final String msg, final Throwable thrown) { getDelegate().log(level, msg, thrown); } @Override public void log(final Level level, final Supplier msgSupplier, final Throwable thrown) { getDelegate().log(level, msgSupplier, thrown); } @Override public void log(final Level level, final String format, final Object... params) { getDelegate().log(level, format, params); } @Override public void log(final Level level, final ResourceBundle bundle, final String msg, final Throwable thrown) { getDelegate().log(level, bundle, msg, thrown); } @Override public void log(final Level level, final ResourceBundle bundle, final String format, final Object... params) { getDelegate().log(level, bundle, format, params); } private System.Logger getDelegate() { return delegate.get(); } } private static class JulSystemLogger implements System.Logger { private static final Map LEVELS = new EnumMap<>(System.Logger.Level.class); static { LEVELS.put(System.Logger.Level.ALL, java.util.logging.Level.ALL); LEVELS.put(System.Logger.Level.TRACE, java.util.logging.Level.FINER); LEVELS.put(System.Logger.Level.DEBUG, java.util.logging.Level.FINE); LEVELS.put(System.Logger.Level.INFO, java.util.logging.Level.INFO); LEVELS.put(System.Logger.Level.WARNING, java.util.logging.Level.WARNING); LEVELS.put(System.Logger.Level.ERROR, java.util.logging.Level.SEVERE); LEVELS.put(System.Logger.Level.OFF, java.util.logging.Level.OFF); } private final Logger delegate; private JulSystemLogger(final Logger delegate) { this.delegate = delegate; } @Override public String getName() { return delegate.getName(); } @Override public boolean isLoggable(final System.Logger.Level level) { return delegate.isLoggable(LEVELS.getOrDefault(level, java.util.logging.Level.INFO)); } @Override public void log(final System.Logger.Level level, final ResourceBundle bundle, final String msg, final Throwable thrown) { delegate.logrb(LEVELS.getOrDefault(level, java.util.logging.Level.INFO), bundle, msg, thrown); } @Override public void log(final System.Logger.Level level, final ResourceBundle bundle, final String format, final Object... params) { delegate.logrb(LEVELS.getOrDefault(level, java.util.logging.Level.INFO), bundle, format, params); } } private static class QueueingSystemLogger implements System.Logger { private static final System.Logger.Level DEFAULT_LEVEL; static { System.Logger.Level level; if (System.getSecurityManager() == null) { try { level = System.Logger.Level.valueOf(System.getProperty("jdk.system.logger.level", "INFO")); } catch (IllegalArgumentException ignore) { level = System.Logger.Level.INFO; } } else { level = AccessController.doPrivileged((PrivilegedAction) () -> { try { return System.Logger.Level.valueOf(System.getProperty("jdk.system.logger.level", "INFO")); } catch (IllegalArgumentException ignore) { return System.Logger.Level.INFO; } }); } DEFAULT_LEVEL = level; } private final String name; private final java.lang.Module module; private QueueingSystemLogger(final String name, final java.lang.Module module) { this.name = name; this.module = module; } @Override public String getName() { return name; } @Override public boolean isLoggable(final System.Logger.Level level) { return level != Level.OFF && level.ordinal() >= DEFAULT_LEVEL.ordinal(); } @Override public void log(final System.Logger.Level level, final ResourceBundle bundle, final String msg, final Throwable thrown) { messages.addLast(new SystemLogRecord(name, module, level, bundle, msg, null, thrown)); } @Override public void log(final System.Logger.Level level, final ResourceBundle bundle, final String format, final Object... params) { messages.addLast(new SystemLogRecord(name, module, level, bundle, format, params, null)); } } private static class SystemLogRecord { private final String name; private final java.lang.Module module; private final System.Logger.Level level; private final ResourceBundle bundle; private final String msg; private final Object[] params; private final Throwable cause; private SystemLogRecord(final String name, final java.lang.Module module, final System.Logger.Level level, final ResourceBundle bundle, final String msg, final Object[] params, final Throwable cause) { this.name = name; this.module = module; this.level = level; this.bundle = bundle; this.msg = msg; this.params = params == null ? null : Arrays.copyOf(params, params.length); this.cause = cause; } @Override public String toString() { return "SystemLogRecord(level=" + level + ", bundle=" + bundle + ", msg=" + msg + ", params=" + (params == null ? "" : Arrays.toString(params)) + ", cause=" + cause + ")"; } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ModuleNotFoundException.java000066400000000000000000000050561472011152000307740ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; /** * Module not found exceptions are thrown when no module loaders can locate a module which fulfills a given module * identifier. * * @author John Bailey * @author David M. Lloyd */ public class ModuleNotFoundException extends ModuleLoadException { private static final long serialVersionUID = -1225396191255481860L; /** * Constructs a {@code ModuleNotFoundException} with no detail message. The cause is not initialized, and may * subsequently be initialized by a call to {@link #initCause(Throwable) initCause}. */ public ModuleNotFoundException() { } /** * Constructs a {@code ModuleNotFoundException} with the specified detail message. The cause is not initialized, and may * subsequently be initialized by a call to {@link #initCause(Throwable) initCause}. * * @param msg the detail message */ public ModuleNotFoundException(final String msg) { super(msg); } /** * Constructs a {@code ModuleNotFoundException} with the specified cause. The detail message is set to: *

(cause == null ? null : cause.toString())
* (which typically contains the class and detail message of {@code cause}). * * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method) */ public ModuleNotFoundException(final Throwable cause) { super(cause); } /** * Constructs a {@code ModuleNotFoundException} with the specified detail message and cause. * * @param msg the detail message * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method) */ public ModuleNotFoundException(final String msg, final Throwable cause) { super(msg, cause); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ModuleSpec.java000066400000000000000000000375071472011152000262610ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.lang.instrument.ClassFileTransformer; import java.security.AllPermission; import java.security.PermissionCollection; import java.security.Permissions; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.jboss.modules.filter.PathFilters; /** * A {@code Module} specification which is used by a {@code ModuleLoader} to define new modules. * * @apiviz.exclude * * @author David M. Lloyd */ public abstract class ModuleSpec { private final String name; ModuleSpec(final String name) { this.name = name; } /** * Get a builder for a new module specification. * * @param moduleIdentifier the module identifier * @return the builder * @deprecated Use {@link #build(String)} instead. */ @Deprecated(forRemoval = true) public static Builder build(final ModuleIdentifier moduleIdentifier) { return build(moduleIdentifier.toString()); } /** * Get a builder for a new module specification. * * @param name the module name * @return the builder */ public static Builder build(final String name) { return build(name, true); } static Builder build(final String name, final boolean addBaseDep) { if (name == null) { throw new IllegalArgumentException("name is null"); } final Builder builder = new Builder() { private String mainClass; private AssertionSetting assertionSetting = AssertionSetting.INHERIT; private final List resourceLoaders = new ArrayList<>(0); private final List dependencies = new ArrayList<>(); private final Map properties = new LinkedHashMap<>(0); private final Map> provides = new HashMap<>(0); private LocalLoader fallbackLoader; private ModuleClassLoaderFactory moduleClassLoaderFactory; private ClassTransformer classFileTransformer; private PermissionCollection permissionCollection = getAllPermission(); private Version version; @Override public Builder setFallbackLoader(final LocalLoader fallbackLoader) { this.fallbackLoader = fallbackLoader; return this; } @Override public Builder setMainClass(final String mainClass) { this.mainClass = mainClass; return this; } @Override public Builder setAssertionSetting(final AssertionSetting assertionSetting) { this.assertionSetting = assertionSetting == null ? AssertionSetting.INHERIT : assertionSetting; return this; } @Override public Builder addDependency(final DependencySpec dependencySpec) { dependencies.add(dependencySpec); return this; } @Override public Builder addResourceRoot(final ResourceLoaderSpec resourceLoader) { resourceLoaders.add(resourceLoader); return this; } @Override public Builder setModuleClassLoaderFactory(final ModuleClassLoaderFactory moduleClassLoaderFactory) { this.moduleClassLoaderFactory = moduleClassLoaderFactory; return this; } @Deprecated @Override public Builder setClassFileTransformer(final ClassFileTransformer classFileTransformer) { this.classFileTransformer = new JLIClassTransformer(classFileTransformer); return this; } @Override public Builder setClassFileTransformer(final ClassTransformer transformer) { this.classFileTransformer = transformer; return this; } @Override public Builder addProperty(final String name, final String value) { properties.put(name, value); return this; } @Override public Builder setPermissionCollection(PermissionCollection permissionCollection) { this.permissionCollection = permissionCollection; return this; } @Override public Builder setVersion(Version version) { this.version = version; return this; } @Override public Builder addProvide(final String serviceTypeName, final String serviceImplClassName) { List infos = provides.get(serviceTypeName); if (infos == null) { provides.put(serviceTypeName, infos = new ArrayList<>(1)); } infos.add(serviceImplClassName); return this; } @Override public Version getVersion() { return version; } @Override public ModuleSpec create() { final List resourceLoaders; if (provides.isEmpty()) { resourceLoaders = this.resourceLoaders; } else { resourceLoaders = new ArrayList<>(this.resourceLoaders.size() + 1); resourceLoaders.add(new ResourceLoaderSpec( ResourceLoaders.createServiceResourceLoader(provides), PathFilters.acceptAll() )); resourceLoaders.addAll(this.resourceLoaders); } return new ConcreteModuleSpec(name, mainClass, assertionSetting, resourceLoaders.toArray(ResourceLoaderSpec.NO_RESOURCE_LOADERS), dependencies.toArray(dependencies.toArray(DependencySpec.NO_DEPENDENCIES)), fallbackLoader, moduleClassLoaderFactory, classFileTransformer, properties, permissionCollection, version); } @Override public String getName() { return name; } private Permissions getAllPermission() { final Permissions permissions = new Permissions(); permissions.add(new AllPermission()); return permissions; } }; if (addBaseDep) builder.addDependency(ModuleDependencySpec.JAVA_BASE); return builder; } /** * Get a builder for a new module alias specification. * * @param moduleIdentifier the module identifier * @param aliasTarget the alias target identifier * @return the builder * @deprecated Use {@link #buildAlias(String, String)} instead. */ @Deprecated(forRemoval = true) public static AliasBuilder buildAlias(final ModuleIdentifier moduleIdentifier, final ModuleIdentifier aliasTarget) { return buildAlias(moduleIdentifier.toString(), aliasTarget.toString()); } /** * Get a builder for a new module alias specification. * * @param name the module name * @param aliasName the alias target name * @return the builder */ public static AliasBuilder buildAlias(final String name, final String aliasName) { if (name == null) { throw new IllegalArgumentException("name is null"); } if (aliasName == null) { throw new IllegalArgumentException("aliasName is null"); } return new AliasBuilder() { public ModuleSpec create() { return new AliasModuleSpec(name, aliasName); } public String getName() { return null; } public String getAliasName() { return null; } }; } /** * Get the module identifier for the module which is specified by this object. * * @return the module identifier * @deprecated Use {@link #getName()} instead. */ @Deprecated(forRemoval = true) public ModuleIdentifier getModuleIdentifier() { return ModuleIdentifier.fromString(name); } /** * Get the module name for the module which is specified by this object. * * @return the module name */ public String getName() { return name; } /** * A builder for new concrete module specifications. * * @apiviz.exclude */ public interface Builder { /** * Set the main class for this module, or {@code null} for none. * * @param mainClass the main class name * @return this builder */ ModuleSpec.Builder setMainClass(String mainClass); /** * Set the default assertion setting for this module. * * @param assertionSetting the assertion setting * @return this builder */ ModuleSpec.Builder setAssertionSetting(AssertionSetting assertionSetting); /** * Add a dependency specification. * * @param dependencySpec the dependency specification * @return this builder */ ModuleSpec.Builder addDependency(DependencySpec dependencySpec); /** * Add a local resource root, from which this module will load class definitions and resources. * * @param resourceLoader the resource loader for the root * @return this builder */ ModuleSpec.Builder addResourceRoot(ResourceLoaderSpec resourceLoader); /** * Create the module specification from this builder. * * @return the module specification */ ModuleSpec create(); /** * Get the identifier of the module being defined by this builder. * * @return the module identifier * @deprecated use {@link #getName()} instead */ @Deprecated(forRemoval = true) default ModuleIdentifier getIdentifier() { return ModuleIdentifier.fromString(getName()); } /** * Get the name of the module being defined by this builder. * * @return the module name */ String getName(); /** * Sets a "fall-back" loader that will attempt to load a class if all other mechanisms * are unsuccessful. * * @param fallbackLoader the fall-back loader * @return this builder */ ModuleSpec.Builder setFallbackLoader(final LocalLoader fallbackLoader); /** * Set the module class loader factory to use to create the module class loader for this module. * * @param moduleClassLoaderFactory the factory * @return this builder */ ModuleSpec.Builder setModuleClassLoaderFactory(ModuleClassLoaderFactory moduleClassLoaderFactory); /** * Set the class file transformer to use for this module. * * @param classFileTransformer the class file transformer * @return this builder * @deprecated Use {@link #setClassFileTransformer(ClassTransformer)} instead. */ @Deprecated ModuleSpec.Builder setClassFileTransformer(ClassFileTransformer classFileTransformer); /** * Set the class file transformer function to use for this module. If the given function returns {@code null} * then no transformation will take place. The function may accept and return a direct or heap byte buffer. * * @param transformer the class file transformer (must not be {@code null}) * @return this builder */ ModuleSpec.Builder setClassFileTransformer(ClassTransformer transformer); /** * Add a property to this module specification. * * @param name the property name * @param value the property value * @return this builder */ ModuleSpec.Builder addProperty(String name, String value); /** * Set the permission collection for this module specification. If none is given, a collection implying * {@link AllPermission} is assumed. * * @param permissionCollection the permission collection * @return this builder */ ModuleSpec.Builder setPermissionCollection(PermissionCollection permissionCollection); /** * Set the version for this module specification, or {@code null} to set no version for this module. * * @param version the module version * @return this builder */ ModuleSpec.Builder setVersion(Version version); /** * Declare that this module provides a service with the given type name with the implementation class with * the given class name. * * @param serviceTypeName the service type name (must not be {@code null}) * @param serviceImplClassName the service implementation class name (must not be {@code null}) * @return this builder */ ModuleSpec.Builder addProvide(String serviceTypeName, String serviceImplClassName); /** * Get the version for this module specification, or {@code null} if none was set. * * @return the currently-set version, or {@code null} if none was set */ Version getVersion(); } /** * A builder for new alias module specifications. */ public interface AliasBuilder { /** * Create the module specification from this builder. * * @return the module specification */ ModuleSpec create(); /** * Get the identifier of the module being defined by this builder. * * @return the module identifier * @deprecated Use {@link #getName()} instead. */ @Deprecated(forRemoval = true) default ModuleIdentifier getIdentifier() { return ModuleIdentifier.fromString(getName()); } /** * Get the name of the module being defined by this builder. * * @return the module name */ String getName(); /** * Get the identifier of the module being referenced by this builder. * * @return the module identifier * @deprecated Use {@link #getAliasName()} instead. */ @Deprecated(forRemoval = true) default ModuleIdentifier getAliasTarget() { return ModuleIdentifier.fromString(getAliasName()); } /** * Get the name of the module being referenced by this builder. * * @return the module name */ String getAliasName(); } static final class ServiceInfo { private final String serviceTypeName; private final String implClassName; ServiceInfo(final String serviceTypeName, final String implClassName) { this.serviceTypeName = serviceTypeName; this.implClassName = implClassName; } String getServiceTypeName() { return serviceTypeName; } String getImplClassName() { return implClassName; } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ModulesPolicy.java000066400000000000000000000051711472011152000270010ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.security.AllPermission; import java.security.CodeSource; import java.security.Permission; import java.security.PermissionCollection; import java.security.Permissions; import java.security.Policy; import java.security.ProtectionDomain; import java.security.Provider; final class ModulesPolicy extends Policy { private static final AllPermission ALL_PERMISSION = new AllPermission(); static final Permissions DEFAULT_PERMISSION_COLLECTION = getAllPermission(); private static final CodeSource ourCodeSource = ModulesPolicy.class.getProtectionDomain().getCodeSource(); private final Policy policy; private static Permissions getAllPermission() { final Permissions permissions = new Permissions(); permissions.add(ALL_PERMISSION); return permissions; } ModulesPolicy(final Policy policy) { this.policy = policy; } public Provider getProvider() { return policy.getProvider(); } public String getType() { return policy.getType(); } public Parameters getParameters() { return policy.getParameters(); } public PermissionCollection getPermissions(final CodeSource codesource) { return codesource != null && codesource.equals(ourCodeSource) ? getAllPermission() : policy.getPermissions(codesource); } public PermissionCollection getPermissions(final ProtectionDomain domain) { final CodeSource codeSource = domain.getCodeSource(); return codeSource != null && codeSource.equals(ourCodeSource) ? getAllPermission() : policy.getPermissions(domain); } public boolean implies(final ProtectionDomain domain, final Permission permission) { final CodeSource codeSource = domain.getCodeSource(); return codeSource != null && codeSource.equals(ourCodeSource) || policy.implies(domain, permission); } public void refresh() { policy.refresh(); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/NamedClassLoader.java000066400000000000000000000037671472011152000273630ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2016 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; /** * A class loader that may be named. On Java 9 and later, the name will be propagated up to the JVM. * * @author David M. Lloyd */ public abstract class NamedClassLoader extends ClassLoader { static { if (! ClassLoader.registerAsParallelCapable()) { throw new Error("Failed to register " + NamedClassLoader.class.getName() + " as parallel-capable"); } } /** * Construct a new instance. * * @param parent the parent class loader (may be {@code null} to indicate that the platform class loader should be used) * @param name the name, or {@code null} if the class loader has no name */ protected NamedClassLoader(final ClassLoader parent, final String name) { super(name, parent == null ? ClassLoader.getPlatformClassLoader() : parent); } /** * Construct a new instance. * * @param name the name, or {@code null} if the class loader has no name */ protected NamedClassLoader(final String name) { this(null, name); } /** * Get the name of this class loader. * * @return the name of this class loader, or {@code null} if it is unnamed */ public String getName() { return super.getName(); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/NativeLibraryResourceLoader.java000066400000000000000000000521331472011152000316230ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URI; import java.nio.charset.StandardCharsets; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * A base class for resource loaders which can load native libraries. * * @author David M. Lloyd */ public class NativeLibraryResourceLoader extends AbstractResourceLoader { /** * Separate class for native platform ID which is only loaded when native libs are loaded. */ static class Identification { static final String OS_ID; static final String CPU_ID; static final String ARCH_NAME; static final String[] NATIVE_SEARCH_PATHS; static final Pattern OS_RELEASE_VERSION_ID_PATTERN = Pattern.compile("([0-9]+).*"); static final Pattern DISTRIBUTION_RELEASE_VERSION_PATTERN = Pattern.compile(".*\\s([0-9]+).*"); static final Pattern MAC_VERSION_PATTERN = Pattern.compile("([0-9]+\\.[0-9]+)\\.[0-9]+"); static final String OS_RELEASE_FILE = "/etc/os-release"; static final String FEDORA_RELEASE_FILE = "/etc/fedora-release"; static final String REDHAT_RELEASE_FILE = "/etc/redhat-release"; static final String ID = "ID="; static final String VERSION_ID = "VERSION_ID="; static final String RHEL = "rhel"; static final String FEDORA = "fedora"; static { final Object[] strings = AccessController.doPrivileged(new PrivilegedAction<>() { public Object[] run() { // First, identify the operating system. boolean knownOs = true; String osName; String osVersion = null; // let the user override it. osName = System.getProperty("jboss.modules.os-name"); if (osName == null) { String sysOs = System.getProperty("os.name"); if (sysOs == null) { osName = "unknown"; knownOs = false; } else { sysOs = sysOs.toUpperCase(Locale.US); if (sysOs.startsWith("LINUX")) { osName = "linux"; osVersion = getLinuxOSVersion(); } else if (sysOs.startsWith("MAC OS")) { osName = "macosx"; String sysVersion = System.getProperty("os.version"); Matcher m = MAC_VERSION_PATTERN.matcher(sysVersion); if (m.matches()) { osVersion = m.group(1); } } else if (sysOs.startsWith("WINDOWS")) { osName = "win"; } else if (sysOs.startsWith("OS/2")) { osName = "os2"; } else if (sysOs.startsWith("SOLARIS") || sysOs.startsWith("SUNOS")) { osName = "solaris"; } else if (sysOs.startsWith("MPE/IX")) { osName = "mpeix"; } else if (sysOs.startsWith("HP-UX")) { osName = "hpux"; } else if (sysOs.startsWith("AIX")) { osName = "aix"; } else if (sysOs.startsWith("OS/390")) { osName = "os390"; } else if (sysOs.startsWith("OS/400")) { osName = "os400"; } else if (sysOs.startsWith("FREEBSD")) { osName = "freebsd"; } else if (sysOs.startsWith("OPENBSD")) { osName = "openbsd"; } else if (sysOs.startsWith("NETBSD")) { osName = "netbsd"; } else if (sysOs.startsWith("IRIX")) { osName = "irix"; } else if (sysOs.startsWith("DIGITAL UNIX")) { osName = "digitalunix"; } else if (sysOs.startsWith("OSF1")) { osName = "osf1"; } else if (sysOs.startsWith("OPENVMS")) { osName = "openvms"; } else if (sysOs.startsWith("IOS")) { osName = "iOS"; } else { osName = "unknown"; knownOs = false; } } } // Next, our CPU ID and its compatible variants. boolean knownCpu = true; ArrayList cpuNames = new ArrayList<>(); String cpuName = System.getProperty("jboss.modules.cpu-name"); if (cpuName == null) { String sysArch = System.getProperty("os.arch"); if (sysArch == null) { cpuName = "unknown"; knownCpu = false; } else { boolean hasEndian = false; boolean hasHardFloatABI = false; sysArch = sysArch.toUpperCase(Locale.US); if (sysArch.startsWith("SPARCV9") || sysArch.startsWith("SPARC64")) { cpuName = "sparcv9"; } else if (sysArch.startsWith("SPARC")) { cpuName = "sparc"; } else if (sysArch.startsWith("X86_64") || sysArch.startsWith("AMD64")) { cpuName = "x86_64"; } else if (sysArch.startsWith("I386") || sysArch.startsWith("I486") || sysArch.startsWith("I586") || sysArch.startsWith("I686") || sysArch.startsWith("X86") || sysArch.contains("IA32")) { cpuName = "i686"; } else if (sysArch.startsWith("X32")) { cpuName = "x32"; } else if (sysArch.startsWith("PPC64")) { cpuName = "ppc64"; } else if (sysArch.startsWith("PPC") || sysArch.startsWith("POWER")) { cpuName = "ppc"; } else if (sysArch.startsWith("ARMV7A") || sysArch.contains("AARCH32")) { hasEndian = true; hasHardFloatABI = true; cpuName = "armv7a"; } else if (sysArch.startsWith("AARCH64") || sysArch.startsWith("ARM64") || sysArch.startsWith("ARMV8") || sysArch.startsWith("PXA9") || sysArch.startsWith("PXA10")) { hasEndian = true; cpuName = "aarch64"; } else if (sysArch.startsWith("PXA27")) { hasEndian = true; cpuName = "armv5t-iwmmx"; } else if (sysArch.startsWith("PXA3")) { hasEndian = true; cpuName = "armv5t-iwmmx2"; } else if (sysArch.startsWith("ARMV4T") || sysArch.startsWith("EP93")) { hasEndian = true; cpuName = "armv4t"; } else if (sysArch.startsWith("ARMV4") || sysArch.startsWith("EP73")) { hasEndian = true; cpuName = "armv4"; } else if (sysArch.startsWith("ARMV5T") || sysArch.startsWith("PXA") || sysArch.startsWith("IXC") || sysArch.startsWith("IOP") || sysArch.startsWith("IXP") || sysArch.startsWith("CE")) { hasEndian = true; String isaList = System.getProperty("sun.arch.isalist"); if (isaList != null) { if (isaList.toUpperCase(Locale.US).contains("MMX2")) { cpuName = "armv5t-iwmmx2"; } else if (isaList.toUpperCase(Locale.US).contains("MMX")) { cpuName = "armv5t-iwmmx"; } else { cpuName = "armv5t"; } } else { cpuName = "armv5t"; } } else if (sysArch.startsWith("ARMV5")) { hasEndian = true; cpuName = "armv5"; } else if (sysArch.startsWith("ARMV6")) { hasEndian = true; hasHardFloatABI = true; cpuName = "armv6"; } else if (sysArch.startsWith("PA_RISC2.0W")) { cpuName = "parisc64"; } else if (sysArch.startsWith("PA_RISC") || sysArch.startsWith("PA-RISC")) { cpuName = "parisc"; } else if (sysArch.startsWith("IA64")) { // HP-UX reports IA64W for 64-bit Itanium and IA64N when running // in 32-bit mode. cpuName = sysArch.toLowerCase(Locale.US); } else if (sysArch.startsWith("ALPHA")) { cpuName = "alpha"; } else if (sysArch.startsWith("MIPS")) { cpuName = "mips"; } else { knownCpu = false; cpuName = "unknown"; } boolean be = false; boolean hf = false; if (knownCpu && hasEndian && "big".equals(System.getProperty("sun.cpu.endian", "little"))) { be = true; } if (knownCpu && hasHardFloatABI) { String archAbi = System.getProperty("sun.arch.abi"); if (archAbi != null) { if (archAbi.toUpperCase(Locale.US).contains("HF")) { hf = true; } } else { String libPath = System.getProperty("java.library.path"); if (libPath != null && libPath.toUpperCase(Locale.US).contains("GNUEABIHF")) { hf = true; } } if (hf) cpuName += "-hf"; } if (knownCpu) { switch (cpuName) { case "i686": cpuNames.add("i686"); case "i586": cpuNames.add("i586"); case "i486": cpuNames.add("i486"); case "i386": cpuNames.add("i386"); break; case "armv7a": cpuNames.add("armv7a"); if (hf) break; case "armv6": cpuNames.add("armv6"); if (hf) break; case "armv5t": cpuNames.add("armv5t"); case "armv5": cpuNames.add("armv5"); case "armv4t": cpuNames.add("armv4t"); case "armv4": cpuNames.add("armv4"); break; case "armv5t-iwmmx2": cpuNames.add("armv5t-iwmmx2"); case "armv5t-iwmmx": cpuNames.add("armv5t-iwmmx"); cpuNames.add("armv5t"); cpuNames.add("armv5"); cpuNames.add("armv4t"); cpuNames.add("armv4"); break; default: cpuNames.add(cpuName); break; } if (hf || be) for (int i = 0; i < cpuNames.size(); i++) { String name = cpuNames.get(i); if (be) name += "-be"; if (hf) name += "-hf"; cpuNames.set(i, name); } cpuName = cpuNames.get(0); } } } else { cpuNames.add(cpuName); } // Finally, search paths. final int cpuCount = cpuNames.size(); final int searchPathsSize = osVersion != null ? cpuCount * 2 : cpuCount; String[] searchPaths = new String[searchPathsSize]; if (knownOs && knownCpu) { // attempt OS-version specific category first String osNameAndVersion = osVersion != null ? osName + "-" + osVersion : osName; for (int i = 0; i < cpuCount; i++) { final String name = cpuNames.get(i); searchPaths[i] = osNameAndVersion + "-" + name; } // fallback to general category if (osVersion != null) { int j = cpuCount; for (int i = 0; i < cpuCount; i++) { final String name = cpuNames.get(i); searchPaths[j++] = osName + "-" + name; } } } else { searchPaths = new String[0]; } return new Object[] { osName, cpuName, osName + "-" + cpuName, searchPaths }; } }); OS_ID = strings[0].toString(); CPU_ID = strings[1].toString(); ARCH_NAME = strings[2].toString(); NATIVE_SEARCH_PATHS = (String[]) strings[3]; } private static String getLinuxOSVersionFromOSReleaseFile() { try (InputStream releaseFile = new FileInputStream(OS_RELEASE_FILE)) { try (InputStreamReader inputStreamReader = new InputStreamReader(releaseFile, StandardCharsets.UTF_8)) { try (BufferedReader reader = new BufferedReader(inputStreamReader)) { String currentLine; String id = null; String versionId = null; while ((id == null || versionId == null) && (currentLine = reader.readLine()) != null) { final String trimmed = currentLine.trim(); if (trimmed.startsWith(ID)) { int equalsIndex = trimmed.indexOf('='); id = trimmed.substring(equalsIndex + 1).replaceAll("\"", ""); } else if (trimmed.startsWith(VERSION_ID)) { int equalsIndex = trimmed.indexOf('='); versionId = trimmed.substring(equalsIndex + 1).replaceAll("\"", ""); } } if (id != null && versionId != null) { String abbreviatedVersionId = versionId; Matcher m = OS_RELEASE_VERSION_ID_PATTERN.matcher(versionId); if (m.matches()) { abbreviatedVersionId = m.group(1); } return id + abbreviatedVersionId; } return null; } } } catch (Exception e) { return null; } } private static String getLinuxOSVersionFromDistributionFile(String distributionFile) { try (InputStream releaseFile = new FileInputStream(distributionFile)) { try (InputStreamReader inputStreamReader = new InputStreamReader(releaseFile, StandardCharsets.UTF_8)) { try (BufferedReader reader = new BufferedReader(inputStreamReader)) { String currentLine; String id = null; String abbreviatedVersionId = null; if ((currentLine = reader.readLine()) != null) { final String trimmed = currentLine.trim(); if (trimmed.startsWith("Red Hat Enterprise Linux")) { id = RHEL; } else if (trimmed.startsWith("Fedora")) { id = FEDORA; } Matcher m = DISTRIBUTION_RELEASE_VERSION_PATTERN.matcher(trimmed); if (m.matches()) { abbreviatedVersionId = m.group(1); } } if (id != null && abbreviatedVersionId != null) { return id + abbreviatedVersionId; } return null; } } } catch (Exception e) { return null; } } private static String getLinuxOSVersion() { String osVersion = getLinuxOSVersionFromOSReleaseFile(); if (osVersion == null) { osVersion = getLinuxOSVersionFromDistributionFile(FEDORA_RELEASE_FILE); if (osVersion == null) { osVersion = getLinuxOSVersionFromDistributionFile(REDHAT_RELEASE_FILE); } } return osVersion; } } /** * The filesystem root of the resource loader. */ private final File root; /** * Construct a new instance. * * @param root the filesystem root of the resource loader */ public NativeLibraryResourceLoader(final File root) { this.root = root; } /** {@inheritDoc} */ public String getLibrary(final String name) { final String mappedName = System.mapLibraryName(name); final File root = this.root; File testFile; for (String path : Identification.NATIVE_SEARCH_PATHS) { testFile = new File(new File(root, path), mappedName); if (testFile.exists()) { return testFile.getAbsolutePath(); } } return null; } public URI getLocation() { return root.toURI(); } /** * Get the filesystem root of the resource loader. * * @return the filesystem root of the resource loader */ public File getRoot() { return root; } /** * Get the detected architecture name for this platform. * * @return the architecture name */ public static String getArchName() { return Identification.ARCH_NAME; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/PackageSpec.java000066400000000000000000000142351472011152000263600ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.net.URL; /** * A specification for a package to define. * * @apiviz.exclude * @author David M. Lloyd */ public final class PackageSpec { private String specTitle; private String specVersion; private String specVendor; private String implTitle; private String implVersion; private String implVendor; private URL sealBase; private AssertionSetting assertionSetting = AssertionSetting.INHERIT; /** * Get the package specification title. * * @return the specification title * @see java.util.jar.Attributes.Name#SPECIFICATION_TITLE */ public String getSpecTitle() { return specTitle; } /** * Set the package specification title. * * @param specTitle the specification title * @see java.util.jar.Attributes.Name#SPECIFICATION_TITLE */ public PackageSpec setSpecTitle(String specTitle) { this.specTitle = specTitle; return this; } public void setSpecTitle$$bridge(String specTitle) { setSpecTitle(specTitle); } /** * Get the package specification version. * * @return the specification version * @see java.util.jar.Attributes.Name#SPECIFICATION_VERSION */ public String getSpecVersion() { return specVersion; } /** * Set the package specification version. * * @param specVersion the specification version * @see java.util.jar.Attributes.Name#SPECIFICATION_VERSION */ public PackageSpec setSpecVersion(String specVersion) { this.specVersion = specVersion; return this; } public void setSpecVersion$$bridge(String specVersion) { setSpecVersion(specVersion); } /** * Set the package specification vendor. * * @return the specification vendor * @see java.util.jar.Attributes.Name#SPECIFICATION_VENDOR */ public String getSpecVendor() { return specVendor; } /** * Set the package specification vendor. * * @param specVendor the specification vendor * @see java.util.jar.Attributes.Name#SPECIFICATION_VENDOR */ public PackageSpec setSpecVendor(String specVendor) { this.specVendor = specVendor; return this; } public void setSpecVendor$$bridge(String specVendor) { setSpecVendor(specVendor); } /** * Get the implementation title. * * @return the implementation title * @see java.util.jar.Attributes.Name#IMPLEMENTATION_TITLE */ public String getImplTitle() { return implTitle; } /** * Set the implementation title. * * @param implTitle the implementation title * @see java.util.jar.Attributes.Name#IMPLEMENTATION_TITLE */ public PackageSpec setImplTitle(String implTitle) { this.implTitle = implTitle; return this; } public void setImplTitle$$bridge(String implTitle) { setImplTitle(implTitle); } /** * Get the implementation version. * * @return the implementation version * @see java.util.jar.Attributes.Name#IMPLEMENTATION_VERSION */ public String getImplVersion() { return implVersion; } /** * Set the implementation version. * * @param implVersion the implementation version * @see java.util.jar.Attributes.Name#IMPLEMENTATION_VENDOR */ public PackageSpec setImplVersion(String implVersion) { this.implVersion = implVersion; return this; } public void setImplVersion$$bridge(String implVersion) { setImplVersion(implVersion); } /** * Get the implementation vendor. * * @return the implementation vendor * @see java.util.jar.Attributes.Name#IMPLEMENTATION_VENDOR */ public String getImplVendor() { return implVendor; } /** * Set the implementation vendor. * * @param implVendor the implementation vendor * @see java.util.jar.Attributes.Name#IMPLEMENTATION_VENDOR */ public PackageSpec setImplVendor(String implVendor) { this.implVendor = implVendor; return this; } public void setImplVendor$$bridge(String implVendor) { setImplVendor(implVendor); } /** * Get the URL against which this package is sealed. * * @return the seal base URL * @see java.util.jar.Attributes.Name#SEALED */ public URL getSealBase() { return sealBase; } /** * Set the URL against which this package is sealed. * * @param sealBase the seal base URL * @see java.util.jar.Attributes.Name#SEALED */ public void setSealBase(URL sealBase) { this.sealBase = sealBase; } /** * Get the package assertion setting. * * @return the package assertion setting */ public AssertionSetting getAssertionSetting() { return assertionSetting; } /** * Set the package assertion setting. * * @param assertionSetting the package assertion setting */ public PackageSpec setAssertionSetting(AssertionSetting assertionSetting) { if (assertionSetting == null) { throw new IllegalArgumentException("assertionSetting is null"); } this.assertionSetting = assertionSetting; return this; } public void setAssertionSetting$$bridge(AssertionSetting assertionSetting) { setAssertionSetting(assertionSetting); } }jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/PathResource.java000066400000000000000000000041041472011152000266100ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2016 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.security.AccessControlContext; import static org.jboss.modules.PathResourceLoader.doPrivilegedIfNeeded; /** * Java NIO Path-based Resource * * @author Sergei Egorov */ class PathResource implements Resource { private final Path path; private final String name; private final AccessControlContext context; PathResource(Path path, final String name, AccessControlContext context) { this.path = path; this.name = name; this.context = context; } @Override public String getName() { return name; } @Override public URL getURL() { return doPrivilegedIfNeeded(context, () -> { final URL url = path.toUri().toURL(); url.openConnection().connect(); return url; }); } @Override public InputStream openStream() throws IOException { return doPrivilegedIfNeeded(context, IOException.class, () -> Files.newInputStream(path)); } @Override public long getSize() { try { return doPrivilegedIfNeeded(context, IOException.class, () -> Files.size(path)); } catch (IOException e) { return 0; } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/PathResourceLoader.java000066400000000000000000000234141472011152000277440ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2016 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.IOException; import java.io.InputStream; import java.lang.ref.SoftReference; import java.lang.reflect.UndeclaredThrowableException; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.nio.file.FileSystems; import java.nio.file.FileVisitOption; import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.security.AccessControlContext; import java.security.AccessController; import java.security.CodeSigner; import java.security.CodeSource; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.jar.Manifest; import java.util.stream.Collectors; /** * Java NIO2 Path-based ResourceLoader * * @author Sergei Egorov */ class PathResourceLoader extends AbstractResourceLoader implements IterableResourceLoader { private final String rootName; protected final Path root; protected final AccessControlContext context; private volatile SoftReference manifestRef; private final CodeSource codeSource; PathResourceLoader(final String rootName, final Path root, final AccessControlContext context) { if (rootName == null) { throw new IllegalArgumentException("rootName is null"); } if (root == null) { throw new IllegalArgumentException("root is null"); } if (context == null) { throw new IllegalArgumentException("context is null"); } this.rootName = rootName; this.root = root; this.context = context; try { codeSource = doPrivilegedIfNeeded(context, MalformedURLException.class, () -> new CodeSource(root.toUri().toURL(), (CodeSigner[]) null)); } catch (MalformedURLException e) { throw new IllegalArgumentException("Invalid root file specified", e); } } private Manifest manifest() { SoftReference ref = manifestRef; if (ref != null) { Manifest manifest = ref.get(); if (manifest != null) { return manifest; } } final Path manifestFile = root.resolve("META-INF").resolve("MANIFEST.MF"); try { return doPrivilegedIfNeeded(context, IOException.class, () -> { if (Files.isDirectory(manifestFile)) { return null; } try (InputStream is = Files.newInputStream(manifestFile)) { Manifest manifest = new Manifest(is); manifestRef = new SoftReference<>(manifest); return manifest; } }); } catch (IOException e) { return null; } } @Override public String getRootName() { return rootName; } @Override public String getLibrary(String name) { if (root.getFileSystem() == FileSystems.getDefault()) { final String mappedName = System.mapLibraryName(name); for (String path : NativeLibraryResourceLoader.Identification.NATIVE_SEARCH_PATHS) { Path testFile; try { testFile = root.resolve(path).resolve(mappedName); } catch (InvalidPathException ignored) { return null; } if (Files.exists(testFile)) { return testFile.toAbsolutePath().toString(); } } } return null; } @Override public ClassSpec getClassSpec(final String fileName) throws IOException { final Path file; try { file = root.resolve(fileName); } catch (InvalidPathException ignored) { return null; } return doPrivilegedIfNeeded(context, IOException.class, () -> { if (!Files.exists(file)) { return null; } final ClassSpec spec = new ClassSpec(); spec.setCodeSource(codeSource); spec.setBytes(Files.readAllBytes(file)); return spec; }); } @Override public PackageSpec getPackageSpec(final String name) throws IOException { URL rootUrl = doPrivilegedIfNeeded(context, IOException.class, () -> root.toUri().toURL()); return getPackageSpec(name, manifest(), rootUrl); } @Override public Resource getResource(final String name) { final String cleanName = PathUtils.canonicalize(PathUtils.relativize(name)); final Path file; try { file = root.resolve(cleanName); } catch (InvalidPathException ignored) { return null; } if (!doPrivilegedIfNeeded(context, () -> Files.exists(file))) { return null; } return new PathResource(file, cleanName, context); } @Override public Iterator iterateResources(final String startPath, final boolean recursive) { try { Path path; try { path = root.resolve(PathUtils.canonicalize(PathUtils.relativize(startPath))); } catch (InvalidPathException ignored) { return Collections.emptyIterator(); } return Files.walk(path, recursive ? Integer.MAX_VALUE : 1, FileVisitOption.FOLLOW_LINKS) .filter(it -> !Files.isDirectory(it)) .map(resourcePath -> new PathResource(resourcePath, PathUtils.toGenericSeparators(root.relativize(resourcePath).toString()), context)) .iterator(); } catch (IOException e) { return Collections.emptyIterator(); } } @Override public Collection getPaths() { try { return doPrivilegedIfNeeded(context, IOException.class, () -> Files.walk(root, FileVisitOption.FOLLOW_LINKS) .filter(Files::isDirectory) .map(dir -> { final String result = root.relativize(dir).toString(); final String canonical = PathUtils.toGenericSeparators(result); // JBoss modules expect folders not to end with a slash, so we have to strip it. if (canonical.endsWith("/")) { return canonical.substring(0, canonical.length() - 1); } else { return canonical; } }) .collect(Collectors.toList())); } catch (IOException e) { return Collections.emptyList(); } } @Override public URI getLocation() { return doPrivilegedIfNeeded(context, root::toUri); } public ResourceLoader createSubloader(final String relativePath, final String rootName) { return new PathResourceLoader(rootName, root.resolve(PathUtils.relativize(PathUtils.canonicalize(relativePath))), context); } static T doPrivilegedIfNeeded(AccessControlContext context, Class exceptionType, PrivilegedExceptionAction action) throws E { SecurityManager sm = System.getSecurityManager(); if (sm == null) { try { return action.run(); } catch (RuntimeException re) { throw re; } catch (Exception e) { if (exceptionType.isInstance(e)) { throw exceptionType.cast(e); } throw new UndeclaredThrowableException(e); } } else { try { return AccessController.doPrivileged(action, context); } catch (PrivilegedActionException e) { try { throw e.getException(); } catch (RuntimeException re) { throw re; } catch (Exception e1) { if (exceptionType.isInstance(e1)) { throw exceptionType.cast(e1); } throw new UndeclaredThrowableException(e1); } } } } static T doPrivilegedIfNeeded(AccessControlContext context, PrivilegedExceptionAction action) { SecurityManager sm = System.getSecurityManager(); if (sm == null) { try { return action.run(); } catch (RuntimeException re) { throw re; } catch (Exception e) { throw new UndeclaredThrowableException(e); } } else { try { return AccessController.doPrivileged(action, context); } catch (PrivilegedActionException e) { try { throw e.getException(); } catch (RuntimeException re) { throw re; } catch (Exception e1) { throw new UndeclaredThrowableException(e1); } } } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/PathUtils.java000066400000000000000000000357541472011152000261400ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import static java.lang.Math.max; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; import java.text.Normalizer; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.jboss.modules.filter.PathFilter; /** * General helpful path utility methods. * * @author David M. Lloyd */ public final class PathUtils { private PathUtils() { } /** * Filter the paths from {@code source} into {@code target} using {@code filter}. * * @param source the source paths * @param filter the filter to apply * @param target the destination for filtered paths * @param the collection type * @return the {@code target} set */ public static > T filterPaths(Iterable source, PathFilter filter, T target) { for (String path : source) { if (filter.accept(path)) { target.add(path); } } return target; } /** * Attempt to get a set of all paths defined directly by the given class loader. If the path set cannot be * ascertained, {@code null} is returned. * * @param classLoader the class loader to inspect * @return the set, or {@code null} if the paths could not be determined */ public static Set getPathSet(ClassLoader classLoader) { if (classLoader == null) { return JDKPaths.JDK; } else if (classLoader instanceof ModuleClassLoader) { final ModuleClassLoader moduleClassLoader = (ModuleClassLoader) classLoader; return Collections.unmodifiableSet(moduleClassLoader.getPaths()); } else if (classLoader instanceof URLClassLoader) { // here's where it starts to get ugly... final URLClassLoader urlClassLoader = (URLClassLoader) classLoader; final URL[] urls = urlClassLoader.getURLs(); final Set paths = new HashSet<>(); for (URL url : urls) { final URI uri; try { uri = url.toURI(); } catch (URISyntaxException e) { return null; } final String scheme = uri.getScheme(); if ("file".equals(scheme)) { final File file; try { file = new File(uri); } catch (Exception e) { return null; } if (file.exists()) { if (file.isDirectory()) { JDKPaths.processDirectory(paths, file); } else { try { JDKPaths.processJar(paths, file); } catch (IOException e) { return null; } } } } } return Collections.unmodifiableSet(paths); } else { // ??? return null; } } /** * Relativize the given path. Removes any leading {@code /} segments from the path. * * @param path the path to relativize * @return the relative path */ public static String relativize(String path) { for (int i = 0; i < path.length(); i ++) { if (path.charAt(i) != '/' && path.charAt(i) != File.separatorChar) { return path.substring(i); } } return ""; } /** * Get the file name (last) segment of the given path. * * @param path the path name * @return the file name */ public static String fileNameOfPath(String path) { return path.substring(max(path.lastIndexOf('/'), path.lastIndexOf(File.separatorChar)) + 1); } /** * Canonicalize the given path. Removes all {@code .} and {@code ..} segments from the path. * * @param path the relative or absolute possibly non-canonical path * @return the canonical path */ public static String canonicalize(String path) { final int length = path.length(); // 0 - start // 1 - got one . // 2 - got two . // 3 - got / int state = 0; if (length == 0) { return path; } final char[] targetBuf = new char[length]; // string segment end exclusive int e = length; // string cursor position int i = length; // buffer cursor position int a = length - 1; // number of segments to skip int skip = 0; loop: while (--i >= 0) { char c = path.charAt(i); outer: switch (c) { case '/': { inner: switch (state) { case 0: state = 3; e = i; break outer; case 1: state = 3; e = i; break outer; case 2: state = 3; e = i; skip ++; break outer; case 3: e = i; break outer; default: throw new IllegalStateException(); } // not reached! } case '.': { inner: switch (state) { case 0: state = 1; break outer; case 1: state = 2; break outer; case 2: break inner; // emit! case 3: state = 1; break outer; default: throw new IllegalStateException(); } // fall thru } default: { if (File.separatorChar != '/' && c == File.separatorChar) { switch (state) { case 0: state = 3; e = i; break outer; case 1: state = 3; e = i; break outer; case 2: state = 3; e = i; skip ++; break outer; case 3: e = i; break outer; default: throw new IllegalStateException(); } // not reached! } final int newE = e > 0 ? path.lastIndexOf('/', e - 1) : -1; final int segmentLength = e - newE - 1; if (skip > 0) { skip--; } else { if (state == 3) { targetBuf[a--] = '/'; } path.getChars(newE + 1, e, targetBuf, (a -= segmentLength) + 1); } state = 0; i = newE + 1; e = newE; break; } } } if (state == 3) { targetBuf[a--] = '/'; } return new String(targetBuf, a + 1, length - a - 1); } /** * Determine whether one path is a child of another. * * @param parent the parent path * @param child the child path * @return {@code true} if the child is truly a child of parent */ public static boolean isChild(final String parent, final String child) { String cp = canonicalize(parent); cp = cp.endsWith("/") ? cp.substring(0, cp.length() - 1) : cp; String cc = canonicalize(child); if (isRelative(cp) != isRelative(cc)) { throw new IllegalArgumentException("Cannot compare relative and absolute paths"); } final int cpl = cp.length(); return cpl == 0 || cc.length() > cpl + 1 && cc.startsWith(cp) && cc.charAt(cpl) == '/'; } /** * Determine whether one path is a direct (or immediate) child of another. * * @param parent the parent path * @param child the child path * @return {@code true} if the child is truly a direct child of parent */ public static boolean isDirectChild(final String parent, final String child) { String cp = canonicalize(parent); cp = cp.endsWith("/") ? cp.substring(0, cp.length() - 1) : cp; String cc = canonicalize(child); if (isRelative(cp) != isRelative(cc)) { throw new IllegalArgumentException("Cannot compare relative and absolute paths"); } final int cpl = cp.length(); if (cpl == 0) { return cc.indexOf('/') < 0; } else { return cc.length() > cpl + 1 && cc.startsWith(cp) && cc.charAt(cpl) == '/' && cc.indexOf('/', cpl + 1) == -1; } } /** * Get the given path name with OS-specific separators replaced with the generic {@code /} separator character. * * @param original the original string * @return the same string with OS-specific separators replaced with {@code /} */ public static String toGenericSeparators(String original) { return File.separatorChar == '/' ? original : original.replace(File.separatorChar, '/'); } /** * Determine whether a path name is relative. * * @param path the path name * @return {@code true} if it is relative */ public static boolean isRelative(final String path) { return path.isEmpty() || !isSeparator(path.charAt(0)); } /** * Determine whether the given character is a {@code /} or a platform-specific separator. * * @param ch the character to test * @return {@code true} if it is a separator */ public static boolean isSeparator(final char ch) { // the second half of this compare will optimize away on / OSes return ch == '/' || File.separatorChar != '/' && ch == File.separatorChar; } private static boolean isAllowedPunct(final int cp) { return cp == '_' || cp == '$' || cp == '%' || cp == '^' || cp == '&' || cp == '(' || cp == ')' || cp == '-' || cp == '+' || cp == '=' || cp == ';' || cp == '[' || cp == ']' || cp == '{' || cp == '}' || cp == '<' || cp == '>' || cp == ',' || cp == '"' || cp == '\''; } /** * Convert a "basic" module name to a relative path specification. * * @param moduleName the basic module name * @return the path specification, or {@code null} if the name is not valid */ public static String basicModuleNameToPath(final String moduleName) { final String normalized = Normalizer.normalize(moduleName, Normalizer.Form.NFKC); final int length = normalized.length(); StringBuilder builder = new StringBuilder(length + 5); boolean slot = false; // are we in the slot part? boolean sep = false; // is a '.' or ':' (to '/') separator allowed here? boolean dot = false; // is a '/' (to '.') separator allowed here? boolean esc = false; // was a '\\' previously given? for (int i = 0; i < length; i = normalized.offsetByCodePoints(i, 1)) { int cp = normalized.codePointAt(i); if (Character.isLetterOrDigit(cp) || isAllowedPunct(cp)) { builder.appendCodePoint(cp); esc = false; sep = true; dot = true; } else if (cp == '\\') { if (esc) return null; esc = true; } else if (cp == ':') { if (esc) { builder.append(':'); esc = false; sep = true; dot = true; } else if (slot) { builder.append(':'); esc = false; sep = true; dot = true; } else if (! sep) { return null; } else { builder.append('/'); slot = true; sep = false; dot = false; } } else if (cp == '.') { if (slot) { if (! dot) { return null; } builder.append('.'); sep = true; esc = false; } else { if (! sep) { return null; } else { builder.append('/'); sep = false; dot = false; esc = false; } } } else if (cp == '/') { if (! dot) { return null; } builder.append('.'); sep = true; dot = false; esc = false; } else { return null; } } if (! dot || ! sep || esc) { // invalid end return null; } if (! slot) { builder.append("/main"); } return builder.toString(); } /** * Takes a list of maps an returns an immutable representation of the same map, with all duplicate lists * coalesced into a single object, and with all lists replaced by immutable array lists that has a backing array * that is the correct size for the number of contents. * * This can result in a significant memory saving for some use cases * */ static Map> deduplicateLists(Map> allPaths) { if (allPaths == null) { return null; } else if (allPaths.size() == 0) { return Collections.emptyMap(); } else { Map> newPaths = new HashMap<>(); Map, List> dedup = new HashMap<>(); for (Map.Entry> e : allPaths.entrySet()) { List l = dedup.get(e.getValue()); if (l == null) { dedup.put(e.getValue(), l = Collections.unmodifiableList(new ArrayList<>(e.getValue()))); } newPaths.put(e.getKey(), l); } return Collections.unmodifiableMap(newPaths); } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/Paths.java000066400000000000000000000032641472011152000252710ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.util.List; import java.util.Map; /** * A pair of path maps. * * @param the type of object that each path refers to * @param the type of the source object used to calculate the path maps * * @author David M. Lloyd */ final class Paths { private final A[] sourceList; private final Map> allPaths; Paths(final A[] sourceList, final Map> allPaths) { this.sourceList = sourceList; this.allPaths = PathUtils.deduplicateLists(allPaths); } Map> getAllPaths() { return allPaths; } A[] getSourceList(A[] defVal) { final A[] sourceList = this.sourceList; return sourceList == null ? defVal : sourceList; } static final Paths NONE = new Paths<>(null, null); @SuppressWarnings({ "unchecked" }) static Paths none() { return (Paths) NONE; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/PreMain.java000066400000000000000000000023121472011152000255360ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2015 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.util.List; /** * An initialization task which is run before the application's {@code main} method. THe main module is searched for * service implementations of this interface before the main method is executed. * * @author David M. Lloyd */ public interface PreMain { /** * Run the initialization task. * * @param args the (mutable) list of command-line arguments */ void run(List args); } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/PropertyReadAction.java000066400000000000000000000023561472011152000277710ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.security.PrivilegedAction; /** * @author David M. Lloyd */ class PropertyReadAction implements PrivilegedAction { private final String key; private final String defVal; PropertyReadAction(final String key) { this(key, null); } PropertyReadAction(final String key, final String defVal) { this.key = key; this.defVal = defVal; } public String run() { return System.getProperty(key, defVal); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/PropertyWriteAction.java000066400000000000000000000023061472011152000302030ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.security.PrivilegedAction; /** * Date: 11.05.2011 * * @author James R. Perkins */ class PropertyWriteAction implements PrivilegedAction { private final String key; private final String value; PropertyWriteAction(final String key, final String value) { this.key = key; this.value = value; } @Override public String run() { return System.setProperty(key, value); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/Resource.java000066400000000000000000000027741472011152000260060ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.IOException; import java.io.InputStream; import java.net.URL; /** * A single resource from a {@link ResourceLoader}. * * @author David M. Lloyd */ public interface Resource { /** * Get the relative resource name. * * @return the name */ String getName(); /** * Get the complete URL of this resource. * * @return the URL */ URL getURL(); /** * Open an input stream to this resource. * * @return the stream * @throws java.io.IOException if an I/O error occurs */ InputStream openStream() throws IOException; /** * Get the size of the resource, if known. * * @return the size, or 0L if unknown */ long getSize(); } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ResourceLoader.java000066400000000000000000000107521472011152000271300ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.IOException; import java.net.URI; import java.util.Collection; /** * A loader for resources from a specific resource root within a module. * * @author David M. Lloyd * @author Richard Opalka */ public interface ResourceLoader extends AutoCloseable { /** * Get the name of the root represented by this resource loader. * * @return the name of the root */ @Deprecated default String getRootName() { return "ignored"; } /** * Get the class specification for the given class name. If no matching class is found, {@code null} is returned. * * @param fileName the fileName of the class, e.g. for the class org.jboss.modules.ResourceLoader * the fileName will be org/jboss/modules/ResourceLoader.class * @return the class specification, or {@code null} if the named class is not found * @throws IOException if an I/O error occurs */ ClassSpec getClassSpec(String fileName) throws IOException; /** * Get the package specification for the given directory name. Always returns a package specification; this * method cannot be used to test for the existence of a package. A package spec should always be acquired from * the same resource loader which provided the class specification. The directory name will always be specified * using "{@code /}" separators. * * @param name the directory name * @return the package specification * @throws IOException if an I/O error occurs */ PackageSpec getPackageSpec(String name) throws IOException; /** * Get a resource with the given name. If no such resource is available, {@code null} is returned. * The resource name will always be specified using "{@code /}" separators for the directory segments. * * @param name the resource name * @return the resource, or {@code null} if it is not available */ Resource getResource(String name); /** * Get the absolute physical filesystem path for a library with the given name. The resultant path should be * path-separated using "{@code /}" characters. * * @param name the name * @return the path or {@code null} if the library is not present */ String getLibrary(String name); /** * Get the collection of resource paths. Called one time only when the resource loader is initialized. The * paths should use "{@code /}" characters to separate the path segments. * * @return the resource paths */ Collection getPaths(); /** * Closes this resource, relinquishing any underlying resources. * This method is invoked automatically on objects managed by the * {@code try}-with-resources statement. */ default void close() {} /** * Get the base location of the resources in this loader (if any). If the location is not known, or the resource * loader does not support locations, or the resource loader does not support this method, {@code null} is returned. * * @return the base location of the resources in this loader, or {@code null} if not available */ default URI getLocation() { return null; } /** * Create a loader which loads resources under a relative subdirectory relative to this loader. If the resource * loader does not support subloaders, {@code null} is returned. * * @param relativePath the relative path * @param rootName the name of the subloader's root * @return the resource loader, or {@code null} if subloaders are not supported */ default ResourceLoader createSubloader(String relativePath, String rootName) { return null; } }jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ResourceLoaderModuleFinder.java000066400000000000000000000103741472011152000314260ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import static org.jboss.modules.Utils.MODULES_DIR; import static org.jboss.modules.Utils.MODULE_FILE; import java.io.IOException; import java.io.InputStream; import org.jboss.modules.xml.ModuleXmlParser; /** * A module loader which loads modules which are stored inside the {@code modules} directory of a single JAR or JAR-like * root. */ public final class ResourceLoaderModuleFinder implements ModuleFinder { private final ResourceLoader resourceLoader; private final String modulesDirectory; private final NestedResourceRootFactory factory; /** * Construct a new instance. The given resource loader should support the nested {@link ResourceLoader#createSubloader(String, String)} * operation if {@code <resource-root>} elements are to be supported in {@code module.xml} files found within * the loader. * * @param resourceLoader the base resource loader to use (must not be {@code null}) * @param modulesDirectory the modules directory to use (must not be {@code null}) */ public ResourceLoaderModuleFinder(final ResourceLoader resourceLoader, final String modulesDirectory) { factory = new NestedResourceRootFactory(resourceLoader); this.resourceLoader = resourceLoader; this.modulesDirectory = modulesDirectory; } /** * Construct a new instance. The given resource loader should support the nested {@link ResourceLoader#createSubloader(String, String)} * operation if {@code <resource-root>} elements are to be supported in {@code module.xml} files found within * the loader. * * @param resourceLoader the base resource loader to use (must not be {@code null}) */ public ResourceLoaderModuleFinder(final ResourceLoader resourceLoader) { this(resourceLoader, MODULES_DIR); } public ModuleSpec findModule(final String name, final ModuleLoader delegateLoader) throws ModuleLoadException { final ResourceLoader resourceLoader = this.resourceLoader; final String path = PathUtils.basicModuleNameToPath(name); if (path == null) { return null; // not valid, so not found } String basePath = modulesDirectory + "/" + path; Resource moduleXmlResource = resourceLoader.getResource(basePath + "/" + MODULE_FILE); if (moduleXmlResource == null) { return null; } ModuleSpec moduleSpec; try { try (final InputStream inputStream = moduleXmlResource.openStream()) { moduleSpec = ModuleXmlParser.parseModuleXml(factory, basePath, inputStream, moduleXmlResource.getName(), delegateLoader, name); } } catch (IOException e) { throw new ModuleLoadException("Failed to read " + MODULE_FILE + " file", e); } return moduleSpec; } static class NestedResourceRootFactory implements ModuleXmlParser.ResourceRootFactory { private final ResourceLoader resourceLoader; NestedResourceRootFactory(final ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } public ResourceLoader createResourceLoader(final String rootPath, final String loaderPath, final String loaderName) throws IOException { final ResourceLoader subloader = resourceLoader.createSubloader(rootPath + "/" + loaderPath, loaderName); if (subloader == null) { throw new IllegalArgumentException("Nested resource loaders not supported by " + resourceLoader); } return subloader; } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ResourceLoaderSpec.java000066400000000000000000000046761472011152000277530ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import org.jboss.modules.filter.PathFilter; import org.jboss.modules.filter.PathFilters; /** * A specification of a resource loader within a module. A resource loader may optionally be associated with a * path filter which can be used to decide which paths of a resource loader to include. * * @apiviz.exclude * * @author David M. Lloyd */ public final class ResourceLoaderSpec { static final ResourceLoaderSpec[] NO_RESOURCE_LOADERS = new ResourceLoaderSpec[0]; private final ResourceLoader resourceLoader; private final PathFilter pathFilter; ResourceLoaderSpec(final ResourceLoader resourceLoader, final PathFilter pathFilter) { this.resourceLoader = resourceLoader; this.pathFilter = pathFilter; } /** * Construct a new instance. * * @param resourceLoader the resource loader to include * @param pathFilter the path filter to apply to the resource loader's paths * @return the specification */ public static ResourceLoaderSpec createResourceLoaderSpec(final ResourceLoader resourceLoader, final PathFilter pathFilter) { return new ResourceLoaderSpec(resourceLoader, pathFilter); } /** * Construct a new instance which accepts all paths in the resource loader. * * @param resourceLoader the resource loader to include * @return the specification */ public static ResourceLoaderSpec createResourceLoaderSpec(final ResourceLoader resourceLoader) { return new ResourceLoaderSpec(resourceLoader, PathFilters.acceptAll()); } ResourceLoader getResourceLoader() { return resourceLoader; } PathFilter getPathFilter() { return pathFilter; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ResourceLoaders.java000066400000000000000000000227101472011152000273100ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.File; import java.nio.file.Path; import java.security.AccessController; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.jar.JarFile; import org.jboss.modules.filter.PathFilter; /** * Static factory methods for various types of resource loaders. * * @apiviz.exclude * * @author David M. Lloyd */ public final class ResourceLoaders { private ResourceLoaders() { } /** * Create a filesystem-backed resource loader with support for native libraries. Created classes * have a code source with a {@code file:} URL. * * @param name the name of the resource root * @param root the root file of the resource loader * @return the resource loader * @deprecated Use {@link #createPathResourceLoader(Path)} instead. */ @Deprecated public static IterableResourceLoader createFileResourceLoader(final String name, final File root) { return createPathResourceLoader(name, root.toPath()); } @Deprecated public static ResourceLoader createFileResourceLoader$$bridge(final String name, final File root) { return createFileResourceLoader(name, root); } /** * Create a filesystem-backed iterable resource loader with support for native libraries. Created classes * have a code source with a {@code file:} URL. * * @param name the name of the resource root * @param root the root file of the resource loader * @return the resource loader * @deprecated Use {@link #createFileResourceLoader(String, File)} instead. */ @Deprecated public static IterableResourceLoader createIterableFileResourceLoader(final String name, final File root) { return createFileResourceLoader(name, root); } /** * Create a JAR-backed resource loader. JAR resource loaders do not have native library support. * Created classes have a code source with a {@code jar:} URL; nested JARs are not supported. * * @param name the name of the resource root * @param jarFile the backing JAR file * @return the resource loader * @deprecated Use {@link #createJarResourceLoader(JarFile)} instead. */ @Deprecated public static IterableResourceLoader createJarResourceLoader(final String name, final JarFile jarFile) { return new JarFileResourceLoader(name, jarFile); } /** * Create a JAR-backed resource loader. JAR resource loaders do not have native library support. * Created classes have a code source with a {@code jar:} URL; nested JARs are not supported. * * @param jarFile the backing JAR file * @return the resource loader */ public static IterableResourceLoader createJarResourceLoader(final JarFile jarFile) { return new JarFileResourceLoader("unnamed", jarFile); } @Deprecated public static ResourceLoader createJarResourceLoader$$bridge(final String name, final JarFile jarFile) { return createJarResourceLoader(name, jarFile); } /** * Create a JAR-backed resource loader. JAR resource loaders do not have native library support. * Created classes have a code source with a {@code jar:} URL; nested JARs are not supported. The given * relative path within the JAR is used as the root of the loader. * * @param name the name of the resource root * @param jarFile the backing JAR file * @return the resource loader * @deprecated Use {@link #createJarResourceLoader(JarFile, String)} instead. */ @Deprecated public static IterableResourceLoader createJarResourceLoader(final String name, final JarFile jarFile, final String relativePath) { return new JarFileResourceLoader(name, jarFile, relativePath); } /** * Create a JAR-backed resource loader. JAR resource loaders do not have native library support. * Created classes have a code source with a {@code jar:} URL; nested JARs are not supported. The given * relative path within the JAR is used as the root of the loader. * * @param jarFile the backing JAR file * @return the resource loader */ public static IterableResourceLoader createJarResourceLoader(final JarFile jarFile, final String relativePath) { return new JarFileResourceLoader("unnamed", jarFile, relativePath); } /** * Create a JAR-backed iterable resource loader. JAR resource loaders do not have native library support. * Created classes have a code source with a {@code jar:} URL; nested JARs are not supported. * * @param name the name of the resource root * @param jarFile the backing JAR file * @return the resource loader * @deprecated Use {@link #createJarResourceLoader(JarFile)} instead. */ @Deprecated public static IterableResourceLoader createIterableJarResourceLoader(final String name, final JarFile jarFile) { return createJarResourceLoader(name, jarFile); } /** * Create a filtered view of a resource loader, which allows classes to be included or excluded on a name basis. * The given filter is matched against the actual class or resource name, not the directory name. * * @param pathFilter the path filter to apply * @param originalLoader the original loader to apply to * @return the filtered resource loader */ public static ResourceLoader createFilteredResourceLoader(final PathFilter pathFilter, final ResourceLoader originalLoader) { return originalLoader instanceof IterableResourceLoader ? new FilteredIterableResourceLoader(pathFilter, (IterableResourceLoader) originalLoader) : new FilteredResourceLoader(pathFilter, originalLoader); } /** * Create a filtered view of an iterable resource loader, which allows classes to be included or excluded on a name basis. * The given filter is matched against the actual class or resource name, not the directory name. * * @param pathFilter the path filter to apply * @param originalLoader the original loader to apply to * @return the filtered resource loader */ public static IterableResourceLoader createFilteredResourceLoader(final PathFilter pathFilter, final IterableResourceLoader originalLoader) { return new FilteredIterableResourceLoader(pathFilter, originalLoader); } /** * Create a filtered view of an iterable resource loader, which allows classes to be included or excluded on a name basis. * The given filter is matched against the actual class or resource name, not the directory name. * * @param pathFilter the path filter to apply * @param originalLoader the original loader to apply to * @return the filtered resource loader * @deprecated Use {@link #createFileResourceLoader(String, File)} instead. */ @Deprecated public static IterableResourceLoader createIterableFilteredResourceLoader(final PathFilter pathFilter, final IterableResourceLoader originalLoader) { return createFilteredResourceLoader(pathFilter, originalLoader); } /** * Create a NIO2 Path-backed iterable resource loader. * * @param name the name of the resource root * @param path the root path of the resource loader * @return the resource loader * @deprecated Use {@link #createPathResourceLoader(Path)} instead. */ @Deprecated public static IterableResourceLoader createPathResourceLoader(final String name, final Path path) { return new PathResourceLoader(name, path, AccessController.getContext()); } /** * Create a NIO2 Path-backed iterable resource loader. * * @param path the root path of the resource loader * @return the resource loader */ public static IterableResourceLoader createPathResourceLoader(final Path path) { return new PathResourceLoader("unnamed", path, AccessController.getContext()); } /** * Create a service resource loader. This is a resource loader which answers service load requests with a preset * implementation name. * * @param serviceMap a map of service types to a list of implementation names (must not be {@code null}) * @return the resource loader (not {@code null}) */ public static ResourceLoader createServiceResourceLoader(final Map> serviceMap) { final Map map = new HashMap<>(); for (Map.Entry> entry : serviceMap.entrySet()) { final String serviceName = entry.getKey(); final List implNames = entry.getValue(); final URLConnectionResource resource = ServiceResourceLoader.createResource(implNames); map.put(serviceName, resource); } return new ServiceResourceLoader(map); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/SecurityActions.java000066400000000000000000000044201472011152000273350ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.security.PrivilegedAction; import static java.lang.System.getSecurityManager; import static java.lang.Thread.currentThread; import static java.security.AccessController.doPrivileged; /** * This class must not be public. * * @author David M. Lloyd */ final class SecurityActions { private static final PrivilegedAction GET_LOADER_ACTION = new PrivilegedAction<>() { public ClassLoader run() { return currentThread().getContextClassLoader(); } }; static ClassLoader setContextClassLoader(final ClassLoader classLoader) { final SecurityManager sm = getSecurityManager(); if (sm != null) { return doPrivileged(new PrivilegedAction<>() { public ClassLoader run() { try { return currentThread().getContextClassLoader(); } finally { currentThread().setContextClassLoader(classLoader); } } }); } else { try { return currentThread().getContextClassLoader(); } finally { currentThread().setContextClassLoader(classLoader); } } } static ClassLoader getContextClassLoader() { final SecurityManager sm = getSecurityManager(); if (sm != null) { return doPrivileged(GET_LOADER_ACTION); } else { return currentThread().getContextClassLoader(); } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ServiceResourceLoader.java000066400000000000000000000050141472011152000304440ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2018 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.IOException; import java.net.URL; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; /** */ final class ServiceResourceLoader extends AbstractResourceLoader { private final Map servicesMap; ServiceResourceLoader(final Map map) { servicesMap = map; } @Override public Resource getResource(final String name) { if (name.startsWith("META-INF/services/")) { return servicesMap.get(name.substring("META-INF/services/".length())); } return null; } @Override public Collection getPaths() { return Collections.singleton("META-INF/services"); } private static final String PREFIX = "data:text/plain;charset=UTF-8,"; static URLConnectionResource createResource(List implNames) { int len = PREFIX.length(); Iterator iterator = implNames.iterator(); if (iterator.hasNext()) { len = iterator.next().length(); while (iterator.hasNext()) { len += 1 + iterator.next().length(); } } if (len == 0) { return null; } StringBuilder sb = new StringBuilder(len); sb.append(PREFIX); iterator = implNames.iterator(); if (iterator.hasNext()) { sb.append(iterator.next()); while (iterator.hasNext()) { sb.append('\n'); sb.append(iterator.next()); } } try { return new URLConnectionResource(new URL(sb.toString())); } catch (IOException e) { throw new IllegalStateException("Failed to create URL", e); } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/SimpleSupplier.java000066400000000000000000000017031472011152000271630ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.util.function.Supplier; /** * */ class SimpleSupplier implements Supplier { private final E e; SimpleSupplier(final E e) { this.e = e; } public E get() { return e; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/StartTimeHolder.java000066400000000000000000000014761472011152000272670ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; final class StartTimeHolder { static final long START_TIME = System.currentTimeMillis(); } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/URLConnectionResource.java000066400000000000000000000031171472011152000304010ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2018 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; /** * @author David M. Lloyd */ final class URLConnectionResource implements Resource { private final URLConnection connection; URLConnectionResource(final URL url) throws IOException { this(url.openConnection()); } URLConnectionResource(final URLConnection connection) { this.connection = connection; } public String getName() { return getURL().getPath(); } public URL getURL() { return connection.getURL(); } public InputStream openStream() throws IOException { return connection.getInputStream(); } public long getSize() { final long len = connection.getContentLengthLong(); return len == -1 ? 0 : len; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/Utils.java000066400000000000000000000243161472011152000253130ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.UndeclaredThrowableException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; import java.nio.file.FileSystems; import java.nio.file.FileVisitResult; import java.nio.file.FileVisitor; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.ServiceLoader; import java.util.Set; import java.util.function.Predicate; import static java.nio.file.FileVisitResult.CONTINUE; import static java.nio.file.FileVisitResult.SKIP_SUBTREE; import static java.security.AccessController.doPrivileged; /** * @author David M. Lloyd * @author Richard Opalka */ final class Utils { static final String MODULE_VERSION = "Module-Version"; static final String DEPENDENCIES = "Dependencies"; static final String EXPORT = "export"; static final String OPTIONAL = "optional"; static final String SERVICES = "services"; static final String MODULES_DIR = "modules"; static final String MODULE_FILE = "module.xml"; static final String[] NO_STRINGS = new String[0]; private Utils() { // forbidden instantiation } static final ModuleLoader JDK_MODULE_LOADER = new ModuleLoader(JDKModuleFinder.getInstance()); static final Set MODULES_PACKAGES = Set.of( "org.jboss.modules", "org.jboss.modules.filter", "org.jboss.modules.log", "org.jboss.modules.management", "org.jboss.modules.maven", "org.jboss.modules.ref", "org.jboss.modules.security", "org.jboss.modules.xml" ); private static final Set MODULES_PATHS = Set.of( "org/jboss/modules", "org/jboss/modules/filter", "org/jboss/modules/log", "org/jboss/modules/management", "org/jboss/modules/maven", "org/jboss/modules/ref", "org/jboss/modules/security", "org/jboss/modules/xml" ); private static final ClassLoader SYSTEM_CLASS_LOADER = doPrivileged((PrivilegedAction) ClassLoader::getSystemClassLoader); private static final ClassLoader OUR_CLASS_LOADER = Utils.class.getClassLoader(); static Set getJDKPaths() { Set pathSet = new FastCopyHashSet<>(1024); processRuntimeImages(pathSet); // TODO: Remove this stuff once jboss-modules is itself a module final String javaClassPath = AccessController.doPrivileged(new PropertyReadAction("java.class.path")); JDKPaths.processClassPathItem(javaClassPath, new FastCopyHashSet<>(1024), pathSet); pathSet.addAll(MODULES_PATHS); return pathSet; } static LocalLoader getSystemLocalLoader() { return new LocalLoader() { public Class loadClassLocal(final String name, final boolean resolve) { try { return Class.forName(name, resolve, getPlatformClassLoader()); } catch (ClassNotFoundException ignored) { try { return Class.forName(name, resolve, OUR_CLASS_LOADER); } catch (ClassNotFoundException e) { return null; } } } public Package loadPackageLocal(final String name) { final Package pkg = getPlatformClassLoader().getDefinedPackage(name); return pkg != null ? pkg : OUR_CLASS_LOADER.getDefinedPackage(name); } public List loadResourceLocal(final String name) { final Enumeration urls; try { urls = getSystemResources(name); } catch (IOException e) { return Collections.emptyList(); } final List list = new ArrayList<>(); while (urls.hasMoreElements()) { final URL url = urls.nextElement(); URLConnection connection = null; try { connection = doPrivileged(new GetURLConnectionAction(url)); } catch (PrivilegedActionException e) { try { throw e.getException(); } catch (IOException e2) { // omit from list } catch (RuntimeException re) { throw re; } catch (Exception e2) { throw new UndeclaredThrowableException(e2); } } list.add(new URLConnectionResource(connection)); } return list; } }; } static ClassLoader getPlatformClassLoader() { return SYSTEM_CLASS_LOADER; } static URL getSystemResource(final String name) { final URL resource = getPlatformClassLoader().getResource(name); return resource != null ? resource : OUR_CLASS_LOADER != null ? OUR_CLASS_LOADER.getResource(name) : ClassLoader.getSystemResource(name); } static Enumeration getSystemResources(final String name) throws IOException { final Enumeration resources = getPlatformClassLoader().getResources(name); return resources != null && resources.hasMoreElements() ? resources : OUR_CLASS_LOADER.getResources(name); } static InputStream getSystemResourceAsStream(final String name) { final InputStream stream = getPlatformClassLoader().getResourceAsStream(name); return stream != null ? stream : OUR_CLASS_LOADER != null ? OUR_CLASS_LOADER.getResourceAsStream(name) : ClassLoader.getSystemResourceAsStream(name); } static Class getSystemClass(final ConcurrentClassLoader caller, final String className) throws ClassNotFoundException { try { return getPlatformClassLoader().loadClass(className); } catch (ClassNotFoundException ignored) { return OUR_CLASS_LOADER != null ? OUR_CLASS_LOADER.loadClass(className) : caller.findSystemClassInternal(className); } } static Iterable findServices(final Class serviceType, final Predicate> filter, final ClassLoader classLoader) { final Iterator> delegate = ServiceLoader.load(serviceType, classLoader).stream().iterator(); return new Iterable<>() { public Iterator iterator() { return new Iterator<>() { T next = null; public boolean hasNext() { ServiceLoader.Provider next; while (this.next == null) { if (!delegate.hasNext()) return false; next = delegate.next(); if (filter.test(next.type())) { this.next = next.get(); return true; } } return true; } public T next() { if (!hasNext()) throw new NoSuchElementException(); T next = this.next; this.next = null; return next; } }; } }; } // === nested util stuff, non-API === private static void processRuntimeImages(final Set pathSet) { try { for (final Path root : FileSystems.getFileSystem(new URI("jrt:/")).getRootDirectories()) { Files.walkFileTree(root, new JrtFileVisitor(pathSet)); } } catch (final URISyntaxException | IOException e) { throw new IllegalStateException("Unable to process java runtime images"); } } private static class JrtFileVisitor implements FileVisitor { private static final String SLASH = "/"; private static final String PACKAGES = "/packages"; private final Set pathSet; private JrtFileVisitor(final Set pathSet) { this.pathSet = pathSet; } @Override public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) { final String d = dir.toString(); return d.equals(SLASH) || d.startsWith(PACKAGES) ? CONTINUE : SKIP_SUBTREE; } @Override public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) { if (file.getNameCount() >= 3 && file.getName(0).toString().equals("packages")) { pathSet.add(file.getName(1).toString().replace('.', '/')); } return CONTINUE; } @Override public FileVisitResult visitFileFailed(final Path file, final IOException exc) { return CONTINUE; } @Override public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) { return CONTINUE; } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/Version.java000066400000000000000000000531201472011152000256330ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2016 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.Serializable; import java.math.BigInteger; import java.text.Normalizer; import java.util.NoSuchElementException; /** * A version for a module. Versions are series of letters and digits, optionally divided by separator characters, which * include {@code .}, {@code -}, {@code +}, and {@code _}. The transition between letter and digit (or vice-versa) is * also considered to be an invisible separator. *

* Versions may be compared, sorted, used as hash keys, and iterated. * * @author David M. Lloyd */ public final class Version implements Comparable, Serializable { private final String version; private static final int TOK_INITIAL = 0; private static final int TOK_PART_NUMBER = 1; private static final int TOK_PART_ALPHA = 2; private static final int TOK_SEP = 3; private static final int TOK_SEP_EMPTY = 4; boolean hasNext(long cookie) { return cookieToEndIndex(cookie) < version.length(); } /** * Go to the next token. * * @param cookie the cookie ({@code 0L} indicates start of search) * @return the next cookie value in the token sequence * @throws IllegalArgumentException if the next token is not a valid token or the string is too long */ long next(long cookie) throws IllegalArgumentException { int start, end, token; // get old end value end = cookieToEndIndex(cookie); final String version = this.version; final int length = version.length(); // hasNext() should have been called first on this cookie value assert end < length; start = end; int cp = version.codePointAt(start); // examine the previous token token = cookieToToken(cookie); if (token == TOK_PART_NUMBER && isValidAlphaPart(cp) || token == TOK_PART_ALPHA && isValidNumberPart(cp)) { token = TOK_SEP_EMPTY; end = start; } else if ((token == TOK_INITIAL || token == TOK_SEP || token == TOK_SEP_EMPTY) && isValidAlphaPart(cp)) { token = TOK_PART_ALPHA; end = length; // find end for (int i = start; i < length; i = version.offsetByCodePoints(i, 1)) { cp = version.codePointAt(i); if (! isValidAlphaPart(cp)) { end = i; break; } } } else if ((token == TOK_INITIAL || token == TOK_SEP || token == TOK_SEP_EMPTY) && isValidNumberPart(cp)) { token = TOK_PART_NUMBER; end = length; // find end for (int i = start; i < length; i = version.offsetByCodePoints(i, 1)) { cp = version.codePointAt(i); if (! isValidNumberPart(cp)) { end = i; break; } } } else if ((token == TOK_PART_NUMBER || token == TOK_PART_ALPHA) && isValidSeparator(cp)) { token = TOK_SEP; end = version.offsetByCodePoints(start, 1); } else { throw new IllegalArgumentException("Invalid version code point \"" + new String(Character.toChars(cp)) + "\" at offset " + start + " of \"" + version + "\""); } if (end > (1 << 28) - 1) { throw new IllegalArgumentException("Version string is too long"); } assert end >= start; return ((long) start) | ((long) end << 28) | ((long) token << 56); } /** * Get the token start index from the cookie. The start index is stored in the lowest 28 bits (bits 0-27) of the cookie. * * @param cookie the cookie * @return the start character index in the version string */ static int cookieToStartIndex(long cookie) { return (int) (cookie & 0xfff_ffff); } /** * Get the token end index from the cookie. The end index is stored in the second 28 bits (bits 28-55) of the cookie. * * @param cookie the cookie * @return the end character index in the version string */ static int cookieToEndIndex(long cookie) { return (int) ((cookie >> 28) & 0xfff_ffff); } /** * Get the token type from the cookie. The token type is stored in bits 56 and up in the cookie. * The value will be one of: *

    *
  • {@link #TOK_PART_NUMBER}
  • *
  • {@link #TOK_PART_ALPHA}
  • *
  • {@link #TOK_SEP}
  • *
  • {@link #TOK_SEP_EMPTY}
  • *
* * @param cookie the cookie * @return the token value */ static int cookieToToken(long cookie) { return (int) (cookie >> 56); } static int sepMagnitude(int codePoint) { switch (codePoint) { case '.': return 1; case '-': return 2; case '+': return 3; case '_': return 4; default: throw new IllegalStateException(); } } static int compareSep(int sep1, int sep2) { return Integer.signum(sepMagnitude(sep1) - sepMagnitude(sep2)); } static boolean isValidAlphaPart(int codePoint) { return Character.isLetter(codePoint); } static boolean isValidNumberPart(int codePoint) { // Use this instead of isDigit(cp) in case a valid digit is not a valid decimal digit return Character.digit(codePoint, 10) != -1; } static boolean isValidSeparator(int codePoint) { return codePoint == '.' || codePoint == '-' || codePoint == '+' || codePoint == '_'; } int comparePart(long cookie, Version other, long otherCookie) { final int token = cookieToToken(cookie); final int otherToken = cookieToToken(otherCookie); final int start = cookieToStartIndex(cookie); final int otherStart = cookieToStartIndex(cookie); final int end = cookieToEndIndex(cookie); final int otherEnd = cookieToEndIndex(otherCookie); switch (token) { case TOK_PART_NUMBER: { if (otherToken == TOK_PART_ALPHA) { return 1; } assert otherToken == TOK_PART_NUMBER; // we need the length in digits, not in characters final int digits = version.codePointCount(start, end); final int otherDigits = other.version.codePointCount(otherStart, otherEnd); // if one is shorter, we need to pad it out with invisible zeros for the value comparison // otherwise, compare digits naively from left to right int res; // in this loop, i represents the place with a higher # being more significant for (int i = Math.max(digits, otherDigits) - 1; i >= 0; i --) { // if the value has no digit at location 'i', i.e. i > length, then the effective value is 0 int a = i >= digits ? 0 : Character.digit(version.codePointBefore(version.offsetByCodePoints(end, -i)), 10); int b = i >= otherDigits ? 0 : Character.digit(other.version.codePointBefore(other.version.offsetByCodePoints(otherEnd, -i)), 10); res = Integer.signum(a - b); if (res != 0) { return res; } } // equal, so now the shortest wins return Integer.signum(digits - otherDigits); } case TOK_PART_ALPHA: { if (otherToken == TOK_PART_NUMBER) { return -1; } assert otherToken == TOK_PART_ALPHA; // compare string naively from left to right for (int i = start; i < Math.min(end, otherEnd); i = version.offsetByCodePoints(i, 1)) { int cp = version.codePointAt(i); int ocp = other.version.codePointAt(i); assert isValidAlphaPart(cp) && isValidAlphaPart(ocp); int res = Integer.signum(cp - ocp); if (res != 0) { return res; } } // identical prefix; fall back to length comparison return Integer.signum(end - otherEnd); } case TOK_SEP: { if (otherToken == TOK_SEP_EMPTY) { return 1; } else { assert otherToken == TOK_SEP; return compareSep(version.codePointAt(start), other.version.codePointAt(cookieToStartIndex(otherCookie))); } } case TOK_SEP_EMPTY: { return otherToken == TOK_SEP_EMPTY ? 0 : -1; } default: throw new IllegalStateException(); } } private Version(String v) { if (v == null) throw new IllegalArgumentException("Null version string"); this.version = Normalizer.normalize(v, Normalizer.Form.NFKC); // validate if (! hasNext(0L)) { throw new IllegalArgumentException("Empty version string"); } long cookie = next(0L); while (hasNext(cookie)) { cookie = next(cookie); } final int lastToken = cookieToToken(cookie); if (lastToken == TOK_SEP || lastToken == TOK_SEP_EMPTY) { throw new IllegalArgumentException("Version ends with a separator"); } } /** * Parses the given string as a version string. * * @param v * The string to parse * * @return The resulting {@code Version} * * @throws IllegalArgumentException * If {@code v} is {@code null}, an empty string, or cannot be * parsed as a version string */ public static Version parse(String v) { return new Version(v); } /** * Construct a new iterator over the parts of this version string. * * @return the iterator */ public Iterator iterator() { return new Iterator(); } /** * Compares this module version to another module version. Module * versions are compared as described in the class description. * * @param that * The module version to compare * * @return A negative integer, zero, or a positive integer as this * module version is less than, equal to, or greater than the * given module version */ @Override public int compareTo(Version that) { long cookie = 0L; long thatCookie = 0L; int res; while (hasNext(cookie)) { cookie = next(cookie); if (that.hasNext(thatCookie)) { thatCookie = that.next(thatCookie); res = comparePart(cookie, that, thatCookie); if (res != 0) { return res; } } else { return 1; } } return that.hasNext(thatCookie) ? - 1 : 0; } /** * Tests this module version for equality with the given object. * *

If the given object is not a {@code Version} then this method * returns {@code false}. Two module version are equal if their * corresponding components are equal.

* *

This method satisfies the general contract of the {@link * java.lang.Object#equals(Object) Object.equals} method.

* * @param ob * the object to which this object is to be compared * * @return {@code true} if, and only if, the given object is a module * reference that is equal to this module reference */ @Override public boolean equals(Object ob) { if (!(ob instanceof Version)) return false; return compareTo((Version)ob) == 0; } /** * Computes a hash code for this module version. * *

The hash code is based upon the components of the version and * satisfies the general contract of the {@link Object#hashCode * Object.hashCode} method.

* * @return The hash-code value for this module version */ @Override public int hashCode() { return version.hashCode(); } /** * Returns the normalized string representation of this version. * * @return The normalized string. */ @Override public String toString() { return version; } /** * An iterator over the parts of a version. */ public class Iterator { long cookie = 0L; Iterator() { } /** * Determine whether another token exists in this version. * * @return {@code true} if more tokens remain, {@code false} otherwise */ public boolean hasNext() { return Version.this.hasNext(cookie); } /** * Move to the next token. * * @throws NoSuchElementException if there are no more tokens to iterate */ public void next() { final long cookie = this.cookie; if (! Version.this.hasNext(cookie)) { throw new NoSuchElementException(); } this.cookie = Version.this.next(cookie); } /** * Get the length of the current token. If there is no current token, zero is returned. * * @return the length of the current token */ public int length() { final long cookie = this.cookie; return cookieToEndIndex(cookie) - cookieToStartIndex(cookie); } /** * Determine if the current token is some kind of separator (a character or a zero-length alphabetical-to-numeric * or numeric-to-alphabetical transition). * * @return {@code true} if the token is a separator, {@code false} otherwise */ public boolean isSeparator() { final int token = cookieToToken(cookie); return token == TOK_SEP_EMPTY || token == TOK_SEP; } /** * Determine if the current token is some kind of part (alphabetical or numeric). * * @return {@code true} if the token is a separator, {@code false} otherwise */ public boolean isPart() { final int token = cookieToToken(cookie); return token == TOK_PART_ALPHA || token == TOK_PART_NUMBER; } /** * Determine if the current token is an empty (or zero-length alphabetical-to-numeric * or numeric-to-alphabetical) separator. * * @return {@code true} if the token is an empty separator, {@code false} otherwise */ public boolean isEmptySeparator() { return cookieToToken(cookie) == TOK_SEP_EMPTY; } /** * Determine if the current token is a non-empty separator. * * @return {@code true} if the token is a non-empty separator, {@code false} otherwise */ public boolean isNonEmptySeparator() { return cookieToToken(cookie) == TOK_SEP; } /** * Get the code point of the current separator. If the iterator is not positioned on a non-empty separator * (i.e. {@link #isNonEmptySeparator()} returns {@code false}), then an exception is thrown. * * @return the code point of the current separator * @throws IllegalStateException if the current token is not a non-empty separator */ public int getSeparatorCodePoint() { final long cookie = this.cookie; if (cookieToToken(cookie) != TOK_SEP) { throw new IllegalStateException(); } return version.codePointAt(cookieToStartIndex(cookie)); } /** * Determine if the current token is an alphabetical part. * * @return {@code true} if the token is an alphabetical part, {@code false} otherwise */ public boolean isAlphaPart() { return cookieToToken(cookie) == TOK_PART_ALPHA; } /** * Determine if the current token is a numeric part. * * @return {@code true} if the token is a numeric part, {@code false} otherwise */ public boolean isNumberPart() { return cookieToToken(cookie) == TOK_PART_NUMBER; } /** * Get the current alphabetical part. If the iterator is not positioned on an alphabetical part (i.e. * {@link #isAlphaPart()} returns {@code false}), then an exception is thrown. * * @return the current alphabetical part * @throws IllegalStateException if the current token is not an alphabetical part */ public String getAlphaPart() { final long cookie = this.cookie; if (cookieToToken(cookie) != TOK_PART_ALPHA) { throw new IllegalStateException(); } return version.substring(cookieToStartIndex(cookie), cookieToEndIndex(cookie)); } /** * Get the current numeric part, as a {@code String}. If the iterator is not positioned on a numeric * part (i.e. {@link #isNumberPart()} returns {@code false}), then an exception is thrown. * * @return the current numeric part as a {@code String} * @throws IllegalStateException if the current token is not a numeric part */ public String getNumberPartAsString() { final long cookie = this.cookie; if (cookieToToken(cookie) != TOK_PART_NUMBER) { throw new IllegalStateException(); } return version.substring(cookieToStartIndex(cookie), cookieToEndIndex(cookie)); } /** * Get the current numeric part, as a {@code long}. If the iterator is not positioned on a numeric * part (i.e. {@link #isNumberPart()} returns {@code false}), then an exception is thrown. If the value * overflows the maximum value for a {@code long}, then only the low-order 64 bits of the version number * value are returned. * * @return the current numeric part as a {@code long} * @throws IllegalStateException if the current token is not a numeric part */ public long getNumberPartAsLong() { final long cookie = this.cookie; if (cookieToToken(cookie) != TOK_PART_NUMBER) { throw new IllegalStateException(); } long total = 0L; final int start = cookieToStartIndex(cookie); final int end = cookieToEndIndex(cookie); for (int i = start; i < end; i = version.offsetByCodePoints(i, 1)) { total = total * 10 + Character.digit(version.codePointAt(i), 10); } return total; } /** * Get the current numeric part, as an {@code int}. If the iterator is not positioned on a numeric * part (i.e. {@link #isNumberPart()} returns {@code false}), then an exception is thrown. If the value * overflows the maximum value for an {@code int}, then only the low-order 32 bits of the version number * value are returned. * * @return the current numeric part as an {@code int} * @throws IllegalStateException if the current token is not a numeric part */ public int getNumberPartAsInt() { final long cookie = this.cookie; if (cookieToToken(cookie) != TOK_PART_NUMBER) { throw new IllegalStateException(); } int total = 0; final int start = cookieToStartIndex(cookie); final int end = cookieToEndIndex(cookie); for (int i = start; i < end; i = version.offsetByCodePoints(i, 1)) { total = total * 10 + Character.digit(version.codePointAt(i), 10); } return total; } /** * Get the current numeric part, as a {@code BigInteger}. If the iterator is not positioned on a numeric * part (i.e. {@link #isNumberPart()} returns {@code false}), then an exception is thrown. * * @return the current numeric part as a {@code BigInteger} * @throws IllegalStateException if the current token is not a numeric part */ public BigInteger getNumberPartAsBigInteger() { final long cookie = this.cookie; if (cookieToToken(cookie) != TOK_PART_NUMBER) { throw new IllegalStateException(); } return new BigInteger(version.substring(cookieToStartIndex(cookie), cookieToEndIndex(cookie))); } } Object writeReplace() { return new Serialized(toString()); } static final class Serialized implements Serializable { private static final long serialVersionUID = - 8720461103628158977L; private final String string; Serialized(final String string) { this.string = string; } Object readResolve() { return new Version(string); } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/VersionDetection.java000066400000000000000000000040721472011152000274740ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2018 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.IOException; import java.io.InputStream; import java.util.jar.Attributes; import java.util.jar.Manifest; /** * A utility class to assist with detecting the version of a resource root or collection of resource roots. */ public final class VersionDetection { private VersionDetection() {} /** * Attempt to guess the version of a resource loader. * * @param resourceLoader the resource loader to check (must not be {@code null}) * @return the version, or {@code null} if no version could be determined * @throws IOException if necessary resource(s) failed to load */ public static Version detectVersion(ResourceLoader resourceLoader) throws IOException { final Resource resource = resourceLoader.getResource("META-INF/MANIFEST.MF"); if (resource != null) { Manifest manifest; try (InputStream is = resource.openStream()) { manifest = new Manifest(is); } final Attributes mainAttributes = manifest.getMainAttributes(); final String versionString = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION); if (versionString != null) try { return Version.parse(versionString); } catch (IllegalArgumentException ignored) { } } return null; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/_private/000077500000000000000000000000001472011152000251535ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/_private/ModulesPrivateAccess.java000066400000000000000000000021131472011152000321000ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules._private; import org.jboss.modules.Module; import org.jboss.modules.ModuleClassLoader; /** * Private-access methods for modules. User classes cannot acquire an instance * of this class. * * @author David M. Lloyd */ public interface ModulesPrivateAccess { ModuleClassLoader getClassLoaderOf(Module module); } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/filter/000077500000000000000000000000001472011152000246275ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/filter/AggregatePathFilter.java000066400000000000000000000050371472011152000313500ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.filter; import java.util.Arrays; /** * PathFilter implementation that aggregates multiple other filters. * * @author John E. Bailey * @author David M. Lloyd */ final class AggregatePathFilter implements PathFilter { private final PathFilter[] delegates; private final boolean any; private final int hashCode; /** * Construct a new instance. * * @param any {@code true} if this is an "any" filter, {@code false} if this an "all" filter * @param delegates the delegate filter list */ AggregatePathFilter(final boolean any, final PathFilter... delegates) { this.any = any; this.delegates = delegates; hashCode = Boolean.valueOf(any).hashCode() ^ Arrays.hashCode(delegates); } /** {@inheritDoc} */ @Override public boolean accept(String path) { for (PathFilter filter : delegates) { if (filter.accept(path) == any) { return any; } } return ! any; } public int hashCode() { return hashCode; } public boolean equals(final Object obj) { return obj instanceof AggregatePathFilter && equals((AggregatePathFilter) obj); } public boolean equals(final AggregatePathFilter obj) { return obj != null && obj.any == any && Arrays.equals(obj.delegates, delegates); } public String toString() { final StringBuilder b = new StringBuilder(); b.append(any ? "Any " : "All ").append("of ("); for (int idx = 0; idx < delegates.length; idx++) { final PathFilter delegate = delegates[idx]; b.append(delegate); if (idx < delegates.length - 1) { b.append(','); } } b.append(')'); return b.toString(); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/filter/BooleanClassFilter.java000066400000000000000000000027121472011152000312070ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.filter; /** * @author David M. Lloyd */ final class BooleanClassFilter implements ClassFilter { private final boolean result; private BooleanClassFilter(final boolean result) { this.result = result; } public boolean accept(final String path) { return result; } static final BooleanClassFilter TRUE = new BooleanClassFilter(true); static final BooleanClassFilter FALSE = new BooleanClassFilter(false); public int hashCode() { return Boolean.valueOf(result).hashCode(); } public boolean equals(final Object obj) { return obj == this; } public String toString() { return result ? "Accept" : "Reject"; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/filter/BooleanPathFilter.java000066400000000000000000000027731472011152000310450ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.filter; /** * @author David M. Lloyd */ final class BooleanPathFilter implements PathFilter { private final boolean result; private BooleanPathFilter(final boolean result) { this.result = result; } public boolean accept(final String path) { return result; } static final BooleanPathFilter TRUE = new BooleanPathFilter(true); static final BooleanPathFilter FALSE = new BooleanPathFilter(false); public int hashCode() { return Boolean.valueOf(result).hashCode(); } public boolean equals(final Object obj) { return obj == this; } public String toString() { return result ? "Accept" : "Reject"; } boolean getResult() { return result; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/filter/ChildPathFilter.java000066400000000000000000000027771472011152000305150ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.filter; /** * @author David M. Lloyd */ final class ChildPathFilter implements PathFilter { private final String prefix; ChildPathFilter(final String path) { prefix = path.charAt(path.length() - 1) == '/' ? path : path + "/"; } public boolean accept(final String path) { return path.startsWith(prefix); } public boolean equals(final Object obj) { return obj instanceof ChildPathFilter && equals((ChildPathFilter) obj); } public boolean equals(final ChildPathFilter obj) { return obj != null && obj.prefix.equals(prefix); } public String toString() { return "children of \"" + prefix + "\""; } public int hashCode() { return prefix.hashCode(); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/filter/ClassFilter.java000066400000000000000000000024011472011152000277020ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.filter; /** * Filter used to determine whether a class name should be included or excluded from imports and exports. * * @author David M. Lloyd */ public interface ClassFilter { /** * Determine whether a class name should be accepted by this filter. The class name is qualified with a dot-separated * package name. * * @param className the class name * @return {@code true} to accept the class, {@code false} otherwise */ boolean accept(String className); } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/filter/ClassFilters.java000066400000000000000000000033511472011152000300720ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.filter; /** * Static factory methods for class filter types. * * @author David M. Lloyd */ public final class ClassFilters { private ClassFilters() { } /** * Get a filter which always returns {@code true}. * * @return the accept-all filter */ public static ClassFilter acceptAll() { return BooleanClassFilter.TRUE; } /** * Get a filter which always returns {@code false}. * * @return the reject-all filter */ public static ClassFilter rejectAll() { return BooleanClassFilter.FALSE; } /** * Get a class filter which uses a resource path filter to filter classes. * * @param resourcePathFilter the resource path filter * @return the class filter */ public static ClassFilter fromResourcePathFilter(final PathFilter resourcePathFilter) { return resourcePathFilter == PathFilters.acceptAll() ? acceptAll() : new PathClassFilter(resourcePathFilter); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/filter/EqualsPathFilter.java000066400000000000000000000030541472011152000307110ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.filter; /** * @author David M. Lloyd */ final class EqualsPathFilter implements PathFilter { private final String path; EqualsPathFilter(final String path) { if (path == null) { throw new IllegalArgumentException("path is null"); } this.path = path; } public boolean accept(final String path) { return path.equals(this.path); } public boolean equals(final Object obj) { return obj instanceof EqualsPathFilter && equals((EqualsPathFilter) obj); } public boolean equals(final EqualsPathFilter obj) { return obj != null && obj.path.equals(path); } public String toString() { return "equals \"" + path + "\""; } public int hashCode() { return path.hashCode() + 7; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/filter/GlobPathFilter.java000066400000000000000000000120051472011152000303360ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.filter; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Default implementation of PathFilter. Uses glob based includes and excludes to determine whether to export. * * @author John E. Bailey * @author David M. Lloyd */ final class GlobPathFilter implements PathFilter { private static final Pattern GLOB_PATTERN = Pattern.compile("(\\*\\*?)|(\\?)|(\\\\.)|(/+)|([^*?]+)"); private final String glob; private final Pattern pattern; /** * Construct a new instance. * * @param glob the path glob to match */ GlobPathFilter(final String glob) { pattern = getGlobPattern(glob); this.glob = glob; } /** * Determine whether a path should be accepted. * * @param path the path to check * @return true if the path should be accepted, false if not */ public boolean accept(final String path) { return pattern.matcher(path).matches(); } /** * Get a regular expression pattern which accept any path names which match the given glob. The glob patterns * function similarly to {@code ant} file patterns. Valid metacharacters in the glob pattern include: *
    *
  • "\" - escape the next character (treat it literally, even if it is itself a recognized metacharacter)
  • *
  • "?" - match any non-slash character
  • *
  • "*" - match zero or more non-slash characters
  • *
  • "**" - match zero or more characters, including slashes
  • *
  • "/" - match one or more slash characters. Consecutive {@code /} characters are collapsed down into one.
  • *
* In addition, any glob pattern matches all subdirectories thereof. A glob pattern ending in {@code /} is equivalent * to a glob pattern ending in /** in that the named directory is not itself included in the glob. *

* See also: "Patterns" in the Ant Manual * * @param glob the glob to match * * @return the pattern */ private static Pattern getGlobPattern(final String glob) { StringBuilder patternBuilder = new StringBuilder(); final Matcher m = GLOB_PATTERN.matcher(glob); boolean lastWasSlash = false; while (m.find()) { lastWasSlash = false; String grp; if ((grp = m.group(1)) != null) { // match a * or ** if (grp.length() == 2) { // it's a ** patternBuilder.append(".*"); } else { // it's a * patternBuilder.append("[^/]*"); } } else if ((grp = m.group(2)) != null) { // match a '?' glob pattern; any non-slash character patternBuilder.append("[^/]"); } else if ((grp = m.group(3)) != null) { // backslash-escaped value patternBuilder.append(Pattern.quote(m.group().substring(1))); } else if ((grp = m.group(4)) != null) { // match any number of / chars patternBuilder.append("/+"); lastWasSlash = true; } else { // some other string patternBuilder.append(Pattern.quote(m.group())); } } if (lastWasSlash) { // ends in /, append ** patternBuilder.append(".*"); } else { patternBuilder.append("(?:/.*)?"); } return Pattern.compile(patternBuilder.toString()); } public int hashCode() { return glob.hashCode() + 13; } public boolean equals(final Object obj) { return obj instanceof GlobPathFilter && equals((GlobPathFilter) obj); } public boolean equals(final GlobPathFilter obj) { return obj != null && obj.pattern.equals(pattern); } public String toString() { final StringBuilder b = new StringBuilder(); b.append("match "); if (glob != null) { b.append('"').append(glob).append('"'); } else { b.append('/').append(pattern).append('/'); } return b.toString(); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/filter/InvertingPathFilter.java000066400000000000000000000035701472011152000314270ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.filter; /** * A path filter which simply inverts the result of another path filter. * * @author David M. Lloyd */ final class InvertingPathFilter implements PathFilter { private final PathFilter delegate; /** * Construct a new instance. * * @param delegate the filter to delegate to */ InvertingPathFilter(final PathFilter delegate) { if (delegate == null) { throw new IllegalArgumentException("delegate is null"); } this.delegate = delegate; } /** {@inheritDoc} */ public boolean accept(final String path) { return ! delegate.accept(path); } PathFilter getDelegate() { return delegate; } public int hashCode() { return 47 + delegate.hashCode(); } public boolean equals(final Object obj) { return obj instanceof InvertingPathFilter && equals((InvertingPathFilter) obj); } public boolean equals(final InvertingPathFilter obj) { return obj != null && obj.delegate.equals(delegate); } public String toString() { return "not " + delegate.toString(); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/filter/MultiplePathFilter.java000066400000000000000000000051621472011152000312540ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.filter; import java.util.Arrays; /** * @author David M. Lloyd */ final class MultiplePathFilter implements PathFilter { private final PathFilter[] filters; private final boolean[] includeFlag; private final boolean defaultVal; private final int hashCode; MultiplePathFilter(final PathFilter[] filters, final boolean[] includeFlag, final boolean defaultVal) { this.filters = filters; this.includeFlag = includeFlag; this.defaultVal = defaultVal; hashCode = Boolean.valueOf(defaultVal).hashCode() * 13 + (Arrays.hashCode(includeFlag) * 13 + (Arrays.hashCode(filters))); } public boolean accept(final String path) { final int len = filters.length; for (int i = 0; i < len; i++) { if (filters[i].accept(path)) return includeFlag[i]; } return defaultVal; } public String toString() { StringBuilder builder = new StringBuilder(); builder.append("multi-path filter {"); int len = filters.length; for (int i = 0; i < len; i++) { final PathFilter filter = filters[i]; final boolean include = includeFlag[i]; builder.append(include ? "include " : "exclude "); builder.append(filter); builder.append(", "); } builder.append("default ").append(defaultVal ? "accept" : "reject"); builder.append('}'); return builder.toString(); } public int hashCode() { return hashCode; } public boolean equals(Object other) { return other instanceof MultiplePathFilter && equals((MultiplePathFilter)other); } public boolean equals(MultiplePathFilter other) { return this == other || other != null && Arrays.equals(filters, other.filters) && Arrays.equals(includeFlag, other.includeFlag) && defaultVal == other.defaultVal; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/filter/MultiplePathFilterBuilder.java000066400000000000000000000051711472011152000325630ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.filter; import java.util.ArrayList; import java.util.List; /** * A builder for a multiple-path filter. * * @apiviz.exclude * @see PathFilters#multiplePathFilterBuilder(boolean) */ public class MultiplePathFilterBuilder { private final List filters = new ArrayList<>(); private final List includeFlags = new ArrayList<>(); private final boolean defaultVal; MultiplePathFilterBuilder(final boolean defaultVal) { this.defaultVal = defaultVal; } /** * Add a filter to this builder. * * @param filter the filter to add * @param include {@code true} if matching paths should be included, {@code false} for excluded */ public void addFilter(final PathFilter filter, final boolean include) { if (filter == null) { throw new IllegalArgumentException("filter is null"); } filters.add(filter); includeFlags.add(Boolean.valueOf(include)); } /** * Create the path filter from this builder's current state. * * @return the path filter */ public PathFilter create() { final PathFilter[] filters = this.filters.toArray(PathFilter[]::new); final boolean[] includeFlags = new boolean[this.includeFlags.size()]; for (int i = 0, includeFlagsSize = this.includeFlags.size(); i < includeFlagsSize; i++) { includeFlags[i] = this.includeFlags.get(i).booleanValue(); } if (filters.length == 0) { return defaultVal ? PathFilters.acceptAll() : PathFilters.rejectAll(); } else { return new MultiplePathFilter(filters, includeFlags, defaultVal); } } /** * Determine if this filter builder is empty (i.e. has no path filters set on it). * * @return {@code true} if this builder is empty, {@code false} otherwise */ public boolean isEmpty() { return filters.isEmpty(); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/filter/PathClassFilter.java000066400000000000000000000022411472011152000305210ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.filter; /** * @author David M. Lloyd */ class PathClassFilter implements ClassFilter { private final PathFilter resourcePathFilter; PathClassFilter(final PathFilter resourcePathFilter) { this.resourcePathFilter = resourcePathFilter; } public boolean accept(final String className) { return resourcePathFilter.accept(className.replace('.', '/').concat(".class")); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/filter/PathFilter.java000066400000000000000000000031721472011152000275370ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.filter; /** * Filter used to determine whether a path should be included or excluded from imports and exports. * * @author John Bailey */ public interface PathFilter { /** * Determine whether a path should be accepted. The given name is a path separated * by "{@code /}" characters. * * @param path the path to check * @return true if the path should be accepted, false if not */ boolean accept(String path); /** * Calculate a unique hash code for this path filter. Equal path filters must yield identical hash codes. * * @return the hash code */ int hashCode(); /** * Determine whether this filter is equal to another. Filters must implement meaningful (non-identity) equality * semantics. * * @param other the other object * @return {@code true} if this filter is the same */ boolean equals(Object other); }jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/filter/PathFilters.java000066400000000000000000000263621472011152000277300ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.filter; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Set; import org.jboss.modules.Resource; /** * Static factory methods for path filter types. * * @author David M. Lloyd */ public final class PathFilters { private PathFilters() {} /** * Get a path filter which returns {@code true} if all of the given filters return {@code true}. * * @param filters the filters * @return the "all" filter */ public static PathFilter all(PathFilter... filters) { return new AggregatePathFilter(false, filters); } /** * Get a path filter which returns {@code true} if all of the given filters return {@code true}. * * @param filters the filters * @return the "all" filter */ public static PathFilter all(Collection filters) { return all(filters.toArray(PathFilter[]::new)); } /** * Get a path filter which returns {@code true} if any of the given filters return {@code true}. * * @param filters the filters * @return the "any" filter */ public static PathFilter any(PathFilter... filters) { return new AggregatePathFilter(true, filters); } /** * Get a path filter which returns {@code true} if any of the given filters return {@code true}. * * @param filters the filters * @return the "any" filter */ public static PathFilter any(Collection filters) { return any(filters.toArray(PathFilter[]::new)); } /** * Get a path filter which returns {@code true} if none of the given filters return {@code true}. * * @param filters the filters * @return the "none" filter */ public static PathFilter none(PathFilter... filters) { return not(any(filters)); } /** * Get a path filter which returns {@code true} if none of the given filters return {@code true}. * * @param filters the filters * @return the "none" filter */ public static PathFilter none(Collection filters) { return not(any(filters)); } /** * Get a path filter which is {@code true} when the given filter is {@code false}, and vice-versa. * * @param filter the filter * @return the inverting filter */ public static PathFilter not(PathFilter filter) { if (filter instanceof BooleanPathFilter) { return booleanFilter(!((BooleanPathFilter) filter).getResult()); } else if (filter instanceof InvertingPathFilter) { return ((InvertingPathFilter) filter).getDelegate(); } else { return new InvertingPathFilter(filter); } } /** * Get a path filter which matches a glob. The given glob is a path separated * by "{@code /}" characters, which may include the special "{@code *}" and "{@code **}" segment strings * which match any directory and any number of nested directories, respectively. * * @param glob the glob * @return a filter which returns {@code true} if the glob matches */ public static PathFilter match(String glob) { return new GlobPathFilter(glob); } /** * Get a path filter which matches an exact path name. * * @param path the path name * @return a filter which returns {@code true} if the path name is an exact match */ public static PathFilter is(String path) { return new EqualsPathFilter(path); } /** * Get a path filter which matches any path which is a child of the given path name (not including the * path name itself). * * @param path the path name * @return a filter which returns {@code true} if the path name is a child of the given path */ public static PathFilter isChildOf(String path) { return new ChildPathFilter(path); } /** * Get a path filter which matches any path which is equal to, or a child of, the given path name. * * @param path the path name * @return a filter which returns {@code true} if the path name is equal to, or a child of, the given path */ public static PathFilter isOrIsChildOf(String path) { return any(is(path), isChildOf(path)); } /** * Get a builder for a multiple-path filter. Such a filter contains multiple filters, each associated * with a flag which indicates that matching paths should be included or excluded. * * @param defaultValue the value to return if none of the nested filters match * @return the builder */ public static MultiplePathFilterBuilder multiplePathFilterBuilder(boolean defaultValue) { return new MultiplePathFilterBuilder(defaultValue); } private static BooleanPathFilter booleanFilter(boolean val) { return val ? BooleanPathFilter.TRUE : BooleanPathFilter.FALSE; } /** * Get a filter which always returns {@code true}. * * @return the accept-all filter */ public static PathFilter acceptAll() { return BooleanPathFilter.TRUE; } /** * Get a filter which always returns {@code false}. * * @return the reject-all filter */ public static PathFilter rejectAll() { return BooleanPathFilter.FALSE; } /** * Get a filter which returns {@code true} if the tested path is contained within the given set. * Each member of the set is a path separated by "{@code /}" characters; {@code null}s are disallowed. * * @param paths the path set * @return the filter */ public static PathFilter in(Set paths) { return new SetPathFilter(new HashSet<>(paths)); } /** * Get a filter which returns {@code true} if the tested path is contained within the given collection. * Each member of the collection is a path separated by "{@code /}" characters; {@code null}s are disallowed. * * @param paths the path collection * @return the filter */ public static PathFilter in(Collection paths) { return new SetPathFilter(new HashSet<>(paths)); } /** * Get a filtered view of a resource iteration. Only resources which pass the given filter are accepted. * * @param filter the filter to check * @param original the original iterator * @return the filtered iterator */ public static Iterator filtered(final PathFilter filter, final Iterator original) { return new Iterator<>() { private Resource next; public boolean hasNext() { Resource next; while (this.next == null && original.hasNext()) { next = original.next(); if (filter.accept(next.getName())) { this.next = next; } } return this.next != null; } public Resource next() { if (! hasNext()) { throw new NoSuchElementException(); } try { return next; } finally { next = null; } } public void remove() { original.remove(); } }; } private static final PathFilter defaultImportFilter; private static final PathFilter defaultImportFilterWithServices; private static final PathFilter metaInfFilter; private static final PathFilter metaInfSubdirectoriesFilter; private static final PathFilter metaInfServicesFilter; private static final PathFilter metaInfSubdirectoriesWithoutMetaInfFilter; static { final PathFilter metaInfChildren = isChildOf("META-INF"); final PathFilter metaInf = is("META-INF"); final PathFilter metaInfServicesChildren = isChildOf("META-INF/services"); final PathFilter metaInfServices = is("META-INF/services"); metaInfFilter = metaInf; metaInfSubdirectoriesFilter = metaInfChildren; metaInfServicesFilter = any(metaInfServices, metaInfServicesChildren); final MultiplePathFilterBuilder builder = multiplePathFilterBuilder(true); builder.addFilter(metaInfChildren, false); builder.addFilter(metaInf, false); defaultImportFilter = builder.create(); final MultiplePathFilterBuilder builder2 = multiplePathFilterBuilder(true); builder2.addFilter(metaInfServices, true); builder2.addFilter(metaInfServicesChildren, true); builder2.addFilter(metaInfChildren, false); builder2.addFilter(metaInf, false); defaultImportFilterWithServices = builder2.create(); final MultiplePathFilterBuilder builder3 = multiplePathFilterBuilder(true); builder2.addFilter(metaInfChildren, true); builder3.addFilter(metaInf, false); metaInfSubdirectoriesWithoutMetaInfFilter = builder3.create(); } /** * Get the default import path filter, which excludes all of {@code META-INF} and its subdirectories. * * @return the default import path filter */ public static PathFilter getDefaultImportFilter() { return defaultImportFilter; } /** * Get the default import-with-services path filter which excludes all of {@code META-INF} and its subdirectories, * with the exception of {@code META-INF/services}. * * @return the default import-with-services path filter */ public static PathFilter getDefaultImportFilterWithServices() { return defaultImportFilterWithServices; } /** * Get a filter which matches the path {@code "META-INF"}. * * @return the filter */ public static PathFilter getMetaInfFilter() { return metaInfFilter; } /** * Get a filter which matches any subdirectory of the path {@code "META-INF"}. * * @return the filter */ public static PathFilter getMetaInfSubdirectoriesFilter() { return metaInfSubdirectoriesFilter; } /** * Get a filter which matches the path {@code "META-INF/services"}. * * @return the filter */ public static PathFilter getMetaInfServicesFilter() { return metaInfServicesFilter; } /** * Get a filter which matches all of {@code META-INF}'s subdirectories, but not {@code META-INF} itself. * * @return the filter */ public static PathFilter getMetaInfSubdirectoriesWithoutMetaInfFilter() { return metaInfSubdirectoriesWithoutMetaInfFilter; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/filter/SetPathFilter.java000066400000000000000000000036201472011152000302110ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.filter; import java.util.Iterator; import java.util.Set; /** * @author David M. Lloyd */ final class SetPathFilter implements PathFilter { private final Set paths; private final int hashCode; SetPathFilter(final Set paths) { this.paths = paths; hashCode = paths.hashCode(); } public boolean accept(final String path) { return paths.contains(path); } public String toString() { final StringBuilder b = new StringBuilder(); b.append("in {"); Iterator iterator = paths.iterator(); while (iterator.hasNext()) { final String path = iterator.next(); b.append(path); if (iterator.hasNext()) { b.append(", "); } } b.append('}'); return b.toString(); } public boolean equals(final Object obj) { return obj instanceof SetPathFilter && equals((SetPathFilter) obj); } public boolean equals(final SetPathFilter obj) { return obj != null && obj.paths.equals(paths); } public int hashCode() { return hashCode; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/filter/package-info.java000066400000000000000000000017701472011152000300230ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Classes related to filtering. See the {@link org.jboss.modules.filter.PathFilter PathFilter} interface for the contract of path filters. See * {@link org.jboss.modules.filter.PathFilters PathFilters} for factory methods for creating simple and complex filters. */ package org.jboss.modules.filter;jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/log/000077500000000000000000000000001472011152000241235ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/log/JDKModuleLogger.java000066400000000000000000000144511472011152000277110ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.log; import java.io.File; import java.util.logging.Level; import java.util.logging.Logger; import org.jboss.modules.Main; import org.jboss.modules.Module; import org.jboss.modules.ModuleLoader; /** * A {@link ModuleLogger} which logs to a JDK logging category. * * @author David M. Lloyd */ public final class JDKModuleLogger implements ModuleLogger { private static final Level TRACE; private static final Level DEBUG; private static final Level WARN; static { Level trace; Level debug; Level warn; try { trace = Level.parse("TRACE"); } catch (IllegalArgumentException ignored) { trace = Level.FINEST; } try { debug = Level.parse("DEBUG"); } catch (IllegalArgumentException ignored) { debug = Level.FINE; } try { warn = Level.parse("WARN"); } catch (IllegalArgumentException ignored) { warn = Level.WARNING; } TRACE = trace; DEBUG = debug; WARN = warn; } @SuppressWarnings({ "NonConstantLogger" }) private final Logger logger; @SuppressWarnings({ "NonConstantLogger" }) private final Logger defineLogger; /** * Construct a new instance. * * @param logger the main logger to write to * @param defineLogger the main logger to write class-define-related trace messages to * @deprecated Use {@link #JDKModuleLogger(String)} instead. */ @Deprecated public JDKModuleLogger(final Logger logger, final Logger defineLogger) { this.logger = logger; this.defineLogger = defineLogger; } /** * Construct a new instance. * * @param category the name of the logger category to write to */ public JDKModuleLogger(final String category) { this(Logger.getLogger(category), Logger.getLogger(category + ".define")); } /** * Construct a new instance using the category {@code org.jboss.modules}. */ public JDKModuleLogger() { this("org.jboss.modules"); } private void doLog(final Logger logger, final Level level, final String str, final Throwable t) { try { final ModuleLogRecord rec = new ModuleLogRecord(level, str); rec.setLoggerName(logger.getName()); if (t != null) rec.setThrown(t); logger.log(rec); } catch (Throwable ignored) { } } /** {@inheritDoc} */ public void trace(final String message) { doLog(logger, TRACE, message, null); } /** {@inheritDoc} */ public void trace(final String format, final Object arg1) { if (logger.isLoggable(TRACE)) { doLog(logger, TRACE, String.format(format, arg1), null); } } /** {@inheritDoc} */ public void trace(final String format, final Object arg1, final Object arg2) { if (logger.isLoggable(TRACE)) { doLog(logger, TRACE, String.format(format, arg1, arg2), null); } } /** {@inheritDoc} */ public void trace(final String format, final Object arg1, final Object arg2, final Object arg3) { if (logger.isLoggable(TRACE)) { doLog(logger, TRACE, String.format(format, arg1, arg2, arg3), null); } } /** {@inheritDoc} */ public void trace(final String format, final Object... args) { if (logger.isLoggable(TRACE)) { doLog(logger, TRACE, String.format(format, (Object[]) args), null); } } /** {@inheritDoc} */ public void trace(final Throwable t, final String message) { doLog(logger, TRACE, message, t); } /** {@inheritDoc} */ public void trace(final Throwable t, final String format, final Object arg1) { if (logger.isLoggable(TRACE)) { doLog(logger, TRACE, String.format(format, arg1), t); } } /** {@inheritDoc} */ public void trace(final Throwable t, final String format, final Object arg1, final Object arg2) { if (logger.isLoggable(TRACE)) { doLog(logger, TRACE, String.format(format, arg1, arg2), t); } } /** {@inheritDoc} */ public void trace(final Throwable t, final String format, final Object arg1, final Object arg2, final Object arg3) { if (logger.isLoggable(TRACE)) { doLog(logger, TRACE, String.format(format, arg1, arg2, arg3), t); } } /** {@inheritDoc} */ public void trace(final Throwable t, final String format, final Object... args) { if (logger.isLoggable(TRACE)) { doLog(logger, TRACE, String.format(format, (Object[]) args), t); } } /** {@inheritDoc} */ public void greeting() { doLog(logger, Level.INFO, String.format("JBoss Modules version %s", Main.getVersionString()), null); } /** {@inheritDoc} */ public void moduleDefined(final String name, final ModuleLoader moduleLoader) { if (logger.isLoggable(DEBUG)) { doLog(logger, DEBUG, String.format("Module %s defined by %s", name, moduleLoader), null); } } public void classDefineFailed(final Throwable throwable, final String className, final Module module) { if (defineLogger.isLoggable(WARN)) { doLog(defineLogger, WARN, String.format("Failed to define class %s in %s", className, module), throwable); } } public void classDefined(final String name, final Module module) { if (defineLogger.isLoggable(TRACE)) { doLog(defineLogger, TRACE, String.format("Defined class %s in %s", name, module), null); } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/log/ModuleLogRecord.java000066400000000000000000000062621472011152000300220ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.log; import java.util.logging.LogRecord; import java.util.logging.Level; /** * A log record class which knows how to divine the proper class and method name. */ class ModuleLogRecord extends LogRecord { private static final long serialVersionUID = 542119905844866161L; private boolean resolved; private static final String LOGGER_CLASS_NAME = JDKModuleLogger.class.getName(); ModuleLogRecord(final Level level, final String msg) { super(level, msg); } public String getSourceClassName() { if (! resolved) { resolve(); } return super.getSourceClassName(); } public void setSourceClassName(final String sourceClassName) { resolved = true; super.setSourceClassName(sourceClassName); } public String getSourceMethodName() { if (! resolved) { resolve(); } return super.getSourceMethodName(); } public void setSourceMethodName(final String sourceMethodName) { resolved = true; super.setSourceMethodName(sourceMethodName); } private void resolve() { resolved = true; final StackTraceElement[] stack = new Throwable().getStackTrace(); boolean found = false; for (StackTraceElement element : stack) { final String className = element.getClassName(); if (found) { if (! LOGGER_CLASS_NAME.equals(className)) { setSourceClassName(className); setSourceMethodName(element.getMethodName()); return; } } else { found = LOGGER_CLASS_NAME.equals(className); } } setSourceClassName(""); setSourceMethodName(""); } protected Object writeReplace() { final LogRecord replacement = new LogRecord(getLevel(), getMessage()); replacement.setResourceBundle(getResourceBundle()); replacement.setLoggerName(getLoggerName()); replacement.setMillis(getMillis()); replacement.setParameters(getParameters()); replacement.setResourceBundleName(getResourceBundleName()); replacement.setSequenceNumber(getSequenceNumber()); replacement.setSourceClassName(getSourceClassName()); replacement.setSourceMethodName(getSourceMethodName()); replacement.setThreadID(getThreadID()); replacement.setThrown(getThrown()); return replacement; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/log/ModuleLogger.java000066400000000000000000000041521472011152000273550ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.log; import java.io.File; import org.jboss.modules.Module; import org.jboss.modules.ModuleIdentifier; import org.jboss.modules.ModuleLoader; /** * A simple Logger abstraction. * * @author thomas.diesler@jboss.com * @author David M. Lloyd * @author Richard Opalka */ public interface ModuleLogger { void trace(String message); void trace(String format, Object arg1); void trace(String format, Object arg1, Object arg2); void trace(String format, Object arg1, Object arg2, Object arg3); void trace(String format, Object... args); void trace(Throwable t, String message); void trace(Throwable t, String format, Object arg1); void trace(Throwable t, String format, Object arg1, Object arg2); void trace(Throwable t, String format, Object arg1, Object arg2, Object arg3); void trace(Throwable t, String format, Object... args); void greeting(); default void moduleDefined(String name, final ModuleLoader moduleLoader) { moduleDefined(ModuleIdentifier.fromString(name), moduleLoader); } @Deprecated(forRemoval = true) default void moduleDefined(ModuleIdentifier identifier, final ModuleLoader moduleLoader) { } void classDefineFailed(Throwable throwable, String className, Module module); void classDefined(String name, Module module); } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/log/NoopModuleLogger.java000066400000000000000000000051231472011152000302100ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.log; import java.io.File; import java.net.URL; import org.jboss.modules.Module; import org.jboss.modules.ModuleLoader; /** * A {@link ModuleLogger} implementation that does not log. * * @author thomas.diesler@jboss.com * @author David M. Lloyd */ public final class NoopModuleLogger implements ModuleLogger { private static ModuleLogger instance = new NoopModuleLogger(); public static ModuleLogger getInstance() { return instance; } @Override public void trace(String message) { } @Override public void trace(final String format, final Object arg1) { } @Override public void trace(final String format, final Object arg1, final Object arg2) { } @Override public void trace(final String format, final Object arg1, final Object arg2, final Object arg3) { } @Override public void trace(final String format, final Object... args) { } @Override public void trace(final Throwable t, final String message) { } @Override public void trace(final Throwable t, final String format, final Object arg1) { } @Override public void trace(final Throwable t, final String format, final Object arg1, final Object arg2) { } @Override public void trace(final Throwable t, final String format, final Object arg1, final Object arg2, final Object arg3) { } @Override public void trace(final Throwable t, final String format, final Object... args) { } @Override public void greeting() { } @Override public void moduleDefined(final String name, final ModuleLoader moduleLoader) { } @Override public void classDefineFailed(final Throwable throwable, final String className, final Module module) { } @Override public void classDefined(final String name, final Module module) { } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/log/StreamModuleLogger.java000066400000000000000000000111351472011152000305300ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.log; import java.io.File; import java.io.OutputStream; import java.io.PrintStream; import org.jboss.modules.Module; import org.jboss.modules.ModuleLoader; /** * A {@link ModuleLogger} implementation that logs all output (including trace) to an output or print stream. * * @author thomas.diesler@jboss.com * @author David M. Lloyd */ public final class StreamModuleLogger implements ModuleLogger { private PrintStream print; /** * Construct a new instance. * * @param stream the print stream to write to */ public StreamModuleLogger(PrintStream stream) { if (stream == null) { throw new IllegalArgumentException("stream is null"); } print = new PrintStream(stream); } /** * Construct a new instance. * * @param stream the output stream to write to */ public StreamModuleLogger(OutputStream stream) { this(new PrintStream(stream)); } /** {@inheritDoc} */ public void trace(final String message) { print.print("modules TRACE: "); print.println(message); print.flush(); } /** {@inheritDoc} */ public void trace(final String format, final Object arg1) { print.print("modules TRACE: "); print.printf(format, arg1); print.println(); print.flush(); } /** {@inheritDoc} */ public void trace(final String format, final Object arg1, final Object arg2) { print.print("modules TRACE: "); print.printf(format, arg1, arg2); print.println(); print.flush(); } /** {@inheritDoc} */ public void trace(final String format, final Object arg1, final Object arg2, final Object arg3) { print.print("modules TRACE: "); print.printf(format, arg1, arg2, arg3); print.println(); print.flush(); } /** {@inheritDoc} */ public void trace(final String format, final Object... args) { print.print("modules TRACE: "); print.printf(format, (Object[]) args); print.println(); print.flush(); } /** {@inheritDoc} */ public void trace(final Throwable t, final String message) { print.print("modules TRACE: "); print.print(message); print.print(": "); t.printStackTrace(print); print.flush(); } /** {@inheritDoc} */ public void trace(final Throwable t, final String format, final Object arg1) { print.print("modules TRACE: "); print.printf(format, arg1); print.print(": "); t.printStackTrace(print); print.flush(); } /** {@inheritDoc} */ public void trace(final Throwable t, final String format, final Object arg1, final Object arg2) { print.print("modules TRACE: "); print.printf(format, arg1, arg2); print.print(": "); t.printStackTrace(print); print.flush(); } /** {@inheritDoc} */ public void trace(final Throwable t, final String format, final Object arg1, final Object arg2, final Object arg3) { print.print("modules TRACE: "); print.printf(format, arg1, arg2, arg3); print.print(": "); t.printStackTrace(print); print.flush(); } /** {@inheritDoc} */ public void trace(final Throwable t, final String format, final Object... args) { print.print("modules TRACE: "); print.printf(format, args); print.print(": "); t.printStackTrace(print); print.flush(); } /** {@inheritDoc} */ public void greeting() { } /** {@inheritDoc} */ public void moduleDefined(final String name, final ModuleLoader moduleLoader) { } /** {@inheritDoc} */ public void classDefineFailed(final Throwable throwable, final String className, final Module module) { } public void classDefined(final String name, final Module module) { } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/log/package-info.java000066400000000000000000000020671472011152000273170ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * The logging interface for JBoss Modules. Logging is abstracted in order to support logging services being provided * by a module. To change the logger in use, use the {@link org.jboss.modules.Module#setModuleLogger(ModuleLogger)} method. * See {@link org.jboss.modules.log.ModuleLogger ModuleLogger} for the logging contract. */ package org.jboss.modules.log;jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/management/000077500000000000000000000000001472011152000254565ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/management/DependencyInfo.java000066400000000000000000000102121472011152000312070ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.management; import java.beans.ConstructorProperties; import java.util.List; /** * Information describing a dependency. * * @author David M. Lloyd */ public final class DependencyInfo { private final String dependencyType; private final String exportFilter; private final String importFilter; private final ModuleLoaderMXBean moduleLoader; private final String moduleName; private final boolean optional; private final String localLoader; private final List localLoaderPaths; /** * Construct a new instance. * * @param dependencyType the dependency type class name * @param exportFilter the export filter, as a string * @param importFilter the import filter, as a string * @param moduleLoader the module loader MXBean of this dependency * @param moduleName the module name, as a string * @param optional {@code true} if this is an optional dependency * @param localLoader the local loader type class name * @param localLoaderPaths the list of paths made available by the local loader */ @ConstructorProperties({"dependencyType", "exportFilter", "importFilter", "moduleLoader", "moduleName", "optional", "localLoader", "localLoaderPaths"}) public DependencyInfo(final String dependencyType, final String exportFilter, final String importFilter, final ModuleLoaderMXBean moduleLoader, final String moduleName, final boolean optional, final String localLoader, final List localLoaderPaths) { this.dependencyType = dependencyType; this.exportFilter = exportFilter; this.importFilter = importFilter; this.moduleLoader = moduleLoader; this.moduleName = moduleName; this.optional = optional; this.localLoader = localLoader; this.localLoaderPaths = localLoaderPaths; } /** * Get the dependency type class name. * * @return the dependency type class name */ public String getDependencyType() { return dependencyType; } /** * Get the export filter, as a string. * * @return the export filter, as a string */ public String getExportFilter() { return exportFilter; } /** * Get the import filter, as a string. * * @return the import filter, as a string */ public String getImportFilter() { return importFilter; } /** * Get the module loader MXBean of this dependency. * * @return the module loader MXBean of this dependency */ public ModuleLoaderMXBean getModuleLoader() { return moduleLoader; } /** * Get the module name, as a string. * * @return the module name, as a string */ public String getModuleName() { return moduleName; } /** * Determine whether this is an optional dependency. * * @return {@code true} if this is an optional dependency */ public boolean isOptional() { return optional; } /** * Get the local loader type class name. * * @return the local loader type class name */ public String getLocalLoader() { return localLoader; } /** * Get the list of paths made available by the local loader. * * @return the list of paths made available by the local loader */ public List getLocalLoaderPaths() { return localLoaderPaths; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/management/ModuleInfo.java000066400000000000000000000071501472011152000303650ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.management; import java.beans.ConstructorProperties; import java.util.List; /** * Management information about a module instance. * * @author David M. Lloyd */ public final class ModuleInfo { private final String name; private final ModuleLoaderMXBean moduleLoader; private final List dependencies; private final List resourceLoaders; private final String mainClass; private final String classLoader; private final String fallbackLoader; /** * Construct a new instance. * * @param name the module name * @param moduleLoader the module loader * @param dependencies the dependencies list * @param resourceLoaders the resource loaders list * @param mainClass the main class name * @param classLoader the class loader * @param fallbackLoader the fallback loader */ @ConstructorProperties({"name", "moduleLoader", "dependencies", "resourceLoaders", "mainClass", "classLoader", "fallbackLoader"}) public ModuleInfo(final String name, final ModuleLoaderMXBean moduleLoader, final List dependencies, final List resourceLoaders, final String mainClass, final String classLoader, final String fallbackLoader) { this.name = name; this.moduleLoader = moduleLoader; this.dependencies = dependencies; this.resourceLoaders = resourceLoaders; this.mainClass = mainClass; this.classLoader = classLoader; this.fallbackLoader = fallbackLoader; } /** * Get the name of the corresponding module. * * @return the name of the corresponding module */ public String getName() { return name; } /** * Get the associated module loader MXBean. * * @return the associated module loader MXBean */ public ModuleLoaderMXBean getModuleLoader() { return moduleLoader; } /** * Get the dependency information list. * * @return the dependency information list */ public List getDependencies() { return dependencies; } /** * Get the resource loader information list. * * @return the resource loader information list */ public List getResourceLoaders() { return resourceLoaders; } /** * Get the main class name. * * @return the main class name */ public String getMainClass() { return mainClass; } /** * Get the class loader (as a string). * * @return the class loader (as a string) */ public String getClassLoader() { return classLoader; } /** * Get the fallback loader (as a string). * * @return the fallback loader (as a string) */ public String getFallbackLoader() { return fallbackLoader; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/management/ModuleLoaderMXBean.java000066400000000000000000000112371472011152000317340ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.management; import java.util.List; import java.util.SortedMap; /** * An MXBean for getting runtime information about a module loader. * * @author David M. Lloyd */ public interface ModuleLoaderMXBean { /** * Get a description of this module loader. * * @return a description of this module loader */ String getDescription(); /** * Get the estimated CPU time (in nanoseconds) spent linking in the life of this module loader. * * @return the estimated time in nanoseconds */ long getLinkTime(); /** * Get the estimated CPU time (in nanoseconds) spent loading modules into this loader. * * @return the estimated time in nanoseconds */ long getLoadTime(); /** * Get the estimated CPU time (in nanoseconds) spent defining classes for this loader. * * @return the estimated time in nanoseconds */ long getClassDefineTime(); /** * Get the number of times that dependencies of a module from this loader have been scanned. * * @return the count */ int getScanCount(); /** * Get the number of modules currently loaded. * * @return the loaded module count */ int getLoadedModuleCount(); /** * Get the number of times a class was defined by two threads at once. * * @return the race count */ int getRaceCount(); /** * Get the number of classes defined in this module loader. * * @return the number of classes defined in this module loader */ int getClassCount(); /** * Obtain a list of the current module names. * * @return the module names */ List queryLoadedModuleNames(); /** * Dump all information for a single module as a string. * * @param name the module name * @return the string of module information */ String dumpModuleInformation(String name); /** * Dump all information for all modules as a string. * * @return the string of module information */ String dumpAllModuleInformation(); /** * Attempt to unload a module from this module loader. * * @param name the string form of the module identifier to unload * @return {@code true} if the module was unloaded */ boolean unloadModule(String name); /** * Attempt to refresh the resource loaders of the given module. * * @param name the name of the module to refresh */ void refreshResourceLoaders(String name); /** * Attempt to relink the given module. * * @param name the name of the module to relink */ void relink(String name); /** * Get the dependencies of the named module. * * @param name the module name * @return the module's dependencies */ List getDependencies(String name); /** * Get the resource loaders of the named module. * * @param name the module name * @return the module's resource loaders */ List getResourceLoaders(String name); /** * Get the complete description of this module. * * @param name the module name * @return the module description */ ModuleInfo getModuleDescription(String name); /** * Get a paths map for a given module. * * @param name the module name * @param exports {@code true} for the exported paths, {@code false} for all paths * @return the paths map information */ SortedMap> getModulePathsInfo(String name, boolean exports); /** * Get the code source location of a class within a module. * * @param moduleName the module name * @param className the class name * @return the location, or {@code null} if the class isn't found or the location cannot be determined */ String getClassLocation(String moduleName, String className); } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/management/ObjectProperties.java000066400000000000000000000106141472011152000316060ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.management; import java.util.Collection; import java.util.Collections; import java.util.Enumeration; import java.util.Hashtable; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; /** * A Hashtable variant which keeps property names in order, for use by MBean {@code ObjectName}s. * * @author David M. Lloyd */ public final class ObjectProperties extends Hashtable { private static final long serialVersionUID = -4691081844415343670L; private final Map realMap; public static Property property(String key, String value) { return new Property(key, value); } public static ObjectProperties properties(Property... properties) { return new ObjectProperties(properties); } public ObjectProperties(final int initialCapacity, final float loadFactor) { realMap = new LinkedHashMap<>(initialCapacity, loadFactor); } public ObjectProperties(final int initialCapacity) { realMap = new LinkedHashMap<>(initialCapacity); } public ObjectProperties() { realMap = new LinkedHashMap<>(); } public ObjectProperties(final Map t) { realMap = new LinkedHashMap<>(t); } public ObjectProperties(Property... properties) { realMap = new LinkedHashMap<>(properties.length); for (Property property : properties) { realMap.put(property.getKey(), property.getValue()); } } public int size() { return realMap.size(); } public boolean isEmpty() { return realMap.isEmpty(); } public Enumeration keys() { return Collections.enumeration(realMap.keySet()); } public Enumeration elements() { return Collections.enumeration(realMap.values()); } public boolean contains(final Object value) { return realMap.containsValue(value); } public boolean containsValue(final Object value) { return realMap.containsValue(value); } public boolean containsKey(final Object key) { return realMap.containsKey(key); } public String get(final Object key) { return realMap.get(key); } protected void rehash() { } public String put(final String key, final String value) { return realMap.put(key, value); } public String remove(final Object key) { return realMap.remove(key); } public void putAll(final Map t) { realMap.putAll(t); } public void clear() { realMap.clear(); } public Object clone() { return super.clone(); } public String toString() { return realMap.toString(); } public Set keySet() { return realMap.keySet(); } public Set> entrySet() { return realMap.entrySet(); } public Collection values() { return realMap.values(); } /** * A single property in a properties list. */ public static final class Property { private final String key; private final String value; public Property(final String key, final String value) { if (key == null) { throw new IllegalArgumentException("key is null"); } if (value == null) { throw new IllegalArgumentException("value is null"); } this.key = key; this.value = value; } public String getKey() { return key; } public String getValue() { return value; } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/management/ResourceLoaderInfo.java000066400000000000000000000037051472011152000320600ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.management; import java.beans.ConstructorProperties; import java.util.List; /** * Information about a resource loader. * * @author David M. Lloyd */ public final class ResourceLoaderInfo { private final String type; private final String location; private final List paths; /** * Construct a new instance. * * @param type the type name * @param location the physical location of the resource loader (if any) * @param paths the paths list */ @ConstructorProperties({"type", "location", "paths"}) public ResourceLoaderInfo(final String type, final String location, final List paths) { this.type = type; this.location = location; this.paths = paths; } /** * Get the type name. * * @return the type name */ public String getType() { return type; } /** * Get the resource loader location. * * @return the resource loader location */ public String getLocation() { return location; } /** * Get the paths list. * * @return the paths list */ public List getPaths() { return paths; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/management/package-info.java000066400000000000000000000014761472011152000306550ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Management interfaces for utilizing JBoss Modules via an MBean container. */ package org.jboss.modules.management;jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/maven/000077500000000000000000000000001472011152000244505ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/maven/ArtifactCoordinates.java000066400000000000000000000157441472011152000312560ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2015 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.maven; import java.io.File; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Maven artifact coordinate specification. * * @author David M. Lloyd */ public final class ArtifactCoordinates { static final Pattern snapshotPattern = Pattern.compile("-\\d{8}\\.\\d{6}-\\d+$"); private static final Pattern VALID_PATTERN = Pattern.compile("^([-_a-zA-Z0-9.]+):([-_a-zA-Z0-9.]+):([-_a-zA-Z0-9.]+)(?::([-_a-zA-Z0-9.]+))?$"); private final String groupId; private final String artifactId; private final String version; private final String classifier; private int hashCode; private String toString; /** * Construct a new instance. * * @param groupId the group ID (must not be {@code null}) * @param artifactId the artifact ID (must not be {@code null}) * @param version the version string (must not be {@code null}) * @param classifier the classifier string (must not be {@code null}, may be empty) */ public ArtifactCoordinates(final String groupId, final String artifactId, final String version, final String classifier) { this.groupId = groupId; this.artifactId = artifactId; this.version = version; this.classifier = classifier; } /** * Construct a new instance with an empty classifier. * * @param groupId the group ID (must not be {@code null}) * @param artifactId the artifact ID (must not be {@code null}) * @param version the version string (must not be {@code null}) */ public ArtifactCoordinates(final String groupId, final String artifactId, final String version) { this(groupId, artifactId, version, ""); } /** * Parse a string and produce artifact coordinates from it. * * @param string the string to parse (must not be {@code null}) * @return the artifact coordinates object (not {@code null}) */ public static ArtifactCoordinates fromString(String string) { final Matcher matcher = VALID_PATTERN.matcher(string); if (matcher.matches()) { if (matcher.group(4) != null) { return new ArtifactCoordinates(matcher.group(1), matcher.group(2), matcher.group(3), matcher.group(4)); } else { return new ArtifactCoordinates(matcher.group(1), matcher.group(2), matcher.group(3)); } } else { throw new IllegalArgumentException(string); } } /** * Get the group ID. * * @return the group ID (not {@code null}) */ public String getGroupId() { return groupId; } /** * Get the artifact ID. * * @return the artifact ID (not {@code null}) */ public String getArtifactId() { return artifactId; } /** * Get the version. * * @return the version (not {@code null}) */ public String getVersion() { return version; } /** * Get the classifier. * * @return the classifier (not {@code null}, may be empty) */ public String getClassifier() { return classifier; } /** * Create a relative repository path for the given artifact coordinates. * * @param separator the separator character to use (typically {@code '/'} or {@link File#separatorChar}) * @return the path string */ public String relativeArtifactPath(char separator) { String artifactId1 = getArtifactId(); String version1 = getVersion(); StringBuilder builder = new StringBuilder(getGroupId().replace('.', separator)); builder.append(separator).append(artifactId1).append(separator); String pathVersion; final Matcher versionMatcher = snapshotPattern.matcher(version1); if (versionMatcher.find()) { // it's really a snapshot pathVersion = version1.substring(0, versionMatcher.start()) + "-SNAPSHOT"; } else { pathVersion = version1; } builder.append(pathVersion).append(separator).append(artifactId1).append('-').append(version1); return builder.toString(); } /** * Create a relative repository path for the given artifact coordinates with a {@code '/'} separator. * * @return the path string */ public String relativeArtifactPath() { return relativeArtifactPath('/'); } /** * Determine whether this coordinates object equals the target object. * * @param obj the target object * @return {@code true} if the object is equal to this one, {@code false} otherwise */ public boolean equals(final Object obj) { return this == obj || obj instanceof ArtifactCoordinates && equals((ArtifactCoordinates) obj); } /** * Determine whether this coordinates object equals the target object. * * @param obj the target object * @return {@code true} if the object is equal to this one, {@code false} otherwise */ public boolean equals(final ArtifactCoordinates obj) { return this == obj || obj != null && groupId.equals(obj.groupId) && artifactId.equals(obj.artifactId) && version.equals(obj.version) && classifier.equals(obj.classifier); } /** * Get the hash code. * * @return the hash code */ public int hashCode() { int hashCode = this.hashCode; if (hashCode == 0) { hashCode = ((groupId.hashCode() * 19 + artifactId.hashCode()) * 19 + version.hashCode()) * 19 + classifier.hashCode(); if (hashCode == 0) { hashCode = -1; } this.hashCode = hashCode; } return hashCode; } /** * Get the string representation. * * @return the string representation */ public String toString() { String toString = this.toString; if (toString == null) { final StringBuilder b = new StringBuilder(groupId.length() + artifactId.length() + version.length() + classifier.length() + 16); b.append(groupId).append(':').append(artifactId).append(':').append(version); if (! classifier.isEmpty()) { b.append(':').append(classifier); } this.toString = toString = b.toString(); } return toString; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/maven/DefaultMavenResolver.java000066400000000000000000000025061472011152000314130ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2015 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.maven; import static org.jboss.modules.maven.MavenArtifactUtil.doIo; import java.io.File; import java.io.IOException; import java.security.AccessControlContext; import java.security.AccessController; final class DefaultMavenResolver implements MavenResolver { private final AccessControlContext context; DefaultMavenResolver() { context = AccessController.getContext(); } public File resolveArtifact(final ArtifactCoordinates coordinates, final String packaging) throws IOException { return doIo(() -> MavenArtifactUtil.resolveArtifact(coordinates, packaging), context); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/maven/MavenArtifactUtil.java000077500000000000000000000262341472011152000307070ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2015 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.maven; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.UndeclaredThrowableException; import java.net.HttpURLConnection; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.security.AccessControlContext; import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.util.List; import java.util.jar.JarFile; import org.jboss.modules.Module; import org.jboss.modules.ResourceLoader; import org.jboss.modules.ResourceLoaders; /** * Helper class to resolve a maven artifact. * * @author Bill Burke * @author Tomaz Cerar * @author David M. Lloyd */ public final class MavenArtifactUtil { static final Object artifactLock = new Object(); /** * Try to resolve a Maven JAR artifact. Calling this method is identical to calling * {@code resolveJarArtifact(qualifier, "jar")}. * * @param coordinates the non-{@code null} Maven coordinates object * @return the absolute path to the artifact, or {@code null} if none exists * @throws IOException if acquiring the artifact path failed for some reason */ public static File resolveJarArtifact(final ArtifactCoordinates coordinates) throws IOException { return resolveArtifact(coordinates, "jar"); } /** * Tries to find a maven jar artifact from the system property {@code "maven.repo.local"} This property is a list of * platform separated directory names. If not specified, then it looks in {@code ${user.home}/.m2/repository} by default. *

* If it can't find it in local paths, then will try to download from a remote repository from the system property * {@code "remote.maven.repo"}. There is no default remote repository. It will download both the pom and jar and put it * into the first directory listed in {@code "maven.repo.local"} (or the default directory). This directory will be * created if it doesn't exist. *

* Finally, if you do not want a message to console, then set the system property {@code "maven.download.message"} to * {@code "false"}. * * @param coordinates the non-{@code null} Maven coordinates object * @param packaging a non-{@code null} string with the exact packaging type desired (e.g. {@code pom}, {@code jar}, etc.) * @return the absolute path to the artifact, or {@code null} if none exists * @throws IOException if acquiring the artifact path failed for some reason */ public static File resolveArtifact(final ArtifactCoordinates coordinates, final String packaging) throws IOException { String artifactRelativePath = coordinates.relativeArtifactPath(File.separatorChar); String artifactRelativeHttpPath = coordinates.relativeArtifactPath('/'); final MavenSettings settings = MavenSettings.getSettings(); final Path localRepository = settings.getLocalRepository(); final File localRepositoryFile = localRepository.toFile(); final String pomPath = artifactRelativePath + ".pom"; // serialize artifact lookup because we want to prevent parallel download synchronized (artifactLock) { if ("pom".equals(packaging)) { // ignore classifier Path fp = localRepository.resolve(pomPath); if (Files.exists(fp)) { return fp.toFile(); } List remoteRepos = settings.getRemoteRepositories(); if (remoteRepos.isEmpty()) { return null; } final File pomFile = new File(localRepositoryFile, pomPath); for (String remoteRepository : remoteRepos) { try { String remotePomPath = remoteRepository + artifactRelativeHttpPath + ".pom"; downloadFile(coordinates + ":" + packaging, remotePomPath, pomFile); if (pomFile.exists()) { //download successful return pomFile; } } catch (IOException e) { Module.getModuleLogger().trace(e, "Could not download '%s' from '%s' repository", artifactRelativePath, remoteRepository); // try next one } } } else { final String coordinatesClassifier = coordinates.getClassifier(); String classifier = coordinatesClassifier.isEmpty() ? "" : "-" + coordinatesClassifier; String artifactPath = artifactRelativePath + classifier + "." + packaging; Path fp = localRepository.resolve(artifactPath); if (Files.exists(fp)) { return fp.toFile(); } List remoteRepos = settings.getRemoteRepositories(); if (remoteRepos.isEmpty()) { return null; } final File artifactFile = new File(localRepositoryFile, artifactPath); final File pomFile = new File(localRepositoryFile, pomPath); for (String remoteRepository : remoteRepos) { try { String remotePomPath = remoteRepository + artifactRelativeHttpPath + ".pom"; String remoteArtifactPath = remoteRepository + artifactRelativeHttpPath + classifier + "." + packaging; downloadFile(coordinates + ":pom", remotePomPath, pomFile); if (! pomFile.exists()) { // no POM; skip it continue; } downloadFile(coordinates + ":" + packaging, remoteArtifactPath, artifactFile); if (artifactFile.exists()) { //download successful return artifactFile; } } catch (IOException e) { Module.getModuleLogger().trace(e, "Could not download '%s' from '%s' repository", artifactRelativePath, remoteRepository); // } } } //could not find it in remote Module.getModuleLogger().trace("Could not find in any remote repository"); return null; } } static void downloadFile(String artifact, String src, File dest) throws IOException { if (dest.exists()){ return; } URL url = new URL(src); HttpURLConnection connection = (HttpURLConnection)MavenSettings.getSettings().openConnection(url); boolean message = Boolean.getBoolean("maven.download.message"); int statusCode = connection.getResponseCode(); if (statusCode == HttpURLConnection.HTTP_NOT_FOUND) { return; } if (statusCode == HttpURLConnection.HTTP_MOVED_TEMP || statusCode == HttpURLConnection.HTTP_MOVED_PERM) { src = connection.getHeaderField("Location"); url = new URL(src); connection = (HttpURLConnection) url.openConnection(); } try (InputStream bis = connection.getInputStream()){ dest.getParentFile().mkdirs(); if (message) { System.out.println("Downloading " + artifact); } Files.copy(bis, dest.toPath(), StandardCopyOption.REPLACE_EXISTING); } } /** * A utility method to create a Maven artifact resource loader for the given artifact name. * * @param name the artifact name * @return the resource loader * @throws IOException if the artifact could not be resolved */ public static ResourceLoader createMavenArtifactLoader(final String name) throws IOException { return createMavenArtifactLoader(MavenResolver.createDefaultResolver(), name); } /** * A utility method to create a Maven artifact resource loader for the given artifact name. * * @param mavenResolver the Maven resolver to use (must not be {@code null}) * @param name the artifact name * @return the resource loader * @throws IOException if the artifact could not be resolved */ public static ResourceLoader createMavenArtifactLoader(final MavenResolver mavenResolver, final String name) throws IOException { return createMavenArtifactLoader(mavenResolver, ArtifactCoordinates.fromString(name), name); } /** * A utility method to create a Maven artifact resource loader for the given artifact coordinates. * * @param rootName the resource root name to use (must not be {@code null}) * @param coordinates the artifact coordinates to use (must not be {@code null}) * @param mavenResolver the Maven resolver to use (must not be {@code null}) * @return the resource loader * @throws IOException if the artifact could not be resolved */ public static ResourceLoader createMavenArtifactLoader(final MavenResolver mavenResolver, final ArtifactCoordinates coordinates, final String rootName) throws IOException { File fp = mavenResolver.resolveJarArtifact(coordinates); if (fp == null) return null; JarFile jarFile = new JarFile(fp, true, JarFile.OPEN_READ, JarFile.runtimeVersion()); return ResourceLoaders.createJarResourceLoader(jarFile); } static T doIo(PrivilegedExceptionAction action) throws IOException { try { return AccessController.doPrivileged(action); } catch (PrivilegedActionException e) { try { throw e.getCause(); } catch (IOException | RuntimeException | Error e1) { throw e1; } catch (Throwable t) { throw new UndeclaredThrowableException(t); } } } static T doIo(PrivilegedExceptionAction action, AccessControlContext context) throws IOException { try { return AccessController.doPrivileged(action, context); } catch (PrivilegedActionException e) { try { throw e.getCause(); } catch (IOException | RuntimeException | Error e1) { throw e1; } catch (Throwable t) { throw new UndeclaredThrowableException(t); } } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/maven/MavenResolver.java000066400000000000000000000072471472011152000301150ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2015 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.maven; import java.io.File; import java.io.IOException; /** * A resolution strategy for Maven artifacts. * * @author David M. Lloyd */ public interface MavenResolver { /** * Try to resolve a Maven JAR artifact. Calling this method is identical to calling * {@code resolveJarArtifact(qualifier, "jar")}. * * @param coordinates the non-{@code null} Maven coordinates object * @return the absolute path to the artifact, or {@code null} if none exists * @throws IOException if acquiring the artifact path failed for some reason */ default File resolveJarArtifact(final ArtifactCoordinates coordinates) throws IOException { return resolveArtifact(coordinates, "jar"); } /** * Tries to find a maven jar artifact from the system property {@code "maven.repo.local"} This property is a list of * platform separated directory names. If not specified, then it looks in {@code ${user.home}/.m2/repository} by default. *

* If it can't find it in local paths, then will try to download from a remote repository from the system property * {@code "remote.maven.repo"}. There is no default remote repository. It will download both the pom and jar and put it * into the first directory listed in {@code "maven.repo.local"} (or the default directory). This directory will be * created if it doesn't exist. *

* Finally, if you do not want a message to console, then set the system property {@code "maven.download.message"} to * {@code "false"}. * * @param coordinates the non-{@code null} Maven coordinates object * @param packaging a non-{@code null} string with the exact packaging type desired (e.g. {@code pom}, {@code jar}, etc.) * @return the absolute path to the artifact, or {@code null} if none exists * @throws IOException if acquiring the artifact path failed for some reason */ File resolveArtifact(final ArtifactCoordinates coordinates, final String packaging) throws IOException; /** * Create a Maven artifact resolver using the default strategy. The permissions of the class calling this method * are captured and used for filesystem and network accesses. The default strategy uses the following system * properties: *

    *
  • {@code maven.repo.local} - a list of directory names using the platform separator which reflect local * Maven repository roots
  • *
  • {@code remote.maven.repo} - a comma-separated list of URIs which refer to remote Maven repositories, * from which artifacts can be downloaded
  • *
  • {@code maven.download.message} - a boolean system property which controls the logging of messages to * the console
  • *
* * @return the maven resolver strategy (not {@code null}) */ static MavenResolver createDefaultResolver() { return new DefaultMavenResolver(); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/maven/MavenSettings.java000066400000000000000000000510211472011152000301010ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2015 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.maven; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.InetSocketAddress; import java.net.URL; import java.net.URLConnection; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.Base64; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Pattern; import org.jboss.modules.xml.MXParser; import org.jboss.modules.xml.XmlPullParser; import org.jboss.modules.xml.XmlPullParserException; import static org.jboss.modules.maven.MavenArtifactUtil.doIo; import static org.jboss.modules.xml.ModuleXmlParser.endOfDocument; import static org.jboss.modules.xml.ModuleXmlParser.unexpectedContent; import static org.jboss.modules.xml.XmlPullParser.END_DOCUMENT; import static org.jboss.modules.xml.XmlPullParser.END_TAG; import static org.jboss.modules.xml.XmlPullParser.FEATURE_PROCESS_NAMESPACES; import static org.jboss.modules.xml.XmlPullParser.START_TAG; /** * @author Tomaz Cerar (c) 2014 Red Hat Inc. */ final class MavenSettings { private static final Object settingLoaderMutex = new Object(); private static volatile MavenSettings mavenSettings; private Path localRepository = null; private final List remoteRepositories = new LinkedList<>(); private final Map profiles = new HashMap<>(); private final List activeProfileNames = new LinkedList<>(); private final List proxies = new ArrayList<>(); MavenSettings() { configureDefaults(); } static MavenSettings getSettings() throws IOException { if (mavenSettings != null) { return mavenSettings; } synchronized (settingLoaderMutex) { if (mavenSettings != null) { return mavenSettings; } return mavenSettings = doIo(() -> { MavenSettings settings = new MavenSettings(); Path settingsPath = null; if ( System.getProperty( "jboss.modules.settings.xml.url" ) != null ) { settingsPath = Paths.get( new URL(System.getProperty( "jboss.modules.settings.xml.url")).toURI()); } Path m2 = Paths.get(System.getProperty("user.home"), ".m2"); if ( settingsPath == null ) { settingsPath = m2.resolve("settings.xml"); } if (Files.notExists(settingsPath)) { String mavenHome = System.getenv("M2_HOME"); if (mavenHome != null) { settingsPath = Paths.get(mavenHome, "conf", "settings.xml"); } } if (Files.exists(settingsPath)) { parseSettingsXml(settingsPath, settings); } if (settings.getLocalRepository() == null) { Path repository = m2.resolve("repository"); settings.setLocalRepository(repository); } settings.resolveActiveSettings(); return settings; }); } } static MavenSettings parseSettingsXml(Path settings, MavenSettings mavenSettings) throws IOException { try { final MXParser reader = new MXParser(); reader.setFeature(FEATURE_PROCESS_NAMESPACES, false); InputStream source = Files.newInputStream(settings, StandardOpenOption.READ); reader.setInput(source, null); int eventType; while ((eventType = reader.next()) != END_DOCUMENT) { switch (eventType) { case START_TAG: { switch (reader.getName()) { case "settings": { parseSettings(reader, mavenSettings); break; } } } default: { break; } } } return mavenSettings; } catch (XmlPullParserException e) { throw new IOException("Could not parse maven settings.xml"); } } static void parseSettings(final XmlPullParser reader, MavenSettings mavenSettings) throws XmlPullParserException, IOException { int eventType; while ((eventType = reader.nextTag()) != END_DOCUMENT) { switch (eventType) { case END_TAG: { return; } case START_TAG: { switch (reader.getName()) { case "localRepository": { String localRepository = reader.nextText(); boolean localRepositoryNotDefinedViaProperty = mavenSettings.getLocalRepository() == null; if (localRepositoryNotDefinedViaProperty && localRepository != null && !localRepository.trim().isEmpty()) { mavenSettings.setLocalRepository(Paths.get(interpolateVariables(localRepository))); } break; } case "proxies": { while ((eventType = reader.nextTag()) != END_DOCUMENT) { if (eventType == START_TAG) { switch (reader.getName()) { case "proxy": { parseProxy(reader, mavenSettings); break; } } } else { break; } } break; } case "profiles": { while ((eventType = reader.nextTag()) != END_DOCUMENT) { if (eventType == START_TAG) { switch (reader.getName()) { case "profile": { parseProfile(reader, mavenSettings); break; } } } else { break; } } break; } case "activeProfiles": { while ((eventType = reader.nextTag()) != END_DOCUMENT) { if (eventType == START_TAG) { switch (reader.getName()) { case "activeProfile": { mavenSettings.addActiveProfile(reader.nextText()); break; } } } else { break; } } break; } default: { skip(reader); } } break; } default: { throw unexpectedContent(reader); } } } throw endOfDocument(reader); } static void parseProxy(final XmlPullParser reader, MavenSettings mavenSettings) throws XmlPullParserException, IOException { int eventType; Proxy proxy = new Proxy(); while ((eventType = reader.nextTag()) != END_DOCUMENT) { if (eventType == START_TAG) { switch (reader.getName()) { case "id": { proxy.setId(reader.nextText()); break; } case "active": { proxy.setActive(Boolean.parseBoolean(reader.nextText())); break; } case "protocol": { proxy.setProtocol(reader.nextText()); break; } case "host": { proxy.setHost(reader.nextText()); break; } case "port": { proxy.setPort(Integer.parseInt(reader.nextText())); break; } case "username": { proxy.setUsername(reader.nextText()); break; } case "password": { proxy.setPassword(reader.nextText()); break; } case "nonProxyHosts": { proxy.setNonProxyHosts(reader.nextText()); break; } default: { skip(reader); } } } else { break; } } mavenSettings.addProxy(proxy); } static void parseProfile(final XmlPullParser reader, MavenSettings mavenSettings) throws XmlPullParserException, IOException { int eventType; Profile profile = new Profile(); while ((eventType = reader.nextTag()) != END_DOCUMENT) { if (eventType == START_TAG) { switch (reader.getName()) { case "id": { profile.setId(reader.nextText()); break; } case "repositories": { while ((eventType = reader.nextTag()) != END_DOCUMENT) { if (eventType == START_TAG) { switch (reader.getName()) { case "repository": { parseRepository(reader, profile); break; } } } else { break; } } break; } default: { skip(reader); } } } else { break; } } mavenSettings.addProfile(profile); } static void parseRepository(final XmlPullParser reader, Profile profile) throws XmlPullParserException, IOException { int eventType; while ((eventType = reader.nextTag()) != END_DOCUMENT) { if (eventType == START_TAG) { switch (reader.getName()) { case "url": { profile.addRepository(reader.nextText()); break; } default: { skip(reader); } } } else { break; } } } static void skip(XmlPullParser parser) throws XmlPullParserException, IOException { if (parser.getEventType() != XmlPullParser.START_TAG) { throw new IllegalStateException(); } int depth = 1; while (depth != 0) { switch (parser.next()) { case XmlPullParser.END_TAG: depth--; break; case XmlPullParser.START_TAG: depth++; break; } } } void configureDefaults() { //always add maven central remoteRepositories.add("https://repo1.maven.org/maven2/"); String localRepositoryPath = System.getProperty("local.maven.repo.path"); if (localRepositoryPath != null && !localRepositoryPath.trim().isEmpty()) { System.out.println("Please use 'maven.repo.local' instead of 'local.maven.repo.path'"); localRepository = java.nio.file.Paths.get(localRepositoryPath.split(File.pathSeparator)[0]); } localRepositoryPath = System.getProperty("maven.repo.local"); if (localRepositoryPath != null && !localRepositoryPath.trim().isEmpty()) { localRepository = java.nio.file.Paths.get(localRepositoryPath); } String remoteRepository = System.getProperty("remote.maven.repo"); if (remoteRepository != null) { for (String repo : remoteRepository.split(",")) { if (!repo.endsWith("/")) { repo += "/"; } remoteRepositories.add(repo); } } } public void setLocalRepository(Path localRepository) { this.localRepository = localRepository; } public Path getLocalRepository() { return localRepository; } public List getRemoteRepositories() { return remoteRepositories; } public void addProfile(Profile profile) { this.profiles.put(profile.getId(), profile); } public void addActiveProfile(String profileName) { activeProfileNames.add(profileName); } public void addProxy(Proxy proxy) { this.proxies.add(proxy); } public List getProxies() { return this.proxies; } public Proxy getProxyFor(URL url) { for (Proxy proxy : this.proxies) { if (proxy.canProxyFor(url)) { return proxy; } } return null; } /** * Opens a connection with appropriate proxy and credentials, if required. * * @param url The URL to open. * @return The opened connection. * @throws IOException If an error occurs establishing the connection. */ public URLConnection openConnection(URL url) throws IOException { Proxy proxy = getProxyFor(url); URLConnection conn = null; if (proxy != null) { conn = url.openConnection(proxy.getProxy()); proxy.authenticate(conn); } else { conn = url.openConnection(); } return conn; } void resolveActiveSettings() { for (String name : activeProfileNames) { Profile p = profiles.get(name); if (p != null) { remoteRepositories.addAll(p.getRepositories()); } } } static String interpolateVariables(String in) { StringBuilder out = new StringBuilder(); int cur = 0; int startLoc = -1; while ((startLoc = in.indexOf("${", cur)) >= 0) { out.append(in.substring(cur, startLoc)); int endLoc = in.indexOf("}", startLoc); if (endLoc > 0) { String name = in.substring(startLoc + 2, endLoc); String value = null; if (name.startsWith("env.")) { value = System.getenv(name.substring(4)); } else { value = System.getProperty(name); } if (value == null) { value = ""; } out.append(value); } else { out.append(in.substring(startLoc)); cur = in.length(); break; } cur = endLoc + 1; } out.append(in.substring(cur)); return out.toString(); } static final class Proxy { private String id; private boolean active = true; private String protocol = "http"; private String host; private int port; private String username; private String password; private Set nonProxyHosts = new HashSet<>(); private AtomicReference netProxy = new AtomicReference<>(); public String getId() { return id; } public void setId(String id) { this.id = id; } public boolean isActive() { return active; } public void setActive(boolean active) { this.active = active; } public String getProtocol() { return protocol; } public void setProtocol(String protocol) { this.protocol = protocol; } public String getHost() { return host; } public void setHost(String host) { this.host = host; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public void setNonProxyHosts(String nonProxyHosts) { String[] specs = nonProxyHosts.split("\\|"); this.nonProxyHosts.clear(); for (String spec : specs) { this.nonProxyHosts.add(new NonProxyHost(spec)); } } public boolean canProxyFor(URL url) { for (NonProxyHost nonProxyHost : this.nonProxyHosts) { if (nonProxyHost.matches(url)) { return false; } } return true; } public java.net.Proxy getProxy() { return this.netProxy.updateAndGet(proxy -> { if (proxy == null) { proxy = new java.net.Proxy(java.net.Proxy.Type.HTTP, new InetSocketAddress(getHost(), getPort())); } return proxy; }); } public String getCredentialsBase64() { Base64.Encoder encoder = Base64.getEncoder(); return encoder.encodeToString((this.username + ":" + this.password).getBytes()); } public void authenticate(URLConnection conn) { if (this.username == null && this.password == null) { return; } String authz = "Basic " + getCredentialsBase64(); conn.addRequestProperty("Proxy-Authorization", authz); } } static final class NonProxyHost { private final Pattern pattern; NonProxyHost(String spec) { spec = spec.replace(".", "\\."); spec = spec.replace("*", ".*"); spec = "^" + spec + "$"; this.pattern = Pattern.compile(spec); } boolean matches(URL url) { return this.pattern.matcher(url.getHost()).matches(); } } static final class Profile { private String id; final List repositories = new LinkedList<>(); Profile() { } public void setId(String id) { this.id = id; } public String getId() { return id; } public void addRepository(String url) { if (!url.endsWith("/")) { url += "/"; } repositories.add(url); } public List getRepositories() { return repositories; } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/package-info.java000066400000000000000000000021261472011152000265320ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * The primary JBoss Modules API. The key classes in this package are {@link org.jboss.modules.Module Module}, {@link org.jboss.modules.ModuleLoader ModuleLoader}, * {@link org.jboss.modules.ConcurrentClassLoader ConcurrentClassLoader}, and {@link org.jboss.modules.ModuleClassLoader ModuleClassLoader}. These classes make up the backbone of the module * system. */ package org.jboss.modules; jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ref/000077500000000000000000000000001472011152000241165ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ref/PhantomReference.java000066400000000000000000000040041472011152000302040ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.ref; import java.lang.ref.ReferenceQueue; /** * A reapable phantom reference with an attachment. If a {@link Reaper} is given, then it will be used to asynchronously * clean up the referent. * * @param the reference value type * @param the attachment type * * @see java.lang.ref.PhantomReference * * @author David M. Lloyd */ public class PhantomReference extends java.lang.ref.PhantomReference implements Reference, Reapable { private final A attachment; private final Reaper reaper; public PhantomReference(final T referent, final A attachment, final ReferenceQueue q) { super(referent, q); this.attachment = attachment; reaper = null; } public PhantomReference(final T referent, final A attachment, final Reaper reaper) { super(referent, References.ReaperThread.REAPER_QUEUE); this.reaper = reaper; this.attachment = attachment; } public A getAttachment() { return attachment; } public Type getType() { return Type.PHANTOM; } public Reaper getReaper() { return reaper; } public String toString() { return "phantom reference to " + String.valueOf(get()); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ref/Reapable.java000066400000000000000000000021551472011152000264770ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.ref; /** * A reference which is reapable (can be automatically collected). * * @param the reference type * @param the reference attachment type * * @apiviz.exclude * * @author David M. Lloyd */ interface Reapable { /** * Get the associated reaper. * * @return the reaper */ Reaper getReaper(); } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ref/Reaper.java000066400000000000000000000021421472011152000261760ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.ref; /** * A cleaner for a dead object. * * @param the reference type * @param the reference attachment type * * @author David M. Lloyd */ public interface Reaper { /** * Perform the cleanup action for a reference. * * @param reference the reference */ void reap(Reference reference); } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ref/Reference.java000066400000000000000000000035441472011152000266650ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.ref; /** * An enhanced reference type with a type-safe attachment. * * @param the reference value type * @param the attachment type * * @see java.lang.ref.Reference * * @author David M. Lloyd */ public interface Reference { /** * Get the value, or {@code null} if the reference has been cleared. * * @return the value */ T get(); /** * Get the attachment, if any. * * @return the attachment */ A getAttachment(); /** * Clear the reference. */ void clear(); /** * Get the type of the reference. * * @return the type */ Type getType(); /** * A reference type. * * @apiviz.exclude */ enum Type { /** * A strong reference. */ STRONG, /** * A weak reference. */ WEAK, /** * A phantom reference. */ PHANTOM, /** * A soft reference. */ SOFT, /** * A {@code null} reference. */ NULL, } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ref/References.java000066400000000000000000000153561472011152000270540ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.ref; import java.lang.ref.ReferenceQueue; /** * A set of utility methods for reference types. */ public final class References { @SuppressWarnings({ "RawUseOfParameterizedType" }) private static final Reference NULL = new Reference() { public Object get() { return null; } public Object getAttachment() { return null; } public void clear() { } public Type getType() { return Type.NULL; } public String toString() { return "NULL reference"; } }; private References() { } static final class ReaperThread extends Thread { static final ReferenceQueue REAPER_QUEUE = new ReferenceQueue<>(); static { final ReaperThread thr = new ReaperThread(); thr.setName("Reference Reaper"); thr.setDaemon(true); thr.start(); } public void run() { for (;;) try { final java.lang.ref.Reference ref = REAPER_QUEUE.remove(); if (ref instanceof Reapable) { reap((Reapable) ref); } } catch (InterruptedException ignored) { } catch (Throwable ignored) { } } @SuppressWarnings({ "unchecked" }) private static void reap(final Reapable reapable) { reapable.getReaper().reap((Reference) reapable); } } /** * Create a reference of a given type with the provided value and attachment. If the reference type is * {@link Reference.Type#STRONG} or {@link Reference.Type#NULL} then the reaper argument is ignored. If * the reference type is {@link Reference.Type#NULL} then the value and attachment arguments are ignored. * * @param type the reference type * @param value the reference value * @param attachment the attachment value * @param reaper the reaper to use, if any * @param the reference value type * @param the reference attachment type * @return the reference */ public static Reference create(Reference.Type type, T value, A attachment, Reaper reaper) { switch (type) { case STRONG: return new StrongReference<>(value, attachment); case WEAK: return new WeakReference<>(value, attachment, reaper); case PHANTOM: return new PhantomReference<>(value, attachment, reaper); case SOFT: return new SoftReference<>(value, attachment, reaper); case NULL: return getNullReference(); default: throw new IllegalStateException(); } } /** * Create a reference of a given type with the provided value and attachment. If the reference type is * {@link Reference.Type#STRONG} or {@link Reference.Type#NULL} then the reference queue argument is ignored. If * the reference type is {@link Reference.Type#NULL} then the value and attachment arguments are ignored. * * @param type the reference type * @param value the reference value * @param attachment the attachment value * @param referenceQueue the reference queue to use, if any * @param the reference value type * @param the reference attachment type * @return the reference */ public static Reference create(Reference.Type type, T value, A attachment, ReferenceQueue referenceQueue) { switch (type) { case STRONG: return new StrongReference<>(value, attachment); case WEAK: return new WeakReference<>(value, attachment, referenceQueue); case PHANTOM: return new PhantomReference<>(value, attachment, referenceQueue); case SOFT: return new SoftReference<>(value, attachment, referenceQueue); case NULL: return getNullReference(); default: throw new IllegalStateException(); } } /** * Create a reference of a given type with the provided value and attachment. If the reference type is * {@link Reference.Type#PHANTOM} then this method will throw an {@code IllegalArgumentException} because * such references are not constructable without a queue or reaper. If the reference type is * {@link Reference.Type#NULL} then the value and attachment arguments are ignored. * * @param type the reference type * @param value the reference value * @param attachment the attachment value * @param the reference value type * @param the reference attachment type * @return the reference * @throws IllegalArgumentException if the reference type is {@link Reference.Type#PHANTOM} */ public static Reference create(Reference.Type type, T value, A attachment) throws IllegalArgumentException { switch (type) { case STRONG: return new StrongReference<>(value, attachment); case WEAK: return new WeakReference<>(value, attachment); case PHANTOM: throw new IllegalArgumentException("Phantom reference may not be created without a queue or reaper"); case SOFT: return new SoftReference<>(value, attachment); case NULL: return getNullReference(); default: throw new IllegalStateException(); } } /** * Get a null reference. This reference type is always cleared and does not retain an attachment; as such * there is only one single instance of it. * * @param the reference value type * @param the attachment value type * @return the null reference */ @SuppressWarnings({ "unchecked" }) public static Reference getNullReference() { return (Reference) NULL; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ref/SoftReference.java000066400000000000000000000043361472011152000275210ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.ref; import java.lang.ref.ReferenceQueue; /** * A reapable soft reference with an attachment. If a {@link Reaper} is given, then it will be used to asynchronously * clean up the referent. * * @param the reference value type * @param the attachment type * * @see java.lang.ref.SoftReference * * @author David M. Lloyd */ public class SoftReference extends java.lang.ref.SoftReference implements Reference, Reapable { private final A attachment; private final Reaper reaper; public SoftReference(final T referent) { this(referent, null, (ReferenceQueue) null); } public SoftReference(final T referent, final A attachment) { this(referent, attachment, (ReferenceQueue) null); } public SoftReference(final T referent, final A attachment, final ReferenceQueue q) { super(referent, q); reaper = null; this.attachment = attachment; } public SoftReference(final T referent, final A attachment, final Reaper reaper) { super(referent, References.ReaperThread.REAPER_QUEUE); this.reaper = reaper; this.attachment = attachment; } public Reaper getReaper() { return reaper; } public A getAttachment() { return attachment; } public Type getType() { return Type.SOFT; } public String toString() { return "soft reference to " + String.valueOf(get()); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ref/StrongReference.java000066400000000000000000000032321472011152000300540ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.ref; /** * A strong reference with an attachment. Since strong references are always reachable, a reaper may not be used. * * @param the reference value type * @param the attachment type * * @author David M. Lloyd */ public class StrongReference implements Reference { private volatile T value; private final A attachment; public StrongReference(final T value, final A attachment) { this.value = value; this.attachment = attachment; } public StrongReference(final T value) { this(value, null); } public T get() { return value; } public void clear() { value = null; } public A getAttachment() { return attachment; } public Type getType() { return Type.STRONG; } public String toString() { return "strong reference to " + String.valueOf(get()); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ref/WeakReference.java000066400000000000000000000043241472011152000274720ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.ref; import java.lang.ref.ReferenceQueue; /** * A reapable weak reference with an attachment. If a {@link Reaper} is given, then it will be used to asynchronously * clean up the referent. * * @param the reference value type * @param the attachment type * * @see java.lang.ref.WeakReference * * @author David M. Lloyd */ public class WeakReference extends java.lang.ref.WeakReference implements Reference, Reapable { private final A attachment; private final Reaper reaper; public WeakReference(final T referent) { this(referent, null, (Reaper) null); } public WeakReference(final T referent, final A attachment) { this(referent, attachment, (Reaper) null); } public WeakReference(final T referent, final A attachment, final ReferenceQueue q) { super(referent, q); this.attachment = attachment; reaper = null; } public WeakReference(final T referent, final A attachment, final Reaper reaper) { super(referent, References.ReaperThread.REAPER_QUEUE); this.attachment = attachment; this.reaper = reaper; } public A getAttachment() { return attachment; } public Type getType() { return Type.WEAK; } public Reaper getReaper() { return reaper; } public String toString() { return "weak reference to " + String.valueOf(get()); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/ref/package-info.java000066400000000000000000000017451472011152000273140ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Classes which implement reference types which can be cleaned up automatically by a background thread. See * {@link org.jboss.modules.ref.Reference Reference} and its subtypes, and {@link org.jboss.modules.ref.Reaper Reaper} for more information. */ package org.jboss.modules.ref;jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/security/000077500000000000000000000000001472011152000252115ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/security/FactoryPermissionCollection.java000066400000000000000000000054471472011152000335620ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.security; import java.security.Permission; import java.security.PermissionCollection; import java.security.Permissions; import java.util.Enumeration; /** * A permission collection which lazily instantiates the permission objects on first use. Any * unavailable permission objects will not be granted to the resultant collection. * * @author David M. Lloyd */ public final class FactoryPermissionCollection extends PermissionCollection { private static final long serialVersionUID = -2524371701490830970L; private final PermissionFactory[] factories; private volatile Permissions assembled; /** * Construct a new instance. * * @param factories the factories to use to construct the permission collection */ public FactoryPermissionCollection(final PermissionFactory... factories) { this.factories = factories.clone(); setReadOnly(); } public void add(final Permission permission) { throw new SecurityException("Read-only permission collection"); } Permissions getAssembled() { if (assembled == null) { synchronized (this) { if (assembled == null) { final Permissions assembled = new Permissions(); for (PermissionFactory factory : factories) { if (factory != null) { final Permission permission = factory.construct(); if (permission != null) { assembled.add(permission); } } } assembled.setReadOnly(); this.assembled = assembled; } } } return assembled; } public boolean implies(final Permission permission) { return getAssembled().implies(permission); } public Enumeration elements() { return getAssembled().elements(); } Object writeReplace() { return getAssembled(); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/security/ImmediatePermissionFactory.java000066400000000000000000000026501472011152000333560ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.security; import java.security.Permission; /** * A permission factory which simply holds a permission object. * * @author David M. Lloyd */ public final class ImmediatePermissionFactory implements PermissionFactory { private final Permission permission; /** * Construct a new instance. * * @param permission the permission to return */ public ImmediatePermissionFactory(final Permission permission) { if (permission == null) { throw new IllegalArgumentException("permission is null"); } this.permission = permission; } public Permission construct() { return permission; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/security/LoadedPermissionFactory.java000066400000000000000000000053401472011152000326470ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.security; import java.security.Permission; /** * A permission factory which instantiates a permission with the given class name. * * @author David M. Lloyd */ public final class LoadedPermissionFactory implements PermissionFactory { private final ClassLoader classLoader; private final String className; private final String targetName; private final String permissionActions; private volatile Permission instance = UninitializedPermission.INSTANCE; /** * Construct a new instance. * * @param classLoader the class loader from which the permission should be loaded * @param className the name of the permission class * @param targetName the name to pass to the permission class constructor or {@code null} for none * @param permissionActions the action list to pass to the permission class constructor or {@code null} for none */ public LoadedPermissionFactory(final ClassLoader classLoader, final String className, final String targetName, final String permissionActions) { if (className == null) { throw new IllegalArgumentException("className is null"); } this.classLoader = classLoader; this.className = className; this.targetName = targetName; this.permissionActions = permissionActions; } public Permission construct() { if (instance != UninitializedPermission.INSTANCE) { return instance; } synchronized (this) { if (instance != UninitializedPermission.INSTANCE) { return instance; } try { final Class permissionClass = classLoader.loadClass(className).asSubclass(Permission.class); return instance = PermissionFactory.constructFromClass(permissionClass, targetName, permissionActions); } catch (Throwable t) { instance = null; return null; } } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/security/ModularPermissionFactory.java000066400000000000000000000110271472011152000330610ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.security; import java.security.Permission; import org.jboss.modules.Module; import org.jboss.modules.ModuleIdentifier; import org.jboss.modules.ModuleLoader; import org.jboss.modules._private.ModulesPrivateAccess; /** * A permission factory which instantiates a permission from a module. * * @author David M. Lloyd */ public final class ModularPermissionFactory implements PermissionFactory { private final ModuleLoader moduleLoader; private final String moduleName; private final String className; private final String targetName; private final String permissionActions; private volatile Permission instance = UninitializedPermission.INSTANCE; private static final ModulesPrivateAccess access = Module.getPrivateAccess(); /** * Construct a new instance. * * @param moduleLoader the module loader from which the module is to be loaded * @param moduleIdentifier the module identifier from which the permission is to be loaded * @param className the name of the permission class * @param targetName the name to pass to the permission class constructor or {@code null} for none * @param permissionActions the action list to pass to the permission class constructor or {@code null} for none * @deprecated Use {@link #ModularPermissionFactory(ModuleLoader, String, String, String, String)} instead. */ @Deprecated(forRemoval = true) public ModularPermissionFactory(final ModuleLoader moduleLoader, final ModuleIdentifier moduleIdentifier, final String className, final String targetName, final String permissionActions) { this(moduleLoader, moduleIdentifier.toString(), className, targetName, permissionActions); } /** * Construct a new instance. * * @param moduleLoader the module loader from which the module is to be loaded * @param moduleName the module name from which the permission is to be loaded * @param className the name of the permission class * @param targetName the name to pass to the permission class constructor or {@code null} for none * @param permissionActions the action list to pass to the permission class constructor or {@code null} for none */ public ModularPermissionFactory(final ModuleLoader moduleLoader, final String moduleName, final String className, final String targetName, final String permissionActions) { if (moduleLoader == null) { throw new IllegalArgumentException("moduleLoader is null"); } if (moduleName == null) { throw new IllegalArgumentException("moduleName is null"); } if (className == null) { throw new IllegalArgumentException("className is null"); } this.moduleLoader = moduleLoader; this.moduleName = moduleName; this.className = className; this.targetName = targetName; this.permissionActions = permissionActions; } public Permission construct() { if (instance != UninitializedPermission.INSTANCE) { return instance; } synchronized (this) { if (instance != UninitializedPermission.INSTANCE) { return instance; } try { final Module module = moduleLoader.loadModule(moduleName); final Class permissionClass = access.getClassLoaderOf(module).loadClass(className, true).asSubclass(Permission.class); return instance = PermissionFactory.constructFromClass(permissionClass, targetName, permissionActions); } catch (Throwable t) { Module.getModuleLogger().trace(t, "Failed to construct permission instance: %s in %s", className, moduleName); instance = null; return null; } } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/security/ModularProtectionDomain.java000066400000000000000000000067541472011152000326720ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2016 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.security; import java.security.CodeSource; import java.security.Permission; import java.security.PermissionCollection; import java.security.ProtectionDomain; import org.jboss.modules.ModuleClassLoader; /** * A protection domain which has a (modular) class loader but whose dynamicity is selectable. * * @author David M. Lloyd */ public class ModularProtectionDomain extends ProtectionDomain { private final boolean dynamic; /** * Construct a new instance. The {@code dynamic} parameter determines whether the policy is consulted for permission * checks; if {@code false}, then only the specified permission collection is consulted. * * @param codeSource the code source of the protection domain (must not be {@code null}) * @param permissions the permission collection (must not be {@code null}) * @param moduleClassLoader the module class loader (must not be {@code null}) * @param dynamic {@code true} if the protection domain should be dynamic, {@code false} otherwise */ public ModularProtectionDomain(final CodeSource codeSource, final PermissionCollection permissions, final ModuleClassLoader moduleClassLoader, boolean dynamic) { super(codeSource, permissions, moduleClassLoader, null); this.dynamic = dynamic; } /** * Construct a new, static instance. Only the specified permission collection is consulted for permission checks. * * @param codeSource the code source of the protection domain (must not be {@code null}) * @param permissions the permission collection (must not be {@code null}) * @param moduleClassLoader the module class loader (must not be {@code null}) */ public ModularProtectionDomain(final CodeSource codeSource, final PermissionCollection permissions, final ModuleClassLoader moduleClassLoader) { this(codeSource, permissions, moduleClassLoader, false); } /** * Determine if the permission collection of this protection domain implies the given permission. This is * just a shortcut for calling {@code getPermissions().implies(permission)}. * * @param permission the permission to check (must not be {@code null}) * @return {@code true} if the permission is implied, {@code false} otherwise. */ public boolean implies(final Permission permission) { return dynamic ? super.implies(permission) : getPermissions().implies(permission); } /** * Get a string representation of this protection domain. * * @return the string representation (not {@code null}) */ public String toString() { return String.format("ProtectionDomain (%s) %s%n%s%n%s", dynamic ? "dynamic" : "static", getCodeSource(), getClassLoader(), getPermissions()); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/security/PermissionFactory.java000066400000000000000000000075741472011152000315510ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.security; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.security.Permission; /** * A factory for {@link Permission} objects. * * @author David M. Lloyd */ public interface PermissionFactory { /** * Construct a new instance of the permission. The instance may be cached. * * @return the permission */ Permission construct(); /** * Utility method to reflectively construct a permission from a given class. * * @param permissionClass the permission class * @param targetName the optional target name * @param permissionActions the optional actions name * @return the permission * @throws IllegalAccessException if the necessary constructor is not accessible * @throws InvocationTargetException if the constructor failed * @throws InstantiationException if the object could not be instantiated for some reason * @throws NoSuchMethodException if none of the candidate constructors exist on the class */ static Permission constructFromClass(Class permissionClass, String targetName, String permissionActions) throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException { final Constructor constructor; boolean hasTarget = targetName != null && ! targetName.isEmpty(); boolean hasAction = permissionActions != null && ! permissionActions.isEmpty(); if (hasTarget && hasAction) { Constructor test; try { test = permissionClass.getConstructor(String.class, String.class); } catch (NoSuchMethodException ignored) { try { test = permissionClass.getConstructor(String.class); hasAction = false; } catch (NoSuchMethodException ignored2) { test = permissionClass.getConstructor(); hasTarget = false; hasAction = false; } } constructor = test; } else if (hasTarget) { assert ! hasAction; Constructor test; try { test = permissionClass.getConstructor(String.class); } catch (NoSuchMethodException ignored) { try { test = permissionClass.getConstructor(String.class, String.class); hasAction = true; } catch (NoSuchMethodException ignored2) { test = permissionClass.getConstructor(); hasTarget = false; hasAction = false; } } constructor = test; } else { constructor = permissionClass.getConstructor(); } if (hasTarget && hasAction) { return constructor.newInstance(targetName, permissionActions); } else if (hasTarget) { return constructor.newInstance(targetName); } else { return constructor.newInstance(); } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/security/UninitializedPermission.java000066400000000000000000000024711472011152000327410ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.security; import java.security.Permission; final class UninitializedPermission extends Permission { private static final long serialVersionUID = 468335190774708422L; static final UninitializedPermission INSTANCE = new UninitializedPermission(); private UninitializedPermission() { super(null); } public boolean implies(final Permission permission) { return false; } public boolean equals(final Object obj) { return false; } public int hashCode() { return 0; } public String getActions() { return null; } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/version.properties000066400000000000000000000013531472011152000271470ustar00rootroot00000000000000# # JBoss, Home of Professional Open Source. # Copyright 2016 Red Hat, Inc., and individual contributors # as indicated by the @author tags. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # version=${project.version} jarName=${project.artifactId} jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/xml/000077500000000000000000000000001472011152000241425ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/xml/MXParser.java000066400000000000000000003442121472011152000265140ustar00rootroot00000000000000/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/ /* * Copyright (c) 2003 Extreme! Lab, Indiana University. All rights reserved. * * This software is open source. See the bottom of this file for the license. * * $Id: MXParser.java,v 1.52 2006/11/09 18:29:37 aslom Exp $ */ package org.jboss.modules.xml; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; //TODO best handling of interning issues // have isAllNewStringInterned ??? //TODO handling surrogate pairs: http://www.unicode.org/unicode/faq/utf_bom.html#6 //TODO review code for use of bufAbsoluteStart when keeping pos between next()/fillBuf() /** * Absolutely minimal implementation of XMLPULL V1 API * * @author Aleksander Slominski */ public class MXParser implements XmlPullParser { //NOTE: no interning of those strings --> by Java lang spec they MUST be already interned protected final static String XML_URI = "http://www.w3.org/XML/1998/namespace"; protected final static String XMLNS_URI = "http://www.w3.org/2000/xmlns/"; protected final static String FEATURE_XML_ROUNDTRIP= "http://xmlpull.org/v1/doc/features.html#xml-roundtrip"; protected final static String FEATURE_NAMES_INTERNED = "http://xmlpull.org/v1/doc/features.html#names-interned"; protected final static String PROPERTY_XMLDECL_VERSION = "http://xmlpull.org/v1/doc/properties.html#xmldecl-version"; protected final static String PROPERTY_XMLDECL_STANDALONE = "http://xmlpull.org/v1/doc/properties.html#xmldecl-standalone"; protected final static String PROPERTY_XMLDECL_CONTENT = "http://xmlpull.org/v1/doc/properties.html#xmldecl-content"; protected final static String PROPERTY_LOCATION = "http://xmlpull.org/v1/doc/properties.html#location"; /** * Implementation notice: * the is instance variable that controls if newString() is interning. *

NOTE: newStringIntern always returns interned strings * and newString MAY return interned String depending on this variable. *

NOTE: by default in this minimal implementation it is false! */ protected boolean allStringsInterned; protected void resetStringCache() { } protected String newString(char[] cbuf, int off, int len) { return new String(cbuf, off, len); } protected String newStringIntern(char[] cbuf, int off, int len) { return (new String(cbuf, off, len)).intern(); } private static final boolean TRACE_SIZING = false; // NOTE: features are not resettable and typically defaults to false ... protected boolean processNamespaces; protected boolean roundtripSupported; // global parser state protected String location; protected int lineNumber; protected int columnNumber; protected boolean seenRoot; protected boolean reachedEnd; protected int eventType; protected boolean emptyElementTag; // element stack protected int depth; protected char[] elRawName[]; protected int elRawNameEnd[]; protected int elRawNameLine[]; protected String elName[]; protected String elPrefix[]; protected String elUri[]; protected int elNamespaceCount[]; /** * Make sure that we have enough space to keep element stack if passed size. * It will always create one additional slot then current depth */ protected void ensureElementsCapacity() { final int elStackSize = elName != null ? elName.length : 0; if( (depth + 1) >= elStackSize) { // we add at least one extra slot ... final int newSize = (depth >= 7 ? 2 * depth : 8) + 2; // = lucky 7 + 1 //25 if(TRACE_SIZING) { System.err.println("TRACE_SIZING elStackSize "+elStackSize+" ==> "+newSize); } final boolean needsCopying = elStackSize > 0; String[] arr = null; // reuse arr local variable slot arr = new String[newSize]; if(needsCopying) System.arraycopy(elName, 0, arr, 0, elStackSize); elName = arr; arr = new String[newSize]; if(needsCopying) System.arraycopy(elPrefix, 0, arr, 0, elStackSize); elPrefix = arr; arr = new String[newSize]; if(needsCopying) System.arraycopy(elUri, 0, arr, 0, elStackSize); elUri = arr; int[] iarr = new int[newSize]; if(needsCopying) { System.arraycopy(elNamespaceCount, 0, iarr, 0, elStackSize); } else { // special initialization iarr[0] = 0; } elNamespaceCount = iarr; //TODO: avoid using element raw name ... iarr = new int[newSize]; if(needsCopying) { System.arraycopy(elRawNameEnd, 0, iarr, 0, elStackSize); } elRawNameEnd = iarr; iarr = new int[newSize]; if(needsCopying) { System.arraycopy(elRawNameLine, 0, iarr, 0, elStackSize); } elRawNameLine = iarr; final char[][] carr = new char[newSize][]; if(needsCopying) { System.arraycopy(elRawName, 0, carr, 0, elStackSize); } elRawName = carr; } } // attribute stack protected int attributeCount; protected String attributeName[]; protected int attributeNameHash[]; protected String attributePrefix[]; protected String attributeUri[]; protected String attributeValue[]; /** * Make sure that in attributes temporary array is enough space. */ protected void ensureAttributesCapacity(int size) { final int attrPosSize = attributeName != null ? attributeName.length : 0; if(size >= attrPosSize) { final int newSize = size > 7 ? 2 * size : 8; // = lucky 7 + 1 //25 if(TRACE_SIZING) { System.err.println("TRACE_SIZING attrPosSize "+attrPosSize+" ==> "+newSize); } final boolean needsCopying = attrPosSize > 0; String[] arr = null; arr = new String[newSize]; if(needsCopying) System.arraycopy(attributeName, 0, arr, 0, attrPosSize); attributeName = arr; arr = new String[newSize]; if(needsCopying) System.arraycopy(attributePrefix, 0, arr, 0, attrPosSize); attributePrefix = arr; arr = new String[newSize]; if(needsCopying) System.arraycopy(attributeUri, 0, arr, 0, attrPosSize); attributeUri = arr; arr = new String[newSize]; if(needsCopying) System.arraycopy(attributeValue, 0, arr, 0, attrPosSize); attributeValue = arr; if( ! allStringsInterned ) { final int[] iarr = new int[newSize]; if(needsCopying) System.arraycopy(attributeNameHash, 0, iarr, 0, attrPosSize); attributeNameHash = iarr; } } } // namespace stack protected int namespaceEnd; protected String namespacePrefix[]; protected int namespacePrefixHash[]; protected String namespaceUri[]; protected void ensureNamespacesCapacity(int size) { final int namespaceSize = namespacePrefix != null ? namespacePrefix.length : 0; if(size >= namespaceSize) { final int newSize = size > 7 ? 2 * size : 8; // = lucky 7 + 1 //25 if(TRACE_SIZING) { System.err.println("TRACE_SIZING namespaceSize "+namespaceSize+" ==> "+newSize); } final String[] newNamespacePrefix = new String[newSize]; final String[] newNamespaceUri = new String[newSize]; if(namespacePrefix != null) { System.arraycopy( namespacePrefix, 0, newNamespacePrefix, 0, namespaceEnd); System.arraycopy( namespaceUri, 0, newNamespaceUri, 0, namespaceEnd); } namespacePrefix = newNamespacePrefix; namespaceUri = newNamespaceUri; if( ! allStringsInterned ) { final int[] newNamespacePrefixHash = new int[newSize]; if(namespacePrefixHash != null) { System.arraycopy( namespacePrefixHash, 0, newNamespacePrefixHash, 0, namespaceEnd); } namespacePrefixHash = newNamespacePrefixHash; } } } /** * simplistic implementation of hash function that has constant * time to compute - so it also means diminishing hash quality for long strings * but for XML parsing it should be good enough ... */ protected static final int fastHash( char ch[], int off, int len ) { if(len == 0) return 0; int hash = ch[off]; // hash at beginning hash = (hash << 7) + ch[ off + len - 1 ]; // hash at the end if(len > 16) hash = (hash << 7) + ch[ off + (len / 4)]; // 1/4 from beginning if(len > 8) hash = (hash << 7) + ch[ off + (len / 2)]; // 1/2 of string size ... // notice that hash is at most done 3 times <<7 so shifted by 21 bits 8 bit value // so max result == 29 bits so it is quite just below 31 bits for long (2^32) ... return hash; } // entity replacement stack protected int entityEnd; protected String entityName[]; protected char[] entityNameBuf[]; protected String entityReplacement[]; protected char[] entityReplacementBuf[]; protected int entityNameHash[]; protected void ensureEntityCapacity() { final int entitySize = entityReplacementBuf != null ? entityReplacementBuf.length : 0; if(entityEnd >= entitySize) { final int newSize = entityEnd > 7 ? 2 * entityEnd : 8; // = lucky 7 + 1 //25 if(TRACE_SIZING) { System.err.println("TRACE_SIZING entitySize "+entitySize+" ==> "+newSize); } final String[] newEntityName = new String[newSize]; final char[] newEntityNameBuf[] = new char[newSize][]; final String[] newEntityReplacement = new String[newSize]; final char[] newEntityReplacementBuf[] = new char[newSize][]; if(entityName != null) { System.arraycopy(entityName, 0, newEntityName, 0, entityEnd); System.arraycopy(entityNameBuf, 0, newEntityNameBuf, 0, entityEnd); System.arraycopy(entityReplacement, 0, newEntityReplacement, 0, entityEnd); System.arraycopy(entityReplacementBuf, 0, newEntityReplacementBuf, 0, entityEnd); } entityName = newEntityName; entityNameBuf = newEntityNameBuf; entityReplacement = newEntityReplacement; entityReplacementBuf = newEntityReplacementBuf; if( ! allStringsInterned ) { final int[] newEntityNameHash = new int[newSize]; if(entityNameHash != null) { System.arraycopy(entityNameHash, 0, newEntityNameHash, 0, entityEnd); } entityNameHash = newEntityNameHash; } } } // input buffer management protected static final int READ_CHUNK_SIZE = 8*1024; //max data chars in one read() call protected Reader reader; protected String inputEncoding; protected InputStream inputStream; protected int bufLoadFactor = 95; // 99% //protected int bufHardLimit; // only matters when expanding protected char buf[] = new char[ Runtime.getRuntime().freeMemory() > 1000000L ? READ_CHUNK_SIZE : 256 ]; protected int bufSoftLimit = ( bufLoadFactor * buf.length ) /100; // desirable size of buffer protected boolean preventBufferCompaction; protected int bufAbsoluteStart; // this is buf protected int bufStart; protected int bufEnd; protected int pos; protected int posStart; protected int posEnd; protected char pc[] = new char[ Runtime.getRuntime().freeMemory() > 1000000L ? READ_CHUNK_SIZE : 64 ]; protected int pcStart; protected int pcEnd; // parsing state protected boolean usePC; protected boolean seenStartTag; protected boolean seenEndTag; protected boolean pastEndTag; protected boolean seenAmpersand; protected boolean seenMarkup; protected boolean seenDocdecl; // transient variable set during each call to next/Token() protected boolean tokenize; protected String text; protected String entityRefName; protected String xmlDeclVersion; protected Boolean xmlDeclStandalone; protected String xmlDeclContent; protected void reset() { location = null; lineNumber = 1; columnNumber = 0; seenRoot = false; reachedEnd = false; eventType = START_DOCUMENT; emptyElementTag = false; depth = 0; attributeCount = 0; namespaceEnd = 0; entityEnd = 0; reader = null; inputEncoding = null; preventBufferCompaction = false; bufAbsoluteStart = 0; bufEnd = bufStart = 0; pos = posStart = posEnd = 0; pcEnd = pcStart = 0; usePC = false; seenStartTag = false; seenEndTag = false; pastEndTag = false; seenAmpersand = false; seenMarkup = false; seenDocdecl = false; xmlDeclVersion = null; xmlDeclStandalone = null; xmlDeclContent = null; resetStringCache(); } public MXParser() { } /** * Method setFeature * * @param name a String * @param state a boolean * * @throws XmlPullParserException * */ public void setFeature(String name, boolean state) throws XmlPullParserException { if(name == null) throw new IllegalArgumentException("feature name should not be null"); if(FEATURE_PROCESS_NAMESPACES.equals(name)) { if(eventType != START_DOCUMENT) throw new XmlPullParserException( "namespace processing feature can only be changed before parsing", this, null); processNamespaces = state; } else if(FEATURE_NAMES_INTERNED.equals(name)) { if(state != false) { throw new XmlPullParserException( "interning names in this implementation is not supported"); } } else if(FEATURE_PROCESS_DOCDECL.equals(name)) { if(state != false) { throw new XmlPullParserException( "processing DOCDECL is not supported"); } } else if(FEATURE_XML_ROUNDTRIP.equals(name)) { roundtripSupported = state; } else { throw new XmlPullParserException("unsupported feature "+name); } } /** Unknown properties are always returned as false */ public boolean getFeature(String name) { if(name == null) throw new IllegalArgumentException("feature name should not be null"); if(FEATURE_PROCESS_NAMESPACES.equals(name)) { return processNamespaces; } else if(FEATURE_NAMES_INTERNED.equals(name)) { return false; } else if(FEATURE_PROCESS_DOCDECL.equals(name)) { return false; } else if(FEATURE_XML_ROUNDTRIP.equals(name)) { return roundtripSupported; } return false; } public void setProperty(String name, Object value) throws XmlPullParserException { if(PROPERTY_LOCATION.equals(name)) { location = (String) value; } else { throw new XmlPullParserException("unsupported property: '"+name+"'"); } } public Object getProperty(String name) { if(name == null) throw new IllegalArgumentException("property name should not be null"); if(PROPERTY_XMLDECL_VERSION.equals(name)) { return xmlDeclVersion; } else if(PROPERTY_XMLDECL_STANDALONE.equals(name)) { return xmlDeclStandalone; } else if(PROPERTY_XMLDECL_CONTENT.equals(name)) { return xmlDeclContent; } else if(PROPERTY_LOCATION.equals(name)) { return location; } return null; } public void setInput(Reader in) throws XmlPullParserException { reset(); reader = in; } public void setInput(InputStream inputStream, String inputEncoding) throws XmlPullParserException { if(inputStream == null) { throw new IllegalArgumentException("input stream can not be null"); } this.inputStream = inputStream; Reader reader; try { if(inputEncoding != null) { reader = new InputStreamReader(inputStream, inputEncoding); } else { //by default use UTF-8 (InputStreamReader(inputStream)) would use OS default ... reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); } } catch (UnsupportedEncodingException une) { throw new XmlPullParserException( "could not create reader for encoding "+inputEncoding+" : "+une, this, une); } setInput(reader); //must be here as reest() was called in setInput() and has set this.inputEncoding to null ... this.inputEncoding = inputEncoding; } public String getInputEncoding() { return inputEncoding; } public void defineEntityReplacementText(String entityName, String replacementText) throws XmlPullParserException { ensureEntityCapacity(); // this is to make sure that if interning works we will take advantage of it ... this.entityName[entityEnd] = newString(entityName.toCharArray(), 0, entityName.length()); entityNameBuf[entityEnd] = entityName.toCharArray(); entityReplacement[entityEnd] = replacementText; entityReplacementBuf[entityEnd] = replacementText.toCharArray(); if(!allStringsInterned) { entityNameHash[ entityEnd ] = fastHash(entityNameBuf[entityEnd], 0, entityNameBuf[entityEnd].length); } ++entityEnd; //TODO disallow < or & in entity replacement text (or ]]>???) // TOOD keepEntityNormalizedForAttributeValue cached as well ... } public int getNamespaceCount(int depth) throws XmlPullParserException { if(processNamespaces == false || depth == 0) { return 0; } if(depth < 0 || depth > this.depth) throw new IllegalArgumentException( "allowed namespace depth 0.."+this.depth+" not "+depth); return elNamespaceCount[ depth ]; } public String getNamespacePrefix(int pos) throws XmlPullParserException { if(pos < namespaceEnd) { return namespacePrefix[ pos ]; } else { throw new XmlPullParserException( "position "+pos+" exceeded number of available namespaces "+namespaceEnd); } } public String getNamespaceUri(int pos) throws XmlPullParserException { if(pos < namespaceEnd) { return namespaceUri[ pos ]; } else { throw new XmlPullParserException( "position "+pos+" exceeded number of available namespaces "+namespaceEnd); } } public String getNamespace( String prefix ) { if(prefix != null) { for( int i = namespaceEnd -1; i >= 0; i--) { if( prefix.equals( namespacePrefix[ i ] ) ) { return namespaceUri[ i ]; } } if("xml".equals( prefix )) { return XML_URI; } else if("xmlns".equals( prefix )) { return XMLNS_URI; } } else { for( int i = namespaceEnd -1; i >= 0; i--) { if( namespacePrefix[ i ] == null) { //"") { //null ) { //TODO check FIXME Alek return namespaceUri[ i ]; } } } return null; } public int getDepth() { return depth; } private static int findFragment(int bufMinPos, char[] b, int start, int end) { if(start < bufMinPos) { start = bufMinPos; if(start > end) start = end; return start; } if(end - start > 65) { start = end - 10; // try to find good location } int i = start + 1; while(--i > bufMinPos) { if((end - i) > 65) break; final char c = b[i]; if(c == '<' && (start - i) > 10) break; } return i; } /** * Return string describing current position of parsers as * text 'STATE [seen %s...] @line:column'. */ public String getPositionDescription () { String fragment = null; if(posStart <= pos) { final int start = findFragment(0, buf, posStart, pos); if(start < pos) { fragment = new String(buf, start, pos - start); } if(bufAbsoluteStart > 0 || start > 0) fragment = "..." + fragment; } return " "+TYPES[ eventType ] + (fragment != null ? " seen "+printable(fragment)+"..." : "") +" "+(location != null ? location : "") +"@"+getLineNumber()+":"+getColumnNumber(); } public int getLineNumber() { return lineNumber; } public int getColumnNumber() { return columnNumber; } public boolean isWhitespace() throws XmlPullParserException { if(eventType == TEXT || eventType == CDSECT) { if(usePC) { for (int i = pcStart; i = attributeCount) throw new IndexOutOfBoundsException( "attribute position must be 0.."+(attributeCount-1)+" and not "+index); return attributeUri[ index ]; } public String getAttributeName(int index) { if(eventType != START_TAG) throw new IndexOutOfBoundsException( "only START_TAG can have attributes"); if(index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException( "attribute position must be 0.."+(attributeCount-1)+" and not "+index); return attributeName[ index ]; } public String getAttributePrefix(int index) { if(eventType != START_TAG) throw new IndexOutOfBoundsException( "only START_TAG can have attributes"); if(processNamespaces == false) return null; if(index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException( "attribute position must be 0.."+(attributeCount-1)+" and not "+index); return attributePrefix[ index ]; } public String getAttributeType(int index) { if(eventType != START_TAG) throw new IndexOutOfBoundsException( "only START_TAG can have attributes"); if(index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException( "attribute position must be 0.."+(attributeCount-1)+" and not "+index); return "CDATA"; } public boolean isAttributeDefault(int index) { if(eventType != START_TAG) throw new IndexOutOfBoundsException( "only START_TAG can have attributes"); if(index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException( "attribute position must be 0.."+(attributeCount-1)+" and not "+index); return false; } public String getAttributeValue(int index) { if(eventType != START_TAG) throw new IndexOutOfBoundsException( "only START_TAG can have attributes"); if(index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException( "attribute position must be 0.."+(attributeCount-1)+" and not "+index); return attributeValue[ index ]; } public String getAttributeValue(String namespace, String name) { if(eventType != START_TAG) throw new IndexOutOfBoundsException( "only START_TAG can have attributes"+getPositionDescription()); if(name == null) { throw new IllegalArgumentException("attribute name can not be null"); } // TODO make check if namespace is interned!!! etc. for names!!! if(processNamespaces) { if(namespace == null) { namespace = ""; } for(int i = 0; i < attributeCount; ++i) { if((namespace == attributeUri[ i ] || namespace.equals(attributeUri[ i ]) ) //(namespace != null && namespace.equals(attributeUri[ i ])) // taking advantage of String.intern() && name.equals(attributeName[ i ]) ) { return attributeValue[i]; } } } else { if(namespace != null && namespace.length() == 0) { namespace = null; } if(namespace != null) throw new IllegalArgumentException( "when namespaces processing is disabled attribute namespace must be null"); for(int i = 0; i < attributeCount; ++i) { if(name.equals(attributeName[i])) { return attributeValue[i]; } } } return null; } public int getEventType() { return eventType; } public void require(int type, String namespace, String name) throws XmlPullParserException, IOException { if(processNamespaces == false && namespace != null) { throw new XmlPullParserException( "processing namespaces must be enabled on parser (or factory)"+ " to have possible namespaces declared on elements" +(" (position:"+ getPositionDescription())+")"); } if (type != getEventType() || (namespace != null && !namespace.equals (getNamespace())) || (name != null && !name.equals (getName ())) ) { throw new XmlPullParserException ( "expected event "+TYPES[ type ] +(name != null ? " with name '"+name+"'" : "") +(namespace != null && name != null ? " and" : "") +(namespace != null ? " with namespace '"+namespace+"'" : "") +" but got" +(type != getEventType() ? " "+TYPES[ getEventType() ] : "") +(name != null && getName() != null && !name.equals (getName ()) ? " name '"+getName()+"'" : "") +(namespace != null && name != null && getName() != null && !name.equals (getName ()) && getNamespace() != null && !namespace.equals (getNamespace()) ? " and" : "") +(namespace != null && getNamespace() != null && !namespace.equals (getNamespace()) ? " namespace '"+getNamespace()+"'" : "") +(" (position:"+ getPositionDescription())+")"); } } /** * Skip sub tree that is currently parser positioned on. *
NOTE: parser must be on START_TAG and when function returns * parser will be positioned on corresponding END_TAG */ public void skipSubTree() throws XmlPullParserException, IOException { require(START_TAG, null, null); int level = 1; while(level > 0) { int eventType = next(); if(eventType == END_TAG) { --level; } else if(eventType == START_TAG) { ++level; } } } public String nextText() throws XmlPullParserException, IOException { if(getEventType() != START_TAG) { throw new XmlPullParserException( "parser must be on START_TAG to read next text", this, null); } int eventType = next(); if(eventType == TEXT) { final String result = getText(); eventType = next(); if(eventType != END_TAG) { throw new XmlPullParserException( "TEXT must be immediately followed by END_TAG and not " +TYPES[ getEventType() ], this, null); } return result; } else if(eventType == END_TAG) { return ""; } else { throw new XmlPullParserException( "parser must be on START_TAG or TEXT to read text", this, null); } } public int nextTag() throws XmlPullParserException, IOException { next(); if(eventType == TEXT && isWhitespace()) { // skip whitespace next(); } if (eventType != START_TAG && eventType != END_TAG) { throw new XmlPullParserException("expected START_TAG or END_TAG not " +TYPES[ getEventType() ], this, null); } return eventType; } public int next() throws XmlPullParserException, IOException { tokenize = false; return nextImpl(); } public int nextToken() throws XmlPullParserException, IOException { tokenize = true; return nextImpl(); } protected int nextImpl() throws XmlPullParserException, IOException { text = null; pcEnd = pcStart = 0; usePC = false; bufStart = posEnd; if(pastEndTag) { pastEndTag = false; --depth; namespaceEnd = elNamespaceCount[ depth ]; // less namespaces available } if(emptyElementTag) { emptyElementTag = false; pastEndTag = true; return eventType = END_TAG; } // [1] document ::= prolog element Misc* if(depth > 0) { if(seenStartTag) { seenStartTag = false; return eventType = parseStartTag(); } if(seenEndTag) { seenEndTag = false; return eventType = parseEndTag(); } // ASSUMPTION: we are _on_ first character of content or markup!!!! // [43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)* char ch; if(seenMarkup) { // we have read ahead ... seenMarkup = false; ch = '<'; } else if(seenAmpersand) { seenAmpersand = false; ch = '&'; } else { ch = more(); } posStart = pos - 1; // VERY IMPORTANT: this is correct start of event!!! // when true there is some potential event TEXT to return - keep gathering boolean hadCharData = false; // when true TEXT data is not continual (like ) and requires PC merging boolean needsMerging = false; MAIN_LOOP: while(true) { // work on MARKUP if(ch == '<') { if(hadCharData) { //posEnd = pos - 1; if(tokenize) { seenMarkup = true; return eventType = TEXT; } } ch = more(); if(ch == '/') { if(!tokenize && hadCharData) { seenEndTag = true; return eventType = TEXT; } return eventType = parseEndTag(); } else if(ch == '!') { ch = more(); if(ch == '-') { // note: if(tokenize == false) posStart/End is NOT changed!!!! parseComment(); if(tokenize) return eventType = COMMENT; if( !usePC && hadCharData ) { needsMerging = true; } else { posStart = pos; //completely ignore comment } } else if(ch == '[') { parseCDSect(hadCharData); if(tokenize) return eventType = CDSECT; final int cdStart = posStart; final int cdEnd = posEnd; final int cdLen = cdEnd - cdStart; if(cdLen > 0) { // was there anything inside CDATA section? hadCharData = true; if(!usePC) { needsMerging = true; } } } else { throw new XmlPullParserException( "unexpected character in markup "+printable(ch), this, null); } } else if(ch == '?') { parsePI(); if(tokenize) return eventType = PROCESSING_INSTRUCTION; if( !usePC && hadCharData ) { needsMerging = true; } else { posStart = pos; //completely ignore PI } } else if( isNameStartChar(ch) ) { if(!tokenize && hadCharData) { seenStartTag = true; //posEnd = pos - 2; return eventType = TEXT; } return eventType = parseStartTag(); } else { throw new XmlPullParserException( "unexpected character in markup "+printable(ch), this, null); } // do content compaction if it makes sense!!!! } else if(ch == '&') { // work on ENTITTY //posEnd = pos - 1; if(tokenize && hadCharData) { seenAmpersand = true; return eventType = TEXT; } final int oldStart = posStart + bufAbsoluteStart; final int oldEnd = posEnd + bufAbsoluteStart; final char[] resolvedEntity = parseEntityRef(); if(tokenize) return eventType = ENTITY_REF; // check if replacement text can be resolved !!! if(resolvedEntity == null) { if(entityRefName == null) { entityRefName = newString(buf, posStart, posEnd - posStart); } throw new XmlPullParserException( "could not resolve entity named '"+printable(entityRefName)+"'", this, null); } posStart = oldStart - bufAbsoluteStart; posEnd = oldEnd - bufAbsoluteStart; if(!usePC) { if(hadCharData) { joinPC(); // posEnd is already set correctly!!! needsMerging = false; } else { usePC = true; pcStart = pcEnd = 0; } } // write into PC replacement text - do merge for replacement text!!!! for (int i = 0; i < resolvedEntity.length; i++) { if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = resolvedEntity[ i ]; } hadCharData = true; } else { if(needsMerging) { joinPC(); // posEnd is already set correctly!!! needsMerging = false; } //no MARKUP not ENTITIES so work on character data ... // [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*) hadCharData = true; boolean normalizedCR = false; final boolean normalizeInput = tokenize == false || roundtripSupported == false; // use loop locality here!!!! boolean seenBracket = false; boolean seenBracketBracket = false; do { // check that ]]> does not show in if(ch == ']') { if(seenBracket) { seenBracketBracket = true; } else { seenBracket = true; } } else if(seenBracketBracket && ch == '>') { throw new XmlPullParserException( "characters ]]> are not allowed in content", this, null); } else { if(seenBracket) { seenBracketBracket = seenBracket = false; } } if(normalizeInput) { // deal with normalization issues ... if(ch == '\r') { normalizedCR = true; posEnd = pos -1; // posEnd is already is set if(!usePC) { if(posEnd > posStart) { joinPC(); } else { usePC = true; pcStart = pcEnd = 0; } } if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = '\n'; } else if(ch == '\n') { if(!normalizedCR && usePC) { if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = '\n'; } normalizedCR = false; } else { if(usePC) { if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = ch; } normalizedCR = false; } } ch = more(); } while(ch != '<' && ch != '&'); posEnd = pos - 1; continue MAIN_LOOP; // skip ch = more() from below - we are alreayd ahead ... } ch = more(); } // endless while(true) } else { if(seenRoot) { return parseEpilog(); } else { return parseProlog(); } } } protected int parseProlog() throws XmlPullParserException, IOException { // [2] prolog: ::= XMLDecl? Misc* (doctypedecl Misc*)? and look for [39] element char ch; if(seenMarkup) { ch = buf[ pos - 1 ]; } else { ch = more(); } if(eventType == START_DOCUMENT) { // bootstrap parsing with getting first character input! // deal with BOM // detect BOM and drop it (Unicode int Order Mark) if(ch == '\uFFFE') { throw new XmlPullParserException( "first character in input was UNICODE noncharacter (0xFFFE)"+ "- input requires int swapping", this, null); } if(ch == '\uFEFF') { // skipping UNICODE int Order Mark (so called BOM) ch = more(); } } seenMarkup = false; boolean gotS = false; posStart = pos - 1; final boolean normalizeIgnorableWS = tokenize == true && roundtripSupported == false; boolean normalizedCR = false; while(true) { // deal with Misc // [27] Misc ::= Comment | PI | S // deal with docdecl --> mark it! // else parseStartTag seen <[^/] if(ch == '<') { if(gotS && tokenize) { posEnd = pos - 1; seenMarkup = true; return eventType = IGNORABLE_WHITESPACE; } ch = more(); if(ch == '?') { // check if it is 'xml' // deal with XMLDecl if(parsePI()) { // make sure to skip XMLDecl if(tokenize) { return eventType = PROCESSING_INSTRUCTION; } } else { // skip over - continue tokenizing posStart = pos; gotS = false; } } else if(ch == '!') { ch = more(); if(ch == 'D') { if(seenDocdecl) { throw new XmlPullParserException( "only one docdecl allowed in XML document", this, null); } seenDocdecl = true; parseDocdecl(); if(tokenize) return eventType = DOCDECL; } else if(ch == '-') { parseComment(); if(tokenize) return eventType = COMMENT; } else { throw new XmlPullParserException( "unexpected markup posStart) { joinPC(); } else { usePC = true; pcStart = pcEnd = 0; } } if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = '\n'; } else if(ch == '\n') { if(!normalizedCR && usePC) { if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = '\n'; } normalizedCR = false; } else { if(usePC) { if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = ch; } normalizedCR = false; } } } else { throw new XmlPullParserException( "only whitespace content allowed before start tag and not "+printable(ch), this, null); } ch = more(); } } protected int parseEpilog() throws XmlPullParserException, IOException { if(eventType == END_DOCUMENT) { throw new XmlPullParserException("already reached end of XML input", this, null); } if(reachedEnd) { return eventType = END_DOCUMENT; } boolean gotS = false; final boolean normalizeIgnorableWS = tokenize == true && roundtripSupported == false; boolean normalizedCR = false; try { // epilog: Misc* char ch; if(seenMarkup) { ch = buf[ pos - 1 ]; } else { ch = more(); } seenMarkup = false; posStart = pos - 1; if(!reachedEnd) { while(true) { // deal with Misc // [27] Misc ::= Comment | PI | S if(ch == '<') { if(gotS && tokenize) { posEnd = pos - 1; seenMarkup = true; return eventType = IGNORABLE_WHITESPACE; } ch = more(); if(reachedEnd) { break; } if(ch == '?') { // check if it is 'xml' // deal with XMLDecl parsePI(); if(tokenize) return eventType = PROCESSING_INSTRUCTION; } else if(ch == '!') { ch = more(); if(reachedEnd) { break; } if(ch == 'D') { parseDocdecl(); //FIXME if(tokenize) return eventType = DOCDECL; } else if(ch == '-') { parseComment(); if(tokenize) return eventType = COMMENT; } else { throw new XmlPullParserException( "unexpected markup posStart) { joinPC(); } else { usePC = true; pcStart = pcEnd = 0; } } if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = '\n'; } else if(ch == '\n') { if(!normalizedCR && usePC) { if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = '\n'; } normalizedCR = false; } else { if(usePC) { if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = ch; } normalizedCR = false; } } } else { throw new XmlPullParserException( "in epilog non whitespace content is not allowed but got "+printable(ch), this, null); } ch = more(); if(reachedEnd) { break; } } } } catch(EOFException ex) { reachedEnd = true; } if(reachedEnd) { if(tokenize && gotS) { posEnd = pos; // well - this is LAST available character pos return eventType = IGNORABLE_WHITESPACE; } return eventType = END_DOCUMENT; } else { throw new XmlPullParserException("internal error in parseEpilog"); } } public int parseEndTag() throws XmlPullParserException, IOException { //ASSUMPTION ch is past "' char ch = more(); if(!isNameStartChar(ch)) { throw new XmlPullParserException( "expected name start and not "+printable(ch), this, null); } posStart = pos - 3; final int nameStart = pos - 1 + bufAbsoluteStart; do { ch = more(); } while(isNameChar(ch)); // now we go one level down -- do checks //--depth; //FIXME // check that end tag name is the same as start tag //String name = new String(buf, nameStart - bufAbsoluteStart, // (pos - 1) - (nameStart - bufAbsoluteStart)); //int last = pos - 1; int off = nameStart - bufAbsoluteStart; final int len = (pos - 1) - off; final char[] cbuf = elRawName[depth]; if(elRawNameEnd[depth] != len) { // construct strings for exception final String startname = new String(cbuf, 0, elRawNameEnd[depth]); final String endname = new String(buf, off, len); throw new XmlPullParserException( "end tag name must match start tag name <"+startname+">" +" from line "+elRawNameLine[depth], this, null); } for (int i = 0; i < len; i++) { if(buf[off++] != cbuf[i]) { // construct strings for exception final String startname = new String(cbuf, 0, len); final String endname = new String(buf, off - i - 1, len); throw new XmlPullParserException( "end tag name must be the same as start tag <"+startname+">" +" from line "+elRawNameLine[depth], this, null); } } while(isS(ch)) { ch = more(); } // skip additional white spaces if(ch != '>') { throw new XmlPullParserException( "expected > to finish end tag not "+printable(ch) +" from line "+elRawNameLine[depth], this, null); } //namespaceEnd = elNamespaceCount[ depth ]; //FIXME posEnd = pos; pastEndTag = true; return eventType = END_TAG; } public int parseStartTag() throws XmlPullParserException, IOException { //ASSUMPTION ch is past ' // [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>' ++depth; //FIXME posStart = pos - 2; emptyElementTag = false; attributeCount = 0; // retrieve name final int nameStart = pos - 1 + bufAbsoluteStart; int colonPos = -1; char ch = buf[ pos - 1]; if(ch == ':' && processNamespaces) throw new XmlPullParserException( "when namespaces processing enabled colon can not be at element name start", this, null); while(true) { ch = more(); if(!isNameChar(ch)) break; if(ch == ':' && processNamespaces) { if(colonPos != -1) throw new XmlPullParserException( "only one colon is allowed in name of element when namespaces are enabled", this, null); colonPos = pos - 1 + bufAbsoluteStart; } } // retrieve name ensureElementsCapacity(); //TODO check for efficient interning and then use elRawNameInterned!!!! int elLen = (pos - 1) - (nameStart - bufAbsoluteStart); if(elRawName[ depth ] == null || elRawName[ depth ].length < elLen) { elRawName[ depth ] = new char[ 2 * elLen ]; } System.arraycopy(buf, nameStart - bufAbsoluteStart, elRawName[ depth ], 0, elLen); elRawNameEnd[ depth ] = elLen; elRawNameLine[ depth ] = lineNumber; // work on prefixes and namespace URI String prefix = null; if(processNamespaces) { if(colonPos != -1) { prefix = elPrefix[ depth ] = newString(buf, nameStart - bufAbsoluteStart, colonPos - nameStart); elName[ depth ] = newString(buf, colonPos + 1 - bufAbsoluteStart, //(pos -1) - (colonPos + 1)); pos - 2 - (colonPos - bufAbsoluteStart)); } else { prefix = elPrefix[ depth ] = null; elName[ depth ] = newString(buf, nameStart - bufAbsoluteStart, elLen); } } else { elName[ depth ] = newString(buf, nameStart - bufAbsoluteStart, elLen); } while(true) { while(isS(ch)) { ch = more(); } // skip additional white spaces if(ch == '>') { break; } else if(ch == '/') { if(emptyElementTag) throw new XmlPullParserException( "repeated / in tag declaration", this, null); emptyElementTag = true; ch = more(); if(ch != '>') throw new XmlPullParserException( "expected > to end empty tag not "+printable(ch), this, null); break; } else if(isNameStartChar(ch)) { ch = parseAttribute(); ch = more(); continue; } else { throw new XmlPullParserException( "start tag unexpected character "+printable(ch), this, null); } //ch = more(); // skip space } // now when namespaces were declared we can resolve them if(processNamespaces) { String uri = getNamespace(prefix); if(uri == null) { if(prefix == null) { // no prefix and no uri => use default namespace uri = NO_NAMESPACE; } else { throw new XmlPullParserException( "could not determine namespace bound to element prefix "+prefix, this, null); } } elUri[ depth ] = uri; // resolve attribute namespaces for (int i = 0; i < attributeCount; i++) { final String attrPrefix = attributePrefix[ i ]; if(attrPrefix != null) { final String attrUri = getNamespace(attrPrefix); if(attrUri == null) { throw new XmlPullParserException( "could not determine namespace bound to attribute prefix "+attrPrefix, this, null); } attributeUri[ i ] = attrUri; } else { attributeUri[ i ] = NO_NAMESPACE; } } //TODO //[ WFC: Unique Att Spec ] // check attribute uniqueness constraint for attributes that has namespace!!! for (int i = 1; i < attributeCount; i++) { for (int j = 0; j < i; j++) { if( attributeUri[j] == attributeUri[i] && (allStringsInterned && attributeName[j].equals(attributeName[i]) || (!allStringsInterned && attributeNameHash[ j ] == attributeNameHash[ i ] && attributeName[j].equals(attributeName[i])) ) ) { // prepare data for nice error message? String attr1 = attributeName[j]; if(attributeUri[j] != null) attr1 = attributeUri[j]+":"+attr1; String attr2 = attributeName[i]; if(attributeUri[i] != null) attr2 = attributeUri[i]+":"+attr2; throw new XmlPullParserException( "duplicated attributes "+attr1+" and "+attr2, this, null); } } } } else { // ! processNamespaces //[ WFC: Unique Att Spec ] // check raw attribute uniqueness constraint!!! for (int i = 1; i < attributeCount; i++) { for (int j = 0; j < i; j++) { if((allStringsInterned && attributeName[j].equals(attributeName[i]) || (!allStringsInterned && attributeNameHash[ j ] == attributeNameHash[ i ] && attributeName[j].equals(attributeName[i])) ) ) { // prepare data for nice error message? final String attr1 = attributeName[j]; final String attr2 = attributeName[i]; throw new XmlPullParserException( "duplicated attributes "+attr1+" and "+attr2, this, null); } } } } elNamespaceCount[ depth ] = namespaceEnd; posEnd = pos; return eventType = START_TAG; } protected char parseAttribute() throws XmlPullParserException, IOException { // parse attribute // [41] Attribute ::= Name Eq AttValue // [WFC: No External Entity References] // [WFC: No < in Attribute Values] final int prevPosStart = posStart + bufAbsoluteStart; final int nameStart = pos - 1 + bufAbsoluteStart; int colonPos = -1; char ch = buf[ pos - 1 ]; if(ch == ':' && processNamespaces) throw new XmlPullParserException( "when namespaces processing enabled colon can not be at attribute name start", this, null); boolean startsWithXmlns = processNamespaces && ch == 'x'; int xmlnsPos = 0; ch = more(); while(isNameChar(ch)) { if(processNamespaces) { if(startsWithXmlns && xmlnsPos < 5) { ++xmlnsPos; if(xmlnsPos == 1) { if(ch != 'm') startsWithXmlns = false; } else if(xmlnsPos == 2) { if(ch != 'l') startsWithXmlns = false; } else if(xmlnsPos == 3) { if(ch != 'n') startsWithXmlns = false; } else if(xmlnsPos == 4) { if(ch != 's') startsWithXmlns = false; } else if(xmlnsPos == 5) { if(ch != ':') throw new XmlPullParserException( "after xmlns in attribute name must be colon" +"when namespaces are enabled", this, null); } } if(ch == ':') { if(colonPos != -1) throw new XmlPullParserException( "only one colon is allowed in attribute name" +" when namespaces are enabled", this, null); colonPos = pos - 1 + bufAbsoluteStart; } } ch = more(); } ensureAttributesCapacity(attributeCount); // --- start processing attributes String name = null; // work on prefixes and namespace URI if(processNamespaces) { if(xmlnsPos < 4) startsWithXmlns = false; if(startsWithXmlns) { if(colonPos != -1) { final int nameLen = pos - 2 - (colonPos - bufAbsoluteStart); if(nameLen == 0) { throw new XmlPullParserException( "namespace prefix is required after xmlns: " +" when namespaces are enabled", this, null); } name = newString(buf, colonPos - bufAbsoluteStart + 1, nameLen); } } else { if(colonPos != -1) { int prefixLen = colonPos - nameStart; attributePrefix[ attributeCount ] = newString(buf, nameStart - bufAbsoluteStart,prefixLen); int nameLen = pos - 2 - (colonPos - bufAbsoluteStart); name = attributeName[ attributeCount ] = newString(buf, colonPos - bufAbsoluteStart + 1, nameLen); } else { attributePrefix[ attributeCount ] = null; name = attributeName[ attributeCount ] = newString(buf, nameStart - bufAbsoluteStart, pos - 1 - (nameStart - bufAbsoluteStart)); } if(!allStringsInterned) { attributeNameHash[ attributeCount ] = name.hashCode(); } } } else { // retrieve name name = attributeName[ attributeCount ] = newString(buf, nameStart - bufAbsoluteStart, pos - 1 - (nameStart - bufAbsoluteStart)); if(!allStringsInterned) { attributeNameHash[ attributeCount ] = name.hashCode(); } } // [25] Eq ::= S? '=' S? while(isS(ch)) { ch = more(); } // skip additional spaces if(ch != '=') throw new XmlPullParserException( "expected = after attribute name", this, null); ch = more(); while(isS(ch)) { ch = more(); } // skip additional spaces // [10] AttValue ::= '"' ([^<&"] | Reference)* '"' // | "'" ([^<&'] | Reference)* "'" final char delimit = ch; if(delimit != '"' && delimit != '\'') throw new XmlPullParserException( "attribute value must start with quotation or apostrophe not " +printable(delimit), this, null); // parse until delimit or < and resolve Reference //[67] Reference ::= EntityRef | CharRef //int valueStart = pos + bufAbsoluteStart; boolean normalizedCR = false; usePC = false; pcStart = pcEnd; posStart = pos; while(true) { ch = more(); if(ch == delimit) { break; } if(ch == '<') { throw new XmlPullParserException( "markup not allowed inside attribute value - illegal < ", this, null); } if(ch == '&') { // extractEntityRef posEnd = pos - 1; if(!usePC) { final boolean hadCharData = posEnd > posStart; if(hadCharData) { // posEnd is already set correctly!!! joinPC(); } else { usePC = true; pcStart = pcEnd = 0; } } final char[] resolvedEntity = parseEntityRef(); // check if replacement text can be resolved !!! if(resolvedEntity == null) { if(entityRefName == null) { entityRefName = newString(buf, posStart, posEnd - posStart); } throw new XmlPullParserException( "could not resolve entity named '"+printable(entityRefName)+"'", this, null); } // write into PC replacement text - do merge for replacement text!!!! for (int i = 0; i < resolvedEntity.length; i++) { if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = resolvedEntity[ i ]; } } else if(ch == '\t' || ch == '\n' || ch == '\r') { // do attribute value normalization // as described in http://www.w3.org/TR/REC-xml#AVNormalize // TODO add test for it form spec ... // handle EOL normalization ... if(!usePC) { posEnd = pos - 1; if(posEnd > posStart) { joinPC(); } else { usePC = true; pcEnd = pcStart = 0; } } if(pcEnd >= pc.length) ensurePC(pcEnd); if(ch != '\n' || !normalizedCR) { pc[pcEnd++] = ' '; //'\n'; } } else { if(usePC) { if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = ch; } } normalizedCR = ch == '\r'; } if(processNamespaces && startsWithXmlns) { String ns = null; if(!usePC) { ns = newStringIntern(buf, posStart, pos - 1 - posStart); } else { ns = newStringIntern(pc, pcStart, pcEnd - pcStart); } ensureNamespacesCapacity(namespaceEnd); int prefixHash = -1; if(colonPos != -1) { if(ns.length() == 0) { throw new XmlPullParserException( "non-default namespace can not be declared to be empty string", this, null); } // declare new namespace namespacePrefix[ namespaceEnd ] = name; if(!allStringsInterned) { prefixHash = namespacePrefixHash[ namespaceEnd ] = name.hashCode(); } } else { // declare new default namespace ... namespacePrefix[ namespaceEnd ] = null; //""; //null; //TODO check FIXME Alek if(!allStringsInterned) { prefixHash = namespacePrefixHash[ namespaceEnd ] = -1; } } namespaceUri[ namespaceEnd ] = ns; // detect duplicate namespace declarations!!! final int startNs = elNamespaceCount[ depth - 1 ]; for (int i = namespaceEnd - 1; i >= startNs; --i) { if(((allStringsInterned || name == null) && namespacePrefix[ i ] == name) || (!allStringsInterned && name != null && namespacePrefixHash[ i ] == prefixHash && name.equals(namespacePrefix[ i ]) )) { final String s = name == null ? "default" : "'"+name+"'"; throw new XmlPullParserException( "duplicated namespace declaration for "+s+" prefix", this, null); } } ++namespaceEnd; } else { if(!usePC) { attributeValue[ attributeCount ] = new String(buf, posStart, pos - 1 - posStart); } else { attributeValue[ attributeCount ] = new String(pc, pcStart, pcEnd - pcStart); } ++attributeCount; } posStart = prevPosStart - bufAbsoluteStart; return ch; } protected char[] charRefOneCharBuf = new char[1]; protected char[] parseEntityRef() throws XmlPullParserException, IOException { // entity reference http://www.w3.org/TR/2000/REC-xml-20001006#NT-Reference // [67] Reference ::= EntityRef | CharRef // ASSUMPTION just after & entityRefName = null; posStart = pos; char ch = more(); if(ch == '#') { // parse character reference char charRef = 0; ch = more(); if(ch == 'x') { //encoded in hex while(true) { ch = more(); if(ch >= '0' && ch <= '9') { charRef = (char)(charRef * 16 + (ch - '0')); } else if(ch >= 'a' && ch <= 'f') { charRef = (char)(charRef * 16 + (ch - ('a' - 10))); } else if(ch >= 'A' && ch <= 'F') { charRef = (char)(charRef * 16 + (ch - ('A' - 10))); } else if(ch == ';') { break; } else { throw new XmlPullParserException( "character reference (with hex value) may not contain " +printable(ch), this, null); } } } else { // encoded in decimal while(true) { if(ch >= '0' && ch <= '9') { charRef = (char)(charRef * 10 + (ch - '0')); } else if(ch == ';') { break; } else { throw new XmlPullParserException( "character reference (with decimal value) may not contain " +printable(ch), this, null); } ch = more(); } } posEnd = pos - 1; charRefOneCharBuf[0] = charRef; if(tokenize) { text = newString(charRefOneCharBuf, 0, 1); } return charRefOneCharBuf; } else { // [68] EntityRef ::= '&' Name ';' // scan name until ; if(!isNameStartChar(ch)) { throw new XmlPullParserException( "entity reference names can not start with character '" +printable(ch)+"'", this, null); } while(true) { ch = more(); if(ch == ';') { break; } if(!isNameChar(ch)) { throw new XmlPullParserException( "entity reference name can not contain character " +printable(ch)+"'", this, null); } } posEnd = pos - 1; // determine what name maps to final int len = posEnd - posStart; if(len == 2 && buf[posStart] == 'l' && buf[posStart+1] == 't') { if(tokenize) { text = "<"; } charRefOneCharBuf[0] = '<'; return charRefOneCharBuf; } else if(len == 3 && buf[posStart] == 'a' && buf[posStart+1] == 'm' && buf[posStart+2] == 'p') { if(tokenize) { text = "&"; } charRefOneCharBuf[0] = '&'; return charRefOneCharBuf; } else if(len == 2 && buf[posStart] == 'g' && buf[posStart+1] == 't') { if(tokenize) { text = ">"; } charRefOneCharBuf[0] = '>'; return charRefOneCharBuf; } else if(len == 4 && buf[posStart] == 'a' && buf[posStart+1] == 'p' && buf[posStart+2] == 'o' && buf[posStart+3] == 's') { if(tokenize) { text = "'"; } charRefOneCharBuf[0] = '\''; return charRefOneCharBuf; } else if(len == 4 && buf[posStart] == 'q' && buf[posStart+1] == 'u' && buf[posStart+2] == 'o' && buf[posStart+3] == 't') { if(tokenize) { text = "\""; } charRefOneCharBuf[0] = '"'; return charRefOneCharBuf; } else { final char[] result = lookuEntityReplacement(len); if(result != null) { return result; } } if(tokenize) text = null; return null; } } protected char[] lookuEntityReplacement(int entitNameLen) throws XmlPullParserException, IOException { if(!allStringsInterned) { final int hash = fastHash(buf, posStart, posEnd - posStart); LOOP: for (int i = entityEnd - 1; i >= 0; --i) { if(hash == entityNameHash[ i ] && entitNameLen == entityNameBuf[ i ].length) { final char[] entityBuf = entityNameBuf[ i ]; for (int j = 0; j < entitNameLen; j++) { if(buf[posStart + j] != entityBuf[j]) continue LOOP; } if(tokenize) text = entityReplacement[ i ]; return entityReplacementBuf[ i ]; } } } else { entityRefName = newString(buf, posStart, posEnd - posStart); for (int i = entityEnd - 1; i >= 0; --i) { // take advantage that interning for newStirng is enforced if(entityRefName == entityName[ i ]) { if(tokenize) text = entityReplacement[ i ]; return entityReplacementBuf[ i ]; } } } return null; } protected void parseComment() throws XmlPullParserException, IOException { // implements XML 1.0 Section 2.5 Comments //ASSUMPTION: seen ch = more(); if(seenDashDash && ch != '>') { throw new XmlPullParserException( "in comment after two dashes (--) next character must be >" +" not "+printable(ch), this, null); } if(ch == '-') { if(!seenDash) { seenDash = true; } else { seenDashDash = true; seenDash = false; } } else if(ch == '>') { if(seenDashDash) { break; // found end sequence!!!! } else { seenDashDash = false; } seenDash = false; } else { seenDash = false; } if(normalizeIgnorableWS) { if(ch == '\r') { normalizedCR = true; // posEnd is already set if(!usePC) { posEnd = pos -1; if(posEnd > posStart) { joinPC(); } else { usePC = true; pcStart = pcEnd = 0; } } if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = '\n'; } else if(ch == '\n') { if(!normalizedCR && usePC) { if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = '\n'; } normalizedCR = false; } else { if(usePC) { if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = ch; } normalizedCR = false; } } } } catch(EOFException ex) { // detect EOF and create meaningful error ... throw new XmlPullParserException( "comment started on line "+curLine+" and column "+curColumn+" was not closed", this, ex); } if(tokenize) { posEnd = pos - 3; if(usePC) { pcEnd -= 2; } } } protected boolean parsePI() throws XmlPullParserException, IOException { // implements XML 1.0 Section 2.6 Processing Instructions // [16] PI ::= '' Char*)))? '?>' // [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l')) //ASSUMPTION: seen ') { if(seenQ) { break; // found end sequence!!!! } seenQ = false; } else { if(piTargetEnd == -1 && isS(ch)) { piTargetEnd = pos - 1 + bufAbsoluteStart; // [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l')) if((piTargetEnd - piTargetStart) == 3) { if((buf[piTargetStart] == 'x' || buf[piTargetStart] == 'X') && (buf[piTargetStart+1] == 'm' || buf[piTargetStart+1] == 'M') && (buf[piTargetStart+2] == 'l' || buf[piTargetStart+2] == 'L') ) { if(piTargetStart > 3) { // posStart) { joinPC(); } else { usePC = true; pcStart = pcEnd = 0; } } if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = '\n'; } else if(ch == '\n') { if(!normalizedCR && usePC) { if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = '\n'; } normalizedCR = false; } else { if(usePC) { if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = ch; } normalizedCR = false; } } ch = more(); } } catch(EOFException ex) { // detect EOF and create meaningful error ... throw new XmlPullParserException( "processing instruction started on line "+curLine+" and column "+curColumn +" was not closed", this, ex); } if(piTargetEnd == -1) { piTargetEnd = pos - 2 + bufAbsoluteStart; } if(tokenize) { posEnd = pos - 2; if(normalizeIgnorableWS) { --pcEnd; } } return true; } protected final static char[] VERSION = "version".toCharArray(); protected final static char[] NCODING = "ncoding".toCharArray(); protected final static char[] TANDALONE = "tandalone".toCharArray(); protected final static char[] YES = "yes".toCharArray(); protected final static char[] NO = "no".toCharArray(); protected void parseXmlDecl(char ch) throws XmlPullParserException, IOException { // [23] XMLDecl ::= '' // first make sure that relative positions will stay OK preventBufferCompaction = true; bufStart = 0; // necessary to keep pos unchanged during expansion! // --- parse VersionInfo // [24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"') // parse is positioned just on first S past 'z') && (ch < 'A' || ch > 'Z') && (ch < '0' || ch > '9') && ch != '_' && ch != '.' && ch != ':' && ch != '-') { throw new XmlPullParserException( " 'z') && (ch < 'A' || ch > 'Z')) { throw new XmlPullParserException( " 'z') && (ch < 'A' || ch > 'Z') && (ch < '0' || ch > '9') && ch != '.' && ch != '_' && ch != '-') { throw new XmlPullParserException( " as last part of ') { throw new XmlPullParserException( "expected ?> as last part of ' int bracketLevel = 0; final boolean normalizeIgnorableWS = tokenize == true && roundtripSupported == false; boolean normalizedCR = false; while(true) { ch = more(); if(ch == '[') ++bracketLevel; if(ch == ']') --bracketLevel; if(ch == '>' && bracketLevel == 0) break; if(normalizeIgnorableWS) { if(ch == '\r') { normalizedCR = true; // posEnd is alreadys set if(!usePC) { posEnd = pos -1; if(posEnd > posStart) { joinPC(); } else { usePC = true; pcStart = pcEnd = 0; } } if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = '\n'; } else if(ch == '\n') { if(!normalizedCR && usePC) { if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = '\n'; } normalizedCR = false; } else { if(usePC) { if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = ch; } normalizedCR = false; } } } posEnd = pos - 1; } protected void parseCDSect(boolean hadCharData) throws XmlPullParserException, IOException { // implements XML 1.0 Section 2.7 CDATA Sections // [18] CDSect ::= CDStart CData CDEnd // [19] CDStart ::= '' Char*)) // [21] CDEnd ::= ']]>' //ASSUMPTION: seen posStart) { joinPC(); } else { usePC = true; pcStart = pcEnd = 0; } } } } boolean seenBracket = false; boolean seenBracketBracket = false; boolean normalizedCR = false; while(true) { // scan until it hits "]]>" ch = more(); if(ch == ']') { if(!seenBracket) { seenBracket = true; } else { seenBracketBracket = true; //seenBracket = false; } } else if(ch == '>') { if(seenBracket && seenBracketBracket) { break; // found end sequence!!!! } else { seenBracketBracket = false; } seenBracket = false; } else { if(seenBracket) { seenBracket = false; } } if(normalizeInput) { // deal with normalization issues ... if(ch == '\r') { normalizedCR = true; posStart = cdStart - bufAbsoluteStart; posEnd = pos - 1; // posEnd is alreadys set if(!usePC) { if(posEnd > posStart) { joinPC(); } else { usePC = true; pcStart = pcEnd = 0; } } if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = '\n'; } else if(ch == '\n') { if(!normalizedCR && usePC) { if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = '\n'; } normalizedCR = false; } else { if(usePC) { if(pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = ch; } normalizedCR = false; } } } } catch(EOFException ex) { // detect EOF and create meaningful error ... throw new XmlPullParserException( "CDATA section started on line "+curLine+" and column "+curColumn+" was not closed", this, ex); } if(normalizeInput) { if(usePC) { pcEnd = pcEnd - 2; } } posStart = cdStart - bufAbsoluteStart; posEnd = pos - 3; } protected void fillBuf() throws IOException, XmlPullParserException { if(reader == null) throw new XmlPullParserException( "reader must be set before parsing is started"); // see if we are in compaction area if(bufEnd > bufSoftLimit) { // expand buffer it makes sense!!!! boolean compact = bufStart > bufSoftLimit; boolean expand = false; if(preventBufferCompaction) { compact = false; expand = true; } else if(!compact) { //freeSpace if(bufStart < buf.length / 2) { // less then half buffer available forcompactin --> expand instead!!! expand = true; } else { // at least half of buffer can be reclaimed --> worthwhile effort!!! compact = true; } } // if buffer almost full then compact it if(compact) { //TODO: look on trashing System.arraycopy(buf, bufStart, buf, 0, bufEnd - bufStart); if(TRACE_SIZING) System.out.println( "TRACE_SIZING fillBuf() compacting "+bufStart +" bufEnd="+bufEnd +" pos="+pos+" posStart="+posStart+" posEnd="+posEnd +" buf first 100 chars:"+new String(buf, bufStart, bufEnd - bufStart < 100 ? bufEnd - bufStart : 100 )); } else if(expand) { final int newSize = 2 * buf.length; final char newBuf[] = new char[ newSize ]; if(TRACE_SIZING) System.out.println("TRACE_SIZING fillBuf() "+buf.length+" => "+newSize); System.arraycopy(buf, bufStart, newBuf, 0, bufEnd - bufStart); buf = newBuf; if(bufLoadFactor > 0) { bufSoftLimit = (int) (( ((long) bufLoadFactor) * buf.length ) /100); } } else { throw new XmlPullParserException("internal error in fillBuffer()"); } bufEnd -= bufStart; pos -= bufStart; posStart -= bufStart; posEnd -= bufStart; bufAbsoluteStart += bufStart; bufStart = 0; if(TRACE_SIZING) System.out.println( "TRACE_SIZING fillBuf() after bufEnd="+bufEnd +" pos="+pos+" posStart="+posStart+" posEnd="+posEnd +" buf first 100 chars:"+new String(buf, 0, bufEnd < 100 ? bufEnd : 100)); } // at least one character must be read or error final int len = buf.length - bufEnd > READ_CHUNK_SIZE ? READ_CHUNK_SIZE : buf.length - bufEnd; final int ret = reader.read(buf, bufEnd, len); if(ret > 0) { bufEnd += ret; if(TRACE_SIZING) System.out.println( "TRACE_SIZING fillBuf() after filling in buffer" +" buf first 100 chars:"+new String(buf, 0, bufEnd < 100 ? bufEnd : 100)); return; } if(ret == -1) { if(bufAbsoluteStart == 0 && pos == 0) { throw new EOFException("input contained no data"); } else { if(seenRoot && depth == 0) { // inside parsing epilog!!! reachedEnd = true; return; } else { StringBuffer expectedTagStack = new StringBuffer(); if(depth > 0) { expectedTagStack.append(" - expected end tag"); if(depth > 1) { expectedTagStack.append("s"); //more than one end tag } expectedTagStack.append(" "); for (int i = depth; i > 0; i--) { String tagName = new String(elRawName[i], 0, elRawNameEnd[i]); expectedTagStack.append("'); } expectedTagStack.append(" to close"); for (int i = depth; i > 0; i--) { if(i != depth) { expectedTagStack.append(" and"); //more than one end tag } String tagName = new String(elRawName[i], 0, elRawNameEnd[i]); expectedTagStack.append(" start tag <"+tagName+">"); expectedTagStack.append(" from line "+elRawNameLine[i]); } expectedTagStack.append(", parser stopped on"); } throw new EOFException("no more data available" +expectedTagStack.toString()+getPositionDescription()); } } } else { throw new IOException("error reading input, returned "+ret); } } protected char more() throws IOException, XmlPullParserException { if(pos >= bufEnd) { fillBuf(); // this return value should be ignonored as it is used in epilog parsing ... if(reachedEnd) return (char)-1; } final char ch = buf[pos++]; //line/columnNumber if(ch == '\n') { ++lineNumber; columnNumber = 1; } else { ++columnNumber; } return ch; } protected void ensurePC(int end) { final int newSize = end > READ_CHUNK_SIZE ? 2 * end : 2 * READ_CHUNK_SIZE; final char[] newPC = new char[ newSize ]; if(TRACE_SIZING) System.out.println("TRACE_SIZING ensurePC() "+pc.length+" ==> "+newSize+" end="+end); System.arraycopy(pc, 0, newPC, 0, pcEnd); pc = newPC; } protected void joinPC() { final int len = posEnd - posStart; final int newEnd = pcEnd + len + 1; if(newEnd >= pc.length) ensurePC(newEnd); // add 1 for extra space for one char System.arraycopy(buf, posStart, pc, pcEnd, len); pcEnd += len; usePC = true; } protected char requireInput(char ch, char[] input) throws XmlPullParserException, IOException { for (int i = 0; i < input.length; i++) { if(ch != input[i]) { throw new XmlPullParserException( "expected "+printable(input[i])+" in "+new String(input) +" and not "+printable(ch), this, null); } ch = more(); } return ch; } protected char requireNextS() throws XmlPullParserException, IOException { final char ch = more(); if(!isS(ch)) { throw new XmlPullParserException( "white space is required and not "+printable(ch), this, null); } return skipS(ch); } protected char skipS(char ch) throws XmlPullParserException, IOException { while(isS(ch)) { ch = more(); } // skip additional spaces return ch; } // nameStart / name lookup tables based on XML 1.1 http://www.w3.org/TR/2001/WD-xml11-20011213/ protected static final int LOOKUP_MAX = 0x400; protected static final char LOOKUP_MAX_CHAR = (char)LOOKUP_MAX; protected static boolean lookupNameStartChar[] = new boolean[ LOOKUP_MAX ]; protected static boolean lookupNameChar[] = new boolean[ LOOKUP_MAX ]; private static final void setName(char ch) { lookupNameChar[ ch ] = true; } private static final void setNameStart(char ch) { lookupNameStartChar[ ch ] = true; setName(ch); } static { setNameStart(':'); for (char ch = 'A'; ch <= 'Z'; ++ch) setNameStart(ch); setNameStart('_'); for (char ch = 'a'; ch <= 'z'; ++ch) setNameStart(ch); for (char ch = '\u00c0'; ch <= '\u02FF'; ++ch) setNameStart(ch); for (char ch = '\u0370'; ch <= '\u037d'; ++ch) setNameStart(ch); for (char ch = '\u037f'; ch < '\u0400'; ++ch) setNameStart(ch); setName('-'); setName('.'); for (char ch = '0'; ch <= '9'; ++ch) setName(ch); setName('\u00b7'); for (char ch = '\u0300'; ch <= '\u036f'; ++ch) setName(ch); } protected boolean isNameStartChar(char ch) { return (ch < LOOKUP_MAX_CHAR && lookupNameStartChar[ ch ]) || (ch >= LOOKUP_MAX_CHAR && ch <= '\u2027') || (ch >= '\u202A' && ch <= '\u218F') || (ch >= '\u2800' && ch <= '\uFFEF') ; } protected boolean isNameChar(char ch) { return (ch < LOOKUP_MAX_CHAR && lookupNameChar[ ch ]) || (ch >= LOOKUP_MAX_CHAR && ch <= '\u2027') || (ch >= '\u202A' && ch <= '\u218F') || (ch >= '\u2800' && ch <= '\uFFEF') ; } protected boolean isS(char ch) { return (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'); } protected String printable(char ch) { if(ch == '\n') { return "\\n"; } else if(ch == '\r') { return "\\r"; } else if(ch == '\t') { return "\\t"; } else if(ch == '\'') { return "\\'"; } if(ch > 127 || ch < 32) { return "\\u"+Integer.toHexString((int)ch); } return ""+ch; } protected String printable(String s) { if(s == null) return null; final int sLen = s.length(); StringBuffer buf = new StringBuffer(sLen + 10); for(int i = 0; i < sLen; ++i) { buf.append(printable(s.charAt(i))); } s = buf.toString(); return s; } } /* * Indiana University Extreme! Lab Software License, Version 1.2 * * Copyright (C) 2003 The Trustees of Indiana University. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * 1) All redistributions of source code must retain the above * copyright notice, the list of authors in the original source * code, this list of conditions and the disclaimer listed in this * license; * * 2) All redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the disclaimer * listed in this license in the documentation and/or other * materials provided with the distribution; * * 3) Any documentation included with all redistributions must include * the following acknowledgement: * * "This product includes software developed by the Indiana * University Extreme! Lab. For further information please visit * http://www.extreme.indiana.edu/" * * Alternatively, this acknowledgment may appear in the software * itself, and wherever such third-party acknowledgments normally * appear. * * 4) The name "Indiana University" or "Indiana University * Extreme! Lab" shall not be used to endorse or promote * products derived from this software without prior written * permission from Indiana University. For written permission, * please contact http://www.extreme.indiana.edu/. * * 5) Products derived from this software may not use "Indiana * University" name nor may "Indiana University" appear in their name, * without prior written permission of the Indiana University. * * Indiana University provides no reassurances that the source code * provided does not infringe the patent or any other intellectual * property rights of any other entity. Indiana University disclaims any * liability to any recipient for claims brought by any other entity * based on infringement of intellectual property rights or otherwise. * * LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH * NO WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA * UNIVERSITY GIVES NO WARRANTIES AND MAKES NO REPRESENTATION THAT * SOFTWARE IS FREE OF INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR * OTHER PROPRIETARY RIGHTS. INDIANA UNIVERSITY MAKES NO WARRANTIES THAT * SOFTWARE IS FREE FROM "BUGS", "VIRUSES", "TROJAN HORSES", "TRAP * DOORS", "WORMS", OR OTHER HARMFUL CODE. LICENSEE ASSUMES THE ENTIRE * RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR ASSOCIATED MATERIALS, * AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION GENERATED USING * SOFTWARE. */ jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/xml/ModuleXmlParser.java000077500000000000000000002222411472011152000300760ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.xml; import java.io.BufferedInputStream; import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Set; import java.util.jar.JarFile; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.jboss.modules.AssertionSetting; import org.jboss.modules.DependencySpec; import org.jboss.modules.LocalDependencySpecBuilder; import org.jboss.modules.ModuleDependencySpec; import org.jboss.modules.ModuleDependencySpecBuilder; import org.jboss.modules.Version; import org.jboss.modules.VersionDetection; import org.jboss.modules.maven.ArtifactCoordinates; import org.jboss.modules.ModuleIdentifier; import org.jboss.modules.ModuleLoadException; import org.jboss.modules.ModuleLoader; import org.jboss.modules.ModuleSpec; import org.jboss.modules.NativeLibraryResourceLoader; import org.jboss.modules.PathUtils; import org.jboss.modules.ResourceLoader; import org.jboss.modules.ResourceLoaderSpec; import org.jboss.modules.ResourceLoaders; import org.jboss.modules.filter.MultiplePathFilterBuilder; import org.jboss.modules.filter.PathFilter; import org.jboss.modules.filter.PathFilters; import org.jboss.modules.maven.MavenResolver; import org.jboss.modules.security.FactoryPermissionCollection; import org.jboss.modules.security.ModularPermissionFactory; import org.jboss.modules.security.PermissionFactory; import static org.jboss.modules.xml.XmlPullParser.CDSECT; import static org.jboss.modules.xml.XmlPullParser.COMMENT; import static org.jboss.modules.xml.XmlPullParser.DOCDECL; import static org.jboss.modules.xml.XmlPullParser.END_DOCUMENT; import static org.jboss.modules.xml.XmlPullParser.END_TAG; import static org.jboss.modules.xml.XmlPullParser.ENTITY_REF; import static org.jboss.modules.xml.XmlPullParser.FEATURE_PROCESS_NAMESPACES; import static org.jboss.modules.xml.XmlPullParser.IGNORABLE_WHITESPACE; import static org.jboss.modules.xml.XmlPullParser.PROCESSING_INSTRUCTION; import static org.jboss.modules.xml.XmlPullParser.START_DOCUMENT; import static org.jboss.modules.xml.XmlPullParser.START_TAG; import static org.jboss.modules.xml.XmlPullParser.TEXT; /** * A fast, validating {@code module.xml} parser. * * @author David M. Lloyd * @author thomas.diesler@jboss.com */ public final class ModuleXmlParser { static final ModuleDependencySpec DEP_JAVA_SE = new ModuleDependencySpecBuilder().setName("java.se").build(); /** * A factory for resource roots, based on a root path, loader path, and loader name. Normally it is sufficient to * accept the default. */ public interface ResourceRootFactory { ResourceLoader createResourceLoader(final String rootPath, final String loaderPath, final String loaderName) throws IOException; /** * Get the default resource root factory. * * @return the default resource root factory (not {@code null}) */ static ResourceRootFactory getDefault() { return DefaultResourceRootFactory.INSTANCE; } } /** * XML parsing callback for property elements. */ private interface PropertiesCallback { void parsedProperty(String name, String value); } private ModuleXmlParser() { } private static final String MODULE_1_0 = "urn:jboss:module:1.0"; private static final String MODULE_1_1 = "urn:jboss:module:1.1"; private static final String MODULE_1_2 = "urn:jboss:module:1.2"; private static final String MODULE_1_3 = "urn:jboss:module:1.3"; // there is no 1.4 private static final String MODULE_1_5 = "urn:jboss:module:1.5"; private static final String MODULE_1_6 = "urn:jboss:module:1.6"; private static final String MODULE_1_7 = "urn:jboss:module:1.7"; private static final String MODULE_1_8 = "urn:jboss:module:1.8"; private static final String MODULE_1_9 = "urn:jboss:module:1.9"; private static final String E_MODULE = "module"; private static final String E_ARTIFACT = "artifact"; private static final String E_NATIVE_ARTIFACT = "native-artifact"; private static final String E_DEPENDENCIES = "dependencies"; private static final String E_RESOURCES = "resources"; private static final String E_MAIN_CLASS = "main-class"; private static final String E_RESOURCE_ROOT = "resource-root"; private static final String E_PATH = "path"; private static final String E_EXPORTS = "exports"; private static final String E_IMPORTS = "imports"; private static final String E_INCLUDE = "include"; private static final String E_EXCLUDE = "exclude"; private static final String E_INCLUDE_SET = "include-set"; private static final String E_EXCLUDE_SET = "exclude-set"; private static final String E_FILTER = "filter"; private static final String E_SYSTEM = "system"; private static final String E_PATHS = "paths"; private static final String E_MODULE_ALIAS = "module-alias"; private static final String E_MODULE_ABSENT = "module-absent"; private static final String E_PROPERTIES = "properties"; private static final String E_PROPERTY = "property"; private static final String E_PERMISSIONS = "permissions"; private static final String E_GRANT = "grant"; private static final String E_CONDITIONS = "conditions"; private static final String E_PROPERTY_EQUAL = "property-equal"; private static final String E_PROPERTY_NOT_EQUAL = "property-not-equal"; private static final String E_PROVIDES = "provides"; private static final String E_SERVICE = "service"; private static final String E_WITH_CLASS = "with-class"; private static final String A_NAME = "name"; private static final String A_SLOT = "slot"; private static final String A_EXPORT = "export"; private static final String A_SERVICES = "services"; private static final String A_PATH = "path"; private static final String A_OPTIONAL = "optional"; private static final String A_TARGET_NAME = "target-name"; private static final String A_TARGET_SLOT = "target-slot"; private static final String A_VALUE = "value"; private static final String A_PERMISSION = "permission"; private static final String A_ACTIONS = "actions"; private static final String A_VERSION = "version"; private static final String D_NONE = "none"; private static final String D_IMPORT = "import"; private static final String D_EXPORT = "export"; private static final List LIST_A_NAME = Collections.singletonList(A_NAME); private static final List LIST_A_PATH = Collections.singletonList(A_PATH); private static final List LIST_A_NAME_A_SLOT = Arrays.asList(A_NAME, A_SLOT); private static final List LIST_A_NAME_A_TARGET_NAME = Arrays.asList(A_NAME, A_TARGET_NAME); private static final List LIST_A_PERMISSION = List.of(A_PERMISSION); private static PropertiesCallback NOOP_PROPS_CALLBACK; /** * Returns a no-op implementation of properties callback currently used for * parsing properties attached to module dependencies that aren't used at * runtime in jboss-modules but are important in other projects where * module dependencies are analyzed. * * @return a no-op implementation of properties callback */ private static PropertiesCallback getNoopPropsCallback() { return NOOP_PROPS_CALLBACK == null ? NOOP_PROPS_CALLBACK = new PropertiesCallback() { @Override public void parsedProperty(String name, String value) { } } : NOOP_PROPS_CALLBACK; } /** * Parse a {@code module.xml} file. * * @param moduleLoader the module loader to use for dependency specifications * @param moduleIdentifier the module identifier of the module to load * @param root the module path root * @param moduleInfoFile the {@code File} of the {@code module.xml} content * @return a module specification * @throws ModuleLoadException if a dependency could not be established or another error occurs * @throws IOException if I/O fails * @deprecated Use {@link #parseModuleXml(ModuleLoader, String, File, File)} instead. */ @Deprecated public static ModuleSpec parseModuleXml(final ModuleLoader moduleLoader, final ModuleIdentifier moduleIdentifier, final File root, final File moduleInfoFile) throws ModuleLoadException, IOException { return parseModuleXml(moduleLoader, moduleIdentifier.toString(), root, moduleInfoFile); } /** * Parse a {@code module.xml} file. * * @param moduleLoader the module loader to use for dependency specifications * @param moduleName the name of the module to load * @param root the module path root * @param moduleInfoFile the {@code File} of the {@code module.xml} content * @return a module specification * @throws ModuleLoadException if a dependency could not be established or another error occurs * @throws IOException if I/O fails */ public static ModuleSpec parseModuleXml(final ModuleLoader moduleLoader, final String moduleName, final File root, final File moduleInfoFile) throws ModuleLoadException, IOException { return parseModuleXml(ResourceRootFactory.getDefault(), moduleLoader, moduleName, root, moduleInfoFile); } /** * Parse a {@code module.xml} file. * * @param factory the resource root factory to use (must not be {@code null}) * @param moduleLoader the module loader to use for dependency specifications * @param moduleName the name of the module to load * @param root the module path root * @param moduleInfoFile the {@code File} of the {@code module.xml} content * @return a module specification * @throws ModuleLoadException if a dependency could not be established or another error occurs * @throws IOException if I/O fails */ public static ModuleSpec parseModuleXml(final ResourceRootFactory factory, final ModuleLoader moduleLoader, final String moduleName, final File root, final File moduleInfoFile) throws ModuleLoadException, IOException { final FileInputStream fis; try { fis = new FileInputStream(moduleInfoFile); } catch (FileNotFoundException e) { throw new ModuleLoadException("No module.xml file found at " + moduleInfoFile); } try { return parseModuleXml(factory, root.getPath(), new BufferedInputStream(fis), moduleInfoFile.getPath(), moduleLoader, moduleName); } finally { safeClose(fis); } } /** * Parse a {@code module.xml} file. * * @param factory the resource root factory to use (must not be {@code null}) * @param rootPath the root path to send in to the resource root factory (must not be {@code null}) * @param source a stream of the {@code module.xml} content (must not be {@code null}) * @param moduleInfoFile the {@code File} of the {@code module.xml} content (must not be {@code null}) * @param moduleLoader the module loader to use for dependency specifications (must not be {@code null}) * @param moduleIdentifier the module identifier of the module to load * @return a module specification * @throws ModuleLoadException if a dependency could not be established or another error occurs * @throws IOException if I/O fails * @deprecated Use {@link #parseModuleXml(ResourceRootFactory, String, InputStream, String, ModuleLoader, String)} instead. */ @Deprecated public static ModuleSpec parseModuleXml(final ResourceRootFactory factory, final String rootPath, InputStream source, final String moduleInfoFile, final ModuleLoader moduleLoader, final ModuleIdentifier moduleIdentifier) throws ModuleLoadException, IOException { return parseModuleXml(factory, MavenResolver.createDefaultResolver(), rootPath, source, moduleInfoFile, moduleLoader, moduleIdentifier); } /** * Parse a {@code module.xml} file. * * @param factory the resource root factory to use (must not be {@code null}) * @param rootPath the root path to send in to the resource root factory (must not be {@code null}) * @param source a stream of the {@code module.xml} content (must not be {@code null}) * @param moduleInfoFile the {@code File} of the {@code module.xml} content (must not be {@code null}) * @param moduleLoader the module loader to use for dependency specifications (must not be {@code null}) * @param moduleName the module name of the module to load * @return a module specification * @throws ModuleLoadException if a dependency could not be established or another error occurs * @throws IOException if I/O fails */ public static ModuleSpec parseModuleXml(final ResourceRootFactory factory, final String rootPath, InputStream source, final String moduleInfoFile, final ModuleLoader moduleLoader, final String moduleName) throws ModuleLoadException, IOException { return parseModuleXml(factory, MavenResolver.createDefaultResolver(), rootPath, source, moduleInfoFile, moduleLoader, moduleName); } /** * Parse a {@code module.xml} file. * * @param factory the resource root factory to use (must not be {@code null}) * @param mavenResolver the Maven artifact resolver to use (must not be {@code null}) * @param rootPath the root path to send in to the resource root factory (must not be {@code null}) * @param source a stream of the {@code module.xml} content (must not be {@code null}) * @param moduleInfoFile the {@code File} of the {@code module.xml} content (must not be {@code null}) * @param moduleLoader the module loader to use for dependency specifications (must not be {@code null}) * @param moduleIdentifier the module identifier of the module to load * @return a module specification * @throws ModuleLoadException if a dependency could not be established or another error occurs * @throws IOException if I/O fails * @deprecated Use {@link #parseModuleXml(ResourceRootFactory, MavenResolver, String, InputStream, String, ModuleLoader, String)} instead. */ @Deprecated public static ModuleSpec parseModuleXml(final ResourceRootFactory factory, final MavenResolver mavenResolver, final String rootPath, InputStream source, final String moduleInfoFile, final ModuleLoader moduleLoader, final ModuleIdentifier moduleIdentifier) throws ModuleLoadException, IOException { return parseModuleXml(factory, mavenResolver, rootPath, source, moduleInfoFile, moduleLoader, moduleIdentifier.toString()); } /** * Parse a {@code module.xml} file. * * @param factory the resource root factory to use (must not be {@code null}) * @param mavenResolver the Maven artifact resolver to use (must not be {@code null}) * @param rootPath the root path to send in to the resource root factory (must not be {@code null}) * @param source a stream of the {@code module.xml} content (must not be {@code null}) * @param moduleInfoFile the {@code File} of the {@code module.xml} content (must not be {@code null}) * @param moduleLoader the module loader to use for dependency specifications (must not be {@code null}) * @param moduleName the module name of the module to load * @return a module specification * @throws ModuleLoadException if a dependency could not be established or another error occurs * @throws IOException if I/O fails */ public static ModuleSpec parseModuleXml(final ResourceRootFactory factory, final MavenResolver mavenResolver, final String rootPath, InputStream source, final String moduleInfoFile, final ModuleLoader moduleLoader, final String moduleName) throws ModuleLoadException, IOException { try { final MXParser parser = new MXParser(); parser.setFeature(FEATURE_PROCESS_NAMESPACES, true); parser.setInput(source, null); return parseDocument(mavenResolver, factory, rootPath, parser, moduleLoader, moduleName); } catch (XmlPullParserException e) { throw new ModuleLoadException("Error loading module from " + moduleInfoFile, e); } finally { safeClose(source); } } public static XmlPullParserException unexpectedContent(final XmlPullParser reader) { final String kind; switch (reader.getEventType()) { case CDSECT: kind = "cdata"; break; case COMMENT: kind = "comment"; break; case DOCDECL: kind = "document decl"; break; case END_DOCUMENT: kind = "document end"; break; case END_TAG: kind = "element end"; break; case ENTITY_REF: kind = "entity ref"; break; case PROCESSING_INSTRUCTION: kind = "processing instruction"; break; case IGNORABLE_WHITESPACE: kind = "whitespace"; break; case START_DOCUMENT: kind = "document start"; break; case START_TAG: kind = "element start"; break; case TEXT: kind = "text"; break; default: kind = "unknown"; break; } final StringBuilder b = new StringBuilder("Unexpected content of type '").append(kind).append('\''); if (reader.getName() != null) { b.append(" named '").append(reader.getName()).append('\''); } if (reader.getText() != null) { b.append(", text is: '").append(reader.getText()).append('\''); } return new XmlPullParserException(b.toString(), reader, null); } public static XmlPullParserException endOfDocument(final XmlPullParser reader) { return new XmlPullParserException("Unexpected end of document", reader, null); } private static XmlPullParserException invalidModuleName(final XmlPullParser reader, final String expected) { return new XmlPullParserException("Invalid/mismatched module name (expected " + expected + ")", reader, null); } private static XmlPullParserException missingAttributes(final XmlPullParser reader, final Set required) { final StringBuilder b = new StringBuilder("Missing one or more required attributes:"); for (String attribute : required) { b.append(' ').append(attribute); } return new XmlPullParserException(b.toString(), reader, null); } static XmlPullParserException unknownAttribute(final XmlPullParser parser, final int index) { final String namespace = parser.getAttributeNamespace(index); final String prefix = parser.getAttributePrefix(index); final String name = parser.getAttributeName(index); final StringBuilder eb = new StringBuilder("Unknown attribute \""); if (prefix != null) eb.append(prefix).append(':'); eb.append(name); if (namespace != null) eb.append("\" from namespace \"").append(namespace); eb.append('"'); return new XmlPullParserException(eb.toString(), parser, null); } private static XmlPullParserException unknownAttributeValue(final XmlPullParser parser, final int index) { final String namespace = parser.getAttributeNamespace(index); final String prefix = parser.getAttributePrefix(index); final String name = parser.getAttributeName(index); final StringBuilder eb = new StringBuilder("Unknown value \""); eb.append(parser.getAttributeValue(index)); eb.append("\" for attribute \""); if (prefix != null && ! prefix.isEmpty()) eb.append(prefix).append(':'); eb.append(name); if (namespace != null && ! namespace.isEmpty()) eb.append("\" from namespace \"").append(namespace); eb.append('"'); return new XmlPullParserException(eb.toString(), parser, null); } private static void validateNamespace(final XmlPullParser reader) throws XmlPullParserException { switch (reader.getNamespace()) { case MODULE_1_0: case MODULE_1_1: case MODULE_1_2: case MODULE_1_3: case MODULE_1_5: case MODULE_1_6: case MODULE_1_7: case MODULE_1_8: case MODULE_1_9: break; default: throw unexpectedContent(reader); } } private static boolean atLeast1_6(final XmlPullParser reader) { return MODULE_1_6.equals(reader.getNamespace()) || atLeast1_7(reader); } private static boolean atLeast1_7(final XmlPullParser reader) { return MODULE_1_7.equals(reader.getNamespace()) || atLeast1_8(reader); } private static boolean atLeast1_8(final XmlPullParser reader) { return MODULE_1_8.equals(reader.getNamespace()) || atLeast1_9(reader); } private static boolean atLeast1_9(final XmlPullParser reader) { return MODULE_1_9.equals(reader.getNamespace()); } private static void assertNoAttributes(final XmlPullParser reader) throws XmlPullParserException { final int attributeCount = reader.getAttributeCount(); if (attributeCount > 0) { throw unknownAttribute(reader, 0); } } private static void validateAttributeNamespace(final XmlPullParser reader, final int index) throws XmlPullParserException { if (! reader.getAttributeNamespace(index).isEmpty()) { throw unknownAttribute(reader, index); } } private static ModuleSpec parseDocument(final MavenResolver mavenResolver, final ResourceRootFactory factory, final String rootPath, XmlPullParser reader, final ModuleLoader moduleLoader, final String moduleName) throws XmlPullParserException, IOException { int eventType; for (;;) { eventType = reader.nextTag(); switch (eventType) { case START_DOCUMENT: { return parseRootElement(mavenResolver, factory, rootPath, reader, moduleLoader, moduleName); } case START_TAG: { validateNamespace(reader); final String element = reader.getName(); switch (element) { case E_MODULE: { final ModuleSpec.Builder specBuilder = parseModuleContents(mavenResolver, reader, factory, moduleLoader, moduleName, rootPath); parseEndDocument(reader); return specBuilder.create(); } case E_MODULE_ALIAS: { final ModuleSpec moduleSpec = parseModuleAliasContents(reader, moduleName); parseEndDocument(reader); return moduleSpec; } case E_MODULE_ABSENT: { parseModuleAbsentContents(reader, moduleName); return null; } default: { throw unexpectedContent(reader); } } } default: { throw unexpectedContent(reader); } } } } private static ModuleSpec parseRootElement(final MavenResolver mavenResolver, final ResourceRootFactory factory, final String rootPath, final XmlPullParser reader, final ModuleLoader moduleLoader, final String moduleName) throws XmlPullParserException, IOException { assertNoAttributes(reader); int eventType; while ((eventType = reader.nextTag()) != END_DOCUMENT) { switch (eventType) { case START_TAG: { validateNamespace(reader); final String element = reader.getName(); switch (element) { case E_MODULE: { final ModuleSpec.Builder specBuilder = parseModuleContents(mavenResolver, reader, factory, moduleLoader, moduleName, rootPath); parseEndDocument(reader); return specBuilder.create(); } case E_MODULE_ALIAS: { final ModuleSpec moduleSpec = parseModuleAliasContents(reader, moduleName); parseEndDocument(reader); return moduleSpec; } case E_MODULE_ABSENT: { parseModuleAbsentContents(reader, moduleName); return null; } default: { throw unexpectedContent(reader); } } } default: { throw unexpectedContent(reader); } } } throw endOfDocument(reader); } private static ModuleSpec parseModuleAliasContents(final XmlPullParser reader, final String moduleName) throws XmlPullParserException, IOException { final int count = reader.getAttributeCount(); String name = null; String slot = null; String targetName = null; String targetSlot = null; boolean noSlots = atLeast1_6(reader); final Set required = new HashSet<>(LIST_A_NAME_A_TARGET_NAME); for (int i = 0; i < count; i ++) { validateAttributeNamespace(reader, i); final String attribute = reader.getAttributeName(i); required.remove(attribute); switch (attribute) { case A_NAME: name = reader.getAttributeValue(i); break; case A_SLOT: if (noSlots) throw unknownAttribute(reader,i); else slot = reader.getAttributeValue(i); break; case A_TARGET_NAME: targetName = reader.getAttributeValue(i); break; case A_TARGET_SLOT: if (noSlots) throw unknownAttribute(reader,i); else targetSlot = reader.getAttributeValue(i); break; default: throw unknownAttribute(reader, i); } } if (! required.isEmpty()) { throw missingAttributes(reader, required); } if (moduleName != null) { if (noSlots) { if (! moduleName.equals(name)) { throw invalidModuleName(reader, moduleName); } } else { if (! ModuleIdentifier.fromString(moduleName).equals(ModuleIdentifier.create(name, slot))) { throw invalidModuleName(reader, moduleName); } } } int eventType; for (;;) { eventType = reader.nextTag(); switch (eventType) { case END_TAG: { if (noSlots) { return ModuleSpec.buildAlias(name, targetName).create(); } else { return ModuleSpec.buildAlias(ModuleIdentifier.create(name, slot), ModuleIdentifier.create(targetName, targetSlot)).create(); } } default: { throw unexpectedContent(reader); } } } } private static void parseModuleAbsentContents(final XmlPullParser reader, final String moduleName) throws XmlPullParserException, IOException { final int count = reader.getAttributeCount(); String name = null; String slot = null; boolean noSlots = atLeast1_6(reader); final Set required = noSlots ? new HashSet<>(LIST_A_NAME) : new HashSet<>(LIST_A_NAME_A_SLOT); for (int i = 0; i < count; i ++) { validateAttributeNamespace(reader, i); final String attribute = reader.getAttributeName(i); required.remove(attribute); switch (attribute) { case A_NAME: name = reader.getAttributeValue(i); break; case A_SLOT: if (noSlots) throw unknownAttribute(reader, i); else slot = reader.getAttributeValue(i); break; default: throw unknownAttribute(reader, i); } } if (! required.isEmpty()) { throw missingAttributes(reader, required); } if (moduleName != null) { if (noSlots) { if (!name.equals(moduleName)) { throw invalidModuleName(reader, moduleName); } } else { if (!ModuleIdentifier.fromString(moduleName).equals(ModuleIdentifier.create(name, slot))) { throw invalidModuleName(reader, moduleName); } } } int eventType; for (;;) { eventType = reader.nextTag(); switch (eventType) { case END_TAG: { return; } default: { throw unexpectedContent(reader); } } } } private static ModuleSpec.Builder parseModuleContents(final MavenResolver mavenResolver, final XmlPullParser reader, final ResourceRootFactory factory, final ModuleLoader moduleLoader, final String moduleName, final String rootPath) throws XmlPullParserException, IOException { final int count = reader.getAttributeCount(); String name = null; String slot = null; boolean is1_6 = atLeast1_6(reader); Version version = null; final Set required = new HashSet<>(LIST_A_NAME); for (int i = 0; i < count; i ++) { validateAttributeNamespace(reader, i); final String attribute = reader.getAttributeName(i); required.remove(attribute); switch (attribute) { case A_NAME: name = reader.getAttributeValue(i); break; case A_SLOT: if (is1_6) throw unknownAttribute(reader, i); else slot = reader.getAttributeValue(i); break; case A_VERSION: try { version = Version.parse(reader.getAttributeValue(i)); break; } catch (IllegalArgumentException ex) { throw new XmlPullParserException(ex.getMessage(), reader, ex); } default: throw unknownAttribute(reader, i); } } if (! required.isEmpty()) { throw missingAttributes(reader, required); } final String realModuleName; if (is1_6) { realModuleName = name; } else { realModuleName = ModuleIdentifier.create(name, slot).toString(); } if (moduleName != null && ! realModuleName.equals(moduleName)) { throw invalidModuleName(reader, realModuleName); } final ModuleSpec.Builder specBuilder = ModuleSpec.build(realModuleName); specBuilder.setVersion(version); // xsd:all MultiplePathFilterBuilder exportsBuilder = PathFilters.multiplePathFilterBuilder(true); ArrayList dependencies = new ArrayList<>(); final boolean is1_8 = atLeast1_8(reader); if (! is1_8) { // add default system dependencies specBuilder.addDependency(DEP_JAVA_SE); } Set visited = new HashSet<>(); int eventType; for (;;) { eventType = reader.nextTag(); switch (eventType) { case END_TAG: { specBuilder.addDependency(new LocalDependencySpecBuilder() .setExportFilter(exportsBuilder.create()) .build()); for (DependencySpec dependency : dependencies) { specBuilder.addDependency(dependency); } return specBuilder; } case START_TAG: { validateNamespace(reader); final String element = reader.getName(); if (visited.contains(element)) { throw unexpectedContent(reader); } visited.add(element); switch (element) { case E_EXPORTS: parseFilterList(reader, exportsBuilder); break; case E_DEPENDENCIES: parseDependencies(reader, dependencies); break; case E_MAIN_CLASS: parseMainClass(reader, specBuilder); break; case E_RESOURCES: parseResources(mavenResolver, factory, rootPath, reader, specBuilder); break; case E_PROPERTIES: parseProperties(reader, new PropertiesCallback() { @Override public void parsedProperty(String name, String value) { specBuilder.addProperty(name, value); if ("jboss.assertions".equals(name)) try { specBuilder.setAssertionSetting(AssertionSetting.valueOf(value.toUpperCase(Locale.US))); } catch (IllegalArgumentException ignored) {} } }); break; case E_PERMISSIONS: parsePermissions(reader, moduleLoader, realModuleName, specBuilder); break; case E_PROVIDES: if (is1_8) parseProvidesType(reader, specBuilder); else throw unexpectedContent(reader); break; default: throw unexpectedContent(reader); } break; } default: { throw unexpectedContent(reader); } } } } private static void parseDependencies(final XmlPullParser reader, final ArrayList dependencies) throws XmlPullParserException, IOException { assertNoAttributes(reader); // xsd:choice int eventType; for (;;) { eventType = reader.nextTag(); switch (eventType) { case END_TAG: { return; } case START_TAG: { validateNamespace(reader); switch (reader.getName()) { case E_MODULE: parseModuleDependency(reader, dependencies); break; case E_SYSTEM: if (! atLeast1_8(reader)) { parseSystemDependency(reader, dependencies); break; } default: throw unexpectedContent(reader); } break; } default: { throw unexpectedContent(reader); } } } } private static void parseModuleDependency(final XmlPullParser reader, final ArrayList dependencies) throws XmlPullParserException, IOException { String name = null; String slot = null; boolean export = false; boolean optional = false; boolean noSlots = atLeast1_6(reader); String services = D_NONE; final Set required = new HashSet<>(LIST_A_NAME); final int count = reader.getAttributeCount(); for (int i = 0; i < count; i ++) { validateAttributeNamespace(reader, i); final String attribute = reader.getAttributeName(i); required.remove(attribute); switch (attribute) { case A_NAME: name = reader.getAttributeValue(i); break; case A_SLOT: if (noSlots) throw unknownAttribute(reader, i); else slot = reader.getAttributeValue(i); break; case A_EXPORT: export = Boolean.parseBoolean(reader.getAttributeValue(i)); break; case A_OPTIONAL: optional = Boolean.parseBoolean(reader.getAttributeValue(i)); break; case A_SERVICES: { services = reader.getAttributeValue(i); switch (services) { case D_NONE: case D_IMPORT: case D_EXPORT: break; default: throw unknownAttributeValue(reader, i); } break; } default: throw unknownAttribute(reader, i); } } if (! required.isEmpty()) { throw missingAttributes(reader, required); } final MultiplePathFilterBuilder importBuilder = PathFilters.multiplePathFilterBuilder(true); final MultiplePathFilterBuilder exportBuilder = PathFilters.multiplePathFilterBuilder(export); int eventType; for (;;) { eventType = reader.nextTag(); switch (eventType) { case END_TAG: { assert services.equals(D_NONE) || services.equals(D_EXPORT) || services.equals(D_IMPORT); if (services.equals(D_EXPORT)) { // If services are to be re-exported, add META-INF/services -> true near the end of the list exportBuilder.addFilter(PathFilters.getMetaInfServicesFilter(), true); } if (export) { // If re-exported, add META-INF/** -> false at the end of the list (require explicit override) exportBuilder.addFilter(PathFilters.getMetaInfSubdirectoriesFilter(), false); exportBuilder.addFilter(PathFilters.getMetaInfFilter(), false); } final PathFilter exportFilter = exportBuilder.create(); final PathFilter importFilter; if (importBuilder.isEmpty()) { importFilter = services.equals(D_NONE) ? PathFilters.getDefaultImportFilter() : PathFilters.getDefaultImportFilterWithServices(); } else { if (! services.equals(D_NONE)) { importBuilder.addFilter(PathFilters.getMetaInfServicesFilter(), true); } importBuilder.addFilter(PathFilters.getMetaInfSubdirectoriesFilter(), false); importBuilder.addFilter(PathFilters.getMetaInfFilter(), false); importFilter = importBuilder.create(); } dependencies.add(new ModuleDependencySpecBuilder() .setImportFilter(importFilter) .setExportFilter(exportFilter) .setName(noSlots ? name : ModuleIdentifier.create(name, slot).toString()) .setOptional(optional) .build()); return; } case START_TAG: { validateNamespace(reader); switch (reader.getName()) { case E_EXPORTS: parseFilterList(reader, exportBuilder); break; case E_IMPORTS: parseFilterList(reader, importBuilder); break; case E_PROPERTIES: if (atLeast1_9(reader)) { parseProperties(reader, getNoopPropsCallback()); break; } default: throw unexpectedContent(reader); } break; } default: { throw unexpectedContent(reader); } } } } private static void parseSystemDependency(final XmlPullParser reader, final ArrayList dependencies) throws XmlPullParserException, IOException { boolean export = false; final int count = reader.getAttributeCount(); for (int i = 0; i < count; i ++) { validateAttributeNamespace(reader, i); final String attribute = reader.getAttributeName(i); switch (attribute) { case A_EXPORT: export = Boolean.parseBoolean(reader.getAttributeValue(i)); break; default: throw unexpectedContent(reader); } } Set paths = Collections.emptySet(); final MultiplePathFilterBuilder exportBuilder = PathFilters.multiplePathFilterBuilder(export); int eventType; for (;;) { eventType = reader.nextTag(); switch (eventType) { case END_TAG: { final PathFilter exportFilter = exportBuilder.create(); dependencies.add(DependencySpec.createSystemDependencySpec(PathFilters.acceptAll(), exportFilter, paths)); return; } case START_TAG: { validateNamespace(reader); switch (reader.getName()) { case E_PATHS: { paths = parseSet(reader); break; } case E_EXPORTS: { parseFilterList(reader, exportBuilder); break; } default: { throw unexpectedContent(reader); } } } } } } private static String parseClassNameType(final XmlPullParser reader) throws IOException, XmlPullParserException { String name = null; final Set required = new HashSet<>(LIST_A_NAME); final int count = reader.getAttributeCount(); for (int i = 0; i < count; i ++) { validateAttributeNamespace(reader, i); final String attribute = reader.getAttributeName(i); required.remove(attribute); switch (attribute) { case A_NAME: name = reader.getAttributeValue(i); break; default: throw unexpectedContent(reader); } } if (! required.isEmpty()) { throw missingAttributes(reader, required); } // consume remainder of element parseNoContent(reader); return name; } private static void parseMainClass(final XmlPullParser reader, final ModuleSpec.Builder specBuilder) throws XmlPullParserException, IOException { specBuilder.setMainClass(parseClassNameType(reader)); } private static void parseResources(final MavenResolver mavenResolver, final ResourceRootFactory factory, final String rootPath, final XmlPullParser reader, final ModuleSpec.Builder specBuilder) throws XmlPullParserException, IOException { assertNoAttributes(reader); final List detectedVersions = new ArrayList<>(); // xsd:choice int eventType; for (;;) { eventType = reader.nextTag(); switch (eventType) { case END_TAG: { final Version specifiedVersion = specBuilder.getVersion(); if (specifiedVersion == null) { final Iterator iterator = detectedVersions.iterator(); if (iterator.hasNext()) { Version guess = iterator.next(); while (iterator.hasNext()) { if (! guess.equals(iterator.next())) { guess = null; break; } } if (guess != null) specBuilder.setVersion(guess); } } specBuilder.addResourceRoot(ResourceLoaderSpec.createResourceLoaderSpec(new NativeLibraryResourceLoader(new File(rootPath, "lib")), PathFilters.rejectAll())); return; } case START_TAG: { validateNamespace(reader); switch (reader.getName()) { case E_RESOURCE_ROOT: { final Version version = parseResourceRoot(factory, rootPath, reader, specBuilder); if (version != null) detectedVersions.add(version); break; } case E_ARTIFACT: { final Version version = parseArtifact(factory, mavenResolver, reader, specBuilder); if (version != null) detectedVersions.add(version); break; } case E_NATIVE_ARTIFACT: { parseNativeArtifact(mavenResolver, reader, specBuilder); break; } default: throw unexpectedContent(reader); } break; } default: { throw unexpectedContent(reader); } } } } private static void createMavenNativeArtifactLoader(final MavenResolver mavenResolver, final String name, final XmlPullParser reader, final ModuleSpec.Builder specBuilder) throws IOException, XmlPullParserException { File fp = mavenResolver.resolveJarArtifact(ArtifactCoordinates.fromString(name)); if (fp == null) throw new XmlPullParserException(String.format("Failed to resolve native artifact '%s'", name), reader, null); File lib = new File(fp.getParentFile(), "lib"); if (!lib.exists()) { if (!fp.getParentFile().canWrite()) throw new XmlPullParserException(String.format("Native artifact '%s' cannot be unpacked", name), reader, null); unzip(fp, fp.getParentFile()); } specBuilder.addResourceRoot(ResourceLoaderSpec.createResourceLoaderSpec(new NativeLibraryResourceLoader(lib), PathFilters.rejectAll())); } private static void parseNativeArtifact(final MavenResolver mavenResolver, final XmlPullParser reader, final ModuleSpec.Builder specBuilder) throws XmlPullParserException, IOException { String name = null; final Set required = new HashSet<>(LIST_A_NAME); final int count = reader.getAttributeCount(); for (int i = 0; i < count; i ++) { validateAttributeNamespace(reader, i); final String attribute = reader.getAttributeName(i); required.remove(attribute); switch (attribute) { case A_NAME: name = reader.getAttributeValue(i); break; default: throw unknownAttribute(reader, i); } } if (! required.isEmpty()) { throw missingAttributes(reader, required); } final SystemPropertyConditionBuilder conditionBuilder = new SystemPropertyConditionBuilder(); final Set encountered = new HashSet<>(); int eventType; for (;;) { eventType = reader.nextTag(); switch (eventType) { case END_TAG: { try { if (conditionBuilder.resolve()) { createMavenNativeArtifactLoader(mavenResolver, name, reader, specBuilder); } } catch (IOException e) { throw new XmlPullParserException(String.format("Failed to add artifact '%s'", name), reader, e); } return; } case START_TAG: { validateNamespace(reader); final String element = reader.getName(); if (! encountered.add(element)) throw unexpectedContent(reader); switch (element) { case E_CONDITIONS: parseConditions(reader, conditionBuilder); break; default: throw unexpectedContent(reader); } break; } default: { throw unexpectedContent(reader); } } } } private static Version parseArtifact(final ResourceRootFactory factory, final MavenResolver mavenResolver, final XmlPullParser reader, final ModuleSpec.Builder specBuilder) throws XmlPullParserException, IOException { String name = null; final Set required = new HashSet<>(LIST_A_NAME); final int count = reader.getAttributeCount(); for (int i = 0; i < count; i ++) { validateAttributeNamespace(reader, i); final String attribute = reader.getAttributeName(i); required.remove(attribute); switch (attribute) { case A_NAME: name = reader.getAttributeValue(i); break; default: throw unknownAttribute(reader, i); } } if (! required.isEmpty()) { throw missingAttributes(reader, required); } final MultiplePathFilterBuilder filterBuilder = PathFilters.multiplePathFilterBuilder(true); final SystemPropertyConditionBuilder conditionBuilder = new SystemPropertyConditionBuilder(); final ResourceLoader resourceLoader; final Set encountered = new HashSet<>(); int eventType; for (;;) { eventType = reader.nextTag(); switch (eventType) { case END_TAG: { if(conditionBuilder.resolve()) { final ArtifactCoordinates coordinates; try { coordinates = ArtifactCoordinates.fromString(name); final File file = mavenResolver.resolveJarArtifact(coordinates); if (file == null) { throw new XmlPullParserException(String.format("Failed to resolve artifact '%s'", coordinates), reader, null); } resourceLoader = factory.createResourceLoader("", file.getPath(), name); } catch (IOException | IllegalArgumentException e) { throw new XmlPullParserException(String.format("Failed to add artifact '%s'", name), reader, e); } if (resourceLoader == null) throw new XmlPullParserException(String.format("Failed to resolve artifact '%s'", name), reader, null); specBuilder.addResourceRoot(ResourceLoaderSpec.createResourceLoaderSpec(resourceLoader, filterBuilder.create())); final String version = coordinates.getVersion(); try { return Version.parse(version); } catch (IllegalArgumentException ignored) { return null; } } return null; } case START_TAG: { validateNamespace(reader); final String element = reader.getName(); if (! encountered.add(element)) throw unexpectedContent(reader); switch (element) { case E_FILTER: parseFilterList(reader, filterBuilder); break; case E_CONDITIONS: parseConditions(reader, conditionBuilder); break; default: throw unexpectedContent(reader); } break; } default: { throw unexpectedContent(reader); } } } } private static Version parseResourceRoot(final ResourceRootFactory factory, final String rootPath, final XmlPullParser reader, final ModuleSpec.Builder specBuilder) throws XmlPullParserException, IOException { String name = null; String path = null; final Set required = new HashSet<>(LIST_A_PATH); final int count = reader.getAttributeCount(); final boolean is1_8 = atLeast1_8(reader); for (int i = 0; i < count; i ++) { validateAttributeNamespace(reader, i); final String attribute = reader.getAttributeName(i); required.remove(attribute); switch (attribute) { case A_NAME: if (!is1_8) name = reader.getAttributeValue(i); else throw unknownAttribute(reader, i); break; case A_PATH: path = PolicyExpander.expand(reader.getAttributeValue(i)); break; default: throw unknownAttribute(reader, i); } } if (! required.isEmpty()) { throw missingAttributes(reader, required); } if (name == null) name = is1_8 ? "unnamed" : path; final MultiplePathFilterBuilder filterBuilder = PathFilters.multiplePathFilterBuilder(true); final SystemPropertyConditionBuilder conditionBuilder = new SystemPropertyConditionBuilder(); final ResourceLoader resourceLoader; final Set encountered = new HashSet<>(); int eventType; for (;;) { eventType = reader.nextTag(); switch (eventType) { case END_TAG: { if(conditionBuilder.resolve()) { try { resourceLoader = factory.createResourceLoader(rootPath, path, name); } catch (IOException e) { throw new XmlPullParserException(String.format("Failed to add resource root '%s' at path '%s'", name, path), reader, e); } specBuilder.addResourceRoot(ResourceLoaderSpec.createResourceLoaderSpec(resourceLoader, filterBuilder.create())); if (specBuilder.getVersion() == null) { return VersionDetection.detectVersion(resourceLoader); } else { return null; } } else { return null; } } case START_TAG: { validateNamespace(reader); final String element = reader.getName(); if (! encountered.add(element)) throw unexpectedContent(reader); switch (element) { case E_FILTER: parseFilterList(reader, filterBuilder); break; case E_CONDITIONS: parseConditions(reader, conditionBuilder); break; default: throw unexpectedContent(reader); } break; } default: { throw unexpectedContent(reader); } } } } private static void parseConditions(XmlPullParser reader, SystemPropertyConditionBuilder conditionBuilder) throws XmlPullParserException, IOException { if(!atLeast1_7(reader)) { throw unexpectedContent(reader); } assertNoAttributes(reader); // xsd:choice int eventType; for (;;) { eventType = reader.nextTag(); switch (eventType) { case END_TAG: { return; } case START_TAG: { validateNamespace(reader); switch (reader.getName()) { case E_PROPERTY_EQUAL: parseConditionalProperty(reader, true, conditionBuilder); break; case E_PROPERTY_NOT_EQUAL: parseConditionalProperty(reader, false, conditionBuilder); break; default: throw unexpectedContent(reader); } break; } default: { throw unexpectedContent(reader); } } } } private static void parseConditionalProperty(XmlPullParser reader, boolean equal, SystemPropertyConditionBuilder builder) throws XmlPullParserException, IOException { String name = null; String value = null; final Set required = new HashSet<>(Arrays.asList(A_NAME, A_VALUE)); final int count = reader.getAttributeCount(); for (int i = 0; i < count; i ++) { validateAttributeNamespace(reader, i); final String attribute = reader.getAttributeName(i); required.remove(attribute); switch (attribute) { case A_NAME: name = reader.getAttributeValue(i); break; case A_VALUE: value = reader.getAttributeValue(i); break; default: throw unknownAttribute(reader, i); } } if (! required.isEmpty()) { throw missingAttributes(reader, required); } builder.add(name, value, equal); // consume remainder of element parseNoContent(reader); } private static void parseFilterList(final XmlPullParser reader, final MultiplePathFilterBuilder builder) throws XmlPullParserException, IOException { assertNoAttributes(reader); // xsd:choice int eventType; for (;;) { eventType = reader.nextTag(); switch (eventType) { case END_TAG: { return; } case START_TAG: { validateNamespace(reader); switch (reader.getName()) { case E_INCLUDE: parsePath(reader, true, builder); break; case E_EXCLUDE: parsePath(reader, false, builder); break; case E_INCLUDE_SET: parseSet(reader, true, builder); break; case E_EXCLUDE_SET: parseSet(reader, false, builder); break; default: throw unexpectedContent(reader); } break; } default: { throw unexpectedContent(reader); } } } } private static void parsePath(final XmlPullParser reader, final boolean include, final MultiplePathFilterBuilder builder) throws XmlPullParserException, IOException { String path = null; final Set required = new HashSet<>(LIST_A_PATH); final int count = reader.getAttributeCount(); for (int i = 0; i < count; i ++) { validateAttributeNamespace(reader, i); final String attribute = reader.getAttributeName(i); required.remove(attribute); switch (attribute) { case A_PATH: path = reader.getAttributeValue(i); break; default: throw unknownAttribute(reader, i); } } if (! required.isEmpty()) { throw missingAttributes(reader, required); } final boolean literal = path.indexOf('*') == -1 && path.indexOf('?') == -1; if (literal) { if (path.charAt(path.length() - 1) == '/') { builder.addFilter(PathFilters.isChildOf(path), include); } else { builder.addFilter(PathFilters.is(path), include); } } else { builder.addFilter(PathFilters.match(path), include); } // consume remainder of element parseNoContent(reader); } private static Set parseSet(final XmlPullParser reader) throws XmlPullParserException, IOException { assertNoAttributes(reader); final Set set = new HashSet<>(); // xsd:choice int eventType; for (;;) { eventType = reader.nextTag(); switch (eventType) { case END_TAG: { return set; } case START_TAG: { validateNamespace(reader); switch (reader.getName()) { case E_PATH: parsePathName(reader, set); break; default: throw unexpectedContent(reader); } } } } } private static void parseSet(final XmlPullParser reader, final boolean include, final MultiplePathFilterBuilder builder) throws XmlPullParserException, IOException { builder.addFilter(PathFilters.in(parseSet(reader)), include); } private static void parsePathName(final XmlPullParser reader, final Set set) throws XmlPullParserException, IOException { String name = null; final Set required = new HashSet<>(LIST_A_NAME); final int count = reader.getAttributeCount(); for (int i = 0; i < count; i ++) { validateAttributeNamespace(reader, i); final String attribute = reader.getAttributeName(i); required.remove(attribute); switch (attribute) { case A_NAME: name = reader.getAttributeValue(i); break; default: throw unknownAttribute(reader, i); } } if (! required.isEmpty()) { throw missingAttributes(reader, required); } set.add(name); // consume remainder of element parseNoContent(reader); } private static void parseProperties(final XmlPullParser reader, final PropertiesCallback propsCallback) throws XmlPullParserException, IOException { assertNoAttributes(reader); // xsd:choice int eventType; for (;;) { eventType = reader.nextTag(); switch (eventType) { case END_TAG: { return; } case START_TAG: { validateNamespace(reader); switch (reader.getName()) { case E_PROPERTY: { parseProperty(reader, propsCallback); break; } default: throw unexpectedContent(reader); } break; } default: { throw unexpectedContent(reader); } } } } private static void parseProperty(final XmlPullParser reader, final PropertiesCallback propsCallback) throws XmlPullParserException, IOException { String name = null; String value = null; final Set required = new HashSet<>(LIST_A_NAME); final int count = reader.getAttributeCount(); for (int i = 0; i < count; i ++) { validateAttributeNamespace(reader, i); final String attribute = reader.getAttributeName(i); required.remove(attribute); switch (attribute) { case A_NAME: name = reader.getAttributeValue(i); break; case A_VALUE: value = reader.getAttributeValue(i); break; default: throw unknownAttribute(reader, i); } } if (! required.isEmpty()) { throw missingAttributes(reader, required); } propsCallback.parsedProperty(name, value == null ? "true" : value); // consume remainder of element parseNoContent(reader); } private static void parsePermissions(final XmlPullParser reader, final ModuleLoader moduleLoader, final String moduleName, final ModuleSpec.Builder specBuilder) throws XmlPullParserException, IOException { assertNoAttributes(reader); // xsd:choice ArrayList list = new ArrayList<>(); int eventType; for (;;) { eventType = reader.nextTag(); switch (eventType) { case END_TAG: { specBuilder.setPermissionCollection(new FactoryPermissionCollection(list.toArray(PermissionFactory[]::new))); return; } case START_TAG: { validateNamespace(reader); switch (reader.getName()) { case E_GRANT: { parseGrant(reader, moduleLoader, moduleName, list); break; } default: throw unexpectedContent(reader); } break; } default: { throw unexpectedContent(reader); } } } } private static void parseGrant(final XmlPullParser reader, final ModuleLoader moduleLoader, final String moduleName, final ArrayList list) throws XmlPullParserException, IOException { String permission = null; String name = null; String actions = null; final Set required = new HashSet<>(LIST_A_PERMISSION); final int count = reader.getAttributeCount(); for (int i = 0; i < count; i ++) { validateAttributeNamespace(reader, i); final String attribute = reader.getAttributeName(i); required.remove(attribute); switch (attribute) { case A_PERMISSION: permission = reader.getAttributeValue(i); break; case A_NAME: name = reader.getAttributeValue(i); break; case A_ACTIONS: actions = reader.getAttributeValue(i); break; default: throw unknownAttribute(reader, i); } } if (! required.isEmpty()) { throw missingAttributes(reader, required); } expandName(moduleLoader, moduleName, list, permission, name, actions); // consume remainder of element parseNoContent(reader); } private static void parseProvidesType(final XmlPullParser reader, final ModuleSpec.Builder specBuilder) throws XmlPullParserException, IOException { assertNoAttributes(reader); int eventType; for (;;) { eventType = reader.nextTag(); switch (eventType) { case END_TAG: { return; } case START_TAG: { validateNamespace(reader); switch (reader.getName()) { case E_SERVICE: { parseProvidedServiceType(reader, specBuilder); break; } default: throw unexpectedContent(reader); } break; } default: { throw unexpectedContent(reader); } } } } private static void parseProvidedServiceType(final XmlPullParser reader, final ModuleSpec.Builder specBuilder) throws XmlPullParserException, IOException { String name = null; final int count = reader.getAttributeCount(); for (int i = 0; i < count; i ++) { validateAttributeNamespace(reader, i); final String attribute = reader.getAttributeName(i); switch (attribute) { case A_NAME: name = reader.getAttributeValue(i); break; default: throw unknownAttribute(reader, i); } } if (name == null) { throw missingAttributes(reader, Collections.singleton("name")); } int eventType; for (;;) { eventType = reader.nextTag(); switch (eventType) { case END_TAG: { return; } case START_TAG: { validateNamespace(reader); switch (reader.getName()) { case E_WITH_CLASS: { specBuilder.addProvide(name, parseClassNameType(reader)); break; } default: throw unexpectedContent(reader); } break; } default: { throw unexpectedContent(reader); } } } } private static void expandName(final ModuleLoader moduleLoader, final String moduleName, final ArrayList list, String permission, String name, String actions) { if (name != null) { String expandedName = PolicyExpander.expand(name); if (expandedName == null) { //If a property can't be expanded in a permission entry that entry is ignored. //https://docs.oracle.com/javase/8/docs/technotes/guides/security/PolicyFiles.html#PropertyExp return; } name = expandedName; } list.add(new ModularPermissionFactory(moduleLoader, moduleName, permission, name, actions)); } private static void parseNoContent(final XmlPullParser reader) throws XmlPullParserException, IOException { int eventType; for (;;) { eventType = reader.nextTag(); switch (eventType) { case END_TAG: { return; } default: { throw unexpectedContent(reader); } } } } private static void parseEndDocument(final XmlPullParser reader) throws XmlPullParserException, IOException { int eventType; for (;;) { eventType = reader.nextToken(); switch (eventType) { case END_DOCUMENT: { return; } case TEXT: case CDSECT: { if (! reader.isWhitespace()) { throw unexpectedContent(reader); } // ignore break; } case IGNORABLE_WHITESPACE: case COMMENT: { // ignore break; } default: { throw unexpectedContent(reader); } } } } private static void unzip(File src, File destDir) throws IOException { final String absolutePath = destDir.getAbsolutePath(); final ZipFile zip = new ZipFile(src); try { final Enumeration entries = zip.entries(); while (entries.hasMoreElements()) { final ZipEntry entry = entries.nextElement(); if (entry.isDirectory()) { continue; } final File fp = new File(absolutePath, PathUtils.canonicalize(PathUtils.relativize(entry.getName()))); final File parent = fp.getParentFile(); if (! parent.exists()) { parent.mkdirs(); } final InputStream is = zip.getInputStream(entry); try { final FileOutputStream os = new FileOutputStream(fp); try { copy(is, os); } finally { safeClose(os); } } finally { safeClose(is); } } } finally { safeClose(zip); } } private static void copy(InputStream in, OutputStream out) throws IOException { byte[] buf = new byte[16384]; int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); } out.flush(); } private static void safeClose(Closeable closeable) { if (closeable != null) try { closeable.close(); } catch (Throwable ignored) {} } static class DefaultResourceRootFactory implements ResourceRootFactory { private DefaultResourceRootFactory() { } static final DefaultResourceRootFactory INSTANCE = new DefaultResourceRootFactory(); public ResourceLoader createResourceLoader(final String rootPath, final String loaderPath, final String loaderName) throws IOException { final File file; final File loaderFile; final String loaderFileName; if (File.separatorChar == '/') { loaderFileName = loaderPath; } else { loaderFileName = loaderPath.replace('/', File.separatorChar); } loaderFile = new File(loaderFileName); if (loaderFile.isAbsolute()) { file = loaderFile; } else { final String rootPathName; if (File.separatorChar == '/') { rootPathName = rootPath; } else { rootPathName = rootPath.replace('/', File.separatorChar); } file = new File(rootPathName, loaderFileName); } if (file.isDirectory()) { return ResourceLoaders.createPathResourceLoader(file.toPath()); } else { final JarFile jarFile = new JarFile(file, true, JarFile.OPEN_READ, JarFile.runtimeVersion()); return ResourceLoaders.createJarResourceLoader(jarFile); } } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/xml/PermissionsXmlParser.java000066400000000000000000000170361472011152000311650ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.xml; import static org.jboss.modules.xml.XmlPullParser.END_TAG; import static org.jboss.modules.xml.XmlPullParser.FEATURE_PROCESS_NAMESPACES; import static org.jboss.modules.xml.XmlPullParser.START_TAG; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import org.jboss.modules.ModuleLoader; import org.jboss.modules.security.FactoryPermissionCollection; import org.jboss.modules.security.ModularPermissionFactory; import org.jboss.modules.security.PermissionFactory; /** * A simple parser for enterprise-style {@code permissions.xml} files. */ public final class PermissionsXmlParser { /** * Parse the {@code permissions.xml} stream content. * * @param inputStream the input stream * @param moduleLoader the module loader to load from * @param moduleName the module name to load from * @return the permission collection (not {@code null}) * @throws IOException if the input stream throws an exception * @throws XmlPullParserException if the XML parser throws an exception */ public static FactoryPermissionCollection parsePermissionsXml(final InputStream inputStream, ModuleLoader moduleLoader, final String moduleName) throws XmlPullParserException, IOException { final MXParser mxParser = new MXParser(); mxParser.setFeature(FEATURE_PROCESS_NAMESPACES, true); mxParser.setInput(inputStream, null); return parsePermissionsXml(mxParser, moduleLoader, moduleName); } /** * Parse the {@code permissions.xml} content. * * @param reader the parser * @param moduleLoader the module loader to load from * @param moduleName the module name to load from * @return the permission collection (not {@code null}) * @throws IOException if the input stream throws an exception * @throws XmlPullParserException if the XML parser throws an exception */ public static FactoryPermissionCollection parsePermissionsXml(final XmlPullParser reader, ModuleLoader moduleLoader, final String moduleName) throws IOException, XmlPullParserException { int eventType; for (;;) { eventType = reader.nextTag(); switch (eventType) { case START_TAG: { validateNamespace(reader); switch (reader.getName()) { case "permissions": { return parsePermissionsElement(reader, moduleLoader, moduleName); } default: { throw ModuleXmlParser.unexpectedContent(reader); } } } case END_TAG: { return new FactoryPermissionCollection(); } } } } private static void validateNamespace(final XmlPullParser reader) throws XmlPullParserException { final String namespace = reader.getNamespace(); if (namespace != null) { switch (namespace) { case "": case "http://xmlns.jcp.org/xml/ns/javaee": case "http://java.sun.com/xml/ns/javaee": case "http://java.sun.com/xml/ns/j2ee": case "http://java.sun.com/dtd": return; } throw ModuleXmlParser.unexpectedContent(reader); } } private static FactoryPermissionCollection parsePermissionsElement(final XmlPullParser reader, final ModuleLoader moduleLoader, final String moduleName) throws IOException, XmlPullParserException { final int attributeCount = reader.getAttributeCount(); for (int i = 0; i < attributeCount; i ++) { if (reader.getAttributeNamespace(i).isEmpty() && ! reader.getAttributeName(i).equals("version")) { throw ModuleXmlParser.unknownAttribute(reader, i); } } final List factories = new ArrayList<>(); int eventType; for (;;) { eventType = reader.nextTag(); switch (eventType) { case START_TAG: { validateNamespace(reader); switch (reader.getName()) { case "permission": { factories.add(parsePermissionElement(reader, moduleLoader, moduleName)); break; } default: { throw ModuleXmlParser.unexpectedContent(reader); } } break; } case END_TAG: { return new FactoryPermissionCollection(factories.toArray(PermissionFactory[]::new)); } } } } private static PermissionFactory parsePermissionElement(final XmlPullParser reader, final ModuleLoader moduleLoader, final String moduleName) throws IOException, XmlPullParserException { if (reader.getAttributeCount() > 0) throw ModuleXmlParser.unknownAttribute(reader, 0); int eventType; String className = null; String name = null; String actions = null; for (;;) { eventType = reader.nextTag(); switch (eventType) { case START_TAG: { validateNamespace(reader); switch (reader.getName()) { case "class-name": { if (className != null) { throw ModuleXmlParser.unexpectedContent(reader); } className = reader.nextText().trim(); break; } case "name": { if (className == null || name != null || actions != null) { throw ModuleXmlParser.unexpectedContent(reader); } name = PolicyExpander.expand(reader.nextText().trim()); break; } case "actions": { if (className == null || actions != null) { throw ModuleXmlParser.unexpectedContent(reader); } actions = reader.nextText().trim(); break; } default: { throw ModuleXmlParser.unexpectedContent(reader); } } break; } case END_TAG: { return new ModularPermissionFactory(moduleLoader, moduleName, className, name, actions); } } } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/xml/PolicyExpander.java000066400000000000000000000140301472011152000277310ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.xml; import java.io.File; import java.security.AccessController; import java.security.PrivilegedAction; /** * Expand EL Expression in Permission grants * Meets requirements set out here: https://docs.oracle.com/javase/8/docs/technotes/guides/security/PolicyFiles.html#PropertyExp * * @author Jason Shepherd */ final class PolicyExpander { private static final int INITIAL = 0; private static final int GOT_DOLLAR = 1; private static final int GOT_OPEN_BRACE = 2; private static final int CAPTURE_EXPRESSION = 3; private static final int GOT_FILE_SEPERATOR = 4; public static final String ENV_START = "env."; private PolicyExpander() { // forbidden instantiation } static String expand(final String input) { StringBuilder valueToReturn = new StringBuilder(); int state = INITIAL; int propStart = -1; for (int i = 0; i < input.length(); i = input.offsetByCodePoints(i, 1)) { final int ch = input.codePointAt(i); switch(state){ case INITIAL: { switch(ch){ case '$': { state = GOT_DOLLAR; continue; } default:{ valueToReturn.appendCodePoint(ch); continue; } } } case GOT_DOLLAR:{ switch(ch){ case '{': { state = GOT_OPEN_BRACE; continue; } default:{ valueToReturn.append('$').appendCodePoint(ch); state = INITIAL; continue; } } } case GOT_OPEN_BRACE:{ switch(ch){ case '}': { expandValue(input, valueToReturn, propStart, i); state = INITIAL; continue; } case '/': { state = GOT_FILE_SEPERATOR; continue; } default:{ propStart = i; state = CAPTURE_EXPRESSION; continue; } } } case CAPTURE_EXPRESSION:{ switch(ch) { case '}': { expandValue(input, valueToReturn, propStart, i); state = INITIAL; continue; } default: { //part of an expression, skip continue; } } } case GOT_FILE_SEPERATOR:{ switch(ch){ case '}': { valueToReturn.append(File.separator); state = INITIAL; continue; } default:{ propStart = i - 1; //include skipped '/' state = CAPTURE_EXPRESSION; continue; } } } } } String returnValue = valueToReturn.toString(); if(returnValue.isEmpty()) return null; return returnValue; } private static void expandValue(String input, StringBuilder valueToReturn, int valueStart, int offset){ final String value = input.substring(valueStart, offset); if(value.startsWith(ENV_START)){ // 'env.' prefix is optional - and supported due to backward compatibility String var = getEnvironmentVariable(value.substring(ENV_START.length())); if(var != null) valueToReturn.append(var); return; } // System properties first String prop = getSystemProperty(value); if(prop != null) { valueToReturn.append(prop); return; } // Environment variables second (some users may prefer to not specify 'env.' prefix) prop = getEnvironmentVariable(value); if(prop != null) { valueToReturn.append(prop); } } private static String getEnvironmentVariable(String key) { if(key == null || key.isEmpty()) return null; return AccessController.doPrivileged(new PrivilegedAction(){ @Override public String run() { return System.getenv(key); } }); } private static String getSystemProperty(String key){ if(key == null || key.isEmpty()) return null; return AccessController.doPrivileged(new PrivilegedAction(){ @Override public String run() { return System.getProperty(key); } }); } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/xml/SystemPropertyConditionBuilder.java000066400000000000000000000023551472011152000332210ustar00rootroot00000000000000package org.jboss.modules.xml; import java.util.ArrayList; import java.util.List; class SystemPropertyConditionBuilder { private final List conditions = new ArrayList<>(); public boolean resolve() { for(Condition condition : conditions) { if(!condition.get()) { return false; } } return true; } public SystemPropertyConditionBuilder add(String name, String value, boolean equal) { conditions.add(new Condition(name, value, equal)); return this; } private static class Condition { private final String name; private final String value; private final boolean equal; private Condition(String name, String value, boolean equal) { this.name = name; this.value = value; this.equal = equal; } public boolean get() { String pval = System.getProperty(name); boolean equalValue; if(pval == null) { equalValue = value.isEmpty(); //treat the empty string as equal to null } else { equalValue = value.equals(pval); } return equal == equalValue; } } } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/xml/XmlPullParser.java000066400000000000000000001275751472011152000276000ustar00rootroot00000000000000/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/ // for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/) package org.jboss.modules.xml; import java.io.IOException; import java.io.InputStream; import java.io.Reader; /** * XML Pull Parser is an interface that defines parsing functionlity provided * in XMLPULL V1 API (visit this website to * learn more about API and its implementations). * *

There are following different * kinds of parser depending on which features are set:

    *
  • non-validating parser as defined in XML 1.0 spec when * FEATURE_PROCESS_DOCDECL is set to true *
  • validating parser as defined in XML 1.0 spec when * FEATURE_VALIDATION is true (and that implies that FEATURE_PROCESS_DOCDECL is true) *
  • when FEATURE_PROCESS_DOCDECL is false (this is default and * if different value is required necessary must be changed before parsing is started) * then parser behaves like XML 1.0 compliant non-validating parser under condition that * no DOCDECL is present in XML documents * (internal entites can still be defined with defineEntityReplacementText()). * This mode of operation is intened for operation in constrained environments such as J2ME. *
* * *

There are two key methods: next() and nextToken(). While next() provides * access to high level parsing events, nextToken() allows access to lower * level tokens. * *

The current event state of the parser * can be determined by calling the * getEventType() method. * Initially, the parser is in the START_DOCUMENT * state. * *

The method next() advances the parser to the * next event. The int value returned from next determines the current parser * state and is identical to the value returned from following calls to * getEventType (). * *

Th following event types are seen by next()

*
START_TAG
An XML start tag was read. *
TEXT
Text content was read; * the text content can be retreived using the getText() method. * (when in validating mode next() will not report ignorable whitespaces, use nextToken() instead) *
END_TAG
An end tag was read *
END_DOCUMENT
No more events are available *
* *

after first next() or nextToken() (or any other next*() method) * is called user application can obtain * XML version, standalone and encoding from XML declaration * in following ways:

    *
  • version: * getProperty("http://xmlpull.org/v1/doc/properties.html#xmldecl-version") * returns String ("1.0") or null if XMLDecl was not read or if property is not supported *
  • standalone: * getProperty("http://xmlpull.org/v1/doc/features.html#xmldecl-standalone") * returns Boolean: null if there was no standalone declaration * or if property is not supported * otherwise returns Boolean(true) if standalon="yes" and Boolean(false) when standalone="no" *
  • encoding: obtained from getInputEncoding() * null if stream had unknown encoding (not set in setInputStream) * and it was not declared in XMLDecl *
* * A minimal example for using this API may look as follows: *
 * import java.io.IOException;
 * import java.io.StringReader;
 *
 * import org.xmlpull.v1.XmlPullParser;
 * import org.xmlpull.v1.XmlPullParserException.html;
 * import org.xmlpull.v1.XmlPullParserFactory;
 *
 * public class SimpleXmlPullApp
 * {
 *
 *     public static void main (String args[])
 *         throws XmlPullParserException, IOException
 *     {
 *         XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
 *         factory.setNamespaceAware(true);
 *         XmlPullParser xpp = factory.newPullParser();
 *
 *         xpp.setInput( new StringReader ( "<foo>Hello World!</foo>" ) );
 *         int eventType = xpp.getEventType();
 *         while (eventType != XmlPullParser.END_DOCUMENT) {
 *          if(eventType == XmlPullParser.START_DOCUMENT) {
 *              System.out.println("Start document");
 *          } else if(eventType == XmlPullParser.END_DOCUMENT) {
 *              System.out.println("End document");
 *          } else if(eventType == XmlPullParser.START_TAG) {
 *              System.out.println("Start tag "+xpp.getName());
 *          } else if(eventType == XmlPullParser.END_TAG) {
 *              System.out.println("End tag "+xpp.getName());
 *          } else if(eventType == XmlPullParser.TEXT) {
 *              System.out.println("Text "+xpp.getText());
 *          }
 *          eventType = xpp.next();
 *         }
 *     }
 * }
 * 
* *

The above example will generate the following output: *

 * Start document
 * Start tag foo
 * Text Hello World!
 * End tag foo
 * 
* *

For more details on API usage, please refer to the * quick Introduction available at http://www.xmlpull.org * * @see #defineEntityReplacementText * @see #getName * @see #getNamespace * @see #getText * @see #next * @see #nextToken * @see #setInput * @see #FEATURE_PROCESS_DOCDECL * @see #FEATURE_VALIDATION * @see #START_DOCUMENT * @see #START_TAG * @see #TEXT * @see #END_TAG * @see #END_DOCUMENT * * @author Stefan Haustein * @author Aleksander Slominski */ public interface XmlPullParser { /** This constant represents the default namespace (empty string "") */ String NO_NAMESPACE = ""; // ---------------------------------------------------------------------------- // EVENT TYPES as reported by next() /** * Signalize that parser is at the very beginning of the document * and nothing was read yet. * This event type can only be observed by calling getEvent() * before the first call to next(), nextToken, or nextTag()). * * @see #next * @see #nextToken */ int START_DOCUMENT = 0; /** * Logical end of the xml document. Returned from getEventType, next() * and nextToken() * when the end of the input document has been reached. *

NOTE: calling again * next() or nextToken() * will result in exception being thrown. * * @see #next * @see #nextToken */ int END_DOCUMENT = 1; /** * Returned from getEventType(), * next(), nextToken() when * a start tag was read. * The name of start tag is available from getName(), its namespace and prefix are * available from getNamespace() and getPrefix() * if namespaces are enabled. * See getAttribute* methods to retrieve element attributes. * See getNamespace* methods to retrieve newly declared namespaces. * * @see #next * @see #nextToken * @see #getName * @see #getPrefix * @see #getNamespace * @see #getAttributeCount * @see #getDepth * @see #getNamespaceCount * @see #getNamespace * @see #FEATURE_PROCESS_NAMESPACES */ int START_TAG = 2; /** * Returned from getEventType(), next(), or * nextToken() when an end tag was read. * The name of start tag is available from getName(), its * namespace and prefix are * available from getNamespace() and getPrefix(). * * @see #next * @see #nextToken * @see #getName * @see #getPrefix * @see #getNamespace * @see #FEATURE_PROCESS_NAMESPACES */ int END_TAG = 3; /** * Character data was read and will is available by calling getText(). *

Please note: next() will * accumulate multiple * events into one TEXT event, skipping IGNORABLE_WHITESPACE, * PROCESSING_INSTRUCTION and COMMENT events, * In contrast, nextToken() will stop reading * text when any other event is observed. * Also, when the state was reached by calling next(), the text value will * be normalized, whereas getText() will * return unnormalized content in the case of nextToken(). This allows * an exact roundtrip without chnanging line ends when examining low * level events, whereas for high level applications the text is * normalized apropriately. * * @see #next * @see #nextToken * @see #getText */ int TEXT = 4; // ---------------------------------------------------------------------------- // additional events exposed by lower level nextToken() /** * A CDATA sections was just read; * this token is available only from calls to nextToken(). * A call to next() will accumulate various text events into a single event * of type TEXT. The text contained in the CDATA section is available * by callling getText(). * * @see #nextToken * @see #getText */ int CDSECT = 5; /** * An entity reference was just read; * this token is available from nextToken() * only. The entity name is available by calling getName(). If available, * the replacement text can be obtained by calling getTextt(); otherwise, * the user is responsibile for resolving the entity reference. * This event type is never returned from next(); next() will * accumulate the replacement text and other text * events to a single TEXT event. * * @see #nextToken * @see #getText */ int ENTITY_REF = 6; /** * Ignorable whitespace was just read. * This token is available only from nextToken()). * For non-validating * parsers, this event is only reported by nextToken() when outside * the root element. * Validating parsers may be able to detect ignorable whitespace at * other locations. * The ignorable whitespace string is available by calling getText() * *

NOTE: this is different from calling the * isWhitespace() method, since text content * may be whitespace but not ignorable. * * Ignorable whitespace is skipped by next() automatically; this event * type is never returned from next(). * * @see #nextToken * @see #getText */ int IGNORABLE_WHITESPACE = 7; /** * An XML processing instruction declaration was just read. This * event type is available only via nextToken(). * getText() will return text that is inside the processing instruction. * Calls to next() will skip processing instructions automatically. * @see #nextToken * @see #getText */ int PROCESSING_INSTRUCTION = 8; /** * An XML comment was just read. This event type is this token is * available via nextToken() only; * calls to next() will skip comments automatically. * The content of the comment can be accessed using the getText() * method. * * @see #nextToken * @see #getText */ int COMMENT = 9; /** * An XML document type declaration was just read. This token is * available from nextToken() only. * The unparsed text inside the doctype is available via * the getText() method. * * @see #nextToken * @see #getText */ int DOCDECL = 10; /** * This array can be used to convert the event type integer constants * such as START_TAG or TEXT to * to a string. For example, the value of TYPES[START_TAG] is * the string "START_TAG". * * This array is intended for diagnostic output only. Relying * on the contents of the array may be dangerous since malicous * applications may alter the array, although it is final, due * to limitations of the Java language. */ String [] TYPES = { "START_DOCUMENT", "END_DOCUMENT", "START_TAG", "END_TAG", "TEXT", "CDSECT", "ENTITY_REF", "IGNORABLE_WHITESPACE", "PROCESSING_INSTRUCTION", "COMMENT", "DOCDECL" }; // ---------------------------------------------------------------------------- // namespace related features /** * This feature determines whether the parser processes * namespaces. As for all features, the default value is false. *

NOTE: The value can not be changed during * parsing an must be set before parsing. * * @see #getFeature * @see #setFeature */ String FEATURE_PROCESS_NAMESPACES = "http://xmlpull.org/v1/doc/features.html#process-namespaces"; /** * This feature determines whether namespace attributes are * exposed via the attribute access methods. Like all features, * the default value is false. This feature cannot be changed * during parsing. * * @see #getFeature * @see #setFeature */ String FEATURE_REPORT_NAMESPACE_ATTRIBUTES = "http://xmlpull.org/v1/doc/features.html#report-namespace-prefixes"; /** * This feature determines whether the document declaration * is processed. If set to false, * the DOCDECL event type is reported by nextToken() * and ignored by next(). * * If this featue is activated, then the document declaration * must be processed by the parser. * *

Please note: If the document type declaration * was ignored, entity references may cause exceptions * later in the parsing process. * The default value of this feature is false. It cannot be changed * during parsing. * * @see #getFeature * @see #setFeature */ String FEATURE_PROCESS_DOCDECL = "http://xmlpull.org/v1/doc/features.html#process-docdecl"; /** * If this feature is activated, all validation errors as * defined in the XML 1.0 sepcification are reported. * This implies that FEATURE_PROCESS_DOCDECL is true and both, the * internal and external document type declaration will be processed. *

Please Note: This feature can not be changed * during parsing. The default value is false. * * @see #getFeature * @see #setFeature */ String FEATURE_VALIDATION = "http://xmlpull.org/v1/doc/features.html#validation"; /** * Use this call to change the general behaviour of the parser, * such as namespace processing or doctype declaration handling. * This method must be called before the first call to next or * nextToken. Otherwise, an exception is thrown. *

Example: call setFeature(FEATURE_PROCESS_NAMESPACES, true) in order * to switch on namespace processing. The initial settings correspond * to the properties requested from the XML Pull Parser factory. * If none were requested, all feautures are deactivated by default. * * @exception XmlPullParserException If the feature is not supported or can not be set * @exception IllegalArgumentException If string with the feature name is null */ void setFeature(String name, boolean state) throws XmlPullParserException; /** * Returns the current value of the given feature. *

Please note: unknown features are * always returned as false. * * @param name The name of feature to be retrieved. * @return The value of the feature. * @exception IllegalArgumentException if string the feature name is null */ boolean getFeature(String name); /** * Set the value of a property. * * The property name is any fully-qualified URI. * * @exception XmlPullParserException If the property is not supported or can not be set * @exception IllegalArgumentException If string with the property name is null */ void setProperty(String name, Object value) throws XmlPullParserException; /** * Look up the value of a property. * * The property name is any fully-qualified URI. *

NOTE: unknown properties are always * returned as null. * * @param name The name of property to be retrieved. * @return The value of named property. */ Object getProperty(String name); /** * Set the input source for parser to the given reader and * resets the parser. The event type is set to the initial value * START_DOCUMENT. * Setting the reader to null will just stop parsing and * reset parser state, * allowing the parser to free internal resources * such as parsing buffers. */ void setInput(Reader in) throws XmlPullParserException; /** * Sets the input stream the parser is going to process. * This call resets the parser state and sets the event type * to the initial value START_DOCUMENT. * *

NOTE: If an input encoding string is passed, * it MUST be used. Otherwise, * if inputEncoding is null, the parser SHOULD try to determine * input encoding following XML 1.0 specification (see below). * If encoding detection is supported then following feature * http://xmlpull.org/v1/doc/features.html#detect-encoding * MUST be true amd otherwise it must be false * * @param inputStream contains a raw byte input stream of possibly * unknown encoding (when inputEncoding is null). * * @param inputEncoding if not null it MUST be used as encoding for inputStream */ void setInput(InputStream inputStream, String inputEncoding) throws XmlPullParserException; /** * Returns the input encoding if known, null otherwise. * If setInput(InputStream, inputEncoding) was called with an inputEncoding * value other than null, this value must be returned * from this method. Otherwise, if inputEncoding is null and * the parser suppports the encoding detection feature * (http://xmlpull.org/v1/doc/features.html#detect-encoding), * it must return the detected encoding. * If setInput(Reader) was called, null is returned. * After first call to next if XML declaration was present this method * will return encoding declared. */ String getInputEncoding(); /** * Set new value for entity replacement text as defined in * XML 1.0 Section 4.5 * Construction of Internal Entity Replacement Text. * If FEATURE_PROCESS_DOCDECL or FEATURE_VALIDATION are set, calling this * function will result in an exception -- when processing of DOCDECL is * enabled, there is no need to the entity replacement text manually. * *

The motivation for this function is to allow very small * implementations of XMLPULL that will work in J2ME environments. * Though these implementations may not be able to process the document type * declaration, they still can work with known DTDs by using this function. * *

Please notes: The given value is used literally as replacement text * and it corresponds to declaring entity in DTD that has all special characters * escaped: left angle bracket is replaced with &lt;, ampersnad with &amp; * and so on. * *

Note: The given value is the literal replacement text and must not * contain any other entity reference (if it contains any entity reference * there will be no further replacement). * *

Note: The list of pre-defined entity names will * always contain standard XML entities such as * amp (&amp;), lt (&lt;), gt (&gt;), quot (&quot;), and apos (&apos;). * Those cannot be redefined by this method! * * @see #setInput * @see #FEATURE_PROCESS_DOCDECL * @see #FEATURE_VALIDATION */ void defineEntityReplacementText(String entityName, String replacementText) throws XmlPullParserException; /** * Returns the numbers of elements in the namespace stack for the given * depth. * If namespaces are not enabled, 0 is returned. * *

NOTE: when parser is on END_TAG then it is allowed to call * this function with getDepth()+1 argument to retrieve position of namespace * prefixes and URIs that were declared on corresponding START_TAG. *

NOTE: to retrieve lsit of namespaces declared in current element:

     *       XmlPullParser pp = ...
     *       int nsStart = pp.getNamespaceCount(pp.getDepth()-1);
     *       int nsEnd = pp.getNamespaceCount(pp.getDepth());
     *       for (int i = nsStart; i < nsEnd; i++) {
     *          String prefix = pp.getNamespacePrefix(i);
     *          String ns = pp.getNamespaceUri(i);
     *           // ...
     *      }
     * 
* * @see #getNamespacePrefix * @see #getNamespaceUri * @see #getNamespace() * @see #getNamespace(String) */ int getNamespaceCount(int depth) throws XmlPullParserException; /** * Returns the namespace prefixe for the given position * in the namespace stack. * Default namespace declaration (xmlns='...') will have null as prefix. * If the given index is out of range, an exception is thrown. *

Please note: when the parser is on an END_TAG, * namespace prefixes that were declared * in the corresponding START_TAG are still accessible * although they are no longer in scope. */ String getNamespacePrefix(int pos) throws XmlPullParserException; /** * Returns the namespace URI for the given position in the * namespace stack * If the position is out of range, an exception is thrown. *

NOTE: when parser is on END_TAG then namespace prefixes that were declared * in corresponding START_TAG are still accessible even though they are not in scope */ String getNamespaceUri(int pos) throws XmlPullParserException; /** * Returns the URI corresponding to the given prefix, * depending on current state of the parser. * *

If the prefix was not declared in the current scope, * null is returned. The default namespace is included * in the namespace table and is available via * getNamespace (null). * *

This method is a convenience method for * *

     *  for (int i = getNamespaceCount(getDepth ())-1; i >= 0; i--) {
     *   if (getNamespacePrefix(i).equals( prefix )) {
     *     return getNamespaceUri(i);
     *   }
     *  }
     *  return null;
     * 
* *

Please note: parser implementations * may provide more efifcient lookup, e.g. using a Hashtable. * The 'xml' prefix is bound to "http://www.w3.org/XML/1998/namespace", as * defined in the * Namespaces in XML * specification. Analogous, the 'xmlns' prefix is resolved to * http://www.w3.org/2000/xmlns/ * * @see #getNamespaceCount * @see #getNamespacePrefix * @see #getNamespaceUri */ String getNamespace(String prefix); // -------------------------------------------------------------------------- // miscellaneous reporting methods /** * Returns the current depth of the element. * Outside the root element, the depth is 0. The * depth is incremented by 1 when a start tag is reached. * The depth is decremented AFTER the end tag * event was observed. * *

     * <!-- outside -->     0
     * <root>               1
     *   sometext                 1
     *     <foobar>         2
     *     </foobar>        2
     * </root>              1
     * <!-- outside -->     0
     * 
*/ int getDepth(); /** * Returns a short text describing the current parser state, including * the position, a * description of the current event and the data source if known. * This method is especially useful to provide meaningful * error messages and for debugging purposes. */ String getPositionDescription(); /** * Returns the current line number, starting from 1. * When the parser does not know the current line number * or can not determine it, -1 is returned (e.g. for WBXML). * * @return current line number or -1 if unknown. */ int getLineNumber(); /** * Returns the current column number, starting from 0. * When the parser does not know the current column number * or can not determine it, -1 is returned (e.g. for WBXML). * * @return current column number or -1 if unknown. */ int getColumnNumber(); // -------------------------------------------------------------------------- // TEXT related methods /** * Checks whether the current TEXT event contains only whitespace * characters. * For IGNORABLE_WHITESPACE, this is always true. * For TEXT and CDSECT, false is returned when the current event text * contains at least one non-white space character. For any other * event type an exception is thrown. * *

Please note: non-validating parsers are not * able to distinguish whitespace and ignorable whitespace, * except from whitespace outside the root element. Ignorable * whitespace is reported as separate event, which is exposed * via nextToken only. * */ boolean isWhitespace() throws XmlPullParserException; /** * Returns the text content of the current event as String. * The value returned depends on current event type, * for example for TEXT event it is element content * (this is typical case when next() is used). * * See description of nextToken() for detailed description of * possible returned values for different types of events. * *

NOTE: in case of ENTITY_REF, this method returns * the entity replacement text (or null if not available). This is * the only case where * getText() and getTextCharacters() return different values. * * @see #getEventType * @see #next * @see #nextToken */ String getText(); /** * Returns the buffer that contains the text of the current event, * as well as the start offset and length relevant for the current * event. See getText(), next() and nextToken() for description of possible returned values. * *

Please note: this buffer must not * be modified and its content MAY change after a call to * next() or nextToken(). This method will always return the * same value as getText(), except for ENTITY_REF. In the case * of ENTITY ref, getText() returns the replacement text and * this method returns the actual input buffer containing the * entity name. * If getText() returns null, this method returns null as well and * the values returned in the holder array MUST be -1 (both start * and length). * * @see #getText * @see #next * @see #nextToken * * @param holderForStartAndLength Must hold an 2-element int array * into which the start offset and length values will be written. * @return char buffer that contains the text of the current event * (null if the current event has no text associated). */ char[] getTextCharacters(int[] holderForStartAndLength); // -------------------------------------------------------------------------- // START_TAG / END_TAG shared methods /** * Returns the namespace URI of the current element. * The default namespace is represented * as empty string. * If namespaces are not enabled, an empty String ("") is always returned. * The current event must be START_TAG or END_TAG; otherwise, * null is returned. */ String getNamespace(); /** * For START_TAG or END_TAG events, the (local) name of the current * element is returned when namespaces are enabled. When namespace * processing is disabled, the raw name is returned. * For ENTITY_REF events, the entity name is returned. * If the current event is not START_TAG, END_TAG, or ENTITY_REF, * null is returned. *

Please note: To reconstruct the raw element name * when namespaces are enabled and the prefix is not null, * you will need to add the prefix and a colon to localName.. * */ String getName(); /** * Returns the prefix of the current element. * If the element is in the default namespace (has no prefix), * null is returned. * If namespaces are not enabled, or the current event * is not START_TAG or END_TAG, null is returned. */ String getPrefix(); /** * Returns true if the current event is START_TAG and the tag * is degenerated * (e.g. <foobar/>). *

NOTE: if the parser is not on START_TAG, an exception * will be thrown. */ boolean isEmptyElementTag() throws XmlPullParserException; // -------------------------------------------------------------------------- // START_TAG Attributes retrieval methods /** * Returns the number of attributes of the current start tag, or * -1 if the current event type is not START_TAG * * @see #getAttributeNamespace * @see #getAttributeName * @see #getAttributePrefix * @see #getAttributeValue */ int getAttributeCount(); /** * Returns the namespace URI of the attribute * with the given index (starts from 0). * Returns an empty string ("") if namespaces are not enabled * or the attribute has no namespace. * Throws an IndexOutOfBoundsException if the index is out of range * or the current event type is not START_TAG. * *

NOTE: if FEATURE_REPORT_NAMESPACE_ATTRIBUTES is set * then namespace attributes (xmlns:ns='...') must be reported * with namespace * http://www.w3.org/2000/xmlns/ * (visit this URL for description!). * The default namespace attribute (xmlns="...") will be reported with empty namespace. *

NOTE:The xml prefix is bound as defined in * Namespaces in XML * specification to "http://www.w3.org/XML/1998/namespace". * * @param index zero based index of attribute * @return attribute namespace, * empty string ("") is returned if namesapces processing is not enabled or * namespaces processing is enabled but attribute has no namespace (it has no prefix). */ String getAttributeNamespace(int index); /** * Returns the local name of the specified attribute * if namespaces are enabled or just attribute name if namespaces are disabled. * Throws an IndexOutOfBoundsException if the index is out of range * or current event type is not START_TAG. * * @param index zero based index of attribute * @return attribute name (null is never returned) */ String getAttributeName(int index); /** * Returns the prefix of the specified attribute * Returns null if the element has no prefix. * If namespaces are disabled it will always return null. * Throws an IndexOutOfBoundsException if the index is out of range * or current event type is not START_TAG. * * @param index zero based index of attribute * @return attribute prefix or null if namespaces processing is not enabled. */ String getAttributePrefix(int index); /** * Returns the type of the specified attribute * If parser is non-validating it MUST return CDATA. * * @param index zero based index of attribute * @return attribute type (null is never returned) */ String getAttributeType(int index); /** * Returns if the specified attribute was not in input was declared in XML. * If parser is non-validating it MUST always return false. * This information is part of XML infoset: * * @param index zero based index of attribute * @return false if attribute was in input */ boolean isAttributeDefault(int index); /** * Returns the given attributes value. * Throws an IndexOutOfBoundsException if the index is out of range * or current event type is not START_TAG. * *

NOTE: attribute value must be normalized * (including entity replacement text if PROCESS_DOCDECL is false) as described in * XML 1.0 section * 3.3.3 Attribute-Value Normalization * * @see #defineEntityReplacementText * * @param index zero based index of attribute * @return value of attribute (null is never returned) */ String getAttributeValue(int index); /** * Returns the attributes value identified by namespace URI and namespace localName. * If namespaces are disabled namespace must be null. * If current event type is not START_TAG then IndexOutOfBoundsException will be thrown. * *

NOTE: attribute value must be normalized * (including entity replacement text if PROCESS_DOCDECL is false) as described in * XML 1.0 section * 3.3.3 Attribute-Value Normalization * * @see #defineEntityReplacementText * * @param namespace Namespace of the attribute if namespaces are enabled otherwise must be null * @param name If namespaces enabled local name of attribute otherwise just attribute name * @return value of attribute or null if attribute with given name does not exist */ String getAttributeValue(String namespace, String name); // -------------------------------------------------------------------------- // actual parsing methods /** * Returns the type of the current event (START_TAG, END_TAG, TEXT, etc.) * * @see #next() * @see #nextToken() */ int getEventType(); /** * Get next parsing event - element content wil be coalesced and only one * TEXT event must be returned for whole element content * (comments and processing instructions will be ignored and emtity references * must be expanded or exception mus be thrown if entity reerence can not be exapnded). * If element content is empty (content is "") then no TEXT event will be reported. * *

NOTE: empty element (such as <tag/>) will be reported * with two separate events: START_TAG, END_TAG - it must be so to preserve * parsing equivalency of empty element to <tag></tag>. * (see isEmptyElementTag ()) * * @see #isEmptyElementTag * @see #START_TAG * @see #TEXT * @see #END_TAG * @see #END_DOCUMENT */ int next() throws XmlPullParserException, IOException; /** * This method works similarly to next() but will expose * additional event types (COMMENT, CDSECT, DOCDECL, ENTITY_REF, PROCESSING_INSTRUCTION, or * IGNORABLE_WHITESPACE) if they are available in input. * *

If special feature * FEATURE_XML_ROUNDTRIP * (identified by URI: http://xmlpull.org/v1/doc/features.html#xml-roundtrip) * is enabled it is possible to do XML document round trip ie. reproduce * exectly on output the XML input using getText(): * returned content is always unnormalized (exactly as in input). * Otherwise returned content is end-of-line normalized as described * XML 1.0 End-of-Line Handling * and. Also when this feature is enabled exact content of START_TAG, END_TAG, * DOCDECL and PROCESSING_INSTRUCTION is available. * *

Here is the list of tokens that can be returned from nextToken() * and what getText() and getTextCharacters() returns:

*
START_DOCUMENT
null *
END_DOCUMENT
null *
START_TAG
null unless FEATURE_XML_ROUNDTRIP * enabled and then returns XML tag, ex: <tag attr='val'> *
END_TAG
null unless FEATURE_XML_ROUNDTRIP * id enabled and then returns XML tag, ex: </tag> *
TEXT
return element content. *
Note: that element content may be delivered in multiple consecutive TEXT events. *
IGNORABLE_WHITESPACE
return characters that are determined to be ignorable white * space. If the FEATURE_XML_ROUNDTRIP is enabled all whitespace content outside root * element will always reported as IGNORABLE_WHITESPACE otherise rteporting is optional. *
Note: that element content may be delevered in multiple consecutive IGNORABLE_WHITESPACE events. *
CDSECT
* return text inside CDATA * (ex. 'fo<o' from <!CDATA[fo<o]]>) *
PROCESSING_INSTRUCTION
* if FEATURE_XML_ROUNDTRIP is true * return exact PI content ex: 'pi foo' from <?pi foo?> * otherwise it may be exact PI content or concatenation of PI target, * space and data so for example for * <?target data?> string "target data" may * be returned if FEATURE_XML_ROUNDTRIP is false. *
COMMENT
return comment content ex. 'foo bar' from <!--foo bar--> *
ENTITY_REF
getText() MUST return entity replacement text if PROCESS_DOCDECL is false * otherwise getText() MAY return null, * additionally getTextCharacters() MUST return entity name * (for example 'entity_name' for &entity_name;). *
NOTE: this is the only place where value returned from getText() and * getTextCharacters() are different *
NOTE: it is user responsibility to resolve entity reference * if PROCESS_DOCDECL is false and there is no entity replacement text set in * defineEntityReplacementText() method (getText() will be null) *
NOTE: character entities (ex. &#32;) and standard entities such as * &amp; &lt; &gt; &quot; &apos; are reported as well * and are not reported as TEXT tokens but as ENTITY_REF tokens! * This requirement is added to allow to do roundtrip of XML documents! *
DOCDECL
* if FEATURE_XML_ROUNDTRIP is true or PROCESS_DOCDECL is false * then return what is inside of DOCDECL for example it returns:
     * " titlepage SYSTEM "http://www.foo.bar/dtds/typo.dtd"
     * [<!ENTITY % active.links "INCLUDE">]"
*

for input document that contained:

     * <!DOCTYPE titlepage SYSTEM "http://www.foo.bar/dtds/typo.dtd"
     * [<!ENTITY % active.links "INCLUDE">]>
* otherwise if FEATURE_XML_ROUNDTRIP is false and PROCESS_DOCDECL is true * then what is returned is undefined (it may be even null) *
*
* *

NOTE: there is no gurantee that there will only one TEXT or * IGNORABLE_WHITESPACE event from nextToken() as parser may chose to deliver element content in * multiple tokens (dividing element content into chunks) * *

NOTE: whether returned text of token is end-of-line normalized * is depending on FEATURE_XML_ROUNDTRIP. * *

NOTE: XMLDecl (<?xml ...?>) is not reported but its content * is available through optional properties (see class description above). * * @see #next * @see #START_TAG * @see #TEXT * @see #END_TAG * @see #END_DOCUMENT * @see #COMMENT * @see #DOCDECL * @see #PROCESSING_INSTRUCTION * @see #ENTITY_REF * @see #IGNORABLE_WHITESPACE */ int nextToken() throws XmlPullParserException, IOException; //----------------------------------------------------------------------------- // utility methods to mak XML parsing easier ... /** * Test if the current event is of the given type and if the * namespace and name do match. null will match any namespace * and any name. If the test is not passed, an exception is * thrown. The exception text indicates the parser position, * the expected event and the current event that is not meeting the * requirement. * *

Essentially it does this *

     *  if (type != getEventType()
     *  || (namespace != null &&  !namespace.equals( getNamespace () ) )
     *  || (name != null &&  !name.equals( getName() ) ) )
     *     throw new XmlPullParserException( "expected "+ TYPES[ type ]+getPositionDescription());
     * 
*/ void require(int type, String namespace, String name) throws XmlPullParserException, IOException; /** * If current event is START_TAG then if next element is TEXT then element content is returned * or if next event is END_TAG then empty string is returned, otherwise exception is thrown. * After calling this function successfully parser will be positioned on END_TAG. * *

The motivation for this function is to allow to parse consistently both * empty elements and elements that has non empty content, for example for input:

    *
  1. <tag>foo</tag> *
  2. <tag></tag> (which is equivalent to <tag/> * both input can be parsed with the same code: *
         *   p.nextTag()
         *   p.requireEvent(p.START_TAG, "", "tag");
         *   String content = p.nextText();
         *   p.requireEvent(p.END_TAG, "", "tag");
         * 
    * This function together with nextTag make it very easy to parse XML that has * no mixed content. * * *

    Essentially it does this *

         *  if(getEventType() != START_TAG) {
         *     throw new XmlPullParserException(
         *       "parser must be on START_TAG to read next text", this, null);
         *  }
         *  int eventType = next();
         *  if(eventType == TEXT) {
         *     String result = getText();
         *     eventType = next();
         *     if(eventType != END_TAG) {
         *       throw new XmlPullParserException(
         *          "event TEXT it must be immediately followed by END_TAG", this, null);
         *      }
         *      return result;
         *  } else if(eventType == END_TAG) {
         *     return "";
         *  } else {
         *     throw new XmlPullParserException(
         *       "parser must be on START_TAG or TEXT to read text", this, null);
         *  }
         * 
    */ String nextText() throws XmlPullParserException, IOException; /** * Call next() and return event if it is START_TAG or END_TAG * otherwise throw an exception. * It will skip whitespace TEXT before actual tag if any. * *

    essentially it does this *

         *   int eventType = next();
         *   if(eventType == TEXT &&  isWhitespace()) {   // skip whitespace
         *      eventType = next();
         *   }
         *   if (eventType != START_TAG &&  eventType != END_TAG) {
         *      throw new XmlPullParserException("expected start or end tag", this, null);
         *   }
         *   return eventType;
         * 
    */ int nextTag() throws XmlPullParserException, IOException; } jboss-modules-2.1.6.Final/src/main/java/org/jboss/modules/xml/XmlPullParserException.java000066400000000000000000000023111472011152000314330ustar00rootroot00000000000000/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/ // for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/) package org.jboss.modules.xml; /** * This exception is thrown to signal XML Pull Parser related faults. * * @author Aleksander Slominski */ public class XmlPullParserException extends Exception { private static final long serialVersionUID = - 8715154876633542268L; protected int row = -1; protected int column = -1; public XmlPullParserException(String s) { super(s); } public XmlPullParserException(String msg, XmlPullParser parser, Throwable chain) { super ((msg == null ? "" : msg+" ") + (parser == null ? "" : "(position:"+parser.getPositionDescription()+") ") + (chain == null ? "" : "caused by: "+chain), chain); if (parser != null) { this.row = parser.getLineNumber(); this.column = parser.getColumnNumber(); } } public int getLineNumber() { return row; } public int getColumnNumber() { return column; } } jboss-modules-2.1.6.Final/src/main/resources/000077500000000000000000000000001472011152000210545ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/main/resources/LICENSE.txt000066400000000000000000000261361472011152000227070ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. jboss-modules-2.1.6.Final/src/main/resources/META-INF/000077500000000000000000000000001472011152000222145ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/main/resources/META-INF/services/000077500000000000000000000000001472011152000240375ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/main/resources/META-INF/services/java.lang.System$LoggerFinder000066400000000000000000000013271472011152000314450ustar00rootroot00000000000000# # JBoss, Home of Professional Open Source. # Copyright 2019 Red Hat, Inc., and individual contributors # as indicated by the @author tags. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # org.jboss.modules.ModuleLoggerFinder jboss-modules-2.1.6.Final/src/main/resources/XPP3-LICENSE.txt000066400000000000000000000042171472011152000234330ustar00rootroot00000000000000Indiana University Extreme! Lab Software License Version 1.1.1 Copyright (c) 2002 Extreme! Lab, Indiana University. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by the Indiana University Extreme! Lab (http://www.extreme.indiana.edu/)." Alternately, this acknowledgment may appear in the software itself, if and wherever such third-party acknowledgments normally appear. 4. The names "Indiana Univeristy" and "Indiana Univeristy Extreme! Lab" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact http://www.extreme.indiana.edu/. 5. Products derived from this software may not use "Indiana Univeristy" name nor may "Indiana Univeristy" appear in their name, without prior written permission of the Indiana University. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED 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 AUTHORS, COPYRIGHT HOLDERS OR ITS 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. jboss-modules-2.1.6.Final/src/main/resources/schema/000077500000000000000000000000001472011152000223145ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/main/resources/schema/module-1_0.xsd000066400000000000000000000515451472011152000247100ustar00rootroot00000000000000 Root element for a module declaration. Root element for a filesystem module loader configuration. The module declaration type; contains dependencies, resources, and the main class specification. Lists filter expressions to apply to the export filter of the local resources of this module (optional). By default, everything is exported. If filter expressions are provided, the default action is to accept all paths if no filters match. Lists the dependencies of this module (optional). Lists the resource roots of this module (optional). Specifies the main class of this module; used to run the module from the command-line (optional). The name of this module (required). The version slot of this module (optional). A module name, which consists of one or more dot (.)-separated segments. Each segment must begin and end with an alphanumeric or underscore (_), and may otherwise contain alphanumerics, underscores, and hyphens (-). A module version slot. A slot may consist of one or more alphanumerics, hyphens (-), underscores (_), plus signs (+), asterisks (*), or dots (.). A list of zero or more module dependencies. A specified module dependency. A single module dependency expression. A filter used to restrict what packages or directories from this dependency are re-exported by this module. See also the "export" and "services" attributes. The default action of this filter list is controlled by the value of the "export" attribute. Regardless of the setting of these attributes, this filter always behaves as if it has a final entry which rejects META-INF and all of its subdirectories. A filter used to restrict what packages or directories from this dependency are visible to this module. See also the "services" attribute. The default action of this filter list is to reject a path if not matched. The dependency module name (required). The dependency module version slot (optional). Specifies whether this module dependency is re-exported by default (default is "false"). Setting this attribute to true sets the default action for the export filter list to "accept"; leaving it as false sets the default action to "reject". Thus you can still export dependency resources even if this attribute is false by listing explicit paths for the export list. Specifies whether and how services found in this dependency are used (default is "none"). Specifying a value of "import" for this attribute is equivalent to adding a filter at the end of the import filter list which includes the META-INF/services path from the dependency module. Setting a value of "export" for this attribute is equivalent to the same action on the export filter list. Specifies whether this dependency is optional (defaults to false). An optional dependency will not cause the module to fail to load if not found; however if the module is added later, it will not be retroactively linked into this module's dependency list. The requested behavior for service handling on a dependency. Do not import or export services from this dependency. Import, but do not re-export, services from this dependency. Import and re-export services found in this dependency. A class name. The class name. A filesystem path name. The path name. A list of zero or more resource roots for this deployment. A resource root within this deployment. A resource root within a deployment. A path filter specification for this resource root (optional). By default all paths are accepted. DEPRECATED. The name of this resource root (optional). If not specified, defaults to the value of the path attribute. The path of this resource root, relative to the path in which the module.xml file is found. A filter specification, consisting of zero or more filter items. A path to include. The path value can be a path name or a "glob" which may include the special wildcards "*", "**", and "?". A path to exclude. The path value can be a path name or a "glob" which may include the special wildcards "*", "**", and "?". A set of literal path names to include. Wildcards are not supported. A set of literal path names to exclude. Wildcards are not supported. A path specification type, which may include wildcards. The path name, which can be a literal path name or it may include the special wildcards "*", "**", and "?". A set of literal path names which can be used for efficient matching against multiple possible values. The path name to include in the set. A configuration for the default module loader. A defined loader. More than one loader may be defined. The loader to use. The name matches the value of the "name" attribute of one of the defined loaders. A module root path for this loader. Paths are relative to user directory (user.dir) by default. Specifies another loader whose content should be imported. Such loaders are visible to modules defined by this loader, but not to modules defined in other loaders. The name of this particular module loader. A loader type name, which may consist of letters, numbers, hyphens, and underscores. jboss-modules-2.1.6.Final/src/main/resources/schema/module-1_1.xsd000066400000000000000000000650571472011152000247140ustar00rootroot00000000000000 Root element for a module declaration. Root element for a filesystem module loader configuration. Root element for a module alias declaration. The module declaration type; contains dependencies, resources, and the main class specification. Lists filter expressions to apply to the export filter of the local resources of this module (optional). By default, everything is exported. If filter expressions are provided, the default action is to accept all paths if no filters match. Lists the dependencies of this module (optional). Lists the resource roots of this module (optional). Specifies the main class of this module; used to run the module from the command-line (optional). Lists the user-defined properties to be associated with this module (optional). The name of this module (required). The version slot of this module (optional). A module name, which consists of one or more dot (.)-separated segments. Each segment must begin and end with an alphanumeric or underscore (_), and may otherwise contain alphanumerics, underscores, and hyphens (-). A module version slot. A slot may consist of one or more alphanumerics, hyphens (-), underscores (_), plus signs (+), asterisks (*), or dots (.). A list of zero or more module dependencies. A specified module dependency. A dependency on the system (or embedding) class loader. A single module dependency expression. A filter used to restrict what packages or directories from this dependency are re-exported by this module. See also the "export" and "services" attributes. The default action of this filter list is controlled by the value of the "export" attribute. Regardless of the setting of these attributes, this filter always behaves as if it has a final entry which rejects META-INF and all of its subdirectories. A filter used to restrict what packages or directories from this dependency are visible to this module. See also the "services" attribute. The default action of this filter list is to reject a path if not matched. The dependency module name (required). The dependency module version slot (optional). Specifies whether this module dependency is re-exported by default (default is "false"). Setting this attribute to true sets the default action for the export filter list to "accept"; leaving it as false sets the default action to "reject". Thus you can still export dependency resources even if this attribute is false by listing explicit paths for the export list. Specifies whether and how services found in this dependency are used (default is "none"). Specifying a value of "import" for this attribute is equivalent to adding a filter at the end of the import filter list which includes the META-INF/services path from the dependency module. Setting a value of "export" for this attribute is equivalent to the same action on the export filter list. Specifies whether this dependency is optional (defaults to false). An optional dependency will not cause the module to fail to load if not found; however if the module is added later, it will not be retroactively linked into this module's dependency list. The list of paths which are applicable for this system dependency. A filter used to restrict what packages or directories from this dependency are re-exported by this module. See also the "export" and "services" attributes. The default action of this filter list is controlled by the value of the "export" attribute. Regardless of the setting of these attributes, this filter always behaves as if it has a final entry which rejects META-INF and all of its subdirectories. Specifies whether this module dependency is re-exported by default (default is "false"). Setting this attribute to true sets the default action for the export filter list to "accept"; leaving it as false sets the default action to "reject". Thus you can still export dependency resources even if this attribute is false by listing explicit paths for the export list. The requested behavior for service handling on a dependency. Do not import or export services from this dependency. Import, but do not re-export, services from this dependency. Import and re-export services found in this dependency. A class name. The class name. A filesystem path name. The path name. A list of zero or more resource roots for this deployment. A resource root within this deployment. A resource root within a deployment. A path filter specification for this resource root (optional). By default all paths are accepted. DEPRECATED. The name of this resource root (optional). If not specified, defaults to the value of the path attribute. The path of this resource root, relative to the path in which the module.xml file is found. A filter specification, consisting of zero or more filter items. A path to include. The path value can be a path name or a "glob" which may include the special wildcards "*", "**", and "?". A path to exclude. The path value can be a path name or a "glob" which may include the special wildcards "*", "**", and "?". A set of literal path names to include. Wildcards are not supported. A set of literal path names to exclude. Wildcards are not supported. A path specification type, which may include wildcards. The path name, which can be a literal path name or it may include the special wildcards "*", "**", and "?". A set of literal path names which can be used for efficient matching against multiple possible values. The path name to include in the set. A configuration for the default module loader. A defined loader. More than one loader may be defined. The loader to use. The name matches the value of the "name" attribute of one of the defined loaders. A module root path for this loader. Paths are relative to user directory (user.dir) by default. Specifies another loader whose content should be imported. Such loaders are visible to modules defined by this loader, but not to modules defined in other loaders. The name of this particular module loader. A loader type name, which may consist of letters, numbers, hyphens, and underscores. A module alias type, which defines the target for a module alias. The name of this module alias (required). The version slot of this module alias (optional). The name of the module to which this alias refers (required). The version slot of the module to which this alias refers (optional). A property in this property list. The property name as a string (required). The property value (optional, defaults to "true"). jboss-modules-2.1.6.Final/src/main/resources/schema/module-1_2.xsd000077500000000000000000000654651472011152000247230ustar00rootroot00000000000000 Root element for a module declaration. Root element for a module alias declaration. Root element for an absent module. The module declaration type; contains dependencies, resources, and the main class specification. Lists filter expressions to apply to the export filter of the local resources of this module (optional). By default, everything is exported. If filter expressions are provided, the default action is to accept all paths if no filters match. Lists the dependencies of this module (optional). Lists the resource roots of this module (optional). Specifies the main class of this module; used to run the module from the command-line (optional). Lists the user-defined properties to be associated with this module (optional). Lists the requested permission set for this module. If the requested permissions cannot be assigned, the module cannot be loaded. The name of this module (required). The version slot of this module (optional). A module name, which consists of one or more dot (.)-separated segments. Each segment must begin and end with an alphanumeric or underscore (_), and may otherwise contain alphanumerics, underscores, and hyphens (-). A module version slot. A slot may consist of one or more alphanumerics, hyphens (-), underscores (_), plus signs (+), asterisks (*), or dots (.). A list of zero or more module dependencies. A specified module dependency. A dependency on the system (or embedding) class loader. A single module dependency expression. A filter used to restrict what packages or directories from this dependency are re-exported by this module. See also the "export" and "services" attributes. The default action of this filter list is controlled by the value of the "export" attribute. Regardless of the setting of these attributes, this filter always behaves as if it has a final entry which rejects META-INF and all of its subdirectories. A filter used to restrict what packages or directories from this dependency are visible to this module. See also the "services" attribute. The default action of this filter list is to reject a path if not matched. The dependency module name (required). The dependency module version slot (optional). Specifies whether this module dependency is re-exported by default (default is "false"). Setting this attribute to true sets the default action for the export filter list to "accept"; leaving it as false sets the default action to "reject". Thus you can still export dependency resources even if this attribute is false by listing explicit paths for the export list. Specifies whether and how services found in this dependency are used (default is "none"). Specifying a value of "import" for this attribute is equivalent to adding a filter at the end of the import filter list which includes the META-INF/services path from the dependency module. Setting a value of "export" for this attribute is equivalent to the same action on the export filter list. Specifies whether this dependency is optional (defaults to false). An optional dependency will not cause the module to fail to load if not found; however if the module is added later, it will not be retroactively linked into this module's dependency list. The list of paths which are applicable for this system dependency. A filter used to restrict what packages or directories from this dependency are re-exported by this module. See also the "export" and "services" attributes. The default action of this filter list is controlled by the value of the "export" attribute. Regardless of the setting of these attributes, this filter always behaves as if it has a final entry which rejects META-INF and all of its subdirectories. Specifies whether this module dependency is re-exported by default (default is "false"). Setting this attribute to true sets the default action for the export filter list to "accept"; leaving it as false sets the default action to "reject". Thus you can still export dependency resources even if this attribute is false by listing explicit paths for the export list. The requested behavior for service handling on a dependency. Do not import or export services from this dependency. Import, but do not re-export, services from this dependency. Import and re-export services found in this dependency. A class name. The class name. A filesystem path name. The path name. A list of zero or more resource roots for this deployment. A resource root within this deployment. A resource root within a deployment. A path filter specification for this resource root (optional). By default all paths are accepted. DEPRECATED. The name of this resource root (optional). If not specified, defaults to the value of the path attribute. The path of this resource root, relative to the path in which the module.xml file is found. A filter specification, consisting of zero or more filter items. A path to include. The path value can be a path name or a "glob" which may include the special wildcards "*", "**", and "?". A path to exclude. The path value can be a path name or a "glob" which may include the special wildcards "*", "**", and "?". A set of literal path names to include. Wildcards are not supported. A set of literal path names to exclude. Wildcards are not supported. A path specification type, which may include wildcards. The path name, which can be a literal path name or it may include the special wildcards "*", "**", and "?". A set of literal path names which can be used for efficient matching against multiple possible values. The path name to include in the set. A module alias type, which defines the target for a module alias. The name of this module alias (required). The version slot of this module alias (optional). The name of the module to which this alias refers (required). The version slot of the module to which this alias refers (optional). An explicitly absent module. The name of the absent module (required). The version slot of the absent module (optional). A property in this property list. The property name as a string (required). The property value (optional, defaults to "true"). A list of permissions that this module requires. The permission to grant. The qualified class name of the permission to grant. The permission name to provide to the permission class constructor. The (optional) list of actions, required by some permission types. jboss-modules-2.1.6.Final/src/main/resources/schema/module-1_3.xsd000077500000000000000000000704501472011152000247120ustar00rootroot00000000000000 Root element for a module declaration. Root element for a module alias declaration. Root element for an absent module. The module declaration type; contains dependencies, resources, and the main class specification. Lists filter expressions to apply to the export filter of the local resources of this module (optional). By default, everything is exported. If filter expressions are provided, the default action is to accept all paths if no filters match. Lists the dependencies of this module (optional). Lists the resource roots of this module (optional). Specifies the main class of this module; used to run the module from the command-line (optional). Lists the user-defined properties to be associated with this module (optional). Lists the requested permission set for this module. If the requested permissions cannot be assigned, the module cannot be loaded. The name of this module (required). The version slot of this module (optional). A module name, which consists of one or more dot (.)-separated segments. Each segment must begin and end with an alphanumeric or underscore (_), and may otherwise contain alphanumerics, underscores, and hyphens (-). A module version slot. A slot may consist of one or more alphanumerics, hyphens (-), underscores (_), plus signs (+), asterisks (*), or dots (.). A list of zero or more module dependencies. A specified module dependency. A dependency on the system (or embedding) class loader. A single module dependency expression. A filter used to restrict what packages or directories from this dependency are re-exported by this module. See also the "export" and "services" attributes. The default action of this filter list is controlled by the value of the "export" attribute. Regardless of the setting of these attributes, this filter always behaves as if it has a final entry which rejects META-INF and all of its subdirectories. A filter used to restrict what packages or directories from this dependency are visible to this module. See also the "services" attribute. The default action of this filter list is to reject a path if not matched. The dependency module name (required). The dependency module version slot (optional). Specifies whether this module dependency is re-exported by default (default is "false"). Setting this attribute to true sets the default action for the export filter list to "accept"; leaving it as false sets the default action to "reject". Thus you can still export dependency resources even if this attribute is false by listing explicit paths for the export list. Specifies whether and how services found in this dependency are used (default is "none"). Specifying a value of "import" for this attribute is equivalent to adding a filter at the end of the import filter list which includes the META-INF/services path from the dependency module. Setting a value of "export" for this attribute is equivalent to the same action on the export filter list. Specifies whether this dependency is optional (defaults to false). An optional dependency will not cause the module to fail to load if not found; however if the module is added later, it will not be retroactively linked into this module's dependency list. The list of paths which are applicable for this system dependency. A filter used to restrict what packages or directories from this dependency are re-exported by this module. See also the "export" and "services" attributes. The default action of this filter list is controlled by the value of the "export" attribute. Regardless of the setting of these attributes, this filter always behaves as if it has a final entry which rejects META-INF and all of its subdirectories. Specifies whether this module dependency is re-exported by default (default is "false"). Setting this attribute to true sets the default action for the export filter list to "accept"; leaving it as false sets the default action to "reject". Thus you can still export dependency resources even if this attribute is false by listing explicit paths for the export list. The requested behavior for service handling on a dependency. Do not import or export services from this dependency. Import, but do not re-export, services from this dependency. Import and re-export services found in this dependency. A class name. The class name. A filesystem path name. The path name. A list of zero or more resource roots for this deployment. A resource root within this deployment. A maven artifact within this deployment. A maven native artifact within this deployment. This is a jar that contains a lib/ directory with corresponding platform directories and binaries. This element will cause the jar to be unzipped within the artifact's local repository directory. A maven artifact within a deployment. URI that points to the maven artifact "group:artifact:version[:classifier]" A resource root within a deployment. A path filter specification for this resource root (optional). By default all paths are accepted. DEPRECATED. The name of this resource root (optional). If not specified, defaults to the value of the path attribute. The path of this resource root, relative to the path in which the module.xml file is found. A filter specification, consisting of zero or more filter items. A path to include. The path value can be a path name or a "glob" which may include the special wildcards "*", "**", and "?". A path to exclude. The path value can be a path name or a "glob" which may include the special wildcards "*", "**", and "?". A set of literal path names to include. Wildcards are not supported. A set of literal path names to exclude. Wildcards are not supported. A path specification type, which may include wildcards. The path name, which can be a literal path name or it may include the special wildcards "*", "**", and "?". A set of literal path names which can be used for efficient matching against multiple possible values. The path name to include in the set. A module alias type, which defines the target for a module alias. The name of this module alias (required). The version slot of this module alias (optional). The name of the module to which this alias refers (required). The version slot of the module to which this alias refers (optional). An explicitly absent module. The name of the absent module (required). The version slot of the absent module (optional). A property in this property list. The property name as a string (required). The property value (optional, defaults to "true"). A list of permissions that this module requires. The permission to grant. The qualified class name of the permission to grant. The permission name to provide to the permission class constructor. The (optional) list of actions, required by some permission types. jboss-modules-2.1.6.Final/src/main/resources/schema/module-1_5.xsd000077500000000000000000000714311472011152000247140ustar00rootroot00000000000000 Root element for a module declaration. Root element for a module alias declaration. Root element for an absent module. The module declaration type; contains dependencies, resources, and the main class specification. Lists filter expressions to apply to the export filter of the local resources of this module (optional). By default, everything is exported. If filter expressions are provided, the default action is to accept all paths if no filters match. Lists the dependencies of this module (optional). Lists the resource roots of this module (optional). Specifies the main class of this module; used to run the module from the command-line (optional). Lists the user-defined properties to be associated with this module (optional). Lists the requested permission set for this module. If the requested permissions cannot be assigned, the module cannot be loaded. The name of this module (required). The version slot of this module (optional). A module name, which consists of one or more dot (.)-separated segments. Each segment must begin and end with an alphanumeric or underscore (_), and may otherwise contain alphanumerics, underscores, and hyphens (-). A module version slot. A slot may consist of one or more alphanumerics, hyphens (-), underscores (_), plus signs (+), asterisks (*), or dots (.). A list of zero or more module dependencies. A specified module dependency. A dependency on the system (or embedding) class loader. A single module dependency expression. A filter used to restrict what packages or directories from this dependency are re-exported by this module. See also the "export" and "services" attributes. The default action of this filter list is controlled by the value of the "export" attribute. Regardless of the setting of these attributes, this filter always behaves as if it has a final entry which rejects META-INF and all of its subdirectories. A filter used to restrict what packages or directories from this dependency are visible to this module. See also the "services" attribute. The default action of this filter list is to reject a path if not matched. The dependency module name (required). The dependency module version slot (optional). Specifies whether this module dependency is re-exported by default (default is "false"). Setting this attribute to true sets the default action for the export filter list to "accept"; leaving it as false sets the default action to "reject". Thus you can still export dependency resources even if this attribute is false by listing explicit paths for the export list. Specifies whether and how services found in this dependency are used (default is "none"). Specifying a value of "import" for this attribute is equivalent to adding a filter at the end of the import filter list which includes the META-INF/services path from the dependency module. Setting a value of "export" for this attribute is equivalent to the same action on the export filter list. Specifies whether this dependency is optional (defaults to false). An optional dependency will not cause the module to fail to load if not found; however if the module is added later, it will not be retroactively linked into this module's dependency list. The list of paths which are applicable for this system dependency. A filter used to restrict what packages or directories from this dependency are re-exported by this module. See also the "export" and "services" attributes. The default action of this filter list is controlled by the value of the "export" attribute. Regardless of the setting of these attributes, this filter always behaves as if it has a final entry which rejects META-INF and all of its subdirectories. Specifies whether this module dependency is re-exported by default (default is "false"). Setting this attribute to true sets the default action for the export filter list to "accept"; leaving it as false sets the default action to "reject". Thus you can still export dependency resources even if this attribute is false by listing explicit paths for the export list. The requested behavior for service handling on a dependency. Do not import or export services from this dependency. Import, but do not re-export, services from this dependency. Import and re-export services found in this dependency. A class name. The class name. A filesystem path name. The path name. A list of zero or more resource roots for this deployment. A resource root within this deployment. A maven artifact within this deployment. A maven native artifact within this deployment. This is a jar that contains a lib/ directory with corresponding platform directories and binaries. This element will cause the jar to be unzipped within the artifact's local repository directory. A maven artifact within a deployment. A path filter specification for this resource root (optional). By default all paths are accepted. URI that points to the maven artifact "group:artifact:version[:classifier]" A resource root within a deployment. A path filter specification for this resource root (optional). By default all paths are accepted. DEPRECATED. The name of this resource root (optional). If not specified, defaults to the value of the path attribute. The path of this resource root, either absolute or relative. Relative paths are resolved with respect to the location at which the module.xml file is found. A filter specification, consisting of zero or more filter items. A path to include. The path value can be a path name or a "glob" which may include the special wildcards "*", "**", and "?". A path to exclude. The path value can be a path name or a "glob" which may include the special wildcards "*", "**", and "?". A set of literal path names to include. Wildcards are not supported. A set of literal path names to exclude. Wildcards are not supported. A path specification type, which may include wildcards. The path name, which can be a literal path name or it may include the special wildcards "*", "**", and "?". A set of literal path names which can be used for efficient matching against multiple possible values. The path name to include in the set. A module alias type, which defines the target for a module alias. The name of this module alias (required). The version slot of this module alias (optional). The name of the module to which this alias refers (required). The version slot of the module to which this alias refers (optional). An explicitly absent module. The name of the absent module (required). The version slot of the absent module (optional). A property in this property list. The property name as a string (required). The property value (optional, defaults to "true"). A list of permissions that this module requires. The permission to grant. The qualified class name of the permission to grant. The permission name to provide to the permission class constructor. The (optional) list of actions, required by some permission types. jboss-modules-2.1.6.Final/src/main/resources/schema/module-1_6.xsd000077500000000000000000000653151472011152000247210ustar00rootroot00000000000000 Root element for a module declaration. Root element for a module alias declaration. Root element for an absent module. The module declaration type; contains dependencies, resources, and the main class specification. Lists filter expressions to apply to the export filter of the local resources of this module (optional). By default, everything is exported. If filter expressions are provided, the default action is to accept all paths if no filters match. Lists the dependencies of this module (optional). Lists the resource roots of this module (optional). Specifies the main class of this module; used to run the module from the command-line (optional). Lists the user-defined properties to be associated with this module (optional). Lists the requested permission set for this module. If the requested permissions cannot be assigned, the module cannot be loaded. The name of this module (required). The version of this module (optional). A module version string. A list of zero or more module dependencies. A specified module dependency. A dependency on the system (or embedding) class loader. A single module dependency expression. A filter used to restrict what packages or directories from this dependency are re-exported by this module. See also the "export" and "services" attributes. The default action of this filter list is controlled by the value of the "export" attribute. Regardless of the setting of these attributes, this filter always behaves as if it has a final entry which rejects META-INF and all of its subdirectories. A filter used to restrict what packages or directories from this dependency are visible to this module. See also the "services" attribute. The default action of this filter list is to reject a path if not matched. The dependency module name (required). Specifies whether this module dependency is re-exported by default (default is "false"). Setting this attribute to true sets the default action for the export filter list to "accept"; leaving it as false sets the default action to "reject". Thus you can still export dependency resources even if this attribute is false by listing explicit paths for the export list. Specifies whether and how services found in this dependency are used (default is "none"). Specifying a value of "import" for this attribute is equivalent to adding a filter at the end of the import filter list which includes the META-INF/services path from the dependency module. Setting a value of "export" for this attribute is equivalent to the same action on the export filter list. Specifies whether this dependency is optional (defaults to false). An optional dependency will not cause the module to fail to load if not found; however if the module is added later, it will not be retroactively linked into this module's dependency list. The list of paths which are applicable for this system dependency. A filter used to restrict what packages or directories from this dependency are re-exported by this module. See also the "export" and "services" attributes. The default action of this filter list is controlled by the value of the "export" attribute. Regardless of the setting of these attributes, this filter always behaves as if it has a final entry which rejects META-INF and all of its subdirectories. Specifies whether this module dependency is re-exported by default (default is "false"). Setting this attribute to true sets the default action for the export filter list to "accept"; leaving it as false sets the default action to "reject". Thus you can still export dependency resources even if this attribute is false by listing explicit paths for the export list. The requested behavior for service handling on a dependency. Do not import or export services from this dependency. Import, but do not re-export, services from this dependency. Import and re-export services found in this dependency. A class name. The class name. A filesystem path name. The path name. A list of zero or more resource roots for this deployment. A resource root within this deployment. A maven artifact within this deployment. A maven native artifact within this deployment. This is a jar that contains a lib/ directory with corresponding platform directories and binaries. This element will cause the jar to be unzipped within the artifact's local repository directory. A maven artifact within a deployment. A path filter specification for this resource root (optional). By default all paths are accepted. URI that points to the maven artifact "group:artifact:version[:classifier]" A resource root within a deployment. A path filter specification for this resource root (optional). By default all paths are accepted. DEPRECATED. The name of this resource root (optional). If not specified, defaults to the value of the path attribute. The path of this resource root, either absolute or relative. Relative paths are resolved with respect to the location at which the module.xml file is found. A filter specification, consisting of zero or more filter items. A path to include. The path value can be a path name or a "glob" which may include the special wildcards "*", "**", and "?". A path to exclude. The path value can be a path name or a "glob" which may include the special wildcards "*", "**", and "?". A set of literal path names to include. Wildcards are not supported. A set of literal path names to exclude. Wildcards are not supported. A path specification type, which may include wildcards. The path name, which can be a literal path name or it may include the special wildcards "*", "**", and "?". A set of literal path names which can be used for efficient matching against multiple possible values. The path name to include in the set. A module alias type, which defines the target for a module alias. The name of this module alias (required). The name of the module to which this alias refers (required). An explicitly absent module. The name of the absent module (required). A property in this property list. The property name as a string (required). The property value (optional, defaults to "true"). A list of permissions that this module requires. The permission to grant. The qualified class name of the permission to grant. The permission name to provide to the permission class constructor. The (optional) list of actions, required by some permission types. jboss-modules-2.1.6.Final/src/main/resources/schema/module-1_7.xsd000077500000000000000000000727501472011152000247230ustar00rootroot00000000000000 Root element for a module declaration. Root element for a module alias declaration. Root element for an absent module. The module declaration type; contains dependencies, resources, and the main class specification. Lists filter expressions to apply to the export filter of the local resources of this module (optional). By default, everything is exported. If filter expressions are provided, the default action is to accept all paths if no filters match. Lists the dependencies of this module (optional). Lists the resource roots of this module (optional). Specifies the main class of this module; used to run the module from the command-line (optional). Lists the user-defined properties to be associated with this module (optional). Lists the requested permission set for this module. If the requested permissions cannot be assigned, the module cannot be loaded. The name of this module (required). The version of this module (optional). A module version string. A list of zero or more module dependencies. A specified module dependency. A dependency on the system (or embedding) class loader. A single module dependency expression. A filter used to restrict what packages or directories from this dependency are re-exported by this module. See also the "export" and "services" attributes. The default action of this filter list is controlled by the value of the "export" attribute. Regardless of the setting of these attributes, this filter always behaves as if it has a final entry which rejects META-INF and all of its subdirectories. A filter used to restrict what packages or directories from this dependency are visible to this module. See also the "services" attribute. The default action of this filter list is to reject a path if not matched. The dependency module name (required). Specifies whether this module dependency is re-exported by default (default is "false"). Setting this attribute to true sets the default action for the export filter list to "accept"; leaving it as false sets the default action to "reject". Thus you can still export dependency resources even if this attribute is false by listing explicit paths for the export list. Specifies whether and how services found in this dependency are used (default is "none"). Specifying a value of "import" for this attribute is equivalent to adding a filter at the end of the import filter list which includes the META-INF/services path from the dependency module. Setting a value of "export" for this attribute is equivalent to the same action on the export filter list. Specifies whether this dependency is optional (defaults to false). An optional dependency will not cause the module to fail to load if not found; however if the module is added later, it will not be retroactively linked into this module's dependency list. The list of paths which are applicable for this system dependency. A filter used to restrict what packages or directories from this dependency are re-exported by this module. See also the "export" and "services" attributes. The default action of this filter list is controlled by the value of the "export" attribute. Regardless of the setting of these attributes, this filter always behaves as if it has a final entry which rejects META-INF and all of its subdirectories. Specifies whether this module dependency is re-exported by default (default is "false"). Setting this attribute to true sets the default action for the export filter list to "accept"; leaving it as false sets the default action to "reject". Thus you can still export dependency resources even if this attribute is false by listing explicit paths for the export list. The requested behavior for service handling on a dependency. Do not import or export services from this dependency. Import, but do not re-export, services from this dependency. Import and re-export services found in this dependency. A class name. The class name. A filesystem path name. The path name. A list of zero or more resource roots for this deployment. A resource root within this deployment. A maven artifact within this deployment. A maven native artifact within this deployment. This is a jar that contains a lib/ directory with corresponding platform directories and binaries. This element will cause the jar to be unzipped within the artifact's local repository directory. A maven artifact within a deployment. A path filter specification for this resource root (optional). By default all paths are accepted. A condition filter specification for this resource root (optional). If this resolves to false the resource will not be used. URI that points to the maven artifact "group:artifact:version[:classifier]" A resource root within a deployment. A path filter specification for this resource root (optional). By default all paths are accepted. A condition filter specification for this resource root (optional). If this resolves to false the resource will not be used. DEPRECATED. The name of this resource root (optional). If not specified, defaults to the value of the path attribute. The path of this resource root, either absolute or relative. Relative paths are resolved with respect to the location at which the module.xml file is found. A filter specification, consisting of zero or more filter items. A path to include. The path value can be a path name or a "glob" which may include the special wildcards "*", "**", and "?". A path to exclude. The path value can be a path name or a "glob" which may include the special wildcards "*", "**", and "?". A set of literal path names to include. Wildcards are not supported. A set of literal path names to exclude. Wildcards are not supported. A path specification type, which may include wildcards. The path name, which can be a literal path name or it may include the special wildcards "*", "**", and "?". A set of literal path names which can be used for efficient matching against multiple possible values. The path name to include in the set. A module alias type, which defines the target for a module alias. The name of this module alias (required). The name of the module to which this alias refers (required). An explicitly absent module. The name of the absent module (required). A property in this property list. The property name as a string (required). The property value (optional, defaults to "true"). A list of permissions that this module requires. The permission to grant. The qualified class name of the permission to grant. The permission name to provide to the permission class constructor. The (optional) list of actions, required by some permission types. A condition that determines if a resource is used. All conditions must resolve to true for the resource to be included in the module. A condition that evaluates to true if the property is equal to the provided value. A condition that evaluates to true if the property is equal to the provided value. A condition based on the value of a system property. The property name The property value jboss-modules-2.1.6.Final/src/main/resources/schema/module-1_8.xsd000077500000000000000000000703731472011152000247230ustar00rootroot00000000000000 Root element for a module declaration. Root element for a module alias declaration. Root element for an absent module. The module declaration type; contains dependencies, resources, and the main class specification. Lists filter expressions to apply to the export filter of the local resources of this module (optional). By default, everything is exported. If filter expressions are provided, the default action is to accept all paths if no filters match. Lists the dependencies of this module (optional). Lists the resource roots of this module (optional). Specifies the main class of this module; used to run the module from the command-line (optional). Lists the user-defined properties to be associated with this module (optional). Lists the requested permission set for this module. If the requested permissions cannot be assigned, the module cannot be loaded. Lists items that are statically provided by this module. The name of this module (required). The version of this module (optional). A module version string. A list of zero or more module dependencies. A specified module dependency. A single module dependency expression. A filter used to restrict what packages or directories from this dependency are re-exported by this module. See also the "export" and "services" attributes. The default action of this filter list is controlled by the value of the "export" attribute. Regardless of the setting of these attributes, this filter always behaves as if it has a final entry which rejects META-INF and all of its subdirectories. A filter used to restrict what packages or directories from this dependency are visible to this module. See also the "services" attribute. The default action of this filter list is to reject a path if not matched. The dependency module name (required). Specifies whether this module dependency is re-exported by default (default is "false"). Setting this attribute to true sets the default action for the export filter list to "accept"; leaving it as false sets the default action to "reject". Thus you can still export dependency resources even if this attribute is false by listing explicit paths for the export list. Specifies whether and how services found in this dependency are used (default is "none"). Specifying a value of "import" for this attribute is equivalent to adding a filter at the end of the import filter list which includes the META-INF/services path from the dependency module. Setting a value of "export" for this attribute is equivalent to the same action on the export filter list. Specifies whether this dependency is optional (defaults to false). An optional dependency will not cause the module to fail to load if not found; however if the module is added later, it will not be retroactively linked into this module's dependency list. The requested behavior for service handling on a dependency. Do not import or export services from this dependency. Import, but do not re-export, services from this dependency. Import and re-export services found in this dependency. A class name. The class name. A filesystem path name. The path name. A list of zero or more resource roots for this deployment. A resource root within this deployment. A maven artifact within this deployment. A maven native artifact within this deployment. This is a jar that contains a lib/ directory with corresponding platform directories and binaries. This element will cause the jar to be unzipped within the artifact's local repository directory. A maven artifact within a deployment. A path filter specification for this resource root (optional). By default all paths are accepted. A condition filter specification for this resource root (optional). If this resolves to false the resource will not be used. URI that points to the maven artifact "group:artifact:version[:classifier]" A resource root within a deployment. A path filter specification for this resource root (optional). By default all paths are accepted. A condition filter specification for this resource root (optional). If this resolves to false the resource will not be used. The path of this resource root, either absolute or relative. Relative paths are resolved with respect to the location at which the module.xml file is found. A filter specification, consisting of zero or more filter items. A path to include. The path value can be a path name or a "glob" which may include the special wildcards "*", "**", and "?". A path to exclude. The path value can be a path name or a "glob" which may include the special wildcards "*", "**", and "?". A set of literal path names to include. Wildcards are not supported. A set of literal path names to exclude. Wildcards are not supported. A path specification type, which may include wildcards. The path name, which can be a literal path name or it may include the special wildcards "*", "**", and "?". A set of literal path names which can be used for efficient matching against multiple possible values. The path name to include in the set. A module alias type, which defines the target for a module alias. The name of this module alias (required). The name of the module to which this alias refers (required). An explicitly absent module. The name of the absent module (required). A property in this property list. The property name as a string (required). The property value (optional, defaults to "true"). A list of permissions that this module requires. The permission to grant. The qualified class name of the permission to grant. The permission name to provide to the permission class constructor. The (optional) list of actions, required by some permission types. A condition that determines if a resource is used. All conditions must resolve to true for the resource to be included in the module. A condition that evaluates to true if the property is equal to the provided value. A condition that evaluates to true if the property is equal to the provided value. A condition based on the value of a system property. The property name The property value The items that are provided by a module. A service to provide. A service that is provided by one or more implementations. The name of the service type. jboss-modules-2.1.6.Final/src/main/resources/schema/module-1_9.xsd000077500000000000000000000712101472011152000247130ustar00rootroot00000000000000 Root element for a module declaration. Root element for a module alias declaration. Root element for an absent module. The module declaration type; contains dependencies, resources, and the main class specification. Lists filter expressions to apply to the export filter of the local resources of this module (optional). By default, everything is exported. If filter expressions are provided, the default action is to accept all paths if no filters match. Lists the dependencies of this module (optional). Lists the resource roots of this module (optional). Specifies the main class of this module; used to run the module from the command-line (optional). Lists the user-defined properties to be associated with this module (optional). Lists the requested permission set for this module. If the requested permissions cannot be assigned, the module cannot be loaded. Lists items that are statically provided by this module. The name of this module (required). The version of this module (optional). A module version string. A list of zero or more module dependencies. A specified module dependency. A single module dependency expression. Lists the user-defined properties to be associated with this module dependency (optional). A filter used to restrict what packages or directories from this dependency are re-exported by this module. See also the "export" and "services" attributes. The default action of this filter list is controlled by the value of the "export" attribute. Regardless of the setting of these attributes, this filter always behaves as if it has a final entry which rejects META-INF and all of its subdirectories. A filter used to restrict what packages or directories from this dependency are visible to this module. See also the "services" attribute. The default action of this filter list is to reject a path if not matched. The dependency module name (required). Specifies whether this module dependency is re-exported by default (default is "false"). Setting this attribute to true sets the default action for the export filter list to "accept"; leaving it as false sets the default action to "reject". Thus you can still export dependency resources even if this attribute is false by listing explicit paths for the export list. Specifies whether and how services found in this dependency are used (default is "none"). Specifying a value of "import" for this attribute is equivalent to adding a filter at the end of the import filter list which includes the META-INF/services path from the dependency module. Setting a value of "export" for this attribute is equivalent to the same action on the export filter list. Specifies whether this dependency is optional (defaults to false). An optional dependency will not cause the module to fail to load if not found; however if the module is added later, it will not be retroactively linked into this module's dependency list. The requested behavior for service handling on a dependency. Do not import or export services from this dependency. Import, but do not re-export, services from this dependency. Import and re-export services found in this dependency. A class name. The class name. A filesystem path name. The path name. A list of zero or more resource roots for this deployment. A resource root within this deployment. A maven artifact within this deployment. A maven native artifact within this deployment. This is a jar that contains a lib/ directory with corresponding platform directories and binaries. This element will cause the jar to be unzipped within the artifact's local repository directory. A maven artifact within a deployment. A path filter specification for this resource root (optional). By default all paths are accepted. A condition filter specification for this resource root (optional). If this resolves to false the resource will not be used. URI that points to the maven artifact "group:artifact:version[:classifier]" A resource root within a deployment. A path filter specification for this resource root (optional). By default all paths are accepted. A condition filter specification for this resource root (optional). If this resolves to false the resource will not be used. The path of this resource root, either absolute or relative. Relative paths are resolved with respect to the location at which the module.xml file is found. A filter specification, consisting of zero or more filter items. A path to include. The path value can be a path name or a "glob" which may include the special wildcards "*", "**", and "?". A path to exclude. The path value can be a path name or a "glob" which may include the special wildcards "*", "**", and "?". A set of literal path names to include. Wildcards are not supported. A set of literal path names to exclude. Wildcards are not supported. A path specification type, which may include wildcards. The path name, which can be a literal path name or it may include the special wildcards "*", "**", and "?". A set of literal path names which can be used for efficient matching against multiple possible values. The path name to include in the set. A module alias type, which defines the target for a module alias. The name of this module alias (required). The name of the module to which this alias refers (required). An explicitly absent module. The name of the absent module (required). A property in this property list. The property name as a string (required). The property value (optional, defaults to "true"). A list of permissions that this module requires. The permission to grant. The qualified class name of the permission to grant. The permission name to provide to the permission class constructor. The (optional) list of actions, required by some permission types. A condition that determines if a resource is used. All conditions must resolve to true for the resource to be included in the module. A condition that evaluates to true if the property is equal to the provided value. A condition that evaluates to true if the property is equal to the provided value. A condition based on the value of a system property. The property name The property value The items that are provided by a module. A service to provide. A service that is provided by one or more implementations. The name of the service type. jboss-modules-2.1.6.Final/src/test/000077500000000000000000000000001472011152000170755ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/java/000077500000000000000000000000001472011152000200165ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/java/org/000077500000000000000000000000001472011152000206055ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/java/org/jboss/000077500000000000000000000000001472011152000217255ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/000077500000000000000000000000001472011152000233755ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/AbstractModuleTestCase.java000066400000000000000000000057261472011152000306170ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import org.jboss.modules.log.StreamModuleLogger; import org.jboss.modules.util.Util; import org.junit.BeforeClass; import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * Abstract Test Case used as a base for all module tests. * * @author John Bailey */ public abstract class AbstractModuleTestCase { @BeforeClass public static void initUrlHandler() { // this also kicks off Module's static init Module.setModuleLogger(new StreamModuleLogger(System.err)); } protected File getResource(final String path) throws Exception { return Util.getResourceFile(getClass(), path); } protected void copyResource(final String inputResource, final String outputBase, final String outputPath) throws Exception { final File resource = getResource(inputResource); final File outputDirectory = new File(getResource(outputBase), outputPath); if(!resource.exists()) throw new IllegalArgumentException("Resource does not exist"); if (outputDirectory.exists() && outputDirectory.isFile()) throw new IllegalArgumentException("OutputDirectory must be a directory"); if (!outputDirectory.exists()) { if (!outputDirectory.mkdirs()) throw new RuntimeException("Failed to create output directory"); } final File outputFile = new File(outputDirectory, resource.getName()); final InputStream in = new FileInputStream(resource); try { final OutputStream out = new FileOutputStream(outputFile); try { final byte[] b = new byte[8192]; int c; while ((c = in.read(b)) != -1) { out.write(b, 0, c); } out.close(); in.close(); } finally { safeClose(out); } } finally { safeClose(in); } } private static void safeClose(final Closeable closeable) { if (closeable != null) try { closeable.close(); } catch (IOException e) { // meh } } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/AbstractResourceLoaderTestCase.java000066400000000000000000000152261472011152000323040ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import static org.jboss.modules.util.Util.readBytes; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.net.URL; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import org.jboss.modules.filter.PathFilter; import org.jboss.modules.filter.PathFilters; import org.junit.Before; import org.junit.Test; /** * Abstract Test Case used as the base for all resource loader tests. * * @author John Bailey */ public abstract class AbstractResourceLoaderTestCase extends AbstractModuleTestCase { protected ResourceLoader loader; @Before public void setupLoader() throws Exception { loader = createLoader(PathFilters.acceptAll()); } protected abstract ResourceLoader createLoader(final PathFilter exportFilter) throws Exception; protected abstract void assertResource(final Resource resource, final String fileName) throws Exception; @Test public void testBasicResource() throws Exception { Resource resource = loader.getResource("/test.txt"); assertNotNull(resource); assertResource(resource, "test.txt"); resource = loader.getResource("/nested/nested.txt"); assertNotNull(resource); assertResource(resource, "nested/nested.txt"); } @Test public void testMissingResource() throws Exception { Resource resource = loader.getResource("/test-bogus.txt"); assertNull(resource); } @Test public void testIndexPaths() throws Exception { final Collection paths = loader.getPaths(); assertFalse(paths.isEmpty()); assertTrue(paths.contains("")); assertTrue(paths.contains("META-INF")); assertTrue(paths.contains("nested")); assertTrue(paths.contains("org")); assertTrue(paths.contains("org/jboss")); assertTrue(paths.contains("org/jboss/modules")); assertTrue(paths.contains("org/jboss/modules/test")); } @Test public void testGetClassSpec() throws Exception { ClassSpec spec = loader.getClassSpec(Module.fileNameOfClass("org.jboss.modules.test.TestClass")); assertNotNull(spec); byte[] bytes = spec.getBytes(); final URL classResource = getClass().getClassLoader().getResource("org/jboss/modules/test/TestClass.class"); final byte[] expectedBytes = readBytes(classResource.openStream()); assertArrayEquals(expectedBytes, bytes); } @Test public void testMissingClassSpec() throws Exception { ClassSpec spec = loader.getClassSpec(Module.fileNameOfClass("org.jboss.modules.test.BogusClass")); assertNull(spec); } @Test public void testGetPackageSpec() throws Exception { PackageSpec spec = loader.getPackageSpec("org.jboss.modules.test"); assertNotNull(spec); assertEquals("JBoss Modules Test Classes", spec.getSpecTitle()); assertEquals("0.1", spec.getSpecVersion()); assertEquals("JBoss", spec.getSpecVendor()); assertEquals("org.jboss.modules.test", spec.getImplTitle()); assertEquals("1.0", spec.getImplVersion()); assertEquals("JBoss", spec.getImplVendor()); } @Test public void testMissingPackageSpec() throws Exception { PackageSpec spec = loader.getPackageSpec("org.jboss.modules.bogus"); assertNotNull(spec); assertEquals("MODULES-89", spec.getSpecTitle()); assertNull(spec.getSpecVersion()); assertNull(spec.getSpecVendor()); assertNull(spec.getImplTitle()); assertNull(spec.getImplVersion()); assertNull(spec.getImplVendor()); } @Test public void testIterateResourcesRootRecursive() throws Exception { Set expected = new HashSet(); expected.add("test.txt"); expected.add("nested/nested.txt"); expected.add("org/jboss/modules/test/TestClass.class"); expected.add("META-INF/MANIFEST.MF"); assertEquals(expected, getResourceNames("/", true)); assertEquals(expected, getResourceNames("", true)); } @Test public void testIterateResourcesRoot() throws Exception { Set expected = new HashSet(); expected.add("test.txt"); assertEquals(expected, getResourceNames("/", false)); assertEquals(expected, getResourceNames("", false)); } @Test public void testIterateResourcesNested() throws Exception { Set expected = new HashSet(); expected.add("nested/nested.txt"); assertEquals(expected, getResourceNames("/nested", true)); assertEquals(expected, getResourceNames("/nested", false)); assertEquals(expected, getResourceNames("nested", true)); assertEquals(expected, getResourceNames("nested", false)); } @Test public void testIterateResourcesClasses() throws Exception { Set expected = new HashSet(); expected.add("org/jboss/modules/test/TestClass.class"); assertEquals(expected, getResourceNames("/org/jboss/modules", true)); assertEquals(expected, getResourceNames("org/jboss/modules", true)); expected = Collections.emptySet(); assertEquals(expected, getResourceNames("/org/jboss/modules", false)); assertEquals(expected, getResourceNames("org/jboss/modules", false)); } private Set getResourceNames(String startPath, boolean recursive) { Set result = new HashSet(); IterableResourceLoader itloader = (IterableResourceLoader) loader; Iterator itres = itloader.iterateResources(startPath, recursive); while(itres.hasNext()) { result.add(itres.next().getName()); } return result; } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ClassDefinerTest.java000066400000000000000000000071111472011152000274420ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2018 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.security.CodeSigner; import java.security.CodeSource; import java.security.ProtectionDomain; import java.util.Collection; import java.util.Collections; import org.jboss.modules.util.TestModuleLoader; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.*; /** */ public class ClassDefinerTest extends AbstractModuleTestCase { private TestModuleLoader moduleLoader; @Before public void setupModuleLoader() { moduleLoader = new TestModuleLoader(); ModuleSpec.Builder builder = ModuleSpec.build("org.module.foo"); builder.addDependency(ModuleDependencySpec.JAVA_BASE); builder.addDependency(DependencySpec.OWN_DEPENDENCY); builder.addResourceRoot(ResourceLoaderSpec.createResourceLoaderSpec(new ResourceLoader() { public ClassSpec getClassSpec(final String fileName) { return null; } public PackageSpec getPackageSpec(final String name) { return null; } public Resource getResource(final String name) { return null; } public String getLibrary(final String name) { return null; } public Collection getPaths() { return Collections.singletonList("org/module/foo"); } })); moduleLoader.addModuleSpec(builder.create()); } @Test public void testDefineClass() throws ModuleLoadException, IOException, ClassNotFoundException { final ClassDefiner classDefiner = ClassDefiner.getInstance(); final Module module = moduleLoader.loadModule("org.module.foo"); final URL resource = ClassDefinerTest.class.getClassLoader().getResource("test/GeneratedClass.class"); assertNotNull(resource); final byte[] classBytes; try (final InputStream stream = resource.openConnection().getInputStream()) { try (final ByteArrayOutputStream os = new ByteArrayOutputStream()) { byte[] buf = new byte[256]; int res; while ((res = stream.read(buf)) != -1) { os.write(buf, 0, res); } classBytes = os.toByteArray(); } } Class c1 = classDefiner.defineClass(module, "org.module.foo.GeneratedClass", new ProtectionDomain( new CodeSource( resource, (CodeSigner[]) null ), ModulesPolicy.DEFAULT_PERMISSION_COLLECTION ), classBytes); Class c2 = module.getClassLoaderPrivate().loadClass("org.module.foo.GeneratedClass"); assertEquals(c1, c2); assertEquals(module.getClassLoaderPrivate(), c1.getClassLoader()); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ClassFilteringTest.java000066400000000000000000000106221472011152000300120ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import org.jboss.modules.filter.ClassFilter; import org.jboss.modules.filter.ClassFilters; import org.jboss.modules.filter.PathFilter; import org.jboss.modules.filter.PathFilters; import org.jboss.modules.test.BarImpl; import org.jboss.modules.test.QuxBar; import org.jboss.modules.test.QuxFoo; import org.jboss.modules.test.QuxImpl; import org.jboss.modules.util.ModulesTestBase; import org.jboss.modules.util.TestResourceLoader; import org.junit.Test; import static org.jboss.modules.ResourceLoaderSpec.createResourceLoaderSpec; import static org.jboss.modules.util.TestResourceLoader.TestResourceLoaderBuilder; /** * [MODULES-69] Allow for OSGi style Class Filtering * * @author Thomas.Diesler@jboss.com * @since 28-Apr-2011 */ public class ClassFilteringTest extends ModulesTestBase { @Test public void testClassFilter() throws Exception { final String identifierA = getClass().getSimpleName(); ModuleSpec.Builder specBuilderA = ModuleSpec.build(identifierA); // Export-Package: com.acme.foo; include:="Qux*,BarImpl";exclude:=QuxImpl String packagePath = QuxBar.class.getPackage().getName().replace('.', '/'); PathFilter inA = PathFilters.match(packagePath + "/Qux*.class"); PathFilter inB = PathFilters.match(packagePath + "/BarImpl.class"); PathFilter exA = PathFilters.match(packagePath + "/QuxImpl.class"); //A class is only visible if it is: // Matched with an entry in the included list, and // Not matched with an entry in the excluded list. PathFilter in = PathFilters.any(inA, inB); PathFilter ex = PathFilters.not(PathFilters.any(exA)); final PathFilter filter = PathFilters.all(in, ex); ClassFilter classImportFilter = ClassFilters.acceptAll(); ClassFilter classExportFilter = ClassFilters.fromResourcePathFilter(filter); specBuilderA.addResourceRoot(createResourceLoaderSpec(getTestResourceLoader())); PathFilter importFilter = PathFilters.acceptAll(); PathFilter exportFilter = PathFilters.acceptAll(); PathFilter resourceImportFilter = PathFilters.acceptAll(); PathFilter resourceExportFilter = PathFilters.acceptAll(); specBuilderA.addDependency(new LocalDependencySpecBuilder() .setImportFilter(importFilter) .setExportFilter(exportFilter) .setResourceImportFilter(resourceImportFilter) .setResourceExportFilter(resourceExportFilter) .setClassImportFilter(classImportFilter) .setClassExportFilter(classExportFilter) .build()); addModuleSpec(specBuilderA.create()); String identifierB = "moduleB"; ModuleSpec.Builder specBuilderB = ModuleSpec.build(identifierB); specBuilderB.addDependency(new ModuleDependencySpecBuilder() .setName(identifierA.toString()) .build()); addModuleSpec(specBuilderB.create()); assertLoadClass(identifierA, QuxFoo.class.getName()); assertLoadClass(identifierA, QuxBar.class.getName()); assertLoadClass(identifierA, QuxImpl.class.getName()); assertLoadClass(identifierA, BarImpl.class.getName()); assertLoadClass(identifierB, QuxFoo.class.getName()); assertLoadClass(identifierB, QuxBar.class.getName()); assertLoadClassFail(identifierB, QuxImpl.class.getName()); assertLoadClass(identifierB, BarImpl.class.getName()); } private TestResourceLoader getTestResourceLoader() throws Exception { TestResourceLoaderBuilder builder = new TestResourceLoaderBuilder(); builder.addClasses(QuxBar.class, QuxFoo.class, QuxImpl.class, BarImpl.class); return builder.create(); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ClassPathModuleLoaderTest.java000066400000000000000000000106211472011152000312570ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.lang.reflect.Method; import org.junit.BeforeClass; import org.junit.Test; import java.io.File; import java.net.URL; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Enumeration; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; /** * Test to verify the functionality of the ClassPathModuleLoader. * * @author @author James R. Perkins * @author Scott Stark (sstark@redhat.com) */ public class ClassPathModuleLoaderTest extends AbstractModuleTestCase { @BeforeClass public static void beforeClass() throws Exception { final Method method = ModuleLoader.class.getDeclaredMethod("installMBeanServer"); method.setAccessible(true); method.invoke(null); } @Test public void testLoader() throws Exception { final File repoRoot = getResource("test/repo"); final String item = Paths.get("").toAbsolutePath().resolve("./target/test-classes/test/repo").normalize().toString(); final String[] classPath = { item }; final String deps = "test.test,test.with-deps"; final String mainClass = "org.jboss.modules.test.TestClass"; final ModuleLoader moduleLoader = new DelegatingModuleLoader(Module.getSystemModuleLoader(), new ClassPathModuleFinder(new LocalModuleLoader(new File[] { repoRoot }), classPath, deps, mainClass)); final Module module = moduleLoader.loadModule(item); module.getClassLoader(); assertNotNull(module); } /** * I need to be able to load EJBContainerProvider from a dependency. * * @author Carlo de Wolf */ @Test public void testService() throws Exception { final File repoRoot = getResource("test/repo"); final String item = Paths.get("").toAbsolutePath().resolve("./target/test-classes/test/repo").normalize().toString(); final String[] classPath = { item }; final String deps = "test.service"; final String mainClass = null; final ModuleLoader moduleLoader = new DelegatingModuleLoader(Module.getSystemModuleLoader(), new ClassPathModuleFinder(new LocalModuleLoader(new File[] { repoRoot }), classPath, deps, mainClass)); final Module module = moduleLoader.loadModule(item); final ClassLoader classLoader = module.getClassLoader(); final URL url = classLoader.getResource("META-INF/services/dummy"); assertNotNull(url); } /** * Validate that dependent module META-INF/services/* content is seen * @throws Exception */ @Test public void testMultipleServices() throws Exception { final File repoRoot = getResource("test/repo"); final String item = Paths.get("").toAbsolutePath().resolve("./target/test-classes/test/repo").normalize().toString(); final String[] classPath = { item }; final String deps = "test.jaxrs"; final String mainClass = null; final ModuleLoader moduleLoader = new DelegatingModuleLoader(Module.getSystemModuleLoader(), new ClassPathModuleFinder(new LocalModuleLoader(new File[] { repoRoot }), classPath, deps, mainClass)); final Module module = moduleLoader.loadModule(item); final ClassLoader classLoader = module.getClassLoader(); final Enumeration services = classLoader.getResources("META-INF/services/javax.ws.rs.ext.Providers"); assertNotNull(services); ArrayList found = new ArrayList(); while(services.hasMoreElements()) { found.add(services.nextElement()); } assertEquals("Found 2 services of type javax.ws.rs.ext.Providers", 2, found.size()); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ConcurrentClassLoaderTest.java000066400000000000000000000122001472011152000313320ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import org.jboss.modules.test.ClassA; import org.jboss.modules.test.ClassB; import org.jboss.modules.test.ClassC; import org.jboss.modules.test.ClassD; import org.jboss.modules.util.Util; import org.junit.Test; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Set; import java.util.concurrent.CountDownLatch; /** * Test case to verify the concurrent classloader base correctly handles common concurrency issues with classloading.. * * @author John E. Bailey */ public class ConcurrentClassLoaderTest { volatile Throwable threadOneProblem; volatile Throwable threadTwoProblem; @Test public void testClassLoadingDeadlockAvoidance() throws Throwable { /* Uncomment the following lines to demonstrate a deadlock that occurs with normal classloader delegation */ //final DeadLockingLoader classLoaderOne = new DeadLockingLoader(ConcurrentClassLoaderTest.class.getClassLoader(), Arrays.asList(ClassA.class.getName(), ClassD.class.getName())); //final DeadLockingLoader classLoaderTwo = new DeadLockingLoader(ConcurrentClassLoaderTest.class.getClassLoader(), Arrays.asList(ClassB.class.getName(), ClassC.class.getName())); final TestConcurrentClassLoader classLoaderOne = new TestConcurrentClassLoader(ConcurrentClassLoaderTest.class.getClassLoader(), Arrays.asList(ClassA.class.getName(), ClassD.class.getName())); final TestConcurrentClassLoader classLoaderTwo = new TestConcurrentClassLoader(ConcurrentClassLoaderTest.class.getClassLoader(), Arrays.asList(ClassB.class.getName(), ClassC.class.getName())); classLoaderOne.delegate = classLoaderTwo; classLoaderTwo.delegate = classLoaderOne; final CountDownLatch latch = new CountDownLatch(1); final Thread threadOne = new Thread(new Runnable() { @Override public void run() { try { latch.await(); classLoaderOne.loadClass(ClassA.class.getName()); } catch (Throwable t) { threadOneProblem = t; } } }); final Thread threadTwo = new Thread(new Runnable() { @Override public void run() { try { latch.await(); classLoaderTwo.loadClass(ClassC.class.getName()); } catch (Throwable t) { threadTwoProblem = t; } } }); threadOne.start(); threadTwo.start(); latch.countDown(); threadOne.join(); threadTwo.join(); if (threadOneProblem != null) throw threadOneProblem; if (threadTwoProblem != null) throw threadTwoProblem; } private static final class TestConcurrentClassLoader extends ConcurrentClassLoader { static { boolean parallelOk = true; try { parallelOk = ClassLoader.registerAsParallelCapable(); } catch (Throwable ignored) { } if (! parallelOk) { throw new Error("Failed to register " + TestConcurrentClassLoader.class.getName() + " as parallel-capable"); } } private final ClassLoader realLoader; private final Set allowedClasses = new HashSet(); private ClassLoader delegate; private TestConcurrentClassLoader(final ClassLoader realLoader, final Collection allowedClasses) { this.realLoader = realLoader; this.allowedClasses.addAll(allowedClasses); } @Override protected Class findClass(String className, boolean exportsOnly, final boolean resolve) throws ClassNotFoundException { Class c = findLoadedClass(className); if(c == null && className.startsWith("java")) c = findSystemClass(className); if(c == null && allowedClasses.contains(className)) { try { final byte[] classBytes = Util.getClassBytes(realLoader.loadClass(className)); c = defineClass(className, classBytes, 0, classBytes.length); } catch(Throwable t) { throw new ClassNotFoundException("Failed to load class " + className, t); } } if(c == null) c = delegate.loadClass(className); return c; } }; } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ConditionalResourceTest.java000066400000000000000000000046771472011152000310710ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import java.io.File; import java.lang.reflect.Method; import java.net.URL; import java.nio.file.Paths; import org.junit.BeforeClass; import org.junit.Test; /** * Test to verify conditional expressions * * @author Stuart Douglas */ public class ConditionalResourceTest extends AbstractModuleTestCase { @BeforeClass public static void beforeClass() throws Exception { final Method method = ModuleLoader.class.getDeclaredMethod("installMBeanServer"); method.setAccessible(true); method.invoke(null); System.setProperty("test-prop", "testval"); } /** * Validate that system property conditional expressions work correctly * @throws Exception */ @Test public void testMultipleServices() throws Exception { final File repoRoot = getResource("test/repo"); final String item = Paths.get("").toAbsolutePath().resolve("./target/test-classes/test/repo").normalize().toString(); final String[] classPath = { item }; final String deps = "test.conditional-active,test.conditional-not-active"; final String mainClass = null; final ModuleLoader moduleLoader = new DelegatingModuleLoader(Module.getSystemModuleLoader(), new ClassPathModuleFinder(new LocalModuleLoader(new File[] { repoRoot }), classPath, deps, mainClass)); final Module module = moduleLoader.loadModule(item); final ClassLoader classLoader = module.getClassLoader(); final URL active = classLoader.getResource("active.txt"); final URL notActive = classLoader.getResource("not-active.txt"); assertNotNull(active); assertNull(notActive); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/DataURLStreamHandlerTest.java000066400000000000000000000111621472011152000310070ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2018 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import static org.junit.Assert.*; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.nio.charset.StandardCharsets; import org.junit.Test; /** */ public class DataURLStreamHandlerTest { public DataURLStreamHandlerTest() { } static URL makeUrl(String str) throws MalformedURLException { return new URL(null, str, DataURLStreamHandler.getInstance()); } static byte[] readAllBytes(URLConnection uc) throws IOException { final byte[] bytes = new byte[uc.getContentLength()]; final InputStream inputStream = uc.getInputStream(); if (inputStream.read(bytes) < bytes.length) { throw new IOException("incomplete read"); } return bytes; } static byte[] bytes(int... vals) { final byte[] bytes = new byte[vals.length]; for (int i = 0; i < bytes.length; i++) { bytes[i] = (byte) vals[i]; } return bytes; } @Test public void testEmpty() throws Exception { final URLConnection urlConnection = makeUrl("data:,").openConnection(); assertEquals(0, urlConnection.getContentLength()); assertEquals("text/plain", urlConnection.getContentType()); assertNull(urlConnection.getContentEncoding()); assertEquals(-1, urlConnection.getInputStream().read()); } @Test public void testText() throws Exception { final URLConnection urlConnection = makeUrl("data:,some kinda text").openConnection(); assertEquals(15, urlConnection.getContentLength()); assertEquals("text/plain", urlConnection.getContentType()); assertEquals("some kinda text", new String(readAllBytes(urlConnection), StandardCharsets.US_ASCII)); } @Test public void testTextUtf8() throws Exception { final URLConnection urlConnection = makeUrl("data:;charset=utf-8,some kïndä tëxt").openConnection(); assertEquals(18, urlConnection.getContentLength()); assertEquals("text/plain;charset=utf-8", urlConnection.getContentType()); assertEquals("some kïndä tëxt", new String(readAllBytes(urlConnection), StandardCharsets.UTF_8)); } @Test public void testTextUtf8Ascii() throws Exception { final URLConnection urlConnection = makeUrl("data:,some kïndä tëxt").openConnection(); assertEquals(15, urlConnection.getContentLength()); assertEquals("text/plain", urlConnection.getContentType()); assertEquals("some k?nd? t?xt", new String(readAllBytes(urlConnection), StandardCharsets.UTF_8)); } @Test public void testPlainBinary() throws Exception { final URLConnection urlConnection = makeUrl("data:x-whatever/stuff;charset=utf-8,some kïndä tëxt").openConnection(); assertEquals(15, urlConnection.getContentLength()); assertEquals("x-whatever/stuff", urlConnection.getContentType()); assertEquals("some k�nd� t�xt", new String(readAllBytes(urlConnection), StandardCharsets.UTF_8)); } @Test public void testRawBinary() throws Exception { final URLConnection urlConnection = makeUrl("data:x-whatever/stuff,%01%02%03%04%05%F0%FF%00").openConnection(); assertEquals(8, urlConnection.getContentLength()); assertEquals("x-whatever/stuff", urlConnection.getContentType()); assertArrayEquals(bytes(0x01, 0x02, 0x03, 0x04, 0x05, 0xf0, 0xff, 0x00), readAllBytes(urlConnection)); } @Test public void testBase64Binary() throws Exception { final URLConnection urlConnection = makeUrl("data:x-whatever/stuff;base64,dGhpcyBpcyBhIHRlc3QhCg==").openConnection(); assertEquals(16, urlConnection.getContentLength()); assertEquals("x-whatever/stuff", urlConnection.getContentType()); assertArrayEquals("this is a test!\n".getBytes(StandardCharsets.UTF_8), readAllBytes(urlConnection)); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ErrorHandlingTest.java000066400000000000000000000041741472011152000276440ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import org.jboss.modules.test.ClassA; import org.jboss.modules.util.TestModuleLoader; import org.jboss.modules.util.TestResourceLoader; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.fail; /** * @author Carlo de Wolf */ public class ErrorHandlingTest extends AbstractModuleTestCase { private static final String MODULE_A = "test-module-a"; private TestModuleLoader moduleLoader; @Before public void before() throws Exception { moduleLoader = new TestModuleLoader(); final ModuleSpec.Builder moduleABuilder = ModuleSpec.build(MODULE_A); moduleABuilder.addResourceRoot(ResourceLoaderSpec.createResourceLoaderSpec( TestResourceLoader.build() .addClass(ClassA.class) .create()) ); moduleABuilder.addDependency(DependencySpec.OWN_DEPENDENCY); moduleLoader.addModuleSpec(moduleABuilder.create()); } @Test public void testNonLinkingClass() throws ModuleLoadException, ClassNotFoundException { final Module module = moduleLoader.loadModule(MODULE_A); final ClassLoader classLoader = module.getClassLoader(); try { classLoader.loadClass(ClassA.class.getName()); fail("Should have thrown a LinkageError"); } catch(LinkageError e) { // good } } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/FileResourceLoaderTest.java000066400000000000000000000035741472011152000306270ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import org.jboss.modules.filter.PathFilter; import org.junit.Assert; import java.io.File; import java.security.AccessController; /** * Test the functionality of the FileResourceLoader * * @author John Bailey */ public class FileResourceLoaderTest extends AbstractResourceLoaderTestCase { private File resourceRoot; protected ResourceLoader createLoader(final PathFilter exportFilter) throws Exception { resourceRoot = getResource("test/fileresourceloader"); // Copy the classfile over copyResource("org/jboss/modules/test/TestClass.class", "test/fileresourceloader", "org/jboss/modules/test"); return new PathResourceLoader("test-root", resourceRoot.toPath(), AccessController.getContext()); } @Override protected void assertResource(Resource resource, String fileName) { final File resourceFile = getExpectedFile(fileName); Assert.assertEquals(resourceFile.length(), resource.getSize()); } public void testGetClassSpec() throws Exception { super.testGetClassSpec(); } protected File getExpectedFile(String fileName) { return new File(resourceRoot, fileName); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/FileSystemClassPathModuleLoaderTest.java000066400000000000000000000036231472011152000332700ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.File; import java.net.URL; import org.jboss.modules.util.Util; import org.junit.Assert; import org.junit.Before; import org.junit.Test; /** * @author David M. Lloyd */ public class FileSystemClassPathModuleLoaderTest { private FileSystemClassPathModuleFinder moduleFinder; private ModuleLoader moduleLoader; @Before public void setup() throws Exception { final File repoRoot = Util.getResourceFile(getClass(), "test/repo"); ModuleLoader localModuleLoader = new LocalModuleLoader(new File[] {repoRoot}); moduleFinder = new FileSystemClassPathModuleFinder(localModuleLoader); moduleLoader = new ModuleLoader(moduleFinder); } @Test public void testModuleLoadFromFileSystemModule() throws Exception { final File resourceFile = Util.getResourceFile(getClass(), "test/filesystem-module-1"); final Module module = moduleLoader.loadModule(resourceFile.getAbsoluteFile().getCanonicalFile().toString()); final URL exportedResource = module.getExportedResource("META-INF/services/javax.ws.rs.ext.Providers"); Assert.assertNotNull(exportedResource); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/InstantiatePrivateAccessTest.java000066400000000000000000000042641472011152000320460ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import java.security.AllPermission; import java.security.Permissions; import org.jboss.modules.security.ModularPermissionFactory; import org.junit.Test; /** * @author David M. Lloyd */ public class InstantiatePrivateAccessTest { @Test public void ensureFailure() { try { Module.getPrivateAccess(); fail("Expected security exception"); } catch (SecurityException ok) {} } @Test public void ensureModularPermissionFactory() { final ModuleLoader moduleLoader = new ModuleLoader(new ModuleFinder[]{ new ModuleFinder() { public ModuleSpec findModule(final String name, final ModuleLoader delegateLoader) throws ModuleLoadException { if (name.equals("test")) { final Permissions perms = new Permissions(); perms.add(new AllPermission()); return ModuleSpec.build("test").setPermissionCollection(perms).create(); } else { return null; } } } }); final ModularPermissionFactory factory = new ModularPermissionFactory(moduleLoader, "test", RuntimePermission.class.getName(), "foo", "*"); assertEquals(new RuntimePermission("foo", "*"), factory.construct()); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/JDKModuleLoaderTest.java000066400000000000000000000052151472011152000300100ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2018 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.net.URL; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.junit.Assert; import org.junit.Assume; import org.junit.Test; /** */ public class JDKModuleLoaderTest extends AbstractModuleTestCase { @Test public void testLoadModulesClassFile() throws ModuleLoadException { final Module module = Module.getSystemModuleLoader().loadModule("org.jboss.modules"); final URL resource = module.getClassLoader().getResource("org/jboss/modules/Main.class"); Assert.assertNotNull("Main.class", resource); } /** * Tests that loading of "java.se" module works and classes that are present * in modules "required" by this "java.se" module can be loaded too * * @throws Exception */ @Test public void testJavaSeModuleLoad() throws Exception { final Module module = Module.getBootModuleLoader().loadModule("java.se"); Assert.assertNotNull("java.se module not found", module); final String resultSetClassName = "java.sql.ResultSet"; final Class klass = module.getClassLoader().loadClass(resultSetClassName); Assert.assertNotNull(resultSetClassName + " class couldn't be loaded from java.se module", klass); // test a class that was introduced in Java 11 String specString = System.getProperty("java.specification.version"); Pattern pat = Pattern.compile("(?:1\\.)?(\\d+)"); Matcher matcher = pat.matcher(specString); Assume.assumeTrue("Java 11 is required to test loading of classes " + "in java.net.http module", matcher.matches() && Integer.parseInt(matcher.group(1)) >= 11); final String httpClientClassName = "java.net.http.HttpClient"; final Class httpClientClass = module.getClassLoader().loadClass(httpClientClassName); Assert.assertNotNull(httpClientClassName + " class couldn't be loaded from java.se module", httpClientClass); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/JarResourceLoaderTest.java000066400000000000000000000074001472011152000304540ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import org.jboss.modules.filter.PathFilter; import org.junit.Assert; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; /** * Test the functionality of the JarResourceLoader. * * @author John Bailey */ public class JarResourceLoaderTest extends AbstractResourceLoaderTestCase { private JarFile jarFile; protected ResourceLoader createLoader(final PathFilter exportFilter) throws Exception { File fileResourceRoot = getResource("test/fileresourceloader"); // Copy the classfile over copyResource("org/jboss/modules/test/TestClass.class", "test/fileresourceloader", "org/jboss/modules/test"); // Build a jar to match the fileresource loader final File outputFile = new File(getResource("test"), "jarresourceloader/test.jar"); outputFile.getParentFile().mkdirs(); buildJar(fileResourceRoot, outputFile); // Create the jar file and resource loader jarFile = new JarFile(outputFile, true); return new JarFileResourceLoader("test-root", jarFile); } @Override protected void assertResource(Resource resource, String fileName) { final JarEntry entry = jarFile.getJarEntry(fileName); Assert.assertEquals(entry.getSize(), resource.getSize()); } static void buildJar(final File source, final File targetFile) throws IOException { final JarOutputStream target = new JarOutputStream(new FileOutputStream(targetFile)); final String sourceBase = source.getPath(); add(sourceBase, source, target); target.close(); } private static void add(final String sourceBase, final File source, final JarOutputStream target) throws IOException { BufferedInputStream in = null; String entryName = source.getPath().replace(sourceBase, "").replace("\\", "/"); if(entryName.startsWith("/")) entryName = entryName.substring(1); try { if (source.isDirectory()) { if (!entryName.isEmpty()) { if (!entryName.endsWith("/")) entryName += "/"; final JarEntry entry = new JarEntry(entryName); target.putNextEntry(entry); target.closeEntry(); } for (File nestedFile : source.listFiles()) add(sourceBase, nestedFile, target); return; } final JarEntry entry = new JarEntry(entryName); target.putNextEntry(entry); in = new BufferedInputStream(new FileInputStream(source)); byte[] buffer = new byte[1024]; int count = 0; while ((count = in.read(buffer)) != -1) { target.write(buffer, 0, count); } target.closeEntry(); } finally { if (in != null) in.close(); } } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/LayeredModulePathFactoryTest.java000066400000000000000000000110241472011152000317760ustar00rootroot00000000000000package org.jboss.modules; import org.junit.Assert; import org.junit.Assume; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import java.io.File; import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.PosixFilePermissions; import java.util.ArrayList; import java.util.List; import java.util.Set; public class LayeredModulePathFactoryTest { private static final String OVERLAYS = ".overlays"; private static final String OVERLAY_NAME = "overlay-1"; @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); private File layeringRoot; private File overlaysDir; private File metadataFile; private File overlayRoot; private final List discoveredPaths = new ArrayList<>(); @Before public void setup() throws IOException { boolean isPosix = FileSystems.getDefault().supportedFileAttributeViews().contains("posix"); Assume.assumeTrue("This test requires POSIX compatible OS", isPosix); layeringRoot = temporaryFolder.getRoot(); // layeringRoot/.overlays/ overlaysDir = new File(layeringRoot, OVERLAYS); Assert.assertTrue(overlaysDir.mkdir()); // layeringRoot/.overlays/.overlays file metadataFile = new File(overlaysDir, OVERLAYS); Assert.assertTrue(metadataFile.createNewFile()); writeRefsFile(metadataFile); // layeringRoot/.overlays/overlay-1/ overlayRoot = new File(overlaysDir, OVERLAY_NAME); Assert.assertTrue(overlayRoot.mkdir()); } @Test public void testReadable() { LayeredModulePathFactory.loadOverlays(layeringRoot, discoveredPaths); } @Test public void testUnreadableOverlays() throws IOException { boolean expectedFailure = false; Set origPermissions = Files.getPosixFilePermissions(overlaysDir.toPath()); try { // make directory non-readable Set testPermissions = PosixFilePermissions.fromString("-w-------"); Files.setPosixFilePermissions(overlaysDir.toPath(), testPermissions); LayeredModulePathFactory.loadOverlays(layeringRoot, discoveredPaths); } catch (IllegalStateException ise) { expectedFailure = ise.getMessage().startsWith("Overlays directory exists but is not readable: "); } finally { Files.setPosixFilePermissions(overlaysDir.toPath(), origPermissions); } Assert.assertTrue(expectedFailure); } @Test public void testUnreadableOverlaysMetadataFile() throws IOException { boolean expectedFailure = false; Set origPermissions = Files.getPosixFilePermissions(overlaysDir.toPath()); try { // make directory non-readable Set testPermissions = PosixFilePermissions.fromString("-w-------"); Files.setPosixFilePermissions(metadataFile.toPath(), testPermissions); try { LayeredModulePathFactory.loadOverlays(layeringRoot, discoveredPaths); } catch (IllegalStateException ise) { expectedFailure = ise.getMessage().startsWith("Overlays metadata file exists but is not readable: "); } } finally { Files.setPosixFilePermissions(overlaysDir.toPath(), origPermissions); } Assert.assertTrue(expectedFailure); } @Test public void testUnreadableOverlayRoot() throws IOException { boolean expectedFailure = false; Set origPermissions = Files.getPosixFilePermissions(overlaysDir.toPath()); try { // make directory non-readable Set testPermissions = PosixFilePermissions.fromString("-w-------"); Files.setPosixFilePermissions(overlayRoot.toPath(), testPermissions); LayeredModulePathFactory.loadOverlays(layeringRoot, discoveredPaths); } catch (IllegalStateException ise) { expectedFailure = ise.getMessage().startsWith("Overlay root directory doesn't exists or is not readable: "); } finally { Files.setPosixFilePermissions(overlaysDir.toPath(), origPermissions); } Assert.assertTrue(expectedFailure); } private static void writeRefsFile(File file) throws IOException { Files.write(file.toPath(), (OVERLAY_NAME + '\n').getBytes()); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/LayeredModulePathTest.java000066400000000000000000000577361472011152000304720ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; /** * Tests of {@link LocalModuleLoader} when "layers" and "add-ons" are configured. * * @author Brian Stansberry (c) 2012 Red Hat Inc. */ public class LayeredModulePathTest extends AbstractModuleTestCase { private static final String PATH = "test/layeredmodulepath/"; private static final String SHARED = "test.shared"; private String originalModulePath; private File reposRoot; private File repoA; private File repoB; @Before public void setUp() throws Exception { originalModulePath = System.getProperty("module.path"); reposRoot = new File(getResource(PATH), "repos"); if (!reposRoot.mkdirs() && !reposRoot.isDirectory()) { throw new IllegalStateException("Cannot create reposRoot"); } repoA = new File(reposRoot, "root-a"); if (!repoA.mkdirs() && !repoA.isDirectory()) { throw new IllegalStateException("Cannot create reposA"); } repoB = new File(reposRoot, "root-b"); if (!repoB.mkdirs() && !repoB.isDirectory()) { throw new IllegalStateException("Cannot create reposB"); } } @After public void tearDown() throws Exception { if (reposRoot != null) { cleanFile(reposRoot); } if (originalModulePath != null) { System.setProperty("module.path", originalModulePath); } else { System.clearProperty("module.path"); } } private void cleanFile(File file) { File[] children = file.listFiles(); if (children != null) { for (File child : children) { cleanFile(child); } } if (!file.delete() && file.exists()) { file.deleteOnExit(); } } @Test public void testBaseLayer() throws Exception { createRepo("root-a", false, false, Collections.singletonList("base")); File[] standardPath = { repoA }; File[] modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); validateModulePath(modulePath, repoA, 0, -1, false, "base"); validateModuleLoading(standardPath, false, false, false, "base"); } @Test public void testSpecifiedBaseLayer() throws Exception { // This setup puts "base" in layers.conf createRepo("root-a", false, false, "base"); File[] standardPath = { repoA }; File[] modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); validateModulePath(modulePath, repoA, 0, -1, false, "base"); validateModuleLoading(standardPath, false, false, false, "base"); } @Test public void testSimpleOverlay() throws Exception { createRepo("root-a", false, false, Collections.singletonList("base"), "top"); File[] standardPath = { repoA }; File[] modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); validateModulePath(modulePath, repoA, 0, -1, false, "top", "base"); validateModuleLoading(standardPath, false, false, false, "top", "base"); } @Test public void testSpecifiedBaseLayerWithSimpleOverlay() throws Exception { // This setup puts "base" in layers.conf createRepo("root-a", false, false, "top", "base"); File[] standardPath = { repoA }; File[] modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); validateModulePath(modulePath, repoA, 0, -1, false, "top", "base"); validateModuleLoading(standardPath, false, false, false, "top", "base"); } @Test public void testMultipleOverlays() throws Exception { createRepo("root-a", false, false, Collections.singletonList("base"), "top", "mid"); File[] standardPath = { repoA }; File[] modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); validateModulePath(modulePath, repoA, 0, -1, false, "top", "mid", "base"); validateModuleLoading(standardPath, false, false, false, "top", "mid", "base"); } @Test public void testSpecifiedBaseLayerWithMultipleOverlays() throws Exception { // This setup puts "base" in layers.conf createRepo("root-a", false, false, "top", "mid", "base"); File[] standardPath = { repoA }; File[] modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); validateModulePath(modulePath, repoA, 0, -1, false, "top", "mid", "base"); validateModuleLoading(standardPath, false, false, false, "top", "mid", "base"); } @Test public void testBasePlusAddOns() throws Exception { createRepo("root-a", true, false, Collections.singletonList("base")); File[] standardPath = { repoA }; File[] modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); validateModulePath(modulePath, repoA, 0, -1, true, "base"); validateModuleLoading(standardPath, true, false, false, "base"); } @Test public void testSpecifiedBasePlusAddOns() throws Exception { // This setup puts "base" in layers.conf createRepo("root-a", true, false, "base"); File[] standardPath = { repoA }; File[] modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); validateModulePath(modulePath, repoA, 0, -1, true, "base"); validateModuleLoading(standardPath, true, false, false, "base"); } @Test public void testLayersAndAddOns() throws Exception { createRepo("root-a", true, false, Collections.singletonList("base"), "top", "mid"); File[] standardPath = { repoA }; File[] modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); validateModulePath(modulePath, repoA, 0, -1, true, "top", "mid", "base"); validateModuleLoading(standardPath, true, false, false, "top", "mid", "base"); } @Test public void testSpecifiedBaseLayersAndAddOns() throws Exception { // This setup puts "base" in layers.conf createRepo("root-a", true, false, "top", "mid", "base"); File[] standardPath = { repoA }; File[] modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); validateModulePath(modulePath, repoA, 0, -1, true, "top", "mid", "base"); validateModuleLoading(standardPath, true, false, false, "top", "mid", "base"); } @Test public void testBaseLayerAndUser() throws Exception { createRepo("root-a", false, false, Collections.singletonList("base")); File[] standardPath = { repoA }; File[] modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); validateModulePath(modulePath, repoA, 0, -1, false, "base"); validateModuleLoading(standardPath, false, false, false, "base"); } @Test public void testSpecifiedBaseLayerAndUser() throws Exception { // This setup puts "base" in layers.conf createRepo("root-a", false, true, "base"); File[] standardPath = { repoA }; File[] modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); validateModulePath(modulePath, repoA, 0, -1, false, "base"); validateModuleLoading(standardPath, false, true, true, "base"); } @Test public void testSingleRootComplete() throws Exception { createRepo("root-a", true, false, Collections.singletonList("base"), "top", "mid"); File[] standardPath = { repoA }; File[] modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); validateModulePath(modulePath, repoA, 0, -1, true, "top", "mid", "base"); validateModuleLoading(standardPath, true, false, false, "top", "mid", "base"); } @Test public void testSpecifiedBaseSingleRootComplete() throws Exception { // This setup puts "base" in layers.conf createRepo("root-a", true, true, "top", "mid", "base"); File[] standardPath = { repoA }; File[] modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); validateModulePath(modulePath, repoA, 0, -1, true, "top", "mid", "base"); validateModuleLoading(standardPath, true, true, true, "top", "mid", "base"); } @Test public void testSecondRepoHigherPrecedence() throws Exception { createRepo("root-a", false, false, Collections.singletonList("base")); createRepo("root-b", false, true); File[] standardPath = { repoB, repoA }; File[] modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); validateModulePath(modulePath, repoA, 1, 0, false, "base"); validateModuleLoading(standardPath, false, true, true, "base"); } @Test public void testSecondRepoLowerPrecedence() throws Exception { createRepo("root-a", false, false, Collections.singletonList("base")); createRepo("root-b", false, true); File[] standardPath = { repoA, repoB }; File[] modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); validateModulePath(modulePath, repoA, 0, 2, false, "base"); validateModuleLoading(standardPath, false, true, false, "base"); } @Test public void testExtraneousOverlay() throws Exception { createRepo("root-a", false, false, Arrays.asList("base", "mid"), "top"); File[] standardPath = { repoA }; File[] modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); validateModulePath(modulePath, repoA, 0, -1, false, "top", "base"); validateModuleLoading(standardPath, false, false, false, "top", "base"); } @Test public void testSpecifiedBaseLayerWithExtraneousOverlay() throws Exception { // This setup puts "base" in layers.conf createRepo("root-a", false, false, Arrays.asList("mid"), "top", "base"); File[] standardPath = { repoA }; File[] modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); validateModulePath(modulePath, repoA, 0, -1, false, "top", "base"); validateModuleLoading(standardPath, false, false, false, "top", "base"); } /** Tests that setting up add-ons has no effect without the layers structure */ @Test public void testLayersRequiredForAddOns() throws Exception { createRepo("root-a", true, false); File[] standardPath = { repoA }; File[] modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); validateModulePath(modulePath, repoA, 0, -1, false); validateModuleLoading(standardPath, false, false, false); // Now add the layers/base dir new File(repoA, "system/layers/base").mkdirs(); modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); validateModulePath(modulePath, repoA, 0, -1, true, "base"); validateModuleLoading(standardPath, true, false, false); } @Test public void testRejectConfWithNoStructure() throws Exception { createRepo("root-a", false, false); writeLayersConf("root-a", "top"); File[] standardPath = { repoA }; try { LayeredModulePathFactory.resolveLayeredModulePath(standardPath); Assert.fail("layers.conf with no layers should fail"); } catch (Exception good) { // good } } @Test public void testRejectConfWithMissingLayer() throws Exception { createRepo("root-a", false, false, Arrays.asList("top", "base")); writeLayersConf("root-a", "top", "mid"); File[] standardPath = { repoA }; try { LayeredModulePathFactory.resolveLayeredModulePath(standardPath); Assert.fail("layers.conf with no layers should fail"); } catch (Exception good) { // good } } @Test public void testEmptyLayersConf() throws Exception { createRepo("root-a", false, false, Collections.singletonList("base")); writeLayersConf("root-a"); File[] standardPath = { repoA }; File[] modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); validateModulePath(modulePath, repoA, 0, -1, false, "base"); validateModuleLoading(standardPath, false, false, false, "base"); } @Test public void testLayersOverlayModulePath() throws Exception { createRepo("root-a", false, false, Arrays.asList("top", "base")); writeLayersConf("root-a", "top", "base"); createOverlays(repoA, "top", false, "top1", "top2"); createOverlays(repoA, "base", false, "base1", "base2"); File[] standardPath = { repoA }; File[] modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); Assert.assertEquals(7, modulePath.length); Assert.assertEquals(repoA, modulePath[0]); Assert.assertEquals(new File(repoA, "system/layers/top/.overlays/top1"), modulePath[1]); Assert.assertEquals(new File(repoA, "system/layers/top/.overlays/top2"), modulePath[2]); Assert.assertEquals(new File(repoA, "system/layers/top"), modulePath[3]); Assert.assertEquals(new File(repoA, "system/layers/base/.overlays/base1"), modulePath[4]); Assert.assertEquals(new File(repoA, "system/layers/base/.overlays/base2"), modulePath[5]); Assert.assertEquals(new File(repoA, "system/layers/base"), modulePath[6]); } @Test public void testAddOnsOverlayModulePath() throws Exception { createRepo("root-a", true, false, Arrays.asList("base")); writeLayersConf("root-a", "base"); createOverlays(repoA, "a", true, "a"); createOverlays(repoA, "b", true, "b"); File[] standardPath = { repoA }; File[] modulePath = LayeredModulePathFactory.resolveLayeredModulePath(standardPath); Assert.assertEquals(6, modulePath.length); Assert.assertEquals(repoA, modulePath[0]); Assert.assertEquals(new File(repoA, "system/layers/base"), modulePath[1]); // The order of the add-ons is non deterministic Assert.assertEquals(".overlays", modulePath[2].getParentFile().getName()); final String firstOverlay = modulePath[2].getName(); Assert.assertEquals(new File(repoA, "system/add-ons/" + firstOverlay), modulePath[3]); Assert.assertEquals(".overlays", modulePath[4].getParentFile().getName()); final String secondOverlays = modulePath[4].getName(); Assert.assertEquals(new File(repoA, "system/add-ons/" + secondOverlays), modulePath[5]); } private void writeLayersConf(String rootName, String... layers) throws IOException { if (layers != null && layers.length > 0) { StringBuilder sb = new StringBuilder("layers="); for (int i = 0; i < layers.length; i++) { if (i > 0) { sb.append(','); } sb.append(layers[i]); } File repo = "root-a".equals(rootName) ? repoA : repoB; File layersConf = new File(repo, "layers.conf"); layersConf.createNewFile(); FileWriter fw = new FileWriter(layersConf); try { PrintWriter pw = new PrintWriter(fw); pw.println(sb.toString()); pw.close(); } finally { try { fw.close(); } catch (Exception e) { // meh } } } } private void createRepo(String rootName, boolean includeAddons, boolean includeUser, String... layers) throws Exception { List empty = Collections.emptyList(); createRepo(rootName, includeAddons, includeUser, empty, layers); } private void createRepo(String rootName, boolean includeAddons, boolean includeUser, List extraLayers, String... layers) throws Exception { if (layers != null && layers.length > 0) { writeLayersConf(rootName, layers); for (String layer : layers) { createLayer(rootName, layer); } } if (extraLayers != null) { for (String extraLayer : extraLayers) { createLayer(rootName, extraLayer); } } if (includeAddons) { createAddOn(rootName, "a"); createAddOn(rootName, "b"); } if (includeUser) { createUserModules(rootName); } } private void createLayer(String rootName, String layerName) throws Exception { createModules("layers/" + layerName, rootName + "/system/layers/" + layerName, layerName); } private void createAddOn(String rootName, String addOnName) throws Exception { createModules("add-ons/" + addOnName, rootName + "/system/add-ons/" + addOnName, addOnName); } private void createUserModules(String rootName) throws Exception { createModules("user", rootName, "user"); } private void createModules(String sourcePath, String relativeRepoPath, String uniqueName) throws Exception { copyResource(PATH + sourcePath + "/shared/module.xml", PATH, "repos/" + relativeRepoPath + "/test/shared/main"); copyResource(PATH + sourcePath + "/unique/module.xml", PATH, "repos/" + relativeRepoPath + "/test/" + uniqueName + "/main"); } private void validateModulePath(File[] modulePath, File repoRoot, int expectedStartPos, int expectedOtherRootPos, boolean expectAddons, String... layers) { int expectedLength = 1 + layers.length + (expectAddons ? 2 : 0); // Validate positional parameters -- check for bad test writers ;) if (expectedOtherRootPos < 0) { Assert.assertEquals(0, expectedStartPos); // } else if (expectedStartPos == 0) { Assert.assertEquals(expectedLength, expectedOtherRootPos); } if (expectedOtherRootPos < 1) { Assert.assertEquals("Correct module path length", expectedStartPos + expectedLength, modulePath.length); } else { Assert.assertTrue("Correct module path length", modulePath.length > expectedStartPos + expectedLength); } Assert.assertEquals(repoRoot, modulePath[expectedStartPos]); for (int i = 0; i < layers.length; i++) { File layer = new File(repoRoot, "system/layers/" + layers[i]); Assert.assertEquals(layer, modulePath[expectedStartPos + i + 1]); } if (expectAddons) { File addOnBase = new File(repoRoot, "system/add-ons"); Set valid = new HashSet(Arrays.asList("a", "b")); for (int i = 0; i < 2; i++) { File addOn = modulePath[expectedStartPos + layers.length + i + 1]; Assert.assertEquals(addOnBase, addOn.getParentFile()); String addOnName = addOn.getName(); Assert.assertTrue(addOnName, valid.remove(addOnName)); } } if (expectedOtherRootPos == 0) { for (int i = 0; i < expectedStartPos; i++) { validateNotChild(modulePath[i], repoRoot); } } else if (expectedOtherRootPos > 0) { for (int i = expectedOtherRootPos; i < modulePath.length; i++) { validateNotChild(modulePath[i], repoRoot); } } } private void validateNotChild(File file, File repoRoot) { File stop = repoRoot.getParentFile(); File testee = file; while (testee != null && !testee.equals(stop)) { Assert.assertFalse(testee.equals(repoRoot)); testee = testee.getParentFile(); } } private void validateModuleLoading(File[] standardPath, boolean expectAddOns, boolean expectUser, boolean expectUserPrecedence, String... layers) throws ModuleLoadException { // This is nasty, but the alternative is exposing the layers config stuff in the LocalModuleLoader API setUpModulePathProperty(standardPath); ModuleLoader moduleLoader = new LocalModuleLoader(); // Validate the expected path produced the shared module if (expectUser || layers.length > 0 || expectAddOns) { Module shared = moduleLoader.loadModule(SHARED); String sharedProp = shared.getProperty("test.prop"); if (expectUserPrecedence) { Assert.assertEquals("user", sharedProp); } else if (layers.length > 0) { Assert.assertEquals(layers[0], sharedProp); } else if (expectAddOns) { Assert.assertTrue("a".equals(sharedProp) || "b".equals(sharedProp)); } } // Validate the expected unique modules are present Set layersSet = new HashSet(Arrays.asList(layers)); loadModule(moduleLoader, "user", expectUser); loadModule(moduleLoader, "top", layersSet.contains("top")); loadModule(moduleLoader, "mid", layersSet.contains("mid")); loadModule(moduleLoader, "base", layersSet.contains("base")); loadModule(moduleLoader, "a", expectAddOns); loadModule(moduleLoader, "b", expectAddOns); } private void setUpModulePathProperty(File[] standardPath) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < standardPath.length; i++) { if (i > 0) { sb.append(File.pathSeparatorChar); } sb.append(standardPath[i].getAbsolutePath()); } System.setProperty("module.path", sb.toString()); } private void loadModule(ModuleLoader moduleLoader, String moduleName, boolean expectAvailable) { try { Module module = moduleLoader.loadModule("test." + moduleName); if (!expectAvailable) { Assert.fail("test." + moduleName + " should not be loadable"); } String prop = module.getProperty("test.prop"); Assert.assertEquals(moduleName, prop); } catch (ModuleLoadException e) { if (expectAvailable) { Assert.fail(e.getMessage()); } } } private void createOverlays(final File root, final String name, boolean addOn, String... overlays) throws IOException { final File system = new File(root, "system"); final File layers = addOn ? new File(system, "add-ons") : new File(system, "layers"); final File repo = new File(layers, name); final File overlaysRoot = new File(repo, ".overlays"); overlaysRoot.mkdir(); final File overlaysConfig = new File(overlaysRoot, ".overlays"); final OutputStream os = new FileOutputStream(overlaysConfig); try { for (final String overlay : overlays) { os.write(overlay.getBytes()); os.write('\n'); new File(overlaysRoot, overlay).mkdirs(); } } finally { if (os != null) try { os.close(); } catch (IOException e) { e.printStackTrace(); } } } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/LocalModuleLoaderTest.java000066400000000000000000000063041472011152000304320ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import org.junit.Before; import org.junit.Test; import java.io.File; import java.util.Iterator; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; /** * Test to verify the functionality of the LocalModuleLoader. * * @author John Bailey */ public class LocalModuleLoaderTest extends AbstractModuleTestCase { private ModuleLoader moduleLoader; @Before public void setupModuleLoader() throws Exception { final File repoRoot = getResource("test/repo"); System.setProperty("foo.bar", "substituted_value"); moduleLoader = new LocalModuleLoader(new File[] {repoRoot}); } @Test public void testBasicLoad() throws Exception { Module module = moduleLoader.loadModule("test.test"); assertNotNull(module); } @Test public void testCurrent() throws Exception { ModuleLoader loader = Module.getCallerModuleLoader(); System.out.println(loader); } @Test public void testLoadWithDeps() throws Exception { Module module = moduleLoader.loadModule("test.with-deps"); assertNotNull(module); } @Test public void testLoadWithBadDeps() throws Exception { try { moduleLoader.loadModule("test.bad-deps.1_0"); fail("Should have thrown a ModuleNotFoundException"); } catch(ModuleNotFoundException expected) {} } @Test public void testLoadWithCircularDeps() throws Exception { assertNotNull(moduleLoader.loadModule("test.circular-deps-A")); assertNotNull(moduleLoader.loadModule("test.circular-deps-B")); assertNotNull(moduleLoader.loadModule("test.circular-deps-C")); assertNotNull(moduleLoader.loadModule("test.circular-deps-D")); } @Test public void testAbsentModule() throws Exception { try { moduleLoader.loadModule("test.absent"); fail("Should have thrown a ModuleNotFoundException"); } catch(ModuleNotFoundException expected) {} } @Test public void testIterateModules() throws Exception { Iterator names = moduleLoader.iterateModules((String) null, true); while (names.hasNext()) { String name = names.next(); assertNotEquals("test.absent", name); if (!name.equals("test.bad-deps")) { Module module = moduleLoader.loadModule(name); assertNotNull(module); } } } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/MODULES_377_Test.java000066400000000000000000000035131472011152000267510ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2020 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.jboss.modules.util.Util; import org.junit.Before; import org.junit.Test; import java.io.File; import java.util.Iterator; /** * [MODULES-377] Getting 'IAE: moduleLoader is null' when iterating modules and module.xml contains a permissions markup * * @author Richard Opalka */ public class MODULES_377_Test extends AbstractModuleTestCase { private LocalModuleFinder moduleFinder; private ModuleLoader moduleLoader; @Before public void setup() throws Exception { final File repoRoot = Util.getResourceFile(getClass(), "test/MODULES_377"); moduleFinder = new LocalModuleFinder(new File[] {repoRoot}); moduleLoader = new ModuleLoader(moduleFinder); } @Test public void issueTest() { Iterator i = moduleLoader.iterateModules((String) null, true); assertTrue(i.hasNext()); assertEquals("local.tests.module", i.next()); assertFalse(i.hasNext()); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/MavenResource2Test.java000077500000000000000000000040661472011152000277510ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import org.jboss.modules.maven.MavenSettingsTest; import org.jboss.modules.util.Util; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import java.io.File; import java.net.URL; /** * @author Bill Burke * @version $Revision: 1 $ */ public class MavenResource2Test { protected static final String MODULE_ID2 = "test.maven:non-main"; private ModuleLoader moduleLoader; @Before public void setupRepo() throws Exception { final File repoRoot = Util.getResourceFile(getClass(), "test/repo"); moduleLoader = new LocalModuleLoader(new File[]{repoRoot}); } @Test public void testDefaultRepositories() throws Exception { try { URL settingsXmlUrl = MavenSettingsTest.class.getResource("jboss-settings.xml"); System.setProperty("jboss.modules.settings.xml.url", settingsXmlUrl.toExternalForm()); Module module = moduleLoader.loadModule(MODULE_ID2); URL url = module.getResource("org/jboss/resteasy/plugins/providers/jackson/ResteasyJacksonProvider.class"); System.out.println(url); Assert.assertNotNull(url); } finally { System.clearProperty("jboss.modules.settings.xml.url"); } } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/MavenResourceTest.java000077500000000000000000000056211472011152000276650ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.File; import java.net.URL; import org.jboss.modules.maven.ArtifactCoordinates; import org.jboss.modules.maven.MavenArtifactUtil; import org.jboss.modules.maven.MavenSettingsTest; import org.jboss.modules.util.Util; import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; /** * @author Bill Burke * @version $Revision: 1 $ */ public class MavenResourceTest { protected static final String MODULE_ID = "test.maven"; @Rule public TemporaryFolder tmpdir = new TemporaryFolder(); private ModuleLoader moduleLoader; @Before public void setupRepo() throws Exception { final File repoRoot = Util.getResourceFile(getClass(), "test/repo"); moduleLoader = new LocalModuleLoader(new File[]{repoRoot}); } @Test public void testWithPassedRepository() throws Exception { System.setProperty("maven.repo.local", tmpdir.newFolder("repository").getAbsolutePath()); System.setProperty("remote.maven.repo", "https://repository.jboss.org/nexus/content/groups/public/,https://maven-central.storage.googleapis.com/"); try { Module module = moduleLoader.loadModule(MODULE_ID); URL url = module.getResource("org/jboss/resteasy/plugins/providers/jackson/ResteasyJacksonProvider.class"); System.out.println(url); Assert.assertNotNull(url); } finally { System.clearProperty("maven.repo.local"); System.clearProperty("remote.repository"); } } /** * we test if it uses repostiory user has configured in user.home/.m2/settings.xml or M2_HOME/conf/settings.xml * * @throws Exception */ @Test @Ignore("Test is mostly meant for manual testing, as snapshot are not parmanent") public void testCustomRepository() throws Exception { File f = MavenArtifactUtil.resolveJarArtifact(ArtifactCoordinates.fromString("org.wildfly.core:wildfly-version:2.0.5.Final-20151222.144931-1")); Assert.assertNotNull("Should resolve", f); System.out.println("f = " + f); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ModuleClassLoaderAliasReloadTest.java000066400000000000000000000225101472011152000325430ustar00rootroot00000000000000package org.jboss.modules; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; import java.io.IOException; import java.util.Collection; import org.jboss.modules.test.TestClass; import org.jboss.modules.util.TestModuleLoader; import org.jboss.modules.util.TestResourceLoader; import org.junit.Test; /** * Verifies the functionality of alias modules in unload/reload scenarios. * * @author Richard Opalka * @author Peter Palaga */ public class ModuleClassLoaderAliasReloadTest extends AbstractModuleTestCase { private static final String MODULE_ONE_ID = "test-module-1"; private static final String MODULE_TWO_ID = "test-module-2"; private static final String MODULE_TWO_AL = "test-module-2-alias"; private TestModuleLoader moduleLoader = new TestModuleLoader(); private static final class CloseAwareResourceLoader implements ResourceLoader { private final ResourceLoader delegate; private volatile boolean closed; private CloseAwareResourceLoader(final ResourceLoader delegate) { this.delegate = delegate; } @Override public ClassSpec getClassSpec(String fileName) throws IOException { if (closed) throw new IllegalStateException(); return delegate.getClassSpec(fileName); } @Override public PackageSpec getPackageSpec(String name) throws IOException { if (closed) throw new IllegalStateException(); return delegate.getPackageSpec(name); } @Override public Resource getResource(String name) { if (closed) throw new IllegalStateException(); return delegate.getResource(name); } @Override public String getLibrary(String name) { if (closed) throw new IllegalStateException(); return delegate.getLibrary(name); } @Override public Collection getPaths() { if (closed) throw new IllegalStateException(); return delegate.getPaths(); } public void close() { closed = true; } } public void configureModules() throws Exception { // first module final ModuleSpec.Builder moduleOneBuilder = ModuleSpec.build(MODULE_ONE_ID); moduleOneBuilder.addResourceRoot(ResourceLoaderSpec.createResourceLoaderSpec( new CloseAwareResourceLoader( TestResourceLoader.build() .addClass(TestClass.class) .addResources(getResource("test/aliasmodule/rootOne")) .create()) )); moduleOneBuilder.addDependency(new ModuleDependencySpecBuilder() .setName(MODULE_TWO_AL.toString()) .build()); moduleOneBuilder.addDependency(DependencySpec.createLocalDependencySpec()); moduleLoader.addModuleSpec(moduleOneBuilder.create()); // second module final ModuleSpec.Builder moduleTwoBuilder = ModuleSpec.build(MODULE_TWO_ID); moduleTwoBuilder.addResourceRoot(ResourceLoaderSpec.createResourceLoaderSpec( new CloseAwareResourceLoader( TestResourceLoader.build() .addClass(TestClass.class) .addResources(getResource("test/aliasmodule/rootTwo")) .create() ) )); moduleTwoBuilder.addDependency(new ModuleDependencySpecBuilder() .setName(MODULE_ONE_ID.toString()) .build()); moduleTwoBuilder.addDependency(DependencySpec.createLocalDependencySpec()); moduleLoader.addModuleSpec(moduleTwoBuilder.create()); // second alias module final ModuleSpec.AliasBuilder moduleTwoAliasBuilder = ModuleSpec.buildAlias(MODULE_TWO_AL, MODULE_TWO_ID); moduleLoader.addModuleSpec(moduleTwoAliasBuilder.create()); } /** * Ensure the Alias modules do not leak during unload/reload, see https://issues.jboss.org/browse/MODULES-241 * * @throws Exception */ @Test public void testAliasModuleReload() throws Exception { // FIRST PHASE configureModules(); Module testModule1 = moduleLoader.loadModule(MODULE_ONE_ID); Module testModule2 = moduleLoader.loadModule(MODULE_TWO_ID); ModuleClassLoader classLoader1 = testModule1.getClassLoader(); ModuleClassLoader classLoader2 = testModule2.getClassLoader(); try { Class testClass1 = classLoader1.loadClass("org.jboss.modules.test.TestClass"); assertNotNull(testClass1); Class testClass2 = classLoader2.loadClass("org.jboss.modules.test.TestClass"); assertNotNull(testClass2); assertNotNull(testClass1.getResource("/test.txt")); assertNotNull(testClass2.getResource("/test.txt")); } catch (ClassNotFoundException e) { fail(); } // cleanup for (final ResourceLoader rl : classLoader1.getResourceLoaders()) { ((CloseAwareResourceLoader)rl).close(); } for (final ResourceLoader rl : classLoader2.getResourceLoaders()) { ((CloseAwareResourceLoader)rl).close(); } moduleLoader.unloadModuleLocal(testModule1.getName(), testModule1); moduleLoader.unloadModuleLocal(testModule2.getName(), testModule2); // SECOND PHASE configureModules(); testModule1 = moduleLoader.loadModule(MODULE_ONE_ID); moduleLoader.relink(testModule1); testModule2 = moduleLoader.loadModule(MODULE_TWO_ID); moduleLoader.relink(testModule2); classLoader1 = testModule1.getClassLoader(); classLoader2 = testModule2.getClassLoader(); try { Class testClass1 = classLoader1.loadClass("org.jboss.modules.test.TestClass"); assertNotNull(testClass1); Class testClass2 = classLoader2.loadClass("org.jboss.modules.test.TestClass"); assertNotNull(testClass2); assertNotNull(testClass1.getResource("/test.txt")); assertNotNull(testClass2.getResource("/test.txt")); } catch (ClassNotFoundException e) { fail(); } // cleanup for (final ResourceLoader rl : classLoader1.getResourceLoaders()) { ((CloseAwareResourceLoader)rl).close(); } for (final ResourceLoader rl : classLoader2.getResourceLoaders()) { ((CloseAwareResourceLoader)rl).close(); } moduleLoader.unloadModuleLocal(testModule1.getName(), testModule1); moduleLoader.unloadModuleLocal(testModule2.getName(), testModule2); } /** * Ensure the Alias modules do not leak during unload/reload, see https://issues.jboss.org/browse/MODULES-241 * * @throws Exception */ @Test public void testAliasModuleReload2() throws Exception { // FIRST PHASE configureModules(); Module testModule1 = moduleLoader.loadModule(MODULE_ONE_ID); Module testModule2 = moduleLoader.loadModule(MODULE_TWO_AL); ModuleClassLoader classLoader1 = testModule1.getClassLoader(); ModuleClassLoader classLoader2 = testModule2.getClassLoader(); try { Class testClass1 = classLoader1.loadClass("org.jboss.modules.test.TestClass"); assertNotNull(testClass1); Class testClass2 = classLoader2.loadClass("org.jboss.modules.test.TestClass"); assertNotNull(testClass2); assertNotNull(testClass1.getResource("/test.txt")); assertNotNull(testClass2.getResource("/test.txt")); } catch (ClassNotFoundException e) { fail(); } // cleanup for (final ResourceLoader rl : classLoader1.getResourceLoaders()) { ((CloseAwareResourceLoader)rl).close(); } for (final ResourceLoader rl : classLoader2.getResourceLoaders()) { ((CloseAwareResourceLoader)rl).close(); } moduleLoader.unloadModuleLocal(testModule1.getName(), testModule1); moduleLoader.unloadModuleLocal(testModule2.getName(), testModule2); // SECOND PHASE configureModules(); testModule1 = moduleLoader.loadModule(MODULE_ONE_ID); moduleLoader.relink(testModule1); testModule2 = moduleLoader.loadModule(MODULE_TWO_AL); moduleLoader.relink(testModule2); classLoader1 = testModule1.getClassLoader(); classLoader2 = testModule2.getClassLoader(); try { Class testClass1 = classLoader1.loadClass("org.jboss.modules.test.TestClass"); assertNotNull(testClass1); Class testClass2 = classLoader2.loadClass("org.jboss.modules.test.TestClass"); assertNotNull(testClass2); assertNotNull(testClass1.getResource("/test.txt")); assertNotNull(testClass2.getResource("/test.txt")); } catch (ClassNotFoundException e) { fail(); } // cleanup for (final ResourceLoader rl : classLoader1.getResourceLoaders()) { ((CloseAwareResourceLoader)rl).close(); } for (final ResourceLoader rl : classLoader2.getResourceLoaders()) { ((CloseAwareResourceLoader)rl).close(); } moduleLoader.unloadModuleLocal(testModule1.getName(), testModule1); moduleLoader.unloadModuleLocal(testModule2.getName(), testModule2); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ModuleClassLoaderAliasTest.java000066400000000000000000000176211472011152000314230ustar00rootroot00000000000000package org.jboss.modules; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; import java.io.File; import java.io.IOException; import java.net.URL; import java.nio.charset.Charset; import org.jboss.modules.util.Util; import org.junit.Test; /** * Tests the basic functionality of alias modules. * * @author Richard Opalka * @author Peter Palaga */ public class ModuleClassLoaderAliasTest extends AbstractModuleTestCase { @Test public void testAliasCyclic() throws Exception { final File repoRoot = getResource("test/repo"); final ModuleLoader moduleLoader = new LocalModuleLoader(new File[] { repoRoot }); Module testModule1 = moduleLoader.loadModule("test.alias-cyclic.module-one"); Module testModule2 = moduleLoader.loadModule("test.alias-cyclic.module-two"); ModuleClassLoader classLoader1 = testModule1.getClassLoader(); ModuleClassLoader classLoader2 = testModule2.getClassLoader(); try { Class testClass1 = classLoader1.loadClass("org.jboss.modules.test.ClassA"); assertNotNull(testClass1); Class testClass2 = classLoader2.loadClass("org.jboss.modules.test.ClassB"); assertNotNull(testClass2); Class testClass1ViaLoader2 = classLoader2.loadClass("org.jboss.modules.test.ClassA"); assertNotNull(testClass1ViaLoader2); assertSame(testClass1, testClass1ViaLoader2); Class testClass2ViaLoader1 = classLoader1.loadClass("org.jboss.modules.test.ClassB"); assertNotNull(testClass2ViaLoader1); assertSame(testClass2, testClass2ViaLoader1); assertResourceString(testClass1.getResource("/test.txt"), "Test file 1"); assertResourceString(testClass2.getResource("/test.txt"), "Test file 2"); assertResourceString(classLoader1.getResource("/test.txt"), "Test file 1"); assertResourceString(classLoader2.getResource("/test.txt"), "Test file 2"); } catch (ClassNotFoundException e) { fail(); } moduleLoader.unloadModuleLocal("test.alias-cyclic.module-one", testModule1); assertNull("module-one should not be present in the moduleLoader after it has been removed", moduleLoader.findLoadedModuleLocal("test.alias-cyclic.module-one")); /* Assert that unloading an aliased module also removes the aliases */ moduleLoader.unloadModuleLocal("test.alias-cyclic.module-two", testModule2); assertNull("module-two should not be present in the moduleLoader after it has been removed", moduleLoader.findLoadedModuleLocal("test.alias-cyclic.module-two")); assertNull("module-two-alias should should not be present in the moduleLoader after module-two has been removed", moduleLoader.findLoadedModuleLocal("test.alias-cyclic.module-two-alias")); } @Test public void testAliasSimple() throws Exception { final File repoRoot = getResource("test/repo"); final ModuleLoader moduleLoader = new LocalModuleLoader(new File[] { repoRoot }); Module testModule1 = moduleLoader.loadModule("test.alias-simple.module-one"); Module testModule2 = moduleLoader.loadModule("test.alias-simple.module-two"); ModuleClassLoader classLoader1 = testModule1.getClassLoader(); ModuleClassLoader classLoader2 = testModule2.getClassLoader(); Class testClass1 = classLoader1.loadClass("org.jboss.modules.test.ClassA"); assertNotNull(testClass1); Class testClass2 = classLoader2.loadClass("org.jboss.modules.test.ClassB"); assertNotNull(testClass2); Class testClass2ViaLoader1 = classLoader1.loadClass("org.jboss.modules.test.ClassB"); assertNotNull(testClass2ViaLoader1); assertSame(testClass2, testClass2ViaLoader1); try { classLoader2.loadClass("org.jboss.modules.test.ClassA"); fail("ClassNotFoundException expected"); } catch (ClassNotFoundException expected) { } assertResourceString(testClass1.getResource("/test.txt"), "Test file 1"); assertResourceString(testClass2.getResource("/test.txt"), "Test file 2"); assertResourceString(classLoader1.getResource("/test.txt"), "Test file 1"); assertResourceString(classLoader2.getResource("/test.txt"), "Test file 2"); moduleLoader.unloadModuleLocal("test.alias-simple.module-one", testModule1); assertNull("module-one should not be present in the moduleLoader after it has been removed", moduleLoader.findLoadedModuleLocal("test.alias-simple.module-one")); /* Assert that unloading an aliased module also removes the aliases */ moduleLoader.unloadModuleLocal("test.alias-simple.module-two", testModule2); assertNull("module-two should not be present in the moduleLoader after it has been removed", moduleLoader.findLoadedModuleLocal("test.alias-simple.module-two")); assertNull("module-two-alias should should not be present in the moduleLoader after module-two has been removed", moduleLoader.findLoadedModuleLocal("test.alias-simple.module-two-alias")); } /** * A reproducer for MODULES-282 */ @Test public void testAliasResource() throws Exception { final File repoRoot = getResource("test/repo"); final ModuleLoader moduleLoader = new LocalModuleLoader(new File[] { repoRoot }); Module dependentAliasModule = moduleLoader.loadModule("test.alias-resources.dependent-module-alias"); /* Assert that the whole dependency graph is there */ assertNotNull("dependent-module-alias should be present in the moduleLoader after dependent-module-alias has been loaded", moduleLoader.findLoadedModuleLocal("test.alias-resources.dependent-module-alias")); assertNotNull("dependent-module should be present in the moduleLoader after dependent-module-alias has been loaded", moduleLoader.findLoadedModuleLocal("test.alias-resources.dependent-module")); assertNotNull("dependency-module should be present in the moduleLoader after dependent-module-alias has been loaded", moduleLoader.findLoadedModuleLocal("test.alias-resources.dependency-module")); ModuleClassLoader dependentAliasClassLoader = dependentAliasModule.getClassLoader(); assertResourceString(dependentAliasClassLoader.getResource("/dependency-resource.txt"), "Dependency resource"); moduleLoader.unloadModuleLocal("test.alias-resources.dependent-module-alias", dependentAliasModule); /* Assert that unloading the alias removes just the alias while leaving the aliased module there */ assertNull("dependent-module-alias should not be present in the moduleLoader after it has been removed", moduleLoader.findLoadedModuleLocal("test.alias-resources.dependent-module-alias")); assertNotNull("dependent-module should be present in the moduleLoader after dependent-module-alias has been removed", moduleLoader.findLoadedModuleLocal("test.alias-resources.dependent-module")); assertNotNull("dependency-module should be present in the moduleLoader after dependent-module-alias has been removed", moduleLoader.findLoadedModuleLocal("test.alias-resources.dependency-module")); moduleLoader.unloadModuleLocal("test.alias-resources.dependent-module", dependentAliasModule); assertNull("dependent-module should not be present in the moduleLoader after it has been removed", moduleLoader.findLoadedModuleLocal("test.alias-resources.dependent-module")); } private static void assertResourceString(URL resource, String expected) throws IOException { assertNotNull(resource); byte[] bytes = Util.readBytes(resource.openStream()); assertEquals(expected, new String(bytes, Charset.forName("utf-8"))); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ModuleClassLoaderTest.java000066400000000000000000000424171472011152000304520ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import org.jboss.modules.filter.MultiplePathFilterBuilder; import org.jboss.modules.filter.PathFilters; import org.jboss.modules.test.ImportedClass; import org.jboss.modules.test.ImportedInterface; import org.jboss.modules.test.TestClass; import org.jboss.modules.util.TestModuleLoader; import org.jboss.modules.util.TestResourceLoader; import org.junit.Before; import org.junit.Test; import java.net.URL; import java.util.Enumeration; import java.util.List; import static org.jboss.modules.util.Util.toList; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** * Test to verify module functionality. * * @author John Bailey * @author Flavia Rainone */ public class ModuleClassLoaderTest extends AbstractModuleTestCase { private static final String MODULE_WITH_CONTENT_ID = "test-with-content"; private static final String MODULE_WITH_RESOURCE_ID = "test-with-resource"; private static final String MODULE_TO_IMPORT_ID = "test-to-import"; private static final String MODULE_WITH_EXPORT_ID = "test-with-export"; private static final String MODULE_WITH_DOUBLE_EXPORT_ID = "test-with-double-export"; private static final String MODULE_WITH_INVERTED_DOUBLE_EXPORT_ID = "test-with-inverted-double-export"; private static final String MODULE_WITH_FILTERED_EXPORT_ID = "test-with-filtered-export"; private static final String MODULE_WITH_FILTERED_IMPORT_ID = "test-with-filtered-import"; private static final String MODULE_WITH_FILTERED_DOUBLE_EXPORT_ID = "test-with-filtered-double-export"; private TestModuleLoader moduleLoader; @Before public void setupModuleLoader() throws Exception { moduleLoader = new TestModuleLoader(); final ModuleSpec.Builder moduleWithContentBuilder = ModuleSpec.build(MODULE_WITH_CONTENT_ID); moduleWithContentBuilder.addResourceRoot(ResourceLoaderSpec.createResourceLoaderSpec( TestResourceLoader.build() .addClass(TestClass.class) .addResources(getResource("test/modulecontentloader/rootOne")) .create() )); moduleWithContentBuilder.addDependency(new ModuleDependencySpecBuilder() .setName(MODULE_TO_IMPORT_ID.toString()) .build()); moduleWithContentBuilder.addDependency(DependencySpec.createLocalDependencySpec()); moduleLoader.addModuleSpec(moduleWithContentBuilder.create()); final ModuleSpec.Builder moduleWithResourceBuilder = ModuleSpec.build(MODULE_WITH_RESOURCE_ID); moduleWithResourceBuilder.addResourceRoot(ResourceLoaderSpec.createResourceLoaderSpec( TestResourceLoader.build() .addClass(TestClass.class) .addResources(getResource("class-resources")) .create() )); moduleWithResourceBuilder.addDependency(new ModuleDependencySpecBuilder() .setName(MODULE_TO_IMPORT_ID.toString()) .build()); moduleWithResourceBuilder.addDependency(DependencySpec.createLocalDependencySpec()); moduleLoader.addModuleSpec(moduleWithResourceBuilder.create()); final ModuleSpec.Builder moduleToImportBuilder = ModuleSpec.build(MODULE_TO_IMPORT_ID); moduleToImportBuilder.addResourceRoot(ResourceLoaderSpec.createResourceLoaderSpec( TestResourceLoader.build() .addClass(ImportedClass.class) .addClass(ImportedInterface.class) .addResources(getResource("test/modulecontentloader/rootTwo")) .create() )); moduleToImportBuilder.addDependency(DependencySpec.createLocalDependencySpec()); moduleLoader.addModuleSpec(moduleToImportBuilder.create()); final ModuleSpec.Builder moduleWithExportBuilder = ModuleSpec.build(MODULE_WITH_EXPORT_ID); moduleWithExportBuilder.addDependency(new ModuleDependencySpecBuilder() .setName(MODULE_TO_IMPORT_ID.toString()) .setExport(true) .setOptional(false) .build()); moduleWithExportBuilder.addDependency(DependencySpec.createLocalDependencySpec()); moduleLoader.addModuleSpec(moduleWithExportBuilder.create()); final MultiplePathFilterBuilder nestedAndOrgJBossExcludingBuilder = PathFilters.multiplePathFilterBuilder(true); nestedAndOrgJBossExcludingBuilder.addFilter(PathFilters.match("org/jboss/**"), false); nestedAndOrgJBossExcludingBuilder.addFilter(PathFilters.match("nested"), false); final ModuleSpec.Builder moduleWithExportFilterBuilder = ModuleSpec.build(MODULE_WITH_FILTERED_EXPORT_ID); moduleWithExportFilterBuilder.addDependency(new ModuleDependencySpecBuilder() .setExportFilter(nestedAndOrgJBossExcludingBuilder.create()) .setModuleLoader(null) .setName(MODULE_TO_IMPORT_ID.toString()) .setOptional(false) .build()); moduleWithExportFilterBuilder.addDependency(DependencySpec.createLocalDependencySpec()); moduleLoader.addModuleSpec(moduleWithExportFilterBuilder.create()); final ModuleSpec.Builder moduleWithImportFilterBuilder = ModuleSpec.build(MODULE_WITH_FILTERED_IMPORT_ID); moduleWithImportFilterBuilder.addDependency(new ModuleDependencySpecBuilder() .setImportFilter(nestedAndOrgJBossExcludingBuilder.create()) .setName(MODULE_TO_IMPORT_ID.toString()) .setOptional(false) .build()); moduleWithImportFilterBuilder.addDependency(DependencySpec.createLocalDependencySpec()); moduleLoader.addModuleSpec(moduleWithImportFilterBuilder.create()); final ModuleSpec.Builder moduleWithDoubleExportBuilder = ModuleSpec.build(MODULE_WITH_DOUBLE_EXPORT_ID); moduleWithDoubleExportBuilder.addDependency(new ModuleDependencySpecBuilder() .setName(MODULE_TO_IMPORT_ID.toString()) .setExport(true) .build()); moduleWithDoubleExportBuilder.addDependency(new ModuleDependencySpecBuilder() .setName(MODULE_WITH_CONTENT_ID.toString()) .setExport(true) .build()); moduleWithDoubleExportBuilder.addDependency(DependencySpec.createLocalDependencySpec()); moduleLoader.addModuleSpec(moduleWithDoubleExportBuilder.create()); final ModuleSpec.Builder moduleWithInvertedDoubleExportBuilder = ModuleSpec.build(MODULE_WITH_INVERTED_DOUBLE_EXPORT_ID); moduleWithInvertedDoubleExportBuilder.addDependency(new ModuleDependencySpecBuilder() .setName(MODULE_WITH_CONTENT_ID.toString()) .setExport(true) .build()); moduleWithInvertedDoubleExportBuilder.addDependency(new ModuleDependencySpecBuilder() .setName(MODULE_TO_IMPORT_ID.toString()) .setExport(true) .build()); moduleWithInvertedDoubleExportBuilder.addDependency(DependencySpec.createLocalDependencySpec()); moduleLoader.addModuleSpec(moduleWithInvertedDoubleExportBuilder.create()); final ModuleSpec.Builder moduleWithFilteredDoubleExportBuilder = ModuleSpec.build(MODULE_WITH_FILTERED_DOUBLE_EXPORT_ID); moduleWithFilteredDoubleExportBuilder.addDependency(new ModuleDependencySpecBuilder() .setImportFilter(PathFilters.not(PathFilters.match("nested"))) .setExport(true) .setName(MODULE_TO_IMPORT_ID.toString()) .build()); moduleWithFilteredDoubleExportBuilder.addDependency(new ModuleDependencySpecBuilder() .setName(MODULE_WITH_EXPORT_ID.toString()) .setExport(true) .build()); moduleWithFilteredDoubleExportBuilder.addDependency(DependencySpec.createLocalDependencySpec()); moduleLoader.addModuleSpec(moduleWithFilteredDoubleExportBuilder.create()); } @Test public void testLocalClassLoad() throws Exception { final Module testModule = moduleLoader.loadModule(MODULE_WITH_CONTENT_ID); final ModuleClassLoader classLoader = testModule.getClassLoader(); try { Class testClass = classLoader.loadClass("org.jboss.modules.test.TestClass"); assertNotNull(testClass); } catch (ClassNotFoundException e) { fail("Should have loaded local class"); } } @Test public void testResourceLoad() throws Exception { final Module testModule = moduleLoader.loadModule(MODULE_WITH_RESOURCE_ID); final ModuleClassLoader classLoader = testModule.getClassLoader(); try { Class testClass = classLoader.loadClass("org.jboss.modules.test.TestClass"); // direct assertNotNull(testClass.getResource("/file1.txt")); // translates to /file1.txt assertNotNull(testClass.getResource("file2.txt")); // translates to /org/jboss/modules/test/file2.txt // relative assertNotNull(testClass.getResource("../../../../file1.txt")); // should translate to /file1.txt assertNotNull(testClass.getResource("test/../file2.txt")); // should translate to /org/jboss/modules/test/file2.txt } catch (ClassNotFoundException e) { e.printStackTrace(); fail("Should have loaded local class"); } } @Test public void testLocalClassLoadNotFound() throws Exception { final Module testModule = moduleLoader.loadModule(MODULE_WITH_CONTENT_ID); final ModuleClassLoader classLoader = testModule.getClassLoader(); try { classLoader.loadClass("org.jboss.modules.test.BogusClass"); fail("Should have thrown ClassNotFoundException"); } catch (ClassNotFoundException expected) { } } @Test public void testImportClassLoad() throws Exception { final Module testModule = moduleLoader.loadModule(MODULE_WITH_CONTENT_ID); final ModuleClassLoader classLoader = testModule.getClassLoader(); try { Class testClass = classLoader.loadClass("org.jboss.modules.test.ImportedClass"); assertNotNull(testClass); } catch (ClassNotFoundException e) { fail("Should have loaded imported class"); } } @Test public void testFilteredImportClassLoad() throws Exception { final Module testModule = moduleLoader.loadModule(MODULE_WITH_FILTERED_IMPORT_ID); final ModuleClassLoader classLoader = testModule.getClassLoader(); try { classLoader.loadClass("org.jboss.modules.test.ImportedClass"); fail("Should have thrown ClassNotFoundException"); } catch (ClassNotFoundException expected) { } } @Test public void testDoubleExportCLassLoad() throws Exception { final Module testModule = moduleLoader.loadModule(MODULE_WITH_DOUBLE_EXPORT_ID); final ModuleClassLoader classLoader = testModule.getClassLoader(); Class testClass = classLoader.loadExportedClass("org.jboss.modules.test.ImportedClass"); assertNotNull(testClass); testClass = classLoader.loadExportedClass("org.jboss.modules.test.TestClass"); assertNotNull(testClass); } @Test public void testInvertedDoubleExportCLassLoad() throws Exception { final Module testModule = moduleLoader.loadModule(MODULE_WITH_INVERTED_DOUBLE_EXPORT_ID); final ModuleClassLoader classLoader = testModule.getClassLoader(); Class testClass = classLoader.loadExportedClass("org.jboss.modules.test.ImportedClass"); assertNotNull(testClass); testClass = classLoader.loadExportedClass("org.jboss.modules.test.TestClass"); assertNotNull(testClass); } @Test public void testFilteredDoubleExportCLassLoad() throws Exception { final Module testModule = moduleLoader.loadModule(MODULE_WITH_FILTERED_DOUBLE_EXPORT_ID); final ModuleClassLoader classLoader = testModule.getClassLoader(); Class testClass = classLoader.loadExportedClass("org.jboss.modules.test.ImportedClass"); assertNotNull(testClass); } @Test public void testLocalResourceRetrieval() throws Exception { final Module testModule = moduleLoader.loadModule(MODULE_WITH_CONTENT_ID); final ModuleClassLoader classLoader = testModule.getClassLoader(); final URL resUrl = classLoader.getResource("test.txt"); assertNotNull(resUrl); } @Test public void testLocalResourceRetrievalNotFound() throws Exception { final Module testModule = moduleLoader.loadModule(MODULE_WITH_CONTENT_ID); final ModuleClassLoader classLoader = testModule.getClassLoader(); final URL resUrl = classLoader.getResource("bogus.txt"); assertNull(resUrl); } @Test public void testImportResourceRetrieval() throws Exception { final Module testModule = moduleLoader.loadModule(MODULE_WITH_CONTENT_ID); final ModuleClassLoader classLoader = testModule.getClassLoader(); final URL resUrl = classLoader.getResource("testTwo.txt"); assertNotNull(resUrl); } @Test public void testFilteredImportResourceRetrieval() throws Exception { final Module testModule = moduleLoader.loadModule(MODULE_WITH_FILTERED_IMPORT_ID); final ModuleClassLoader classLoader = testModule.getClassLoader(); URL resUrl = classLoader.getResource("nested/nested.txt"); assertNull(resUrl); } @Test public void testLocalResourcesRetrieval() throws Exception { final Module testModule = moduleLoader.loadModule(MODULE_WITH_CONTENT_ID); final ModuleClassLoader classLoader = testModule.getClassLoader(); final Enumeration resUrls = classLoader.getResources("test.txt"); assertNotNull(resUrls); final List resUrlList = toList(resUrls); assertEquals(1, resUrlList.size()); assertTrue(resUrlList.get(0).getPath().contains("rootOne")); } @Test public void testLocalResourcesRetrievalNotFound() throws Exception { final Module testModule = moduleLoader.loadModule(MODULE_WITH_CONTENT_ID); final ModuleClassLoader classLoader = testModule.getClassLoader(); final Enumeration resUrls = classLoader.getResources("bogus.txt"); assertNotNull(resUrls); final List resUrlList = toList(resUrls); assertTrue(resUrlList.isEmpty()); } @Test public void testImportResourcesRetrieval() throws Exception { final Module testModule = moduleLoader.loadModule(MODULE_WITH_CONTENT_ID); final ModuleClassLoader classLoader = testModule.getClassLoader(); final Enumeration resUrls = classLoader.getResources("testTwo.txt"); assertNotNull(resUrls); final List resUrlList = toList(resUrls); assertEquals(1, resUrlList.size()); assertTrue(resUrlList.get(0).getPath().contains("rootTwo")); } @Test public void testLocalAndImportResourcesRetrieval() throws Exception { final Module testModule = moduleLoader.loadModule(MODULE_WITH_CONTENT_ID); final ModuleClassLoader classLoader = testModule.getClassLoader(); final Enumeration resUrls = classLoader.getResources("nested/nested.txt"); assertNotNull(resUrls); final List resUrlList = toList(resUrls); assertEquals(2, resUrlList.size()); boolean rootOne = false; boolean rootTwo = false; for(URL resUrl : resUrlList) { if(!rootOne) rootOne = resUrl.getPath().contains("rootOne"); if(!rootTwo) rootTwo = resUrl.getPath().contains("rootTwo"); } assertTrue(rootOne); assertTrue(rootTwo); } @Test public void testFilteredImportResourcesRetrieval() throws Exception { final Module testModule = moduleLoader.loadModule(MODULE_WITH_FILTERED_IMPORT_ID); final ModuleClassLoader classLoader = testModule.getClassLoader(); Enumeration resUrls = classLoader.getResources("nested/nested.txt"); List resUrlList = toList(resUrls); assertTrue(resUrlList.isEmpty()); } @Test public void testManifest() throws Exception { final Module testModule = moduleLoader.loadModule(MODULE_WITH_CONTENT_ID); final ModuleClassLoader classLoader = testModule.getClassLoader(); final Class testClass = classLoader.loadClass("org.jboss.modules.test.TestClass"); System.out.println(testClass.getClassLoader()); final Package pkg = testClass.getPackage(); assertEquals("JBoss Modules Test Classes", pkg.getSpecificationTitle()); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ModuleExportTest.java000066400000000000000000000157571472011152000275460ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.lang.reflect.Field; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.jboss.modules.filter.PathFilters; import org.jboss.modules.test.ImportedClass; import org.jboss.modules.util.TestModuleLoader; import org.jboss.modules.util.TestResourceLoader; import org.junit.Ignore; import org.junit.Test; /** * Test to verify the module export dependencies and imports are created correctly. Each module should have an entry * directly to the module that has an exported path. * * @author John E. Bailey */ public class ModuleExportTest extends AbstractModuleTestCase { private static final String MODULE_A = "a"; private static final String MODULE_B = "b"; private static final String MODULE_C = "c"; private static final String MODULE_D = "d"; @Test public void testExportDependencies() throws Exception { final TestModuleLoader moduleLoader = new TestModuleLoader(); ModuleSpec.Builder builder = ModuleSpec.build(MODULE_A); builder.addDependency(new ModuleDependencySpecBuilder() .setName(MODULE_B.toString()) .setExport(true) .build()); moduleLoader.addModuleSpec(builder.create()); builder = ModuleSpec.build(MODULE_B); builder.addDependency(new ModuleDependencySpecBuilder() .setName(MODULE_C.toString()) .setExport(true) .build()); builder.addDependency(new ModuleDependencySpecBuilder() .setName(MODULE_D.toString()) .build()); moduleLoader.addModuleSpec(builder.create()); builder = ModuleSpec.build(MODULE_C); moduleLoader.addModuleSpec(builder.create()); builder = ModuleSpec.build(MODULE_D); moduleLoader.addModuleSpec(builder.create()); Module module = moduleLoader.loadModule(MODULE_A); final Set dependencyExports = new HashSet<>(); getExportedModuleDeps(module, dependencyExports); assertEquals(2, dependencyExports.size()); assertTrue(dependencyExports.contains(MODULE_B)); assertTrue(dependencyExports.contains(MODULE_C)); dependencyExports.clear(); module = moduleLoader.loadModule(MODULE_B); getExportedModuleDeps(module, dependencyExports); assertEquals(1, dependencyExports.size()); assertTrue(dependencyExports.contains(MODULE_C)); dependencyExports.clear(); module = moduleLoader.loadModule(MODULE_C); getExportedModuleDeps(module, dependencyExports); assertEquals(0, dependencyExports.size()); dependencyExports.clear(); module = moduleLoader.loadModule(MODULE_D); getExportedModuleDeps(module, dependencyExports); assertEquals(0, dependencyExports.size()); } private static void getExportedModuleDeps(final Module module, final Set dependencyExports) throws ModuleLoadException { getExportedModuleDeps(module, new HashSet(Collections.singleton(module)), dependencyExports); } private static void getExportedModuleDeps(final Module module, final Set visited, final Set dependencyExports) throws ModuleLoadException { for (Dependency dependency : module.getDependenciesInternal()) { if (dependency instanceof ModuleDependency && dependency.getExportFilter() != PathFilters.rejectAll()) { final ModuleDependency moduleDependency = (ModuleDependency) dependency; final Module md = moduleDependency.getModuleLoader().loadModule(moduleDependency.getName()); if (md != null && moduleDependency.getExportFilter() != PathFilters.rejectAll()) { if (visited.add(md)) { dependencyExports.add(md.getName()); getExportedModuleDeps(md, visited, dependencyExports); } } } } } @SuppressWarnings({ "unchecked" }) @Test @Ignore("Disabled; relies on modules not inheriting full set of JDK paths which is incorrect behavior") public void testImportPaths() throws Exception { final TestModuleLoader moduleLoader = new TestModuleLoader(); ModuleSpec.Builder builder = ModuleSpec.build(MODULE_A); builder.addDependency(new ModuleDependencySpecBuilder() .setName(MODULE_B.toString()) .setExport(true) .build()); moduleLoader.addModuleSpec(builder.create()); builder = ModuleSpec.build(MODULE_B); builder.addDependency(new ModuleDependencySpecBuilder() .setName(MODULE_C.toString()) .setExport(true) .build()); builder.addDependency(new ModuleDependencySpecBuilder() .setName(MODULE_D.toString()) .build()); moduleLoader.addModuleSpec(builder.create()); builder = ModuleSpec.build(MODULE_C); builder.addResourceRoot(ResourceLoaderSpec.createResourceLoaderSpec(TestResourceLoader.build() .addClass(ImportedClass.class) .create() )); builder.addDependency(DependencySpec.createLocalDependencySpec()); moduleLoader.addModuleSpec(builder.create()); builder = ModuleSpec.build(MODULE_D); moduleLoader.addModuleSpec(builder.create()); Module module = moduleLoader.loadModule(MODULE_A); module.getClassLoader().loadClass(ImportedClass.class.getName()); final Field pathsField = Module.class.getDeclaredField("linkage"); pathsField.setAccessible(true); final Object paths = pathsField.get(module); final Field allPathsField = paths.getClass().getDeclaredField("allPaths"); allPathsField.setAccessible(true); final Map> allPaths = (Map>) allPathsField.get(paths); Module moduleC = moduleLoader.loadModule(MODULE_C); assertEquals(4, allPaths.size()); for(Map.Entry> entry : allPaths.entrySet()) { assertEquals(1, entry.getValue().size()); assertEquals(moduleC.getClassLoaderPrivate().getLocalLoader(), entry.getValue().get(0)); } } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ModuleIteratorTest.java000066400000000000000000000117751472011152000300520ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.File; import java.io.IOException; import java.util.Iterator; import java.util.jar.JarFile; import org.jboss.modules.filter.PathFilter; import org.jboss.modules.filter.PathFilters; import org.jboss.modules.util.TestModuleLoader; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.asset.StringAsset; import org.jboss.shrinkwrap.api.exporter.ZipExporter; import org.jboss.shrinkwrap.api.spec.JavaArchive; import org.junit.Assert; import org.junit.Test; /** * * * @author Thomas.Diesler@jboss.com */ public class ModuleIteratorTest extends AbstractModuleTestCase { private static final String MODULE_A = "a"; private static final String MODULE_B = "b"; @Test public void testMetaInfServicesIterator() throws Exception { TestModuleLoader moduleLoader = new TestModuleLoader(); ModuleSpec.Builder builder = ModuleSpec.build(MODULE_A); builder.addDependency(new ModuleDependencySpecBuilder() .setName(MODULE_B) .build()); PathFilter importFilter = PathFilters.getMetaInfServicesFilter(); builder.addDependency(new ModuleDependencySpecBuilder() .setImportFilter(importFilter) .setExport(true) .setModuleLoader(moduleLoader) .setName(MODULE_B) .build()); moduleLoader.addModuleSpec(builder.create()); builder = ModuleSpec.build(MODULE_B); ResourceLoader resB = new JarFileResourceLoader("jarB", toJarFile(getModuleB())); builder.addResourceRoot(ResourceLoaderSpec.createResourceLoaderSpec(resB)); builder.addDependency(DependencySpec.createLocalDependencySpec()); moduleLoader.addModuleSpec(builder.create()); Module moduleA = moduleLoader.loadModule(MODULE_A); Iterator itres = moduleA.iterateResources(PathFilters.getMetaInfServicesFilter()); Assert.assertTrue("Found a resource", itres.hasNext()); Assert.assertEquals("META-INF/services/org/apache/camel/component/jms", itres.next().getName()); Assert.assertFalse("No other resource", itres.hasNext()); } @Test public void testIterateModules() throws Exception { IterableModuleFinder fakeFinder = new IterableModuleFinder() { private String[] modules = { "a", "b"}; @Override public Iterator iterateModules(String baseIdentifier, boolean recursive, final ModuleLoader delegateLoader) { return new Iterator() { private int pos = 0; @Override public boolean hasNext() { return pos < modules.length; } @Override public String next() { return modules[pos++]; } @Override public void remove() { throw new UnsupportedOperationException(); } }; } @Override public ModuleSpec findModule(String name, ModuleLoader delegateLoader) throws ModuleLoadException { for (String m : modules) { if (m.equals(name)) { return ModuleSpec.build(m).create(); } } return null; } }; ModuleLoader loader = new ModuleLoader(new ModuleFinder[]{fakeFinder}); Iterator it = loader.iterateModules((String) null, true); int count = 0; while (it.hasNext()) { it.next(); count++; } Assert.assertEquals(2, count); } private JarFile toJarFile(JavaArchive archive) throws IOException { ZipExporter exporter = archive.as(ZipExporter.class); File targetFile = new File("target/shrinkwrap/" + archive.getName()); targetFile.getParentFile().mkdirs(); exporter.exportTo(targetFile, true); return new JarFile(targetFile); } private JavaArchive getModuleB() { JavaArchive archive = ShrinkWrap.create(JavaArchive.class, "moduleB"); archive.addAsManifestResource(new StringAsset("someContent"), "services/org/apache/camel/component/jms"); return archive; } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ModulePropertyTest.java000066400000000000000000000057441472011152000301040ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.File; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; /** * Test to verify the functionality of module properties. * * @author David M. Lloyd */ public class ModulePropertyTest extends AbstractModuleTestCase { private ModuleLoader moduleLoader; @Before public void setupModuleLoader() throws Exception { final File repoRoot = getResource("test/repo"); moduleLoader = new LocalModuleLoader(new File[] {repoRoot}); } @Test public void testBasic() throws Exception { Module module = moduleLoader.loadModule("test.test"); assertNull(module.getProperty("non-existent")); assertEquals("blah", module.getProperty("non-existent", "blah")); assertEquals("true", module.getProperty("test.prop.1")); assertEquals("propertyValue", module.getProperty("test.prop.2")); } /** * This test parses properties attached to module dependencies. * The properties are currently not exposed via the dependency spec API, * so the test simply makes sure they can be parsed w/o errors. * @throws Exception */ @Test public void testModuleDependencyProperties() throws Exception { Module module = moduleLoader.loadModule("test.dep-props"); assertNull(module.getProperty("non-existent")); assertEquals("blah", module.getProperty("non-existent", "blah")); final DependencySpec[] deps = module.getDependencies(); int testedDepsTotal = 0; for(DependencySpec dep : deps) { if(!(dep instanceof ModuleDependencySpec)) { continue; } final ModuleDependencySpec moduleDep = (ModuleDependencySpec) dep; String depName = moduleDep.getName(); if(!depName.startsWith("test.")) { continue; } ++testedDepsTotal; depName = depName.substring("test.".length()); if(depName.equals("test")) { } else { fail("Unexpected module dependency " + moduleDep); } } assertEquals(1, testedDepsTotal); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/PathFilterTest.java000066400000000000000000000051511472011152000271440ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import org.jboss.modules.filter.MultiplePathFilterBuilder; import org.jboss.modules.filter.PathFilter; import org.jboss.modules.filter.PathFilters; import org.junit.Test; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; /** * Test to verify the PathFilter functionality. * * @author John E. Bailey */ public class PathFilterTest { @Test public void testMatch() throws Exception { PathFilter pathFilter = PathFilters.match("foo/**"); assertFalse(pathFilter.accept("foo")); assertTrue(pathFilter.accept("foo/bar")); assertTrue(pathFilter.accept("foo/bar/baz")); pathFilter = PathFilters.match("foo/*"); assertFalse(pathFilter.accept("foo")); assertTrue(pathFilter.accept("foo/bar")); assertTrue(pathFilter.accept("foo/bar/baz")); pathFilter = PathFilters.match("foo"); assertTrue(pathFilter.accept("foo")); assertTrue(pathFilter.accept("foo/bar")); assertTrue(pathFilter.accept("foo/bar/baz")); pathFilter = PathFilters.match("**/bar/**"); assertFalse(pathFilter.accept("foo")); assertFalse(pathFilter.accept("foo/bar")); assertTrue(pathFilter.accept("foo/bar/baz")); assertTrue(pathFilter.accept("foo/baz/bar/biff")); } @Test public void testDelegating() throws Exception { final MultiplePathFilterBuilder builder = PathFilters.multiplePathFilterBuilder(true); builder.addFilter(PathFilters.match("foo/*"), false); builder.addFilter(PathFilters.match("**/bar/**"), false); builder.addFilter(PathFilters.match("baz/**"), false); PathFilter pathFilter = builder.create(); assertTrue(pathFilter.accept("foo")); assertFalse(pathFilter.accept("foo/bar")); assertFalse(pathFilter.accept("foo/bar/baz")); assertFalse(pathFilter.accept("baz/foo/bar")); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/PathResourceLoaderTest.java000066400000000000000000000063051472011152000306370ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2016 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import org.jboss.modules.filter.PathFilter; import org.junit.Assert; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import java.io.File; import java.io.IOException; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; import java.util.Collection; /** * Test the functionality of the PathResourceLoader * * @author Sergei Egorov */ @RunWith(Parameterized.class) public class PathResourceLoaderTest extends AbstractResourceLoaderTestCase { @Parameterized.Parameters(name = "{0}") public static Collection data() { return Arrays.asList(new Object[][]{ {TestMode.FOLDER}, {TestMode.JAR} }); } @Parameterized.Parameter public TestMode testMode; private Path resourceRoot; @Override protected ResourceLoader createLoader(PathFilter exportFilter) throws Exception { resourceRoot = testMode.getResourceRoot(this); return ResourceLoaders.createPathResourceLoader(resourceRoot); } @Override protected void assertResource(Resource resource, String fileName) throws IOException { final Path resourceFile = resourceRoot.resolve(fileName); Assert.assertEquals(Files.size(resourceFile), resource.getSize()); Assert.assertEquals(resourceFile.toUri().toURL(), resource.getURL()); } private enum TestMode { FOLDER, JAR { @Override Path getResourceRoot(PathResourceLoaderTest test) throws Exception { // Build a jar to match the fileresource loader final File outputFile = new File(test.getResource("test"), "jarresourceloader/test.jar"); outputFile.getParentFile().mkdirs(); JarResourceLoaderTest.buildJar(super.getResourceRoot(test).toFile(), outputFile); FileSystem fileSystem = FileSystems.newFileSystem(outputFile.toPath(), (ClassLoader) null); return fileSystem.getRootDirectories().iterator().next(); } }; Path getResourceRoot(PathResourceLoaderTest test) throws Exception { Path resourceRoot = test.getResource("test/fileresourceloader").toPath().toAbsolutePath(); // Copy the classfile over test.copyResource("org/jboss/modules/test/TestClass.class", "test/fileresourceloader", "org/jboss/modules/test"); return resourceRoot; } } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/PathUtilsTest.java000066400000000000000000000052541472011152000270230ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2015 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import static org.jboss.modules.PathUtils.*; import org.junit.Test; import static org.junit.Assert.*; /** * Test to verify the PathUtils functionality. * * @author Richard Opalka */ public class PathUtilsTest { @Test public void testIsChild() { assertTrue(isChild("app.war/", "app.war/W")); assertTrue(isDirectChild("app.war/", "app.war/W")); assertTrue(isChild("app.war/", "app.war/FOO/BAR")); assertFalse(isDirectChild("app.war/", "app.war/FOO/BAR")); assertTrue(isChild("app.war", "app.war/W")); assertTrue(isDirectChild("app.war", "app.war/W")); assertTrue(isChild("app.war", "app.war/FOO/BAR")); assertFalse(isDirectChild("app.war", "app.war/FOO/BAR")); assertFalse(isDirectChild("app.war", "app.war/")); assertFalse(isChild("app.war", "app.war/")); } @Test public void testBasicNames() { assertEquals("basic/main", basicModuleNameToPath("basic")); assertEquals("a/b/main", basicModuleNameToPath("a.b")); assertEquals("a/b/c", basicModuleNameToPath("a.b:c")); assertEquals("a/b/c.d", basicModuleNameToPath("a.b:c.d")); assertEquals("a/b/c:d", basicModuleNameToPath("a.b:c:d")); assertEquals("a/b/c.d", basicModuleNameToPath("a.b:c/d")); assertEquals("a.b/c.d", basicModuleNameToPath("a/b:c.d")); assertEquals("a:b/c.d", basicModuleNameToPath("a\\:b:c.d")); assertNull(basicModuleNameToPath(".")); assertNull(basicModuleNameToPath("..")); assertNull(basicModuleNameToPath("./")); assertNull(basicModuleNameToPath("/foo")); assertNull(basicModuleNameToPath(".foo")); assertNull(basicModuleNameToPath("foo/.")); assertNull(basicModuleNameToPath("foo/")); assertNull(basicModuleNameToPath("foo:")); assertNull(basicModuleNameToPath("foo//bar")); assertNull(basicModuleNameToPath("foo..bar")); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ResourceRootPathsTest.java000066400000000000000000000161621472011152000305410ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2016 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.File; import java.io.IOException; import java.net.JarURLConnection; import java.net.URI; import java.nio.file.FileVisitResult; import java.nio.file.FileVisitor; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.nio.file.StandardOpenOption; import java.nio.file.attribute.BasicFileAttributes; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; /** * Test absolute and relative paths in resource-roots' path attribute (MODULES-218) * @author Martin Simka */ public class ResourceRootPathsTest extends AbstractModuleTestCase { @Rule public TemporaryFolder tmpDir = new TemporaryFolder(); private File repoRoot; private File testModuleRoot; private File fileResourceRoot; private static final String MODULE_XML_TEMPLATE = "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + ""; private ModuleLoader moduleLoader; @Before public void setupModuleLoader() throws Exception { repoRoot = tmpDir.newFolder("repo").getCanonicalFile(); testModuleRoot = new File(repoRoot, "test/test/main/"); // Build a jar in module copyResource("org/jboss/modules/test/TestClass.class", "test/fileresourceloader", "org/jboss/modules/test"); fileResourceRoot = getResource("test/fileresourceloader"); final File jarInModule = new File(testModuleRoot, "relative.jar"); jarInModule.getParentFile().mkdirs(); JarResourceLoaderTest.buildJar(fileResourceRoot, jarInModule); // Build a jar outside of module final File jarOutsideModule = new File(repoRoot, "relative.jar"); JarResourceLoaderTest.buildJar(fileResourceRoot, jarOutsideModule); // copy resource dir to module copyDir(fileResourceRoot, new File(testModuleRoot, "relativedir")); //create module.xml final File moduleXml = new File(testModuleRoot, "module.xml"); String moduleXmlContent = MODULE_XML_TEMPLATE.replaceAll("@absolutejar@", jarOutsideModule.getCanonicalPath().replace(File.separatorChar, '/')); moduleXmlContent = moduleXmlContent.replaceAll("@absolutedir@", fileResourceRoot.getCanonicalPath().replace(File.separatorChar, '/')); Files.write(moduleXml.toPath(), moduleXmlContent.getBytes(), StandardOpenOption.CREATE_NEW); moduleLoader = new LocalModuleLoader(new File[] {repoRoot}); } @Test public void testPaths() throws Exception { ConcreteModuleSpec moduleSpec = (ConcreteModuleSpec) moduleLoader.findModule("test.test"); ResourceLoaderSpec[] resourceLoaders = moduleSpec.getResourceLoaders(); int checkCount = 0; for (ResourceLoaderSpec r : resourceLoaders) { ResourceLoader resourceLoader = r.getResourceLoader(); if (resourceLoader instanceof JarFileResourceLoader) { final File jar = getFileFromJarUri(resourceLoader.getLocation()); // validate jar with relative path if (testModuleRoot.equals(jar.getParentFile().getCanonicalFile())) { checkCount++; continue; } // validate jar with absolute path if (repoRoot.equals(jar.getParentFile().getCanonicalFile())) { checkCount++; continue; } } else if (resourceLoader instanceof PathResourceLoader) { final File dir = new File(resourceLoader.getLocation()); // validate dir with relative path if (testModuleRoot.equals(dir.getParentFile())) { checkCount++; continue; } // validate dir with absolute path if (fileResourceRoot.getParentFile().equals(dir.getParentFile())) { checkCount++; continue; } } } Assert.assertEquals("Test should have checked 4 ResourceLoaders", 4, checkCount); } private File getFileFromJarUri(URI uri) throws Exception { JarURLConnection connection = (JarURLConnection) uri.toURL().openConnection(); File file = new File(connection.getJarFileURL().toURI()); return file; } static void copyDir(File sourceDir, File targetDir) throws Exception { abstract class CopyFileVisitor implements FileVisitor { boolean isFirst = true; Path ptr; } CopyFileVisitor copyVisitor = new CopyFileVisitor() { @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { if (!isFirst) { Path target = ptr.resolve(dir.getName(dir.getNameCount() - 1)); ptr = target; } Files.copy(dir, ptr, StandardCopyOption.COPY_ATTRIBUTES); isFirst = false; return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { Path target = ptr.resolve(file.getFileName()); Files.copy(file, target, StandardCopyOption.COPY_ATTRIBUTES); return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { throw exc; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { Path target = ptr.getParent(); ptr = target; return FileVisitResult.CONTINUE; } }; copyVisitor.ptr = targetDir.toPath(); Files.walkFileTree(sourceDir.toPath(), copyVisitor); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/SymlinkResourceLoaderTest.java000066400000000000000000000050721472011152000313710ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import java.io.File; import java.nio.file.FileSystemException; import java.nio.file.Files; import java.security.AccessController; import org.jboss.modules.filter.PathFilter; import org.junit.After; import org.junit.Assert; import org.junit.Assume; /** * Test the functionality of the PathResourceLoader with resources containing symbolic links * * @author Bartosz Spyrko-Smietanko */ public class SymlinkResourceLoaderTest extends AbstractResourceLoaderTestCase { private File resourceRoot; @After public void tearDown() throws Exception { File base = getResource("test"); File symlink = new File(base, "symlink"); if (symlink.exists()) { symlink.delete(); } } protected ResourceLoader createLoader(final PathFilter exportFilter) throws Exception { File base = getResource("test"); File realRoot = getResource("test/fileresourceloader"); try { resourceRoot = Files.createSymbolicLink(new File(base, "symlink").toPath(), realRoot.toPath()).toFile(); } catch (UnsupportedOperationException | FileSystemException e) { Assume.assumeNoException(e); } // Copy the classfile over copyResource("org/jboss/modules/test/TestClass.class", "test/fileresourceloader", "org/jboss/modules/test"); return new PathResourceLoader("test-root", resourceRoot.toPath(), AccessController.getContext()); } @Override protected void assertResource(Resource resource, String fileName) { final File resourceFile = getExpectedFile(fileName); Assert.assertEquals(resourceFile.length(), resource.getSize()); } public void testGetClassSpec() throws Exception { super.testGetClassSpec(); } protected File getExpectedFile(String fileName) { return new File(resourceRoot, fileName); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/VersionTest.java000066400000000000000000000140121472011152000265230ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2016 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules; import static org.jboss.modules.Version.parse; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import org.junit.Test; /** * @author David M. Lloyd */ public class VersionTest { private static void parseFail(String str) { try { parse(str); fail("Expected parsing to fail for " + str); } catch (IllegalArgumentException ok) { } } @Test public void testParsing() { parse("1"); parse("a"); parseFail("."); parse("1.1"); parse("1.a"); parse("1a"); parse("a1"); parse("1+1"); parse("1-1"); parse("1_1"); parse("1_1a.1993-12-31"); parseFail("1."); parseFail("1.."); parseFail(".1"); } private boolean testCompare(Version v1, Version v2) { final boolean res = v1.equals(v2); if (res) { assertTrue(v1.hashCode() == v2.hashCode()); } return res; } @Test public void testEquals() { assertTrue(testCompare(parse("1.0"), parse("1.0"))); assertTrue(testCompare(parse("a1"), parse("a1"))); assertFalse(testCompare(parse("1.1"), parse("1.0"))); assertFalse(testCompare(parse("1.1"), parse("1.01"))); assertFalse(testCompare(parse("1.1"), parse("1.10"))); assertFalse(testCompare(parse("1.1"), parse("1.100"))); } @Test public void testCompareTo() { assertEquals(0, parse("1.0").compareTo(parse("1.0"))); assertEquals(-1, parse("1.0").compareTo(parse("1.0.0"))); assertEquals(1, parse("1.0.0.0").compareTo(parse("1.0.0"))); assertEquals(1, parse("5u1").compareTo(parse("5"))); assertEquals(-1, parse("5u1").compareTo(parse("5.1"))); } @Test public void testIterate() { Version.Iterator i = parse("1.0.0u2").iterator(); assertTrue(i.hasNext()); i.next(); assertTrue(i.isPart()); assertTrue(i.isNumberPart()); assertFalse(i.isAlphaPart()); assertFalse(i.isSeparator()); assertFalse(i.isEmptySeparator()); assertFalse(i.isNonEmptySeparator()); assertEquals(1, i.getNumberPartAsInt()); assertEquals(1, i.getNumberPartAsLong()); assertEquals("1", i.getNumberPartAsString()); assertTrue(i.hasNext()); i.next(); assertFalse(i.isPart()); assertFalse(i.isNumberPart()); assertFalse(i.isAlphaPart()); assertTrue(i.isSeparator()); assertFalse(i.isEmptySeparator()); assertTrue(i.isNonEmptySeparator()); assertEquals('.', i.getSeparatorCodePoint()); assertTrue(i.hasNext()); i.next(); assertTrue(i.isPart()); assertTrue(i.isNumberPart()); assertFalse(i.isAlphaPart()); assertFalse(i.isSeparator()); assertFalse(i.isEmptySeparator()); assertFalse(i.isNonEmptySeparator()); assertEquals(0, i.getNumberPartAsInt()); assertEquals(0, i.getNumberPartAsLong()); assertEquals("0", i.getNumberPartAsString()); assertTrue(i.hasNext()); i.next(); assertFalse(i.isPart()); assertFalse(i.isNumberPart()); assertFalse(i.isAlphaPart()); assertTrue(i.isSeparator()); assertFalse(i.isEmptySeparator()); assertTrue(i.isNonEmptySeparator()); assertEquals('.', i.getSeparatorCodePoint()); assertTrue(i.hasNext()); i.next(); assertTrue(i.isPart()); assertTrue(i.isNumberPart()); assertFalse(i.isAlphaPart()); assertFalse(i.isSeparator()); assertFalse(i.isEmptySeparator()); assertFalse(i.isNonEmptySeparator()); assertEquals(0, i.getNumberPartAsInt()); assertEquals(0, i.getNumberPartAsLong()); assertEquals("0", i.getNumberPartAsString()); assertTrue(i.hasNext()); i.next(); assertFalse(i.isPart()); assertFalse(i.isNumberPart()); assertFalse(i.isAlphaPart()); assertTrue(i.isSeparator()); assertTrue(i.isEmptySeparator()); assertFalse(i.isNonEmptySeparator()); assertTrue(i.hasNext()); i.next(); assertTrue(i.isPart()); assertFalse(i.isNumberPart()); assertTrue(i.isAlphaPart()); assertFalse(i.isSeparator()); assertFalse(i.isEmptySeparator()); assertFalse(i.isNonEmptySeparator()); assertEquals("u", i.getAlphaPart()); assertTrue(i.hasNext()); i.next(); assertFalse(i.isPart()); assertFalse(i.isNumberPart()); assertFalse(i.isAlphaPart()); assertTrue(i.isSeparator()); assertTrue(i.isEmptySeparator()); assertFalse(i.isNonEmptySeparator()); assertTrue(i.hasNext()); i.next(); assertTrue(i.isPart()); assertTrue(i.isNumberPart()); assertFalse(i.isAlphaPart()); assertFalse(i.isSeparator()); assertFalse(i.isEmptySeparator()); assertFalse(i.isNonEmptySeparator()); assertEquals(2, i.getNumberPartAsInt()); assertEquals(2, i.getNumberPartAsLong()); assertEquals("2", i.getNumberPartAsString()); assertFalse(i.hasNext()); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/maven/000077500000000000000000000000001472011152000245035ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/maven/MavenSettingsTest.java000066400000000000000000000223611472011152000310010ustar00rootroot00000000000000package org.jboss.modules.maven; import java.io.File; import java.lang.reflect.Field; import java.net.InetSocketAddress; import java.net.Proxy; import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import org.jboss.modules.Module; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; /** * @author Tomaz Cerar (c) 2015 Red Hat Inc. */ public class MavenSettingsTest { void clearCachedSettings() throws Exception { Field mavenSettings = MavenSettings.class.getDeclaredField("mavenSettings"); mavenSettings.setAccessible(true); mavenSettings.set(null, null); } @Rule public TemporaryFolder tmpdir = new TemporaryFolder(); @Test public void testLocalRepositoryOverriddenViaSystemProperty() throws Exception { URL settingsXmlUrl = MavenSettingsTest.class.getResource("settings-with-local-repo-defined.xml"); System.setProperty("jboss.modules.settings.xml.url", settingsXmlUrl.toExternalForm()); String temporaryLocalRepository = tmpdir.newFolder("repository").getAbsolutePath(); System.setProperty("maven.repo.local", temporaryLocalRepository); try { clearCachedSettings(); MavenSettings settings = MavenSettings.getSettings(); Assert.assertEquals(temporaryLocalRepository, settings.getLocalRepository().toString()); } finally { System.clearProperty("maven.repo.local"); System.clearProperty("jboss.modules.settings.xml.url"); } } @Test public void testLocalRepositoryNotOverriddenViaSystemProperty() throws Exception { URL settingsXmlUrl = MavenSettingsTest.class.getResource("settings-with-local-repo-defined.xml"); System.setProperty("jboss.modules.settings.xml.url", settingsXmlUrl.toExternalForm()); try { clearCachedSettings(); MavenSettings settings = MavenSettings.getSettings(); Assert.assertEquals("/user/defined/path/in/settings/xml".replace('/', File.separatorChar), settings.getLocalRepository().toString()); } finally { System.clearProperty("jboss.modules.settings.xml.url"); } } @Test public void testWithPassedRepository() throws Exception { System.setProperty("maven.repo.local", tmpdir.newFolder("repository").getAbsolutePath()); System.setProperty("remote.maven.repo", "http://repository.jboss.org/nexus/content/groups/public/,https://maven-central.storage.googleapis.com/"); try { clearCachedSettings(); MavenSettings settings = MavenSettings.getSettings(); List remoteRepos = settings.getRemoteRepositories(); Assert.assertTrue(remoteRepos.size() >= 3); //at least 3 must be present, other can come from settings.xml Assert.assertTrue(remoteRepos.contains("https://repo1.maven.org/maven2/")); Assert.assertTrue(remoteRepos.contains("http://repository.jboss.org/nexus/content/groups/public/")); Assert.assertTrue(remoteRepos.contains("https://maven-central.storage.googleapis.com/")); } finally { System.clearProperty("maven.repo.local"); System.clearProperty("remote.repository"); } } @Test public void testWithEmptyPassedRepository() throws Exception { Path userRepo = tmpdir.newFolder(".m2", "repository").toPath(); String userHome = System.getProperty("user.home"); System.setProperty("user.home", tmpdir.getRoot().getAbsolutePath()); System.setProperty("maven.repo.local", ""); try { clearCachedSettings(); MavenSettings settings = MavenSettings.getSettings(); Assert.assertEquals(userRepo, settings.getLocalRepository()); } finally { System.setProperty("user.home", userHome); System.clearProperty("maven.repo.local"); } } @Test public void testEmptyLocalRepo() throws Exception { MavenSettings settings = new MavenSettings(); MavenSettings.parseSettingsXml(Paths.get(MavenSettingsTest.class.getResource("settings-empty-local-repo.xml").toURI()), settings); Assert.assertNull(settings.getLocalRepository());//local repo shouldn't be set } @Test public void testInterpolatedLocalRepo() throws Exception { Path userRepo = tmpdir.newFolder(".m2", "repository").toPath(); String userHome = System.getProperty("user.home"); System.setProperty("user.home", tmpdir.getRoot().getAbsolutePath()); try { clearCachedSettings(); MavenSettings settings = new MavenSettings(); MavenSettings.parseSettingsXml(Paths.get(MavenSettingsTest.class.getResource("settings-interpolated-local-repo.xml").toURI()), settings); Assert.assertEquals(Paths.get(tmpdir.getRoot().getAbsolutePath() + "/.mvnrepository"), settings.getLocalRepository()); } finally { System.setProperty("user.home", userHome); } } @Test public void testProxies() throws Exception { MavenSettings settings = new MavenSettings(); MavenSettings.parseSettingsXml(Paths.get(MavenSettingsTest.class.getResource("settings-empty-local-repo.xml").toURI()), settings); List proxies = settings.getProxies(); Assert.assertEquals(1, proxies.size()); MavenSettings.Proxy proxy = proxies.get(0); Assert.assertEquals("my-proxy", proxy.getId()); Assert.assertEquals("myproxy.corp.com", proxy.getHost()); Assert.assertEquals(8080, proxy.getPort()); Assert.assertEquals("http", proxy.getProtocol()); Assert.assertEquals("bob", proxy.getUsername()); Assert.assertEquals("hunter2", proxy.getPassword()); Assert.assertTrue(proxy.canProxyFor(new URL("http://www.redhat.com/"))); Assert.assertFalse(proxy.canProxyFor(new URL("http://genius.apple.com/"))); Proxy netProxy = proxy.getProxy(); Assert.assertNotNull(netProxy); Assert.assertEquals("myproxy.corp.com", ((InetSocketAddress) netProxy.address()).getHostName()); Assert.assertEquals(8080, ((InetSocketAddress) netProxy.address()).getPort()); } @Test public void testProxySelection() throws Exception { MavenSettings settings = new MavenSettings(); MavenSettings.parseSettingsXml(Paths.get(MavenSettingsTest.class.getResource("settings-empty-local-repo.xml").toURI()), settings); List proxies = settings.getProxies(); Assert.assertEquals(1, proxies.size()); MavenSettings.Proxy proxy = settings.getProxyFor(new URL("http://genius.apple.com/foo/bar/baz")); Assert.assertNull(proxy); proxy = settings.getProxyFor(new URL("http://repository.jboss.org/foo/bar/baz")); Assert.assertNotNull(proxy); Assert.assertEquals("myproxy.corp.com", ((InetSocketAddress) proxy.getProxy().address()).getHostName()); Assert.assertEquals(8080, ((InetSocketAddress) proxy.getProxy().address()).getPort()); } /** * testing is snapshot resolving works properly, as in case of snapshot version, we need to use different path than exact version. * * @throws Exception */ @Test public void testSnapshotResolving() throws Exception { ArtifactCoordinates coordinates = ArtifactCoordinates.fromString("org.wildfly.core:wildfly-version:2.0.5.Final-20151222.144931-1"); String path = coordinates.relativeArtifactPath('/'); Assert.assertEquals("org/wildfly/core/wildfly-version/2.0.5.Final-SNAPSHOT/wildfly-version-2.0.5.Final-20151222.144931-1", path); } @Test public void testInterpolateVariablesOneVariable() throws Exception { try { System.setProperty( "test.user.home", "/home/bob" ); Assert.assertEquals("/home/bob/.m2/repository", MavenSettings.interpolateVariables("${test.user.home}/.m2/repository")); } finally { System.clearProperty("test.user.home"); } } @Test public void testInterpolateVariablesTwoVariables() throws Exception { try { System.setProperty( "test.user.home", "/home/bob" ); System.setProperty( "test.repo.dir", "repository" ); Assert.assertEquals("/home/bob/.m2/repository", MavenSettings.interpolateVariables("${test.user.home}/.m2/${test.repo.dir}")); } finally { System.clearProperty("test.user.home"); } } @Test public void testInterpolateVariablesInvalidExpression() throws Exception { try { System.setProperty( "test.user.home", "/home/bob" ); Assert.assertEquals("${test.user.home/.m2/repository", MavenSettings.interpolateVariables("${test.user.home/.m2/repository")); } finally { System.clearProperty("test.user.home"); } } @Test public void testInterpolateVariablesInvalidExpression2() throws Exception { try { System.setProperty( "test.user.home", "/home/bob" ); Assert.assertEquals("/home/bob/.m2/${repoName", MavenSettings.interpolateVariables("${test.user.home}/.m2/${repoName")); } finally { System.clearProperty("test.user.home"); } } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/maven/NonProxyHostTest.java000066400000000000000000000020711472011152000306400ustar00rootroot00000000000000package org.jboss.modules.maven; import java.net.MalformedURLException; import java.net.URL; import org.junit.Assert; import org.junit.Test; /** * Created by bob on 4/21/17. */ public class NonProxyHostTest { @Test public void testExactMatch() throws MalformedURLException { MavenSettings.NonProxyHost nph = new MavenSettings.NonProxyHost("www.google.com"); Assert.assertTrue(nph.matches(new URL("http://www.google.com/"))); Assert.assertFalse(nph.matches(new URL("http://google.com/"))); Assert.assertFalse(nph.matches(new URL("http://www.apple.com/"))); } @Test public void testWildcardMatch() throws MalformedURLException { MavenSettings.NonProxyHost nph = new MavenSettings.NonProxyHost("*.google.com"); Assert.assertTrue(nph.matches(new URL("http://www.google.com/"))); Assert.assertTrue(nph.matches(new URL("http://wave.google.com/"))); Assert.assertFalse(nph.matches(new URL("http://google.com/"))); Assert.assertFalse(nph.matches(new URL("http://www.apple.com/"))); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ref/000077500000000000000000000000001472011152000241515ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ref/AbstractReapableReferenceTest.java000066400000000000000000000023661472011152000327010ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.ref; import org.jboss.modules.ref.util.Assert; /** * Super class for all test cases that apply to reapable references. * * @author Flavia Rainone * @see Reapable */ public abstract class AbstractReapableReferenceTest extends AbstractReferenceTest { final void assertReference(Reference reference, T referenceValue, A attachment, Reaper reaper) { Assert.assertReference(reference, referenceValue, attachment, getTestedReferenceType(), reaper); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ref/AbstractReferenceTest.java000066400000000000000000000065111472011152000312410ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.ref; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import org.jboss.modules.ref.Reference.Type; import org.jboss.modules.ref.util.Assert; import org.junit.Test; /** * Super class for all reference test cases, contains a few tests for functionality common to all * references, and a reference assertion method. * * @author Flavia Rainone */ public abstract class AbstractReferenceTest { abstract Reference createReference(T value, A attachment); abstract Type getTestedReferenceType(); @Test public void referenceEqualsReference() { final Reference reference1 = createReference(new StringBuffer().append("some text text"), (Number) Long.valueOf(5L)); final Reference reference2 = createReference(new StringBuffer().append("some text"), (Number) Double.valueOf(5.5)); final Reference reference3 = createReference(null, null); final Reference reference4 = createReference(new StringBuffer().append("some text text"), (Number) Long.valueOf(5L)); assertEquals(reference1, reference1); assertEquals(reference1.hashCode(), reference1.hashCode()); assertFalse(reference1.equals(reference2)); assertFalse(reference1.equals(reference3)); assertFalse(reference1.equals(reference4)); assertEquals(reference2, reference2); assertEquals(reference2.hashCode(), reference2.hashCode()); assertFalse(reference2.equals(reference3)); assertFalse(reference2.equals(reference4)); assertEquals(reference3, reference3); assertEquals(reference3.hashCode(), reference3.hashCode()); assertFalse(reference3.equals(reference4)); assertEquals(reference4, reference4); assertEquals(reference4.hashCode(), reference4.hashCode()); } @Test public void clearReference() { final Reference reference = createReference(Boolean.TRUE, "attachment for true"); assertTrue(reference.get().booleanValue()); assertEquals("attachment for true", reference.getAttachment()); reference.clear(); assertNull(reference.get()); assertEquals("attachment for true", reference.getAttachment()); } final void assertReference(Reference reference, T referent, A attachment) { Assert.assertReference(reference, referent, attachment, getTestedReferenceType()); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ref/PhantomReferenceTestCase.java000066400000000000000000000070101472011152000316730ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.ref; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import java.lang.ref.ReferenceQueue; import java.util.ArrayList; import java.util.Collection; import org.jboss.modules.ref.Reference.Type; import org.jboss.modules.ref.util.TestReaper; import org.junit.Test; /** * Test for PhantomReference. * * @author Flavia Rainone * @see PhantomReference */ public class PhantomReferenceTestCase extends AbstractReapableReferenceTest { @Test public void plainPhantomReference() { final Reference reference = new PhantomReference("referent", "attachment", (ReferenceQueue) null); assertReference(reference, null, "attachment", null); } @Test public void nullPhantomReference() throws Exception { final Reference reference = new PhantomReference(null, Integer.valueOf(0), new ReferenceQueue()); assertReference(reference, null, Integer.valueOf(0), null); } @Test public void phantomReferenceWithReferenceQueue() throws Exception { final ReferenceQueue> referenceQueue = new ReferenceQueue>(); Collection collection = new ArrayList(); final Reference, String> reference = new PhantomReference, String>(collection, "collection", referenceQueue); assertReference(reference, null, "collection", null); collection = null; System.gc(); assertSame(reference, referenceQueue.remove(300)); } @Test public void phantomReferenceWithReaper() throws Exception { Thing thing = new Thing(); final TestReaper reaper = new TestReaper(); final Reference reference = new PhantomReference(thing, null, reaper); assertReference(reference, null, null, reaper); thing = null; System.gc(); assertSame(reference, reaper.getReapedReference()); } @Override @Test public void clearReference() { final Reference reference = createReference(Boolean.TRUE, "attachment for true"); assertNull(reference.get()); assertEquals("attachment for true", reference.getAttachment()); reference.clear(); assertNull(reference.get()); assertEquals("attachment for true", reference.getAttachment()); } @Override Reference createReference(T value, A attachment) { return new PhantomReference(value, attachment, new TestReaper()); } @Override Type getTestedReferenceType() { return Type.PHANTOM; } }jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ref/ReferencesTestCase.java000066400000000000000000000207461472011152000305420ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.ref; import static org.jboss.modules.ref.util.Assert.assertReference; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.lang.ref.ReferenceQueue; import java.util.ArrayList; import java.util.Collection; import java.util.concurrent.TimeUnit; import org.jboss.modules.ref.Reference.Type; import org.jboss.modules.ref.References.ReaperThread; import org.jboss.modules.ref.util.TestReaper; import org.junit.Test; /** * Test for {@link References} class and internal classes. * * @author Flavia Rainone */ public class ReferencesTestCase { @Test public void nullReference() { final Reference nullReference = References.getNullReference(); assertReference(nullReference, null, null, Type.NULL); nullReference.clear(); assertReference(nullReference, null, null, Type.NULL); assertEquals(nullReference, References.create(Type.NULL, null, null)); assertEquals(nullReference, References.create(Type.NULL, null, null, (Reaper) null)); assertEquals(nullReference, References.create(Type.NULL, null, null, (ReferenceQueue) null)); } @Test public void createStrongReference() { final Reference reference = createReference(Type.STRONG); assertTrue(reference instanceof StrongReference); } @Test public void createSoftReference() { final Reference reference = createReference(Type.SOFT); assertTrue(reference instanceof SoftReference); } @Test public void createWeakReference() { final Reference reference = createReference(Type.WEAK); assertTrue(reference instanceof WeakReference); } @Test public void createIllegalPhantomReference() { try { References.create(Type.PHANTOM, "value", "attachment"); fail("IllegalArgumentException expected because of missing reaper/reference queue"); } catch (IllegalArgumentException e) {} } @Test public void createStrongReferenceWithReaper() throws Exception { final Object referent = new Object(); final Reference reference = References.create(Type.STRONG, referent, "attachment", new TestReaper()); assertReference(reference, referent, "attachment", Type.STRONG); assertTrue(reference instanceof StrongReference); } @Test public void createSoftReferenceWithReaper() throws Exception { final Reference reference = createReferenceWithReaper(Type.SOFT, false, false); assertTrue(reference instanceof SoftReference); } @Test public void createWeakReferenceWithReaper() throws Exception { final Reference reference = createReferenceWithReaper(Type.WEAK, false, true); assertTrue(reference instanceof WeakReference); } @Test public void createPhantomReferenceWithReaper() throws Exception { final Reference reference = createReferenceWithReaper(Type.PHANTOM, true, true); assertTrue(reference instanceof PhantomReference); } @Test public void createStrongReferenceWithQueue() throws Exception { final Object referent = new Object(); final Reference reference = References.create(Type.STRONG, referent, "attachment", new ReferenceQueue()); assertReference(reference, referent, "attachment", Type.STRONG); assertTrue(reference instanceof StrongReference); } @Test public void createSoftReferenceWithQueue() throws Exception { final Reference reference = createReferenceWithQueue(Type.SOFT, false, false); assertTrue(reference instanceof SoftReference); } @Test public void createWeakReferenceWithQueue() throws Exception { final Reference reference = createReferenceWithQueue(Type.WEAK, false, true); assertTrue(reference instanceof WeakReference); } @Test public void createPhantomReferenceWithQueue() throws Exception { final Reference reference = createReferenceWithQueue(Type.PHANTOM, true, true); assertTrue(reference instanceof PhantomReference); } @Test public void reapUnreapableReference() throws Exception { Object referent = new Object(); final TestReaper reaper = new TestReaper(); final Reference reference = new UnreapableWeakReference(referent); assertReference(reference, referent, null, Type.WEAK); referent = null; System.gc(); assertNull(reaper.get(200, TimeUnit.MILLISECONDS)); } @Test public void failToReapReference() throws Exception { final TestReaper reaper = new FailToReap(); Object referent = new Object(); final Reference reference = new WeakReference(referent, null, reaper); assertReference(reference, referent, null, Type.WEAK, reaper); referent = null; System.gc(); assertNull(reaper.get(200, TimeUnit.MILLISECONDS)); } private Reference createReference(Type type) { final Reference reference = References.create(type, "value", "attachment"); assertReference(reference, "value", "attachment", type); return reference; } private Reference createReferenceWithReaper(Type type, boolean expectedNullValue, boolean testReaper) throws Exception { Object referent = new Object(); final TestReaper reaper = new TestReaper(); final Reference reference = References.create(type, referent, "attachment", reaper); assertReference(reference, expectedNullValue? null: referent, "attachment", type, reaper); if (testReaper) { referent = null; System.gc(); assertSame(reference, reaper.get()); } return reference; } private Reference, Object> createReferenceWithQueue(Type type, boolean expectedNullValue, boolean testQueue) throws Exception { final Object referenceAttachment = new Object(); Collection referent = new ArrayList(); referent.add(Integer.valueOf(1)); referent.add(Integer.valueOf(11)); referent.add(Integer.valueOf(111)); final ReferenceQueue> referenceQueue = new ReferenceQueue>(); final Reference, Object> reference = References.create(type, referent, referenceAttachment, referenceQueue); assertReference(reference, expectedNullValue? null: referent, referenceAttachment, type, null); if (testQueue) { referent = null; System.gc(); assertSame(reference, referenceQueue.remove(300)); } return reference; } private static final class UnreapableWeakReference extends java.lang.ref.WeakReference implements Reference { UnreapableWeakReference(Object referent) { super(referent, ReaperThread.REAPER_QUEUE); } @Override public Void getAttachment() { return null; } @Override public Reference.Type getType() { return Type.WEAK; } } private static final class FailToReap extends TestReaper { @Override public void reap(Reference reference) { throw new RuntimeException("fail to reap"); } } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ref/SoftReferenceTestCase.java000066400000000000000000000055661472011152000312160ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.ref; import java.lang.ref.ReferenceQueue; import java.util.ArrayList; import java.util.Collection; import org.jboss.modules.ref.Reference.Type; import org.jboss.modules.ref.util.TestReaper; import org.junit.Test; /** * Test for {@link SoftReference}. * * @author Flavia Rainone */ public class SoftReferenceTestCase extends AbstractReapableReferenceTest { @Test public void plainSoftReference() { final Reference reference = new SoftReference("referent", "attachment"); assertReference(reference, "referent", "attachment", null); } @Test public void softReferenceWithoutAttachment() { final Reference reference = new SoftReference("referent"); assertReference(reference, "referent", null, null); } @Test public void nullSoftReference() throws Exception { final Reference reference = new SoftReference(null, Integer.valueOf(0)); assertReference(reference, null, Integer.valueOf(0), null); } @Test public void softReferenceWithReferenceQueue() throws Exception { final ReferenceQueue> referenceQueue = new ReferenceQueue>(); final Collection collection = new ArrayList(); final Reference, String> reference = new SoftReference, String>(collection, "collection", referenceQueue); assertReference(reference, collection, "collection", null); } @Test public void softReferenceWithReaper() throws Exception { final Thing thing = new Thing(); final TestReaper reaper = new TestReaper(); final Reference reference = new SoftReference(thing, null, reaper); assertReference(reference, thing, null, reaper); } @Override Reference createReference(T value, A attachment) { return new SoftReference(value, attachment); } @Override Type getTestedReferenceType() { return Type.SOFT; } }jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ref/StrongReferenceTestCase.java000066400000000000000000000042031472011152000315420ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.ref; import org.jboss.modules.ref.Reference.Type; import org.junit.Test; /** * Test for {@link StrongReference}. * * @author Flavia Rainone */ public class StrongReferenceTestCase extends AbstractReferenceTest{ @Test public void plainStrongReference() { final Reference reference = new StrongReference("referent", "attachment"); assertReference(reference, "referent", "attachment"); } @Test public void noAttachmentReference() { final Reference reference = new StrongReference("noAttachmentReference"); assertReference(reference, "noAttachmentReference", null); } @Test public void nullReference() { final Reference reference = new StrongReference(null, "attachment of null reference"); assertReference(reference, null, "attachment of null reference"); } @Test public void nullReferenceWithoutAttachment() { final Reference reference = new StrongReference(null); assertReference(reference, null, null); } @Override Reference createReference(T value, A attachment) { return new StrongReference(value, attachment); } @Override Type getTestedReferenceType() { return Type.STRONG; } }jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ref/Thing.java000066400000000000000000000020101472011152000260560ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.ref; /** * @author David M. Lloyd */ public final class Thing { private final String blah = "blah!"; private final int boo = 123; public String getBlah() { return blah; } public int getBoo() { return boo; } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ref/WeakReferenceTestCase.java000066400000000000000000000061421472011152000311610ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.ref; import static org.junit.Assert.assertSame; import java.lang.ref.ReferenceQueue; import java.util.ArrayList; import java.util.Collection; import org.jboss.modules.ref.Reference.Type; import org.jboss.modules.ref.util.TestReaper; import org.junit.Test; /** * Test for {@link WeakReference}. * * @author Flavia Rainone */ public class WeakReferenceTestCase extends AbstractReapableReferenceTest { @Test public void plainWeakReference() { final Reference reference = new WeakReference("referent", "attachment"); assertReference(reference, "referent", "attachment", null); } @Test public void weakReferenceWithoutAttachment() { final Reference reference = new WeakReference("referent"); assertReference(reference, "referent", null, null); } @Test public void nullWeakReference() throws Exception { final Reference reference = new WeakReference(null, Integer.valueOf(0)); assertReference(reference, null, Integer.valueOf(0)); } @Test public void weakReferenceWithReferenceQueue() throws Exception { final ReferenceQueue> referenceQueue = new ReferenceQueue>(); Collection collection = new ArrayList(); final Reference, String> reference = new WeakReference, String>(collection, "collection", referenceQueue); assertReference(reference, collection, "collection", null); collection = null; System.gc(); assertSame(reference, referenceQueue.remove(300)); } @Test public void weakReferenceWithReaper() throws Exception { Thing thing = new Thing(); final TestReaper reaper = new TestReaper(); final Reference reference = new WeakReference(thing, null, reaper); assertReference(reference, thing, null, reaper); thing = null; System.gc(); assertSame(reference, reaper.getReapedReference()); } @Override Reference createReference(T value, A attachment) { return new WeakReference(value, attachment); } @Override Type getTestedReferenceType() { return Type.WEAK; } }jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ref/util/000077500000000000000000000000001472011152000251265ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ref/util/Assert.java000066400000000000000000000067731472011152000272470ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.ref.util; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; import org.jboss.modules.ref.Reaper; import org.jboss.modules.ref.Reference; import org.jboss.modules.ref.Reference.Type; /** * Assertion methods used by reference tests. * * @author Flavia Rainone */ public class Assert { /** * Assert that {@code reference} contains {@code referent}, {@code attachment}, and that its type is {@code type}. * * @param the type of referent * @param the type of attachment * @param reference the reference that needs to be checked * @param referent the expected content for {@code reference} * @param attachment the expected attachment contained in {@code reference} * @param type the expected type of {@code reference} */ public static final void assertReference(Reference reference, T referent, A attachment, Type type) { assertEquals(referent, reference.get()); assertEquals(attachment, reference.getAttachment()); assertSame(type, reference.getType()); assertNotNull(reference.toString()); // make sure that no exception is thrown and that null is never returned } /** * Assert that {@code reference} contains {@code referent}, {@code attachment}, and that its type is {@code type}. * Also asserts that {@code reaper} is the reaper used by {@code referent}. *

    * Call this method only for {@link org.jboss.msc.ref.Reapable Reapable} references. This method assumes that * {@code reference} has a method called {@code getReaper} that will return the reaper. * * @param the type of referent * @param the type of attachment * @param reference the {@code Reapable} reference that needs to be checked * @param referent the expected content for {@code reference} * @param attachment the expected attachment contained in {@code reference} * @param type the expected type of {@code reference} * @param reaper the expected reaper */ public static final void assertReference(Reference reference, T referent, A attachment, Type type, Reaper reaper) { assertReference(reference, referent, attachment, type); try { assertEquals(reaper, reference.getClass().getMethod("getReaper").invoke(reference)); } catch (NoSuchMethodException e) { fail("Can't find getReaper method at clas " + reference.getClass()); } catch (RuntimeException e) { throw e; } catch (Exception e) { fail(e.getMessage()); } } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/ref/util/TestReaper.java000066400000000000000000000045301472011152000300510ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.ref.util; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.jboss.modules.ref.Reaper; import org.jboss.modules.ref.Reference; /** * Reaper used by tests. * * @author Flavia Rainone * */ public class TestReaper implements Reaper, Future> { private Reference reaped; private final CountDownLatch countDownLatch = new CountDownLatch(1); @Override public void reap(Reference reference) { reaped = reference; countDownLatch.countDown(); } public Reference getReapedReference() throws InterruptedException, ExecutionException { return get(); } @Override public boolean cancel(boolean mayInterruptIfRunning) { return false; } @Override public boolean isCancelled() { return false; } @Override public boolean isDone() { return reaped != null; } @Override public Reference get() throws InterruptedException, ExecutionException { try { return get(30L, TimeUnit.SECONDS); } catch (TimeoutException e) { throw new RuntimeException("Could not get reaped in 30 second timeout."); } } @Override public Reference get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { countDownLatch.await(timeout, unit); return reaped; } }jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/test/000077500000000000000000000000001472011152000243545ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/test/BarImpl.java000066400000000000000000000013771472011152000265550ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.test; public class BarImpl { } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/test/ClassA.java000066400000000000000000000014561472011152000263730ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.test; /** * @author John E. Bailey */ public class ClassA extends ClassB { } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/test/ClassB.java000066400000000000000000000014371472011152000263730ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.test; /** * @author John E. Bailey */ public class ClassB { } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/test/ClassC.java000066400000000000000000000014561472011152000263750ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.test; /** * @author John E. Bailey */ public class ClassC extends ClassD { } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/test/ClassD.java000066400000000000000000000014371472011152000263750ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.test; /** * @author John E. Bailey */ public class ClassD { } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/test/ImportedClass.java000066400000000000000000000014711472011152000277730ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.test; /** * ImportedClass - * * @author John Bailey */ public class ImportedClass { } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/test/ImportedInterface.java000066400000000000000000000015621472011152000306270ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.test; /** * ImportedInterface - * * @author Flavia Rainone */ public class ImportedInterface { } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/test/QuxBar.java000066400000000000000000000013751472011152000264270ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.test; public class QuxBar { } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/test/QuxFoo.java000066400000000000000000000013761472011152000264470ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.test; public class QuxFoo { } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/test/QuxImpl.java000066400000000000000000000013771472011152000266260ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.test; public class QuxImpl { } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/test/TestClass.java000066400000000000000000000014401472011152000271230ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.test; /** * @author John Bailey */ public class TestClass { } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/util/000077500000000000000000000000001472011152000243525ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/util/ModulesTestBase.java000066400000000000000000000126751472011152000302730ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.util; import org.jboss.modules.DependencySpec; import org.jboss.modules.Module; import org.jboss.modules.ModuleClassLoader; import org.jboss.modules.ModuleLoadException; import org.jboss.modules.ModuleLoader; import org.jboss.modules.ModuleSpec; import org.jboss.modules.filter.PathFilter; import org.jboss.modules.filter.PathFilters; import org.junit.Before; import java.net.URL; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; /** * Test low level modules use cases. * * @author Thomas.Diesler@jboss.com * @since 15-Sep-2010 */ public abstract class ModulesTestBase { private ModuleLoaderSupport moduleLoader; @Before public void setUp() throws Exception { moduleLoader = new ModuleLoaderSupport("default"); } protected ModuleLoaderSupport getModuleLoader() { return moduleLoader; } protected void addModuleSpec(ModuleSpec moduleSpec) { moduleLoader.addModuleSpec(moduleSpec); } protected Module loadModule(String identifier) throws ModuleLoadException { return moduleLoader.loadModule(identifier); } protected PathFilter getPathFilter(Class... classes) { Set paths = getFilterPaths(classes); return PathFilters.in(paths); } protected Set getFilterPaths(Class... classes) { Set paths = new HashSet(); for (Class clazz : classes) { paths.add(getPathForClassName(clazz.getName())); } return Collections.unmodifiableSet(paths); } protected String getPathForClassName(String className) { className = className.substring(0, className.lastIndexOf('.')); className = className.replace('.', '/'); return className; } protected void assertLoadClass(String identifier, String className) throws Exception { Class clazz = loadClass(identifier, className); assertNotNull(clazz); } protected void assertLoadClass(String identifier, String className, String exporterId) throws Exception { Class clazz = loadClass(identifier, className); ClassLoader wasClassLoader = clazz.getClassLoader(); if (exporterId == null && wasClassLoader == null) { return; } ModuleClassLoader expClassLoader = loadModule(exporterId).getClassLoader(); assertEquals(expClassLoader, wasClassLoader); } protected void assertLoadClassFail(String identifier, String className) throws Exception { try { Class clazz = loadClass(identifier, className); assertNotNull("ClassNotFoundException expected for [" + className + "], but was: " + clazz, clazz); fail("ClassNotFoundException expected for [" + className + "], but was loaded from: " + clazz.getClassLoader()); } catch (ClassNotFoundException ex) { // expected } catch (NoClassDefFoundError ex) { // expected } } protected Class loadClass(String identifier, String className) throws Exception { // ClassLoader#resolveClass() only links the class; it doesn't necessarily force it to be initialized. // To initialize the class you can do Class.forName(name, true, classLoader) ModuleClassLoader classLoader = loadModule(identifier).getClassLoader(); Class clazz = Class.forName(className, true, classLoader); return clazz; } protected URL getResource(String identifier, String resourcePath) throws Exception { ModuleClassLoader classLoader = loadModule(identifier).getClassLoader(); return classLoader.getResource(resourcePath); } static class ModuleLoaderSupport extends ModuleLoader { private String loaderName; private Map modules = new HashMap<>(); ModuleLoaderSupport(String loaderName) { this.loaderName = loaderName; } void addModuleSpec(ModuleSpec moduleSpec) { modules.put(moduleSpec.getName(), moduleSpec); } @Override protected ModuleSpec findModule(String name) throws ModuleLoadException { ModuleSpec moduleSpec = modules.get(name); return moduleSpec; } @Override protected void setAndRelinkDependencies(Module module, List dependencies) throws ModuleLoadException { super.setAndRelinkDependencies(module, dependencies); } @Override public String toString() { return "ModuleLoaderSupport[" + loaderName + "]"; } } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/util/TestModuleLoader.java000066400000000000000000000031601472011152000304310ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.util; import org.jboss.modules.DelegatingModuleLoader; import org.jboss.modules.Module; import org.jboss.modules.ModuleSpec; import java.util.HashMap; import java.util.Map; /** * Test module loader that allows for modules specs to be added at runtime and it will only load modules from the * provided specs. * * @author John E. Bailey */ public class TestModuleLoader extends DelegatingModuleLoader { private final Map moduleSpecs = new HashMap<>(); public TestModuleLoader() { super(Module.getSystemModuleLoader(), NO_FINDERS); } @Override protected ModuleSpec findModule(String name) { return moduleSpecs.get(name); } public void addModuleSpec(final ModuleSpec moduleSpec) { moduleSpecs.put(moduleSpec.getName(), moduleSpec); } public String toString() { return "test@" + System.identityHashCode(this); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/util/TestResourceLoader.java000066400000000000000000000206201472011152000307730ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.util; import org.jboss.modules.AbstractResourceLoader; import org.jboss.modules.ClassSpec; import org.jboss.modules.PackageSpec; import org.jboss.modules.Resource; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.jar.Attributes; import java.util.jar.Manifest; import static org.junit.Assert.assertTrue; import static org.jboss.modules.util.Util.getClassBytes; /** * A test resource loader that simple retrieves resources frm maps. This allows tests to build * arbitrary modules with arbitrary content without having to have the module on disk. * * @author John E. Bailey */ public class TestResourceLoader extends AbstractResourceLoader { private final Map classSpecs = new HashMap(); private final Map resources = new HashMap(); private final Set paths = new HashSet(); private Manifest manifest; public String getRootName() { return "test"; } @Override public ClassSpec getClassSpec(final String fileName) throws IOException { final Map classSpecs = this.classSpecs; return classSpecs.get(fileName); } void addClassSpec(final String name, final ClassSpec classSpec) { final Map classSpecs = this.classSpecs; classSpecs.put(name.replace('.', '/') + ".class", classSpec); addPaths(getPathFromClassName(name)); } @Override public PackageSpec getPackageSpec(final String name) throws IOException { return getPackageSpec(name, getManifest(), null); } private Manifest getManifest() throws IOException { if(manifest != null) return manifest; final Resource manifestResource = getResource("META-INF/MANIFEST.MF"); if(manifestResource == null) return null; final InputStream manifestStream = manifestResource.openStream(); try { manifest = new Manifest(manifestStream); } finally { if(manifestStream != null) manifestStream.close(); } return manifest; } private static String getDefinedAttribute(Attributes.Name name, Attributes entryAttribute, Attributes mainAttribute) { final String value = entryAttribute == null ? null : entryAttribute.getValue(name); return value == null ? mainAttribute == null ? null : mainAttribute.getValue(name) : value; } @Override public Resource getResource(final String name) { String resourceName = name; if (resourceName.startsWith("/")) resourceName = resourceName.substring(1); final Map resources = this.resources; return resources.get(resourceName); } void addResource(final String name, final Resource resource) { final Map resources = this.resources; resources.put(name, resource); addPaths(getPathFromResourceName(name)); } private void addPaths(String path) { final String[] parts = path.split("/"); String current = ""; for(String part : parts) { current += part; paths.add(current); current += "/"; } } @Override public String getLibrary(String name) { return null; } @Override public Collection getPaths() { return paths; } private String getPathFromResourceName(final String resourcePath) { int idx = resourcePath.lastIndexOf('/'); final String path = idx > -1 ? resourcePath.substring(0, idx) : ""; return path; } private String getPathFromClassName(final String className) { int idx = className.lastIndexOf('.'); return idx > -1 ? className.substring(0, idx).replace('.', '/') : ""; } public static TestResourceLoaderBuilder build() { return new TestResourceLoaderBuilder(); } public static class TestResourceLoaderBuilder { private final TestResourceLoader resourceLoader = new TestResourceLoader(); public TestResourceLoader create() { return resourceLoader; } public TestResourceLoaderBuilder addResource(final String name, final URL resourceUrl) { addResource(name, new Resource() { @Override public String getName() { return name; } @Override public URL getURL() { return resourceUrl; } @Override public InputStream openStream() throws IOException { return resourceUrl.openStream(); } @Override public long getSize() { return 0L; } }); return this; } public TestResourceLoaderBuilder addResource(final String name, final File resource) throws MalformedURLException { final URL url = resource.toURI().toURL(); addResource(name, new Resource() { @Override public String getName() { return name; } @Override public URL getURL() { return url; } @Override public InputStream openStream() throws IOException { return new FileInputStream(resource); } @Override public long getSize() { return resource.length(); } }); return this; } public TestResourceLoaderBuilder addResource(final String name, final Resource resource) { final TestResourceLoader resourceLoader = this.resourceLoader; resourceLoader.addResource(name, resource); return this; } public TestResourceLoaderBuilder addResources(final File base) throws Exception { addResources("", base); return this; } private void addResources(final String pathBase, final File base) throws Exception { assertTrue(base.isDirectory()); final File[] children = base.listFiles(); for (File child : children) { final String childPath = pathBase + child.getName(); if (child.isDirectory()) { addResources(childPath + "/", child); } else { addResource(childPath, child); } } } public TestResourceLoaderBuilder addClass(final Class aClass) throws Exception { final ClassSpec classSpec = new ClassSpec(); classSpec.setCodeSource(aClass.getProtectionDomain().getCodeSource()); final byte[] classBytes = getClassBytes(aClass); classSpec.setBytes(classBytes); addClassSpec(aClass.getName(), classSpec); return this; } public TestResourceLoaderBuilder addClasses(final Class... classes) throws Exception { for(Class aClass : classes) { addClass(aClass); } return this; } public TestResourceLoaderBuilder addClassSpec(final String name, final ClassSpec classSpec) { final TestResourceLoader resourceLoader = this.resourceLoader; resourceLoader.addClassSpec(name, classSpec); return this; } } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/util/Util.java000066400000000000000000000053141472011152000261350ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.util; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; /** * Utility class providing commonly used test utilities. * * @author John E. Bailey */ public class Util { public static byte[] readBytes(final InputStream is) throws IOException { ByteArrayOutputStream os = new ByteArrayOutputStream(); try { byte[] buff = new byte[1024]; int read; while((read = is.read(buff)) > -1) { os.write(buff, 0, read); } } finally { is.close(); } return os.toByteArray(); } public static URL getResource(final Class baseClass, final String path) throws Exception { final URL url = baseClass.getClassLoader().getResource(path); return url; } public static File getResourceFile(final Class baseClass, final String path) throws Exception { return new File(getResource(baseClass, path).toURI()); } public static List toList(Enumeration enumeration) { final List list = new ArrayList(); while(enumeration.hasMoreElements()) { list.add(enumeration.nextElement()); } return list; } public static byte[] getClassBytes(final Class aClass) throws Exception { final String resourcePath = getResourceNameOfClass(aClass); final File classFile = Util.getResourceFile(aClass, resourcePath); byte[] classBytes = Util.readBytes(new FileInputStream(classFile)); return classBytes; } public static String getResourceNameOfClass(final Class aClass) throws IllegalArgumentException { final String nameAsResourcePath = aClass.getName().replace('.', '/'); final String resourceName = nameAsResourcePath + ".class"; return resourceName; } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/xml/000077500000000000000000000000001472011152000241755ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/xml/PermissionsTest.java000066400000000000000000000046061472011152000302210ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.modules.xml; import static org.junit.Assert.*; import java.io.File; import java.io.FilePermission; import java.security.Permission; import java.util.Enumeration; import org.jboss.modules.AbstractModuleTestCase; import org.jboss.modules.LocalModuleLoader; import org.jboss.modules.Module; import org.jboss.modules.ModuleLoader; import org.junit.Before; import org.junit.Test; /** * Test to verify the functionality of module permissions * * @author Jason Shepherd */ public class PermissionsTest extends AbstractModuleTestCase { private static final String JBOSS_HOME_DIR_VALUE = "someDir/someOtherDir"; protected static final String MODULE_WITH_INVALID_EXPANSION = "test.permissions"; private ModuleLoader moduleLoader; @Before public void setupModuleLoader() throws Exception { System.setProperty("jboss.home.dir", JBOSS_HOME_DIR_VALUE); System.setProperty("foo.bar", "substituted_value"); final File repoRoot = getResource("test/repo"); moduleLoader = new LocalModuleLoader(new File[] {repoRoot}); } @Test public void testExpansion() throws Exception { Module module = moduleLoader.loadModule(MODULE_WITH_INVALID_EXPANSION); assertTrue(module.getExportedResource("active.txt").toString().contains("substituted_value")); Enumeration permissions = module.getPermissionCollection().elements(); assertTrue(permissions.hasMoreElements()); Permission firstPermission = permissions.nextElement(); assertEquals(FilePermission.class.getName(), firstPermission.getClass().getName()); assertFalse(permissions.hasMoreElements()); } } jboss-modules-2.1.6.Final/src/test/java/org/jboss/modules/xml/PropertyExpanderTestCase.java000066400000000000000000000055421472011152000320150ustar00rootroot00000000000000package org.jboss.modules.xml; import static org.junit.Assert.*; import org.jboss.modules.util.ModulesTestBase; import org.junit.Before; import org.junit.Test; public class PropertyExpanderTestCase extends ModulesTestBase{ private static final String FILE_SEPATATOR = System.getProperty("file.separator"); private static final String SOME_PROPERTY = "some.property"; private static final String SOME_PROPERTY_VALUE = "someProperty"; private static final String OTHER_PROPERTY = "other.property"; private static final String OTHER_PROPERTY_VALUE ="otherProperty"; private static final String JBOSS_HOME = "jboss.home.dir"; private static final String JBOSS_HOME_VALUE = "/Users/home/jshepher/eap/jboss-eap-7"; @Before public void setup() throws Exception{ super.setUp(); System.setProperty(SOME_PROPERTY, SOME_PROPERTY_VALUE); System.setProperty(OTHER_PROPERTY, OTHER_PROPERTY_VALUE); System.setProperty(JBOSS_HOME, JBOSS_HOME_VALUE); } @Test public void systemProp(){ String result = PolicyExpander.expand(String.format("${%s}", SOME_PROPERTY)); assertEquals(SOME_PROPERTY_VALUE, result); } @Test public void multiSystemProp(){ String result = PolicyExpander.expand(String.format("${%s}${%s}", SOME_PROPERTY, OTHER_PROPERTY)); assertEquals(String.format("%s%s", SOME_PROPERTY_VALUE, OTHER_PROPERTY_VALUE), result); } @Test public void multiSystemPropWithNonSpecial(){ String result = PolicyExpander.expand(String.format("${%s}abc${%s}", SOME_PROPERTY, OTHER_PROPERTY)); assertEquals(String.format("%sabc%s", SOME_PROPERTY_VALUE, OTHER_PROPERTY_VALUE), result); } @Test public void multiSystemPropWithSpecial(){ String result = PolicyExpander.expand(String.format("${%s}a$bc${%s}", SOME_PROPERTY, OTHER_PROPERTY)); assertEquals(String.format("%sa$bc%s", SOME_PROPERTY_VALUE, OTHER_PROPERTY_VALUE), result); } @Test public void fileSeperator(){ String result = PolicyExpander.expand("${/}"); assertEquals(FILE_SEPATATOR, result); } @Test public void fileSeperatorInExpression(){ String result = PolicyExpander.expand("${/abc}"); if(result != null) System.out.println(result); assertNull(result); } @Test public void propAndFileSeperator(){ String result = PolicyExpander.expand(String.format("${%s}${/}abc${/}", SOME_PROPERTY)); assertEquals(String.format("%s%sabc%s", SOME_PROPERTY_VALUE, FILE_SEPATATOR, FILE_SEPATATOR), result); } @Test public void propAndPath(){ String result = PolicyExpander.expand(String.format("${%s}/standalone/configuration/logging.properties", JBOSS_HOME)); assertEquals(String.format("%s/standalone/configuration/logging.properties", JBOSS_HOME_VALUE), result); } } jboss-modules-2.1.6.Final/src/test/resources/000077500000000000000000000000001472011152000211075ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/class-resources/000077500000000000000000000000001472011152000242245ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/class-resources/file1.txt000066400000000000000000000000001472011152000257530ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/class-resources/org/000077500000000000000000000000001472011152000250135ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/class-resources/org/jboss/000077500000000000000000000000001472011152000261335ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/class-resources/org/jboss/modules/000077500000000000000000000000001472011152000276035ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/class-resources/org/jboss/modules/test/000077500000000000000000000000001472011152000305625ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/class-resources/org/jboss/modules/test/file2.txt000066400000000000000000000000001472011152000323120ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/org/000077500000000000000000000000001472011152000216765ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/org/jboss/000077500000000000000000000000001472011152000230165ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/org/jboss/modules/000077500000000000000000000000001472011152000244665ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/org/jboss/modules/maven/000077500000000000000000000000001472011152000255745ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/org/jboss/modules/maven/jboss-settings.xml000066400000000000000000000051711472011152000313000ustar00rootroot00000000000000 jboss-public-repository jboss-public-repository-group JBoss Public Maven Repository Group https://repository.jboss.org/nexus/content/groups/public/ default true never true never jboss-developer-repository-group JBoss Developer Maven Repository Group https://repository.jboss.org/nexus/content/groups/developer/ default true never true never eap-repo brew-maven-repo Red Hat Brew repo http://download.lab.bos.redhat.com/brewroot/repos/jb-eap-6-rhel-6-build/latest/maven/ default true never true never brew-maven-repo Red Hat Brew repo http://download.lab.bos.redhat.com/brewroot/repos/jb-eap-6-rhel-6-build/latest/maven/ default true never true never jboss-public-repository jboss-modules-2.1.6.Final/src/test/resources/org/jboss/modules/maven/settings-empty-local-repo.xml000066400000000000000000000056761472011152000333630ustar00rootroot00000000000000 my-proxy true myproxy.corp.com 8080 http bob hunter2 www.google.com|*.apple.com jboss-public-repository jboss-public-repository-group JBoss Public Maven Repository Group https://repository.jboss.org/nexus/content/groups/public/ default true never true never jboss-developer-repository-group JBoss Developer Maven Repository Group https://repository.jboss.org/nexus/content/groups/developer/ default true never true never eap-repo brew-maven-repo Red Hat Brew repo http://download.lab.bos.redhat.com/brewroot/repos/jb-eap-6-rhel-6-build/latest/maven/ default true never true never brew-maven-repo Red Hat Brew repo http://download.lab.bos.redhat.com/brewroot/repos/jb-eap-6-rhel-6-build/latest/maven/ default true never true never jboss-public-repository settings-interpolated-local-repo.xml000066400000000000000000000052431472011152000346260ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/org/jboss/modules/maven ${user.home}/.mvnrepository jboss-public-repository jboss-public-repository-group JBoss Public Maven Repository Group https://repository.jboss.org/nexus/content/groups/public/ default true never true never jboss-developer-repository-group JBoss Developer Maven Repository Group https://repository.jboss.org/nexus/content/groups/developer/ default true never true never eap-repo brew-maven-repo Red Hat Brew repo http://download.lab.bos.redhat.com/brewroot/repos/jb-eap-6-rhel-6-build/latest/maven/ default true never true never brew-maven-repo Red Hat Brew repo http://download.lab.bos.redhat.com/brewroot/repos/jb-eap-6-rhel-6-build/latest/maven/ default true never true never jboss-public-repository settings-with-local-repo-defined.xml000066400000000000000000000003531472011152000345000ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/org/jboss/modules/maven /user/defined/path/in/settings/xml jboss-modules-2.1.6.Final/src/test/resources/test/000077500000000000000000000000001472011152000220665ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/GeneratedClass.class000066400000000000000000000003311472011152000257760ustar00rootroot00000000000000Êþº¾4    ()VCodeLineNumberTable SourceFileGeneratedClass.java org/module/foo/GeneratedClassjava/lang/Object1*·± jboss-modules-2.1.6.Final/src/test/resources/test/MODULES_377/000077500000000000000000000000001472011152000235765ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/MODULES_377/local/000077500000000000000000000000001472011152000246705ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/MODULES_377/local/tests/000077500000000000000000000000001472011152000260325ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/MODULES_377/local/tests/module/000077500000000000000000000000001472011152000273175ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/MODULES_377/local/tests/module/main/000077500000000000000000000000001472011152000302435ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/MODULES_377/local/tests/module/main/module.xml000066400000000000000000000005221472011152000322510ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/aliasmodule/000077500000000000000000000000001472011152000243655ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/aliasmodule/rootOne/000077500000000000000000000000001472011152000260125ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/aliasmodule/rootOne/test.txt000066400000000000000000000000131472011152000275240ustar00rootroot00000000000000Test file 1jboss-modules-2.1.6.Final/src/test/resources/test/aliasmodule/rootTwo/000077500000000000000000000000001472011152000260425ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/aliasmodule/rootTwo/test.txt000066400000000000000000000000131472011152000275540ustar00rootroot00000000000000Test file 2jboss-modules-2.1.6.Final/src/test/resources/test/fileresourceloader/000077500000000000000000000000001472011152000257445ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/fileresourceloader/META-INF/000077500000000000000000000000001472011152000271045ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/fileresourceloader/META-INF/MANIFEST.MF000066400000000000000000000004421472011152000305360ustar00rootroot00000000000000Manifest-Version: 1.0 Specification-Title: MODULES-89 Name: org/jboss/modules/test/ Specification-Title: JBoss Modules Test Classes Specification-Version: 0.1 Specification-Vendor: JBoss Implementation-Title: org.jboss.modules.test Implementation-Version: 1.0 Implementation-Vendor: JBoss jboss-modules-2.1.6.Final/src/test/resources/test/fileresourceloader/nested/000077500000000000000000000000001472011152000272265ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/fileresourceloader/nested/nested.txt000066400000000000000000000000201472011152000312410ustar00rootroot00000000000000nested test filejboss-modules-2.1.6.Final/src/test/resources/test/fileresourceloader/test.txt000066400000000000000000000000111472011152000274540ustar00rootroot00000000000000test filejboss-modules-2.1.6.Final/src/test/resources/test/filesystem-module-1/000077500000000000000000000000001472011152000256735ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/filesystem-module-1/META-INF/000077500000000000000000000000001472011152000270335ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/filesystem-module-1/META-INF/MANIFEST.MF000066400000000000000000000005241472011152000304660ustar00rootroot00000000000000Manifest-Version: 1.0 Specification-Title: Modules Test Dependencies: test.jaxrs-jaxb-provider services Name: org/jboss/modules/test/ Specification-Title: JBoss Modules Test Classes Specification-Version: 0.1 Specification-Vendor: JBoss Implementation-Title: org.jboss.modules.test Implementation-Version: 1.0 Implementation-Vendor: JBoss jboss-modules-2.1.6.Final/src/test/resources/test/filesystem-module-1/nested/000077500000000000000000000000001472011152000271555ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/filesystem-module-1/nested/nested.txt000066400000000000000000000000201472011152000311700ustar00rootroot00000000000000nested test filejboss-modules-2.1.6.Final/src/test/resources/test/filesystem-module-1/test.txt000066400000000000000000000000111472011152000274030ustar00rootroot00000000000000test filejboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/000077500000000000000000000000001472011152000255765ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/add-ons/000077500000000000000000000000001472011152000271235ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/add-ons/a/000077500000000000000000000000001472011152000273435ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/add-ons/a/shared/000077500000000000000000000000001472011152000306115ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/add-ons/a/shared/module.xml000066400000000000000000000016731472011152000326270ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/add-ons/a/unique/000077500000000000000000000000001472011152000306515ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/add-ons/a/unique/module.xml000066400000000000000000000016661472011152000326710ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/add-ons/b/000077500000000000000000000000001472011152000273445ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/add-ons/b/shared/000077500000000000000000000000001472011152000306125ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/add-ons/b/shared/module.xml000066400000000000000000000016731472011152000326300ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/add-ons/b/unique/000077500000000000000000000000001472011152000306525ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/add-ons/b/unique/module.xml000066400000000000000000000016661472011152000326720ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/layers/000077500000000000000000000000001472011152000270755ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/layers/base/000077500000000000000000000000001472011152000300075ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/layers/base/shared/000077500000000000000000000000001472011152000312555ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/layers/base/shared/module.xml000066400000000000000000000016761472011152000332760ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/layers/base/unique/000077500000000000000000000000001472011152000313155ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/layers/base/unique/module.xml000066400000000000000000000016741472011152000333340ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/layers/mid/000077500000000000000000000000001472011152000276465ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/layers/mid/shared/000077500000000000000000000000001472011152000311145ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/layers/mid/shared/module.xml000066400000000000000000000016751472011152000331340ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/layers/mid/unique/000077500000000000000000000000001472011152000311545ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/layers/mid/unique/module.xml000066400000000000000000000016721472011152000331710ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/layers/top/000077500000000000000000000000001472011152000276775ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/layers/top/shared/000077500000000000000000000000001472011152000311455ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/layers/top/shared/module.xml000066400000000000000000000016751472011152000331650ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/layers/top/unique/000077500000000000000000000000001472011152000312055ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/layers/top/unique/module.xml000066400000000000000000000016721472011152000332220ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/user/000077500000000000000000000000001472011152000265545ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/user/shared/000077500000000000000000000000001472011152000300225ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/user/shared/module.xml000066400000000000000000000016761472011152000320430ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/user/unique/000077500000000000000000000000001472011152000300625ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/layeredmodulepath/user/unique/module.xml000066400000000000000000000016741472011152000321010ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/modulecontentloader/000077500000000000000000000000001472011152000261355ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/modulecontentloader/rootOne/000077500000000000000000000000001472011152000275625ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/modulecontentloader/rootOne/META-INF/000077500000000000000000000000001472011152000307225ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/modulecontentloader/rootOne/META-INF/MANIFEST.MF000066400000000000000000000004021472011152000323500ustar00rootroot00000000000000Manifest-Version: 1.0 Name: org/jboss/modules/test/ Specification-Title: JBoss Modules Test Classes Specification-Version: 0.1 Specification-Vendor: JBoss Implementation-Title: org.jboss.modules.test Implementation-Version: 1.0 Implementation-Vendor: JBoss jboss-modules-2.1.6.Final/src/test/resources/test/modulecontentloader/rootOne/nested/000077500000000000000000000000001472011152000310445ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/modulecontentloader/rootOne/nested/nested.txt000066400000000000000000000000201472011152000330570ustar00rootroot00000000000000nested test filejboss-modules-2.1.6.Final/src/test/resources/test/modulecontentloader/rootOne/test.txt000066400000000000000000000000111472011152000312720ustar00rootroot00000000000000test filejboss-modules-2.1.6.Final/src/test/resources/test/modulecontentloader/rootTwo/000077500000000000000000000000001472011152000276125ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/modulecontentloader/rootTwo/nested/000077500000000000000000000000001472011152000310745ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/modulecontentloader/rootTwo/nested/nested.txt000066400000000000000000000000201472011152000331070ustar00rootroot00000000000000nested test filejboss-modules-2.1.6.Final/src/test/resources/test/modulecontentloader/rootTwo/nestedTwo/000077500000000000000000000000001472011152000315665ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/modulecontentloader/rootTwo/nestedTwo/nested.txt000066400000000000000000000000171472011152000336070ustar00rootroot00000000000000nested file twojboss-modules-2.1.6.Final/src/test/resources/test/modulecontentloader/rootTwo/testTwo.txt000066400000000000000000000000101472011152000320130ustar00rootroot00000000000000test twojboss-modules-2.1.6.Final/src/test/resources/test/repo/000077500000000000000000000000001472011152000230335ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/000077500000000000000000000000001472011152000240125ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/absent/000077500000000000000000000000001472011152000252665ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/absent/main/000077500000000000000000000000001472011152000262125ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/absent/main/module.xml000066400000000000000000000015121472011152000302200ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/000077500000000000000000000000001472011152000263475ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-one/000077500000000000000000000000001472011152000304135ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-one/main/000077500000000000000000000000001472011152000313375ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-one/main/dir/000077500000000000000000000000001472011152000321155ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-one/main/dir/org/000077500000000000000000000000001472011152000327045ustar00rootroot00000000000000jboss/000077500000000000000000000000001472011152000337455ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-one/main/dir/orgmodules/000077500000000000000000000000001472011152000354155ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-one/main/dir/org/jbosstest/000077500000000000000000000000001472011152000363745ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-one/main/dir/org/jboss/modulesClassA.class000066400000000000000000000004561472011152000405760ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-one/main/dir/org/jboss/modules/testÊþº¾2org/jboss/modules/test/ClassAorg/jboss/modules/test/ClassB ClassA.java()V  thisLorg/jboss/modules/test/ClassA;CodeLocalVariableTableLineNumberTable SourceFile! /*· ±  test.txt000066400000000000000000000000131472011152000335500ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-one/main/dirTest file 1jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-one/main/module.xml000066400000000000000000000020431472011152000333450ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-two-alias/000077500000000000000000000000001472011152000315325ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-two-alias/main/000077500000000000000000000000001472011152000324565ustar00rootroot00000000000000module.xml000066400000000000000000000016021472011152000344050ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-two-alias/main jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-two/000077500000000000000000000000001472011152000304435ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-two/main/000077500000000000000000000000001472011152000313675ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-two/main/dir/000077500000000000000000000000001472011152000321455ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-two/main/dir/org/000077500000000000000000000000001472011152000327345ustar00rootroot00000000000000jboss/000077500000000000000000000000001472011152000337755ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-two/main/dir/orgmodules/000077500000000000000000000000001472011152000354455ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-two/main/dir/org/jbosstest/000077500000000000000000000000001472011152000364245ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-two/main/dir/org/jboss/modulesClassB.class000066400000000000000000000004411472011152000406210ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-two/main/dir/org/jboss/modules/testÊþº¾2org/jboss/modules/test/ClassBjava/lang/Object ClassB.java()V  thisLorg/jboss/modules/test/ClassB;CodeLocalVariableTableLineNumberTable SourceFile! /*· ±  test.txt000066400000000000000000000000131472011152000336000ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-two/main/dirTest file 2jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-cyclic/module-two/main/module.xml000066400000000000000000000020351472011152000333760ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/000077500000000000000000000000001472011152000271135ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/dependency-module/000077500000000000000000000000001472011152000325145ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/dependency-module/main/000077500000000000000000000000001472011152000334405ustar00rootroot00000000000000dir/000077500000000000000000000000001472011152000341375ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/dependency-module/maindependency-resource.txt000066400000000000000000000000231472011152000406360ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/dependency-module/main/dirDependency resourceorg/000077500000000000000000000000001472011152000347265ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/dependency-module/main/dirjboss/000077500000000000000000000000001472011152000360465ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/dependency-module/main/dir/orgmodules/000077500000000000000000000000001472011152000375165ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/dependency-module/main/dir/org/jbosstest/000077500000000000000000000000001472011152000404755ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/dependency-module/main/dir/org/jboss/modulesClassB.class000066400000000000000000000004411472011152000426720ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/dependency-module/main/dir/org/jboss/modules/testÊþº¾2org/jboss/modules/test/ClassBjava/lang/Object ClassB.java()V  thisLorg/jboss/modules/test/ClassB;CodeLocalVariableTableLineNumberTable SourceFile! /*· ±  module.xml000066400000000000000000000017611472011152000353750ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/dependency-module/main jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/dependent-module-alias/000077500000000000000000000000001472011152000334335ustar00rootroot00000000000000main/000077500000000000000000000000001472011152000343005ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/dependent-module-aliasmodule.xml000066400000000000000000000016241472011152000363120ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/dependent-module-alias/main jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/dependent-module/000077500000000000000000000000001472011152000323445ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/dependent-module/main/000077500000000000000000000000001472011152000332705ustar00rootroot00000000000000dir/000077500000000000000000000000001472011152000337675ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/dependent-module/mainorg/000077500000000000000000000000001472011152000345565ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/dependent-module/main/dirjboss/000077500000000000000000000000001472011152000356765ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/dependent-module/main/dir/orgmodules/000077500000000000000000000000001472011152000373465ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/dependent-module/main/dir/org/jbosstest/000077500000000000000000000000001472011152000403255ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/dependent-module/main/dir/org/jboss/modulesClassA.class000066400000000000000000000004561472011152000425270ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/dependent-module/main/dir/org/jboss/modules/testÊþº¾2org/jboss/modules/test/ClassAorg/jboss/modules/test/ClassB ClassA.java()V  thisLorg/jboss/modules/test/ClassA;CodeLocalVariableTableLineNumberTable SourceFile! /*· ±  module.xml000066400000000000000000000020601472011152000352160ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-resources/dependent-module/main jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/000077500000000000000000000000001472011152000263725ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-one/000077500000000000000000000000001472011152000304365ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-one/main/000077500000000000000000000000001472011152000313625ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-one/main/dir/000077500000000000000000000000001472011152000321405ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-one/main/dir/org/000077500000000000000000000000001472011152000327275ustar00rootroot00000000000000jboss/000077500000000000000000000000001472011152000337705ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-one/main/dir/orgmodules/000077500000000000000000000000001472011152000354405ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-one/main/dir/org/jbosstest/000077500000000000000000000000001472011152000364175ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-one/main/dir/org/jboss/modulesClassA.class000066400000000000000000000004561472011152000406210ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-one/main/dir/org/jboss/modules/testÊþº¾2org/jboss/modules/test/ClassAorg/jboss/modules/test/ClassB ClassA.java()V  thisLorg/jboss/modules/test/ClassA;CodeLocalVariableTableLineNumberTable SourceFile! /*· ±  test.txt000066400000000000000000000000131472011152000335730ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-one/main/dirTest file 1jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-one/main/module.xml000066400000000000000000000020431472011152000333700ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-two-alias/000077500000000000000000000000001472011152000315555ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-two-alias/main/000077500000000000000000000000001472011152000325015ustar00rootroot00000000000000module.xml000066400000000000000000000016021472011152000344300ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-two-alias/main jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-two/000077500000000000000000000000001472011152000304665ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-two/main/000077500000000000000000000000001472011152000314125ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-two/main/dir/000077500000000000000000000000001472011152000321705ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-two/main/dir/org/000077500000000000000000000000001472011152000327575ustar00rootroot00000000000000jboss/000077500000000000000000000000001472011152000340205ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-two/main/dir/orgmodules/000077500000000000000000000000001472011152000354705ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-two/main/dir/org/jbosstest/000077500000000000000000000000001472011152000364475ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-two/main/dir/org/jboss/modulesClassB.class000066400000000000000000000004411472011152000406440ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-two/main/dir/org/jboss/modules/testÊþº¾2org/jboss/modules/test/ClassBjava/lang/Object ClassB.java()V  thisLorg/jboss/modules/test/ClassB;CodeLocalVariableTableLineNumberTable SourceFile! /*· ±  test.txt000066400000000000000000000000131472011152000336230ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-two/main/dirTest file 2jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/alias-simple/module-two/main/module.xml000066400000000000000000000017471472011152000334320ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/bad-deps/000077500000000000000000000000001472011152000254715ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/bad-deps/main/000077500000000000000000000000001472011152000264155ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/bad-deps/main/module.xml000066400000000000000000000017251472011152000304310ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/circular-deps-A/000077500000000000000000000000001472011152000267255ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/circular-deps-A/main/000077500000000000000000000000001472011152000276515ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/circular-deps-A/main/module.xml000066400000000000000000000020271472011152000316610ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/circular-deps-B/000077500000000000000000000000001472011152000267265ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/circular-deps-B/main/000077500000000000000000000000001472011152000276525ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/circular-deps-B/main/module.xml000066400000000000000000000017511472011152000316650ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/circular-deps-C/000077500000000000000000000000001472011152000267275ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/circular-deps-C/main/000077500000000000000000000000001472011152000276535ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/circular-deps-C/main/module.xml000066400000000000000000000020271472011152000316630ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/circular-deps-D/000077500000000000000000000000001472011152000267305ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/circular-deps-D/main/000077500000000000000000000000001472011152000276545ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/circular-deps-D/main/module.xml000066400000000000000000000017511472011152000316670ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/conditional-active/000077500000000000000000000000001472011152000275665ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/conditional-active/main/000077500000000000000000000000001472011152000305125ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/conditional-active/main/active.txt000066400000000000000000000000061472011152000325220ustar00rootroot00000000000000activejboss-modules-2.1.6.Final/src/test/resources/test/repo/test/conditional-active/main/module.xml000066400000000000000000000020411472011152000325160ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/conditional-not-active/000077500000000000000000000000001472011152000303645ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/conditional-not-active/main/000077500000000000000000000000001472011152000313105ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/conditional-not-active/main/module.xml000066400000000000000000000020511472011152000333150ustar00rootroot00000000000000 not-active.txt000066400000000000000000000000121472011152000340340ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/conditional-not-active/mainnot activejboss-modules-2.1.6.Final/src/test/resources/test/repo/test/dep-props/000077500000000000000000000000001472011152000257235ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/dep-props/main/000077500000000000000000000000001472011152000266475ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/dep-props/main/module.xml000066400000000000000000000021451472011152000306600ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/jaxrs-jaxb-provider/000077500000000000000000000000001472011152000277135ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/jaxrs-jaxb-provider/main/000077500000000000000000000000001472011152000306375ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/jaxrs-jaxb-provider/main/META-INF/000077500000000000000000000000001472011152000317775ustar00rootroot00000000000000services/000077500000000000000000000000001472011152000335435ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/jaxrs-jaxb-provider/main/META-INFjavax.ws.rs.ext.Providers000066400000000000000000000013411472011152000404240ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/jaxrs-jaxb-provider/main/META-INF/services# # JBoss, Home of Professional Open Source. # Copyright 2014 Red Hat, Inc., and individual contributors # as indicated by the @author tags. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # jaxrs.jaxb.providers.P0 jaxrs.jaxb.providers.P1jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/jaxrs-jaxb-provider/main/module.xml000066400000000000000000000017421472011152000326520ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/jaxrs/000077500000000000000000000000001472011152000251415ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/jaxrs/main/000077500000000000000000000000001472011152000260655ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/jaxrs/main/META-INF/000077500000000000000000000000001472011152000272255ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/jaxrs/main/META-INF/services/000077500000000000000000000000001472011152000310505ustar00rootroot00000000000000javax.ws.rs.ext.Providers000066400000000000000000000013411472011152000356520ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/jaxrs/main/META-INF/services# # JBoss, Home of Professional Open Source. # Copyright 2014 Red Hat, Inc., and individual contributors # as indicated by the @author tags. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # jaxrs.core.providers.P0 jaxrs.core.providers.P1jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/jaxrs/main/module.xml000066400000000000000000000020271472011152000300750ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/maven/000077500000000000000000000000001472011152000251205ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/maven/main/000077500000000000000000000000001472011152000260445ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/maven/main/module.xml000077500000000000000000000020421472011152000300540ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/maven/non-main/000077500000000000000000000000001472011152000266345ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/maven/non-main/module.xml000066400000000000000000000021611472011152000306430ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/permissions/000077500000000000000000000000001472011152000263655ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/permissions/main/000077500000000000000000000000001472011152000273115ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/permissions/main/module.xml000066400000000000000000000020761472011152000313250ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/permissions/main/substituted_value/000077500000000000000000000000001472011152000330645ustar00rootroot00000000000000active.txt000066400000000000000000000000061472011152000350150ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/permissions/main/substituted_valueactivejboss-modules-2.1.6.Final/src/test/resources/test/repo/test/service/000077500000000000000000000000001472011152000254525ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/service/main/000077500000000000000000000000001472011152000263765ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/service/main/META-INF/000077500000000000000000000000001472011152000275365ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/service/main/META-INF/services/000077500000000000000000000000001472011152000313615ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/service/main/META-INF/services/dummy000066400000000000000000000012671472011152000324450ustar00rootroot00000000000000# # JBoss, Home of Professional Open Source. # Copyright 2014 Red Hat, Inc., and individual contributors # as indicated by the @author tags. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # dummyjboss-modules-2.1.6.Final/src/test/resources/test/repo/test/service/main/module.xml000066400000000000000000000016731472011152000304140ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/test/000077500000000000000000000000001472011152000247715ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/test/main/000077500000000000000000000000001472011152000257155ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/test/main/module.xml000066400000000000000000000017561472011152000277350ustar00rootroot00000000000000 jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/with-deps/000077500000000000000000000000001472011152000257165ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/with-deps/main/000077500000000000000000000000001472011152000266425ustar00rootroot00000000000000jboss-modules-2.1.6.Final/src/test/resources/test/repo/test/with-deps/main/module.xml000066400000000000000000000017301472011152000306520ustar00rootroot00000000000000