aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSorin Basca <sorinbasca@google.com>2024-05-24 08:44:36 +0100
committerSorin Basca <sorinbasca@google.com>2024-05-24 08:44:36 +0100
commit72f6971b327429551fb7543bf17e36ef9d8a8343 (patch)
tree62fa812797c731460c4accaea211e0212fcddb33
parent76d2a11286542b37dcc583942b23abbd69efca2e (diff)
parent3ba11f51e948be042a593ffe919727be68e67de7 (diff)
downloadapache-commons-bcel-master.tar.gz
Upgrade apache-commons-bcel to BCEL-6.3HEADmastermain
Generated by merging to commit 3ba11f51 from aosp/upstream-master. Bug: 335612268 Test: TreeHugger Change-Id: I3b36fe5a6de9b40dcb4c35e611a9403e5c5e340e
-rw-r--r--.travis.yml3
-rw-r--r--CONTRIBUTING.md230
-rw-r--r--NOTICE.txt2
-rw-r--r--README.md12
-rw-r--r--RELEASE-NOTES.txt59
-rw-r--r--pom.xml34
-rw-r--r--src/changes/changes.xml13
-rw-r--r--src/main/java/org/apache/bcel/Const.java92
-rw-r--r--src/main/java/org/apache/bcel/classfile/Constant.java80
-rw-r--r--src/main/java/org/apache/bcel/classfile/ConstantClass.java15
-rw-r--r--src/main/java/org/apache/bcel/classfile/ConstantDynamic.java90
-rw-r--r--src/main/java/org/apache/bcel/classfile/DescendingVisitor.java8
-rw-r--r--src/main/java/org/apache/bcel/classfile/EmptyVisitor.java8
-rw-r--r--src/main/java/org/apache/bcel/classfile/Visitor.java7
-rw-r--r--src/main/java/org/apache/bcel/util/ClassPath.java971
-rw-r--r--src/main/java/org/apache/bcel/util/ModularRuntimeImage.java154
-rw-r--r--src/main/java/org/apache/bcel/util/Repository.java16
-rw-r--r--src/site/resources/bcel5-bcel6-clirr-report.html4
-rw-r--r--src/site/xdoc/download_bcel.xml44
-rw-r--r--src/site/xdoc/index.xml14
-rw-r--r--src/site/xdoc/issue-tracking.xml2
-rw-r--r--src/site/xdoc/mail-lists.xml2
-rw-r--r--src/test/java/org/apache/bcel/generic/JdkGenericDumpTestCase.java (renamed from src/test/java/org/apache/bcel/generic/JDKGenericDumpTestCase.java)113
-rw-r--r--src/test/java/org/apache/bcel/util/ClassPathTestCase.java43
-rw-r--r--src/test/java/org/apache/bcel/util/ModularRuntimeImageTestCase.java84
-rw-r--r--src/test/java/org/apache/bcel/visitors/CounterVisitor.java10
26 files changed, 1504 insertions, 606 deletions
diff --git a/.travis.yml b/.travis.yml
index fc2a03ac..9b592760 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -17,8 +17,7 @@ language: java
sudo: false
jdk:
- - openjdk7
- oraclejdk8
after_success:
- - mvn clean cobertura:cobertura coveralls:report
+ - mvn -Ddoclint:none clean cobertura:cobertura coveralls:report
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 18c4540c..be7e41ea 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,115 +1,115 @@
-<!---
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
--->
-<!---
- +======================================================================+
- |**** ****|
- |**** THIS FILE IS GENERATED BY THE COMMONS BUILD PLUGIN ****|
- |**** DO NOT EDIT DIRECTLY ****|
- |**** ****|
- +======================================================================+
- | TEMPLATE FILE: contributing-md-template.md |
- | commons-build-plugin/trunk/src/main/resources/commons-xdoc-templates |
- +======================================================================+
- | |
- | 1) Re-generate using: mvn commons:contributing-md |
- | |
- | 2) Set the following properties in the component's pom: |
- | - commons.jira.id (required, alphabetic, upper case) |
- | |
- | 3) Example Properties |
- | |
- | <properties> |
- | <commons.jira.id>MATH</commons.jira.id> |
- | </properties> |
- | |
- +======================================================================+
---->
-Contributing to Apache Commons BCEL
-======================
-
-You have found a bug or you have an idea for a cool new feature? Contributing code is a great way to give something back to
-the open source community. Before you dig right into the code there are a few guidelines that we need contributors to
-follow so that we can have a chance of keeping on top of things.
-
-Getting Started
----------------
-
-+ Make sure you have a [JIRA account](https://issues.apache.org/jira/).
-+ Make sure you have a [GitHub account](https://github.com/signup/free).
-+ If you're planning to implement a new feature it makes sense to discuss you're changes on the [dev list](https://commons.apache.org/mail-lists.html) first. This way you can make sure you're not wasting your time on something that isn't considered to be in Apache Commons BCEL's scope.
-+ Submit a [Jira Ticket][jira] for your issue, assuming one does not already exist.
- + Clearly describe the issue including steps to reproduce when it is a bug.
- + Make sure you fill in the earliest version that you know has the issue.
-+ Find the corresponding [repository on GitHub](https://github.com/apache/?query=commons-),
-[fork](https://help.github.com/articles/fork-a-repo/) and check out your forked repository.
-
-Making Changes
---------------
-
-+ Create a _topic branch_ for your isolated work.
- * Usually you should base your branch on the `master` or `trunk` branch.
- * A good topic branch name can be the JIRA bug id plus a keyword, e.g. `BCEL-123-InputStream`.
- * If you have submitted multiple JIRA issues, try to maintain separate branches and pull requests.
-+ Make commits of logical units.
- * Make sure your commit messages are meaningful and in the proper format. Your commit message should contain the key of the JIRA issue.
- * e.g. `BCEL-123: Close input stream earlier`
-+ Respect the original code style:
- + Only use spaces for indentation.
- + Create minimal diffs - disable _On Save_ actions like _Reformat Source Code_ or _Organize Imports_. If you feel the source code should be reformatted create a separate PR for this change first.
- + Check for unnecessary whitespace with `git diff` -- check before committing.
-+ Make sure you have added the necessary tests for your changes, typically in `src/test/java`.
-+ Run all the tests with `mvn clean verify` to assure nothing else was accidentally broken.
-
-Making Trivial Changes
-----------------------
-
-The JIRA tickets are used to generate the changelog for the next release.
-
-For changes of a trivial nature to comments and documentation, it is not always necessary to create a new ticket in JIRA.
-In this case, it is appropriate to start the first line of a commit with '(doc)' instead of a ticket number.
-
-
-Submitting Changes
-------------------
-
-+ Sign and submit the Apache [Contributor License Agreement][cla] if you haven't already.
- * Note that small patches & typical bug fixes do not require a CLA as
- clause 5 of the [Apache License](https://www.apache.org/licenses/LICENSE-2.0.html#contributions)
- covers them.
-+ Push your changes to a topic branch in your fork of the repository.
-+ Submit a _Pull Request_ to the corresponding repository in the `apache` organization.
- * Verify _Files Changed_ shows only your intended changes and does not
- include additional files like `target/*.class`
-+ Update your JIRA ticket and include a link to the pull request in the ticket.
-
-If you prefer to not use GitHub, then you can instead use
-`git format-patch` (or `svn diff`) and attach the patch file to the JIRA issue.
-
-
-Additional Resources
---------------------
-
-+ [Contributing patches](https://commons.apache.org/patches.html)
-+ [Apache Commons BCEL JIRA project page][jira]
-+ [Contributor License Agreement][cla]
-+ [General GitHub documentation](https://help.github.com/)
-+ [GitHub pull request documentation](https://help.github.com/send-pull-requests/)
-+ [Apache Commons Twitter Account](https://twitter.com/ApacheCommons)
-+ `#apache-commons` IRC channel on `irc.freenode.net`
-
-[cla]:https://www.apache.org/licenses/#clas
-[jira]:https://issues.apache.org/jira/browse/BCEL
+<!---
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<!---
+ +======================================================================+
+ |**** ****|
+ |**** THIS FILE IS GENERATED BY THE COMMONS BUILD PLUGIN ****|
+ |**** DO NOT EDIT DIRECTLY ****|
+ |**** ****|
+ +======================================================================+
+ | TEMPLATE FILE: contributing-md-template.md |
+ | commons-build-plugin/trunk/src/main/resources/commons-xdoc-templates |
+ +======================================================================+
+ | |
+ | 1) Re-generate using: mvn commons-build:contributing-md |
+ | |
+ | 2) Set the following properties in the component's pom: |
+ | - commons.jira.id (required, alphabetic, upper case) |
+ | |
+ | 3) Example Properties |
+ | |
+ | <properties> |
+ | <commons.jira.id>MATH</commons.jira.id> |
+ | </properties> |
+ | |
+ +======================================================================+
+--->
+Contributing to Apache Commons BCEL
+======================
+
+You have found a bug or you have an idea for a cool new feature? Contributing code is a great way to give something back to
+the open source community. Before you dig right into the code there are a few guidelines that we need contributors to
+follow so that we can have a chance of keeping on top of things.
+
+Getting Started
+---------------
+
++ Make sure you have a [JIRA account](https://issues.apache.org/jira/).
++ Make sure you have a [GitHub account](https://github.com/signup/free).
++ If you're planning to implement a new feature it makes sense to discuss your changes on the [dev list](https://commons.apache.org/mail-lists.html) first. This way you can make sure you're not wasting your time on something that isn't considered to be in Apache Commons BCEL's scope.
++ Submit a [Jira Ticket][jira] for your issue, assuming one does not already exist.
+ + Clearly describe the issue including steps to reproduce when it is a bug.
+ + Make sure you fill in the earliest version that you know has the issue.
++ Find the corresponding [repository on GitHub](https://github.com/apache/?query=commons-),
+[fork](https://help.github.com/articles/fork-a-repo/) and check out your forked repository.
+
+Making Changes
+--------------
+
++ Create a _topic branch_ for your isolated work.
+ * Usually you should base your branch on the `master` or `trunk` branch.
+ * A good topic branch name can be the JIRA bug id plus a keyword, e.g. `BCEL-123-InputStream`.
+ * If you have submitted multiple JIRA issues, try to maintain separate branches and pull requests.
++ Make commits of logical units.
+ * Make sure your commit messages are meaningful and in the proper format. Your commit message should contain the key of the JIRA issue.
+ * e.g. `BCEL-123: Close input stream earlier`
++ Respect the original code style:
+ + Only use spaces for indentation.
+ + Create minimal diffs - disable _On Save_ actions like _Reformat Source Code_ or _Organize Imports_. If you feel the source code should be reformatted create a separate PR for this change first.
+ + Check for unnecessary whitespace with `git diff` -- check before committing.
++ Make sure you have added the necessary tests for your changes, typically in `src/test/java`.
++ Run all the tests with `mvn clean verify` to assure nothing else was accidentally broken.
+
+Making Trivial Changes
+----------------------
+
+The JIRA tickets are used to generate the changelog for the next release.
+
+For changes of a trivial nature to comments and documentation, it is not always necessary to create a new ticket in JIRA.
+In this case, it is appropriate to start the first line of a commit with '(doc)' instead of a ticket number.
+
+
+Submitting Changes
+------------------
+
++ Sign and submit the Apache [Contributor License Agreement][cla] if you haven't already.
+ * Note that small patches & typical bug fixes do not require a CLA as
+ clause 5 of the [Apache License](https://www.apache.org/licenses/LICENSE-2.0.html#contributions)
+ covers them.
++ Push your changes to a topic branch in your fork of the repository.
++ Submit a _Pull Request_ to the corresponding repository in the `apache` organization.
+ * Verify _Files Changed_ shows only your intended changes and does not
+ include additional files like `target/*.class`
++ Update your JIRA ticket and include a link to the pull request in the ticket.
+
+If you prefer to not use GitHub, then you can instead use
+`git format-patch` (or `svn diff`) and attach the patch file to the JIRA issue.
+
+
+Additional Resources
+--------------------
+
++ [Contributing patches](https://commons.apache.org/patches.html)
++ [Apache Commons BCEL JIRA project page][jira]
++ [Contributor License Agreement][cla]
++ [General GitHub documentation](https://help.github.com/)
++ [GitHub pull request documentation](https://help.github.com/articles/creating-a-pull-request/)
++ [Apache Commons Twitter Account](https://twitter.com/ApacheCommons)
++ `#apache-commons` IRC channel on `irc.freenode.net`
+
+[cla]:https://www.apache.org/licenses/#clas
+[jira]:https://issues.apache.org/jira/browse/BCEL
diff --git a/NOTICE.txt b/NOTICE.txt
index 98dd5d02..4a68d998 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -1,5 +1,5 @@
Apache Commons BCEL
-Copyright 2004-2017 The Apache Software Foundation
+Copyright 2004-2019 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
diff --git a/README.md b/README.md
index 6e4fe2b3..1620ff97 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@
| commons-build-plugin/trunk/src/main/resources/commons-xdoc-templates |
+======================================================================+
| |
- | 1) Re-generate using: mvn commons:readme-md |
+ | 1) Re-generate using: mvn commons-build:readme-md |
| |
| 2) Set the following properties in the component's pom: |
| - commons.componentid (required, alphabetic, lower case) |
@@ -43,10 +43,10 @@
Apache Commons BCEL
===================
-[![Build Status](https://travis-ci.org/apache/bcel.svg?branch=master)](https://travis-ci.org/apache/bcel)
-[![Coverage Status](https://coveralls.io/repos/apache/bcel/badge.svg?branch=master)](https://coveralls.io/r/apache/bcel)
+[![Build Status](https://travis-ci.org/apache/commons-bcel.svg)](https://travis-ci.org/apache/commons-bcel)
+[![Coverage Status](https://coveralls.io/repos/apache/commons-bcel/badge.svg)](https://coveralls.io/r/apache/commons-bcel)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.bcel/bcel/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.apache.bcel/bcel/)
-[![License](http://img.shields.io/:license-apache-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0.html)
+[![Javadocs](https://javadoc.io/badge/org.apache.bcel/bcel/6.3.svg)](https://javadoc.io/doc/org.apache.bcel/bcel/6.3)
Apache Commons Bytecode Engineering Library
@@ -54,7 +54,7 @@ Documentation
-------------
More information can be found on the [Apache Commons BCEL homepage](https://commons.apache.org/proper/commons-bcel).
-The [JavaDoc](https://commons.apache.org/proper/commons-bcel/javadocs/api-release) can be browsed.
+The [Javadoc](https://commons.apache.org/proper/commons-bcel/javadocs/api-release) can be browsed.
Questions related to the usage of Apache Commons BCEL should be posted to the [user mailing list][ml].
Where can I get the latest release?
@@ -67,7 +67,7 @@ Alternatively you can pull it from the central Maven repositories:
<dependency>
<groupId>org.apache.bcel</groupId>
<artifactId>bcel</artifactId>
- <version>6.2</version>
+ <version>6.3</version>
</dependency>
```
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index cb0f3fbf..4f579d18 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -1,4 +1,63 @@
Apache Commons BCEL
+ Version 6.3-SNAPSHOT
+ RELEASE NOTES
+
+
+INTRODUCTION:
+
+The Apache Commons BCEL team is pleased to announce the release of
+Apache Commons BCEL 6.3-SNAPSHOT!
+
+The Byte Code Engineering Library (BCEL) is intended to give users a convenient
+way to analyze, create, and manipulate compiled .class files. Classes are
+represented by objects containing all the symbolic information of the given
+class: methods, fields and byte code instructions.
+
+?
+
+NEW FEATURES:
+=============
+
+o Added org.apache.bcel.classfile.Visitor.visitConstantDynamic(ConstantDynamic) Thanks to Mark Thomas.
+o Added org.apache.bcel.classfile.ConstantDynamic Thanks to Mark Thomas.
+o Added fields in org.apache.bcel.Const for Java 9, 10, and 11. Thanks to Mark Thomas.
+o Added fields in org.apache.bcel.Const for Java 12 and 13 based on Java Early Access releases. Thanks to Mark Thomas.
+
+FIXED BUGS:
+===========
+
+o BCEL-304: ClassPath.getClassFile() and friends do not work with JDK 9 and higher (PR #22.) Thanks to Gary Gregory, Ed Pavlak.
+o BCEL-305: ClassPath.getClassFile() and friends do not work with JRE 9 and higher Thanks to Gary Gregory.
+
+CHANGES:
+========
+
+o Initial support for Java 11 Thanks to Mark Thomas, Gary Gregory.
+o Update Java requirement from Java 7 to Java 8. Thanks to Gary Gregory.
+
+
+
+Have fun!
+-Apache Commons BCEL team
+
+Feedback
+--------
+
+Open source works best when you give feedback:
+
+ http://commons.apache.org/bcel
+
+Please direct all bug reports to JIRA:
+
+ https://issues.apache.org/jira/browse/BCEL
+
+Or subscribe to the commons-user mailing list
+
+The Apache Commons Team
+
+-----------------------------------------------------------------------------
+
+ Apache Commons BCEL
Version 6.2
RELEASE NOTES
diff --git a/pom.xml b/pom.xml
index dff48fc9..6807020a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -27,13 +27,13 @@
<parent>
<groupId>org.apache.commons</groupId>
<artifactId>commons-parent</artifactId>
- <version>42</version>
+ <version>47</version>
</parent>
<groupId>org.apache.bcel</groupId>
<artifactId>bcel</artifactId>
<packaging>jar</packaging>
- <version>6.2</version>
+ <version>6.3</version>
<name>Apache Commons BCEL</name>
<description>Apache Commons Bytecode Engineering Library</description>
@@ -43,13 +43,19 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
- <maven.compiler.source>1.7</maven.compiler.source>
- <maven.compiler.target>1.7</maven.compiler.target>
+ <maven.compiler.source>1.8</maven.compiler.source>
+ <maven.compiler.target>1.8</maven.compiler.target>
<commons.componentid>bcel</commons.componentid>
<commons.module.name>org.apache.bcel</commons.module.name>
- <commons.release.version>6.2</commons.release.version>
- <commons.release.desc>(Java 7+)</commons.release.desc>
+ <commons.release.version>6.3</commons.release.version>
+ <commons.release.isDistModule>true</commons.release.isDistModule>
+ <commons.rc.version>RC1</commons.rc.version>
+ <commons.bc.version>6.2</commons.bc.version>
+ <commons.release.desc>(Java 8)</commons.release.desc>
<commons.scmPubUrl>https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-bcel</commons.scmPubUrl>
+ <commons.distSvnStagingUrl>scm:svn:https://dist.apache.org/repos/dist/dev/commons/${commons.componentid}</commons.distSvnStagingUrl>
+ <commons.releaseManagerName>Gary Gregory</commons.releaseManagerName>
+ <commons.releaseManagerKey>86fdc7e2a11262cb</commons.releaseManagerKey>
<!-- Configuration properties for the OSGi maven-bundle-plugin -->
<commons.osgi.symbolicName>org.apache.${commons.componentid}</commons.osgi.symbolicName>
<commons.osgi.export>org.apache.bcel.*;version=${project.version};-noimport:=true</commons.osgi.export>
@@ -59,6 +65,7 @@
<commons.jira.id>BCEL</commons.jira.id>
<commons.jira.pid>12314220</commons.jira.pid>
<commons.findbugs.version>3.0.5</commons.findbugs.version>
+ <commons.surefire.version>3.0.0-M3</commons.surefire.version>
<checkstyle.plugin.version>2.17</checkstyle.plugin.version>
<commons.clirr.version>2.8</commons.clirr.version>
<jna.version>4.5.0</jna.version>
@@ -442,7 +449,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
- <version>3.7</version>
+ <version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
@@ -518,7 +525,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
- <version>4.1</version>
+ <version>4.2</version>
<scope>test</scope>
</dependency>
</dependencies>
@@ -568,16 +575,7 @@
</plugins>
</build>
</profile>
-
- <profile>
- <id>jdk8-javadoc</id>
- <activation>
- <jdk>[1.8,)</jdk>
- </activation>
- <properties>
- <additionalparam>-Xdoclint:none</additionalparam>
- </properties>
- </profile>
+
</profiles>
</project>
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 7f0f07a0..4f97f62a 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -62,7 +62,18 @@ The <action> type attribute can be add,update,fix,remove.
-->
<body>
- <release version="6.2" date="2017-12-DD" description="Experimental Java 9 Support">
+ <release version="6.3" date="2019-01-23" description="Experimental Java 9, 10, 11, 12-EA, and 13-EA Support">
+ <action issue="BCEL-304" type="fix" dev="ggregory" due-to="Gary Gregory, Ed Pavlak">ClassPath.getClassFile() and friends do not work with JDK 9 and higher (PR #22.)</action>
+ <action issue="BCEL-305" type="fix" dev="ggregory" due-to="Gary Gregory">ClassPath.getClassFile() and friends do not work with JRE 9 and higher</action>
+ <action type="update" dev="ggregory" due-to="Mark Thomas, Gary Gregory">Initial support for Java 11</action>
+ <action type="add" dev="ggregory" due-to="Mark Thomas">Added org.apache.bcel.classfile.Visitor.visitConstantDynamic(ConstantDynamic)</action>
+ <action type="add" dev="ggregory" due-to="Mark Thomas">Added org.apache.bcel.classfile.ConstantDynamic</action>
+ <action type="add" dev="ggregory" due-to="Mark Thomas">Added fields in org.apache.bcel.Const for Java 9, 10, and 11.</action>
+ <action type="add" dev="ggregory" due-to="Mark Thomas">Added fields in org.apache.bcel.Const for Java 12 and 13 based on Java Early Access releases.</action>
+ <action type="update" dev="ggregory" due-to="Gary Gregory">Update Java requirement from Java 7 to Java 8.</action>
+ </release>
+
+ <release version="6.2" date="2017-12-08" description="Experimental Java 9 Support">
<action issue="BCEL-294" type="fix" dev="britter" due-to="Mark Roberts">Incorrect comment in StackMap.java</action>
<action issue="BCEL-296" type="fix" dev="ggregory" due-to="Mark Roberts">Incorrect comment in several classes.</action>
<action issue="BCEL-295" type="fix" dev="ggregory" due-to="Mark Roberts">Fix local variable live range length; add test case.</action>
diff --git a/src/main/java/org/apache/bcel/Const.java b/src/main/java/org/apache/bcel/Const.java
index 2423811b..43b5c98a 100644
--- a/src/main/java/org/apache/bcel/Const.java
+++ b/src/main/java/org/apache/bcel/Const.java
@@ -111,20 +111,72 @@ public final class Const {
* */
public static final short MAJOR_1_8 = 52;
- /** Major version number of class files for Java 1.9.
- * @see #MINOR_1_9
- * */
- public static final short MAJOR_1_9 = 53;
-
/** Minor version number of class files for Java 1.8.
* @see #MAJOR_1_8
* */
public static final short MINOR_1_8 = 0;
- /** Minor version number of class files for Java 1.9.
- * @see #MAJOR_1_9
+ /** Major version number of class files for Java 9.
+ * @see #MINOR_9
+ * */
+ public static final short MAJOR_9 = 53;
+
+ /** Minor version number of class files for Java 9.
+ * @see #MAJOR_9
+ * */
+ public static final short MINOR_9 = 0;
+
+ /**
+ * @deprecated Use {@link #MAJOR_9} instead
+ */
+ @Deprecated
+ public static final short MAJOR_1_9 = MAJOR_9;
+
+ /**
+ * @deprecated Use {@link #MINOR_9} instead
+ */
+ @Deprecated
+ public static final short MINOR_1_9 = MINOR_9;
+
+ /** Major version number of class files for Java 10.
+ * @see #MINOR_10
+ * */
+ public static final short MAJOR_10 = 54;
+
+ /** Minor version number of class files for Java 10.
+ * @see #MAJOR_10
+ * */
+ public static final short MINOR_10 = 0;
+
+ /** Major version number of class files for Java 11.
+ * @see #MINOR_11
+ * */
+ public static final short MAJOR_11 = 55;
+
+ /** Minor version number of class files for Java 11.
+ * @see #MAJOR_11
* */
- public static final short MINOR_1_9 = 0;
+ public static final short MINOR_11 = 0;
+
+ /** Major version number of class files for Java 12.
+ * @see #MINOR_12
+ * */
+ public static final short MAJOR_12 = 56;
+
+ /** Minor version number of class files for Java 12.
+ * @see #MAJOR_12
+ * */
+ public static final short MINOR_12 = 0;
+
+ /** Major version number of class files for Java 13.
+ * @see #MINOR_13
+ * */
+ public static final short MAJOR_13 = 57;
+
+ /** Minor version number of class files for Java 13.
+ * @see #MAJOR_13
+ * */
+ public static final short MINOR_13 = 0;
/** Default major version number. Class file is for Java 1.1.
* @see #MAJOR_1_1
@@ -365,6 +417,14 @@ public final class Const {
public static final byte CONSTANT_MethodType = 16;
/**
+ * Marks a constant pool entry as dynamically computed.
+ * @see <a href="https://bugs.openjdk.java.net/secure/attachment/74618/constant-dynamic.html">
+ * Change request for JEP 309</a>
+ * @since 6.3
+ */
+ public static final byte CONSTANT_Dynamic = 17;
+
+ /**
* Marks a constant pool entry as an Invoke Dynamic
* @see <a href="http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.10">
* The Constant Pool in The Java Virtual Machine Specification</a>
@@ -373,22 +433,16 @@ public final class Const {
/**
* Marks a constant pool entry as a Module Reference.
- *
- * <p>Note: Early access Java 9 support- currently subject to change</p>
- *
- * @see <a href="http://cr.openjdk.java.net/~mr/jigsaw/spec/lang-vm.html#jigsaw-2.6">
- * JPMS: Modules in the Java Language and JVM</a>
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.4.11">
+ * The Constant Pool in The Java Virtual Machine Specification</a>
* @since 6.1
*/
public static final byte CONSTANT_Module = 19;
/**
* Marks a constant pool entry as a Package Reference.
- *
- * <p>Note: Early access Java 9 support- currently subject to change</p>
- *
- * @see <a href="http://cr.openjdk.java.net/~mr/jigsaw/spec/lang-vm.html#jigsaw-2.6">
- * JPMS: Modules in the Java Language and JVM</a>
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.4.12">
+ * The Constant Pool in The Java Virtual Machine Specification</a>
* @since 6.1
*/
public static final byte CONSTANT_Package = 20;
@@ -403,7 +457,7 @@ public final class Const {
"CONSTANT_Class", "CONSTANT_String", "CONSTANT_Fieldref",
"CONSTANT_Methodref", "CONSTANT_InterfaceMethodref",
"CONSTANT_NameAndType", "", "", "CONSTANT_MethodHandle",
- "CONSTANT_MethodType", "", "CONSTANT_InvokeDynamic",
+ "CONSTANT_MethodType", "CONSTANT_Dynamic", "CONSTANT_InvokeDynamic",
"CONSTANT_Module", "CONSTANT_Package"};
/**
diff --git a/src/main/java/org/apache/bcel/classfile/Constant.java b/src/main/java/org/apache/bcel/classfile/Constant.java
index 10859634..dac28190 100644
--- a/src/main/java/org/apache/bcel/classfile/Constant.java
+++ b/src/main/java/org/apache/bcel/classfile/Constant.java
@@ -127,52 +127,54 @@ public abstract class Constant implements Cloneable, Node {
/**
* Read one constant from the given input, the type depends on a tag byte.
*
- * @param input Input stream
+ * @param dataInput Input stream
* @return Constant object
+ * @throws IOException if an I/O error occurs reading from the given {@code dataInput}.
+ * @throws ClassFormatException if the next byte is not recognized
* @since 6.0 made public
*/
- public static Constant readConstant( final DataInput input ) throws IOException,
- ClassFormatException {
- final byte b = input.readByte(); // Read tag byte
+ public static Constant readConstant(final DataInput dataInput) throws IOException, ClassFormatException {
+ final byte b = dataInput.readByte(); // Read tag byte
switch (b) {
- case Const.CONSTANT_Class:
- return new ConstantClass(input);
- case Const.CONSTANT_Fieldref:
- return new ConstantFieldref(input);
- case Const.CONSTANT_Methodref:
- return new ConstantMethodref(input);
- case Const.CONSTANT_InterfaceMethodref:
- return new ConstantInterfaceMethodref(input);
- case Const.CONSTANT_String:
- return new ConstantString(input);
- case Const.CONSTANT_Integer:
- return new ConstantInteger(input);
- case Const.CONSTANT_Float:
- return new ConstantFloat(input);
- case Const.CONSTANT_Long:
- return new ConstantLong(input);
- case Const.CONSTANT_Double:
- return new ConstantDouble(input);
- case Const.CONSTANT_NameAndType:
- return new ConstantNameAndType(input);
- case Const.CONSTANT_Utf8:
- return ConstantUtf8.getInstance(input);
- case Const.CONSTANT_MethodHandle:
- return new ConstantMethodHandle(input);
- case Const.CONSTANT_MethodType:
- return new ConstantMethodType(input);
- case Const.CONSTANT_InvokeDynamic:
- return new ConstantInvokeDynamic(input);
- case Const.CONSTANT_Module:
- return new ConstantModule(input);
- case Const.CONSTANT_Package:
- return new ConstantPackage(input);
- default:
- throw new ClassFormatException("Invalid byte tag in constant pool: " + b);
+ case Const.CONSTANT_Class:
+ return new ConstantClass(dataInput);
+ case Const.CONSTANT_Fieldref:
+ return new ConstantFieldref(dataInput);
+ case Const.CONSTANT_Methodref:
+ return new ConstantMethodref(dataInput);
+ case Const.CONSTANT_InterfaceMethodref:
+ return new ConstantInterfaceMethodref(dataInput);
+ case Const.CONSTANT_String:
+ return new ConstantString(dataInput);
+ case Const.CONSTANT_Integer:
+ return new ConstantInteger(dataInput);
+ case Const.CONSTANT_Float:
+ return new ConstantFloat(dataInput);
+ case Const.CONSTANT_Long:
+ return new ConstantLong(dataInput);
+ case Const.CONSTANT_Double:
+ return new ConstantDouble(dataInput);
+ case Const.CONSTANT_NameAndType:
+ return new ConstantNameAndType(dataInput);
+ case Const.CONSTANT_Utf8:
+ return ConstantUtf8.getInstance(dataInput);
+ case Const.CONSTANT_MethodHandle:
+ return new ConstantMethodHandle(dataInput);
+ case Const.CONSTANT_MethodType:
+ return new ConstantMethodType(dataInput);
+ case Const.CONSTANT_Dynamic:
+ return new ConstantDynamic(dataInput);
+ case Const.CONSTANT_InvokeDynamic:
+ return new ConstantInvokeDynamic(dataInput);
+ case Const.CONSTANT_Module:
+ return new ConstantModule(dataInput);
+ case Const.CONSTANT_Package:
+ return new ConstantPackage(dataInput);
+ default:
+ throw new ClassFormatException("Invalid byte tag in constant pool: " + b);
}
}
-
/**
* @return Comparison strategy object
*/
diff --git a/src/main/java/org/apache/bcel/classfile/ConstantClass.java b/src/main/java/org/apache/bcel/classfile/ConstantClass.java
index 9be55ec5..25ebfabc 100644
--- a/src/main/java/org/apache/bcel/classfile/ConstantClass.java
+++ b/src/main/java/org/apache/bcel/classfile/ConstantClass.java
@@ -27,7 +27,6 @@ import org.apache.bcel.Const;
* This class is derived from the abstract {@link Constant}
* and represents a reference to a (external) class.
*
- * @version $Id$
* @see Constant
*/
public final class ConstantClass extends Constant implements ConstantObject {
@@ -44,13 +43,13 @@ public final class ConstantClass extends Constant implements ConstantObject {
/**
- * Initialize instance from file data.
+ * Constructs an instance from file data.
*
- * @param file Input stream
- * @throws IOException
+ * @param dataInput Input stream
+ * @throws IOException if an I/O error occurs reading from the given {@code dataInput}.
*/
- ConstantClass(final DataInput file) throws IOException {
- this(file.readUnsignedShort());
+ ConstantClass(final DataInput dataInput) throws IOException {
+ this(dataInput.readUnsignedShort());
}
@@ -78,10 +77,10 @@ public final class ConstantClass extends Constant implements ConstantObject {
/**
- * Dump constant class to file stream in binary format.
+ * Dumps constant class to file stream in binary format.
*
* @param file Output file stream
- * @throws IOException
+ * @throws IOException if an I/O error occurs writing to the DataOutputStream.
*/
@Override
public final void dump( final DataOutputStream file ) throws IOException {
diff --git a/src/main/java/org/apache/bcel/classfile/ConstantDynamic.java b/src/main/java/org/apache/bcel/classfile/ConstantDynamic.java
new file mode 100644
index 00000000..df3add13
--- /dev/null
+++ b/src/main/java/org/apache/bcel/classfile/ConstantDynamic.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.bcel.classfile;
+
+import java.io.DataInput;
+import java.io.IOException;
+
+import org.apache.bcel.Const;
+
+/**
+ * This class is derived from the abstract {@link Constant}
+ * and represents a reference to a dynamically computed constant.
+ *
+ * @see Constant
+ * @see <a href="https://bugs.openjdk.java.net/secure/attachment/74618/constant-dynamic.html">
+ * Change request for JEP 309</a>
+ * @since 6.3
+ */
+public final class ConstantDynamic extends ConstantCP {
+
+ /**
+ * Initialize from another object.
+ */
+ public ConstantDynamic(final ConstantDynamic c) {
+ this(c.getBootstrapMethodAttrIndex(), c.getNameAndTypeIndex());
+ }
+
+
+ /**
+ * Initialize instance from file data.
+ *
+ * @param file Input stream
+ * @throws IOException
+ */
+ ConstantDynamic(final DataInput file) throws IOException {
+ this(file.readShort(), file.readShort());
+ }
+
+
+ public ConstantDynamic(final int bootstrap_method_attr_index, final int name_and_type_index) {
+ super(Const.CONSTANT_Dynamic, bootstrap_method_attr_index, name_and_type_index);
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitly
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ @Override
+ public void accept( final Visitor v ) {
+ v.visitConstantDynamic(this);
+ }
+
+ /**
+ * @return Reference (index) to bootstrap method this constant refers to.
+ *
+ * Note that this method is a functional duplicate of getClassIndex
+ * for use by ConstantInvokeDynamic.
+ * @since 6.0
+ */
+ public final int getBootstrapMethodAttrIndex() {
+ return super.getClassIndex(); // AKA bootstrap_method_attr_index
+ }
+
+ /**
+ * @return String representation
+ */
+ @Override
+ public final String toString() {
+ return super.toString().replace("class_index", "bootstrap_method_attr_index");
+ }
+}
diff --git a/src/main/java/org/apache/bcel/classfile/DescendingVisitor.java b/src/main/java/org/apache/bcel/classfile/DescendingVisitor.java
index 21b05fe3..4f1c6498 100644
--- a/src/main/java/org/apache/bcel/classfile/DescendingVisitor.java
+++ b/src/main/java/org/apache/bcel/classfile/DescendingVisitor.java
@@ -543,4 +543,12 @@ public class DescendingVisitor implements Visitor
obj.accept(visitor);
stack.pop();
}
+
+ /** @since 6.3 */
+ @Override
+ public void visitConstantDynamic(final ConstantDynamic obj) {
+ stack.push(obj);
+ obj.accept(visitor);
+ stack.pop();
+ }
}
diff --git a/src/main/java/org/apache/bcel/classfile/EmptyVisitor.java b/src/main/java/org/apache/bcel/classfile/EmptyVisitor.java
index d7b20a40..74866ec1 100644
--- a/src/main/java/org/apache/bcel/classfile/EmptyVisitor.java
+++ b/src/main/java/org/apache/bcel/classfile/EmptyVisitor.java
@@ -310,4 +310,12 @@ public class EmptyVisitor implements Visitor
@Override
public void visitConstantModule(final ConstantModule constantModule) {
}
+
+
+ /**
+ * @since 6.3
+ */
+ @Override
+ public void visitConstantDynamic(final ConstantDynamic obj) {
+ }
}
diff --git a/src/main/java/org/apache/bcel/classfile/Visitor.java b/src/main/java/org/apache/bcel/classfile/Visitor.java
index 6d2f6fb7..71b90d9c 100644
--- a/src/main/java/org/apache/bcel/classfile/Visitor.java
+++ b/src/main/java/org/apache/bcel/classfile/Visitor.java
@@ -156,4 +156,11 @@ public interface Visitor
* @since 6.1
*/
void visitConstantModule(ConstantModule constantModule);
+
+ /**
+ * @since 6.3
+ */
+ default void visitConstantDynamic(ConstantDynamic constantDynamic) {
+ // empty
+ }
}
diff --git a/src/main/java/org/apache/bcel/util/ClassPath.java b/src/main/java/org/apache/bcel/util/ClassPath.java
index 1c2cf312..57314ef7 100644
--- a/src/main/java/org/apache/bcel/util/ClassPath.java
+++ b/src/main/java/org/apache/bcel/util/ClassPath.java
@@ -17,6 +17,7 @@
*/
package org.apache.bcel.util;
+import java.io.Closeable;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -25,141 +26,476 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.Locale;
+import java.util.Objects;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
- * Responsible for loading (class) files from the CLASSPATH. Inspired by
- * sun.tools.ClassPath.
+ * Responsible for loading (class) files from the CLASSPATH. Inspired by sun.tools.ClassPath.
*
* @version $Id$
*/
-public class ClassPath {
+public class ClassPath implements Closeable {
- public static final ClassPath SYSTEM_CLASS_PATH = new ClassPath(getClassPath());
+ private abstract static class AbstractPathEntry implements Closeable {
- private static final FilenameFilter ARCHIVE_FILTER = new FilenameFilter() {
+ abstract ClassFile getClassFile(String name, String suffix) throws IOException;
+
+ abstract URL getResource(String name);
+
+ abstract InputStream getResourceAsStream(String name);
+ }
+
+ private abstract static class AbstractZip extends AbstractPathEntry {
+
+ private final ZipFile zipFile;
+
+ AbstractZip(final ZipFile zipFile) {
+ this.zipFile = Objects.requireNonNull(zipFile, "zipFile");
+ }
@Override
- public boolean accept( final File dir, String name ) {
- name = name.toLowerCase(Locale.ENGLISH);
- return name.endsWith(".zip") || name.endsWith(".jar");
+ public void close() throws IOException {
+ if (zipFile != null) {
+ zipFile.close();
+ }
+
}
- };
- private final PathEntry[] paths;
- private final String class_path;
- private ClassPath parent;
+ @Override
+ ClassFile getClassFile(final String name, final String suffix) throws IOException {
+ final ZipEntry entry = zipFile.getEntry(toEntryName(name, suffix));
- public ClassPath(final ClassPath parent, final String class_path) {
- this(class_path);
- this.parent = parent;
- }
+ if (entry == null) {
+ return null;
+ }
- /**
- * Search for classes in given path.
- *
- * @param class_path
- */
- public ClassPath(final String class_path) {
- this.class_path = class_path;
- final List<PathEntry> list = new ArrayList<>();
- for (final StringTokenizer tok = new StringTokenizer(class_path, File.pathSeparator); tok.hasMoreTokens();) {
- final String path = tok.nextToken();
- if (!path.isEmpty()) {
- final File file = new File(path);
- try {
- if (file.exists()) {
- if (file.isDirectory()) {
- list.add(new Dir(path));
- } else {
- list.add(new Zip(new ZipFile(file)));
- }
- }
- } catch (final IOException e) {
- if (path.endsWith(".zip") || path.endsWith(".jar")) {
- System.err.println("CLASSPATH component " + file + ": " + e);
- }
+ return new ClassFile() {
+
+ @Override
+ public String getBase() {
+ return zipFile.getName();
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ return zipFile.getInputStream(entry);
+ }
+
+ @Override
+ public String getPath() {
+ return entry.toString();
+ }
+
+ @Override
+ public long getSize() {
+ return entry.getSize();
+ }
+
+ @Override
+ public long getTime() {
+ return entry.getTime();
}
+ };
+ }
+
+ @Override
+ URL getResource(final String name) {
+ final ZipEntry entry = zipFile.getEntry(name);
+ try {
+ return entry != null ? new URL("jar:file:" + zipFile.getName() + "!/" + name) : null;
+ } catch (final MalformedURLException e) {
+ return null;
}
}
- paths = new PathEntry[list.size()];
- list.toArray(paths);
+
+ @Override
+ InputStream getResourceAsStream(final String name) {
+ final ZipEntry entry = zipFile.getEntry(name);
+ try {
+ return entry != null ? zipFile.getInputStream(entry) : null;
+ } catch (final IOException e) {
+ return null;
+ }
+ }
+
+ protected abstract String toEntryName(final String name, final String suffix);
+
+ @Override
+ public String toString() {
+ return zipFile.getName();
+ }
+
}
/**
- * Search for classes in CLASSPATH.
- * @deprecated Use SYSTEM_CLASS_PATH constant
+ * Contains information about file/ZIP entry of the Java class.
*/
- @Deprecated
- public ClassPath() {
- this(getClassPath());
+ public interface ClassFile {
+
+ /**
+ * @return base path of found class, i.e. class is contained relative to that path, which may either denote a
+ * directory, or zip file
+ */
+ String getBase();
+
+ /**
+ * @return input stream for class file.
+ */
+ InputStream getInputStream() throws IOException;
+
+ /**
+ * @return canonical path to class file.
+ */
+ String getPath();
+
+ /**
+ * @return size of class file.
+ */
+ long getSize();
+
+ /**
+ * @return modification time of class file.
+ */
+ long getTime();
}
- /** @return used class path string
- */
- @Override
- public String toString() {
- if (parent != null) {
- return parent + File.pathSeparator + class_path;
+ private static class Dir extends AbstractPathEntry {
+
+ private final String dir;
+
+ Dir(final String d) {
+ dir = d;
+ }
+
+ @Override
+ public void close() throws IOException {
+ // Nothing to do
+
+ }
+
+ @Override
+ ClassFile getClassFile(final String name, final String suffix) throws IOException {
+ final File file = new File(dir + File.separatorChar + name.replace('.', File.separatorChar) + suffix);
+ return file.exists() ? new ClassFile() {
+
+ @Override
+ public String getBase() {
+ return dir;
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ return new FileInputStream(file);
+ }
+
+ @Override
+ public String getPath() {
+ try {
+ return file.getCanonicalPath();
+ } catch (final IOException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public long getSize() {
+ return file.length();
+ }
+
+ @Override
+ public long getTime() {
+ return file.lastModified();
+ }
+ } : null;
+ }
+
+ @Override
+ URL getResource(final String name) {
+ // Resource specification uses '/' whatever the platform
+ final File file = toFile(name);
+ try {
+ return file.exists() ? file.toURI().toURL() : null;
+ } catch (final MalformedURLException e) {
+ return null;
+ }
+ }
+
+ @Override
+ InputStream getResourceAsStream(final String name) {
+ // Resource specification uses '/' whatever the platform
+ final File file = toFile(name);
+ try {
+ return file.exists() ? new FileInputStream(file) : null;
+ } catch (final IOException e) {
+ return null;
+ }
+ }
+
+ private File toFile(final String name) {
+ return new File(dir + File.separatorChar + name.replace('/', File.separatorChar));
+ }
+
+ @Override
+ public String toString() {
+ return dir;
}
- return class_path;
}
- @Override
- public int hashCode() {
- if (parent != null) {
- return class_path.hashCode() + parent.hashCode();
+ private static class Jar extends AbstractZip {
+
+ Jar(final ZipFile zip) {
+ super(zip);
}
- return class_path.hashCode();
+
+ @Override
+ protected String toEntryName(final String name, final String suffix) {
+ return packageToFolder(name) + suffix;
+ }
+
}
+ private static class JrtModule extends AbstractPathEntry {
- @Override
- public boolean equals( final Object o ) {
- if (o instanceof ClassPath) {
- final ClassPath cp = (ClassPath)o;
- return class_path.equals(cp.toString());
+ private final Path modulePath;
+
+ public JrtModule(final Path modulePath) {
+ this.modulePath = Objects.requireNonNull(modulePath, "modulePath");
}
- return false;
+
+ @Override
+ public void close() throws IOException {
+ // Nothing to do.
+
+ }
+
+ @Override
+ ClassFile getClassFile(final String name, final String suffix) throws IOException {
+ final Path resolved = modulePath.resolve(packageToFolder(name) + suffix);
+ if (Files.exists(resolved)) {
+ return new ClassFile() {
+
+ @Override
+ public String getBase() {
+ return resolved.getFileName().toString();
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ return Files.newInputStream(resolved);
+ }
+
+ @Override
+ public String getPath() {
+ return resolved.toString();
+ }
+
+ @Override
+ public long getSize() {
+ try {
+ return Files.size(resolved);
+ } catch (final IOException e) {
+ return 0;
+ }
+ }
+
+ @Override
+ public long getTime() {
+ try {
+ return Files.getLastModifiedTime(resolved).toMillis();
+ } catch (final IOException e) {
+ return 0;
+ }
+ }
+ };
+ }
+ return null;
+ }
+
+ @Override
+ URL getResource(final String name) {
+ final Path resovled = modulePath.resolve(name);
+ try {
+ return Files.exists(resovled) ? new URL("jrt:" + modulePath + "/" + name) : null;
+ } catch (final MalformedURLException e) {
+ return null;
+ }
+ }
+
+ @Override
+ InputStream getResourceAsStream(final String name) {
+ try {
+ return Files.newInputStream(modulePath.resolve(name));
+ } catch (final IOException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return modulePath.toString();
+ }
+
}
+ private static class JrtModules extends AbstractPathEntry {
- private static void getPathComponents( final String path, final List<String> list ) {
- if (path != null) {
- final StringTokenizer tok = new StringTokenizer(path, File.pathSeparator);
- while (tok.hasMoreTokens()) {
- final String name = tok.nextToken();
- final File file = new File(name);
- if (file.exists()) {
- list.add(name);
+ private final ModularRuntimeImage modularRuntimeImage;
+ private final JrtModule[] modules;
+
+ public JrtModules(String path) throws IOException {
+ this.modularRuntimeImage = new ModularRuntimeImage();
+ final List<Path> list = modularRuntimeImage.list(path);
+ this.modules = new JrtModule[list.size()];
+ for (int i = 0; i < modules.length; i++) {
+ modules[i] = new JrtModule(list.get(i));
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (modules != null) {
+ // don't use a for each loop to avoid creating an iterator for the GC to collect.
+ for (int i = 0; i < modules.length; i++) {
+ modules[i].close();
+ }
+ }
+ if (modularRuntimeImage != null) {
+ modularRuntimeImage.close();
+ }
+ }
+
+ @Override
+ ClassFile getClassFile(final String name, final String suffix) throws IOException {
+ // don't use a for each loop to avoid creating an iterator for the GC to collect.
+ for (int i = 0; i < modules.length; i++) {
+ final ClassFile classFile = modules[i].getClassFile(name, suffix);
+ if (classFile != null) {
+ return classFile;
}
}
+ return null;
+ }
+
+ @Override
+ URL getResource(final String name) {
+ // don't use a for each loop to avoid creating an iterator for the GC to collect.
+ for (int i = 0; i < modules.length; i++) {
+ final URL url = modules[i].getResource(name);
+ if (url != null) {
+ return url;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ InputStream getResourceAsStream(final String name) {
+ // don't use a for each loop to avoid creating an iterator for the GC to collect.
+ for (int i = 0; i < modules.length; i++) {
+ final InputStream inputStream = modules[i].getResourceAsStream(name);
+ if (inputStream != null) {
+ return inputStream;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return Arrays.toString(modules);
+ }
+
+ }
+
+ private static class Module extends AbstractZip {
+
+ Module(final ZipFile zip) {
+ super(zip);
+ }
+
+ @Override
+ protected String toEntryName(final String name, final String suffix) {
+ return "classes/" + packageToFolder(name) + suffix;
}
+
}
+ private static final FilenameFilter ARCHIVE_FILTER = new FilenameFilter() {
+
+ @Override
+ public boolean accept(final File dir, String name) {
+ name = name.toLowerCase(Locale.ENGLISH);
+ return name.endsWith(".zip") || name.endsWith(".jar");
+ }
+ };
+
+ private static final FilenameFilter MODULES_FILTER = new FilenameFilter() {
+
+ @Override
+ public boolean accept(final File dir, String name) {
+ name = name.toLowerCase(Locale.ENGLISH);
+ return name.endsWith(".jmod");
+ }
+ };
+
+ public static final ClassPath SYSTEM_CLASS_PATH = new ClassPath(getClassPath());
+
+ private static void addJdkModules(final String javaHome, final List<String> list) {
+ String modulesPath = System.getProperty("java.modules.path");
+ if (modulesPath == null || modulesPath.trim().isEmpty()) {
+ // Default to looking in JAVA_HOME/jmods
+ modulesPath = javaHome + File.separator + "jmods";
+ }
+ final File modulesDir = new File(modulesPath);
+ if (modulesDir.exists()) {
+ final String[] modules = modulesDir.list(MODULES_FILTER);
+ for (int i = 0; i < modules.length; i++) {
+ list.add(modulesDir.getPath() + File.separatorChar + modules[i]);
+ }
+ }
+ }
- /** Checks for class path components in the following properties:
- * "java.class.path", "sun.boot.class.path", "java.ext.dirs"
+ /**
+ * Checks for class path components in the following properties: "java.class.path", "sun.boot.class.path",
+ * "java.ext.dirs"
*
* @return class path as used by default by BCEL
*/
// @since 6.0 no longer final
public static String getClassPath() {
- final String class_path = System.getProperty("java.class.path");
- final String boot_path = System.getProperty("sun.boot.class.path");
- final String ext_path = System.getProperty("java.ext.dirs");
+ final String classPathProp = System.getProperty("java.class.path");
+ final String bootClassPathProp = System.getProperty("sun.boot.class.path");
+ final String extDirs = System.getProperty("java.ext.dirs");
+ // System.out.println("java.version = " + System.getProperty("java.version"));
+ // System.out.println("java.class.path = " + classPathProp);
+ // System.out.println("sun.boot.class.path=" + bootClassPathProp);
+ // System.out.println("java.ext.dirs=" + extDirs);
+ final String javaHome = System.getProperty("java.home");
final List<String> list = new ArrayList<>();
- getPathComponents(class_path, list);
- getPathComponents(boot_path, list);
+
+ // Starting in JRE 9, .class files are in the modules directory. Add them to the path.
+ final Path modulesPath = Paths.get(javaHome).resolve("lib/modules");
+ if (Files.exists(modulesPath) && Files.isRegularFile(modulesPath)) {
+ list.add(modulesPath.toAbsolutePath().toString());
+ }
+ // Starting in JDK 9, .class files are in the jmods directory. Add them to the path.
+ addJdkModules(javaHome, list);
+
+ getPathComponents(classPathProp, list);
+ getPathComponents(bootClassPathProp, list);
final List<String> dirs = new ArrayList<>();
- getPathComponents(ext_path, dirs);
+ getPathComponents(extDirs, dirs);
for (final String d : dirs) {
final File ext_dir = new File(d);
final String[] extensions = ext_dir.list(ARCHIVE_FILTER);
@@ -169,6 +505,7 @@ public class ClassPath {
}
}
}
+
final StringBuilder buf = new StringBuilder();
String separator = "";
for (final String path : list) {
@@ -179,89 +516,148 @@ public class ClassPath {
return buf.toString().intern();
}
+ private static void getPathComponents(final String path, final List<String> list) {
+ if (path != null) {
+ final StringTokenizer tokenizer = new StringTokenizer(path, File.pathSeparator);
+ while (tokenizer.hasMoreTokens()) {
+ final String name = tokenizer.nextToken();
+ final File file = new File(name);
+ if (file.exists()) {
+ list.add(name);
+ }
+ }
+ }
+ }
+
+ static String packageToFolder(final String name) {
+ return name.replace('.', '/');
+ }
+
+ private final String classPath;
+
+ private ClassPath parent;
+
+ private final AbstractPathEntry[] paths;
/**
- * @param name fully qualified class name, e.g. java.lang.String
- * @return input stream for class
+ * Search for classes in CLASSPATH.
+ *
+ * @deprecated Use SYSTEM_CLASS_PATH constant
*/
- public InputStream getInputStream( final String name ) throws IOException {
- return getInputStream(name.replace('.', '/'), ".class");
+ @Deprecated
+ public ClassPath() {
+ this(getClassPath());
}
+ public ClassPath(final ClassPath parent, final String classPath) {
+ this(classPath);
+ this.parent = parent;
+ }
/**
- * Return stream for class or resource on CLASSPATH.
+ * Search for classes in given path.
*
- * @param name fully qualified file name, e.g. java/lang/String
- * @param suffix file name ends with suff, e.g. .java
- * @return input stream for file on class path
+ * @param classPath
*/
- public InputStream getInputStream( final String name, final String suffix ) throws IOException {
- InputStream is = null;
- try {
- is = getClass().getClassLoader().getResourceAsStream(name + suffix); // may return null
- } catch (final Exception e) {
- // ignored
+ @SuppressWarnings("resource")
+ public ClassPath(final String classPath) {
+ this.classPath = classPath;
+ final List<AbstractPathEntry> list = new ArrayList<>();
+ for (final StringTokenizer tokenizer = new StringTokenizer(classPath, File.pathSeparator); tokenizer
+ .hasMoreTokens();) {
+ final String path = tokenizer.nextToken();
+ if (!path.isEmpty()) {
+ final File file = new File(path);
+ try {
+ if (file.exists()) {
+ if (file.isDirectory()) {
+ list.add(new Dir(path));
+ } else if (path.endsWith(".jmod")) {
+ list.add(new Module(new ZipFile(file)));
+ } else if (path.endsWith(ModularRuntimeImage.MODULES_PATH)) {
+ list.add(new JrtModules(ModularRuntimeImage.MODULES_PATH));
+ } else {
+ list.add(new Jar(new ZipFile(file)));
+ }
+ }
+ } catch (final IOException e) {
+ if (path.endsWith(".zip") || path.endsWith(".jar")) {
+ System.err.println("CLASSPATH component " + file + ": " + e);
+ }
+ }
+ }
+ }
+ paths = new AbstractPathEntry[list.size()];
+ list.toArray(paths);
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (paths != null) {
+ for (final AbstractPathEntry path : paths) {
+ path.close();
+ }
}
- if (is != null) {
- return is;
+
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o instanceof ClassPath) {
+ final ClassPath cp = (ClassPath) o;
+ return classPath.equals(cp.toString());
}
- return getClassFile(name, suffix).getInputStream();
+ return false;
}
/**
- * @param name fully qualified resource name, e.g. java/lang/String.class
- * @return InputStream supplying the resource, or null if no resource with that name.
- * @since 6.0
+ * @return byte array for class
*/
- public InputStream getResourceAsStream(final String name) {
- for (final PathEntry path : paths) {
- InputStream is;
- if ((is = path.getResourceAsStream(name)) != null) {
- return is;
- }
- }
- return null;
+ public byte[] getBytes(final String name) throws IOException {
+ return getBytes(name, ".class");
}
/**
- * @param name fully qualified resource name, e.g. java/lang/String.class
- * @return URL supplying the resource, or null if no resource with that name.
- * @since 6.0
+ * @param name
+ * fully qualified file name, e.g. java/lang/String
+ * @param suffix
+ * file name ends with suffix, e.g. .java
+ * @return byte array for file on class path
*/
- public URL getResource(final String name) {
- for (final PathEntry path : paths) {
- URL url;
- if ((url = path.getResource(name)) != null) {
- return url;
+ public byte[] getBytes(final String name, final String suffix) throws IOException {
+ DataInputStream dis = null;
+ try (InputStream inputStream = getInputStream(name, suffix)) {
+ if (inputStream == null) {
+ throw new IOException("Couldn't find: " + name + suffix);
+ }
+ dis = new DataInputStream(inputStream);
+ final byte[] bytes = new byte[inputStream.available()];
+ dis.readFully(bytes);
+ return bytes;
+ } finally {
+ if (dis != null) {
+ dis.close();
}
}
- return null;
}
/**
- * @param name fully qualified resource name, e.g. java/lang/String.class
- * @return An Enumeration of URLs supplying the resource, or an
- * empty Enumeration if no resource with that name.
- * @since 6.0
+ * @param name
+ * fully qualified class name, e.g. java.lang.String
+ * @return input stream for class
*/
- public Enumeration<URL> getResources(final String name) {
- final Vector<URL> results = new Vector<>();
- for (final PathEntry path : paths) {
- URL url;
- if ((url = path.getResource(name)) != null) {
- results.add(url);
- }
- }
- return results.elements();
+ public ClassFile getClassFile(final String name) throws IOException {
+ return getClassFile(name, ".class");
}
/**
- * @param name fully qualified file name, e.g. java/lang/String
- * @param suffix file name ends with suff, e.g. .java
+ * @param name
+ * fully qualified file name, e.g. java/lang/String
+ * @param suffix
+ * file name ends with suff, e.g. .java
* @return class file for the java class
*/
- public ClassFile getClassFile( final String name, final String suffix ) throws IOException {
+ public ClassFile getClassFile(final String name, final String suffix) throws IOException {
ClassFile cf = null;
if (parent != null) {
@@ -281,63 +677,54 @@ public class ClassPath {
private ClassFile getClassFileInternal(final String name, final String suffix) throws IOException {
- for (final PathEntry path : paths) {
- final ClassFile cf = path.getClassFile(name, suffix);
+ for (final AbstractPathEntry path : paths) {
+ final ClassFile cf = path.getClassFile(name, suffix);
- if(cf != null) {
- return cf;
- }
- }
-
- return null;
- }
+ if (cf != null) {
+ return cf;
+ }
+ }
+ return null;
+ }
/**
- * @param name fully qualified class name, e.g. java.lang.String
+ * @param name
+ * fully qualified class name, e.g. java.lang.String
* @return input stream for class
*/
- public ClassFile getClassFile( final String name ) throws IOException {
- return getClassFile(name, ".class");
+ public InputStream getInputStream(final String name) throws IOException {
+ return getInputStream(packageToFolder(name), ".class");
}
-
/**
- * @param name fully qualified file name, e.g. java/lang/String
- * @param suffix file name ends with suffix, e.g. .java
- * @return byte array for file on class path
+ * Return stream for class or resource on CLASSPATH.
+ *
+ * @param name
+ * fully qualified file name, e.g. java/lang/String
+ * @param suffix
+ * file name ends with suff, e.g. .java
+ * @return input stream for file on class path
*/
- public byte[] getBytes(final String name, final String suffix) throws IOException {
- DataInputStream dis = null;
- try (InputStream is = getInputStream(name, suffix)) {
- if (is == null) {
- throw new IOException("Couldn't find: " + name + suffix);
- }
- dis = new DataInputStream(is);
- final byte[] bytes = new byte[is.available()];
- dis.readFully(bytes);
- return bytes;
- } finally {
- if (dis != null) {
- dis.close();
- }
+ public InputStream getInputStream(final String name, final String suffix) throws IOException {
+ InputStream inputStream = null;
+ try {
+ inputStream = getClass().getClassLoader().getResourceAsStream(name + suffix); // may return null
+ } catch (final Exception e) {
+ // ignored
}
+ if (inputStream != null) {
+ return inputStream;
+ }
+ return getClassFile(name, suffix).getInputStream();
}
-
- /**
- * @return byte array for class
- */
- public byte[] getBytes( final String name ) throws IOException {
- return getBytes(name, ".class");
- }
-
-
/**
- * @param name name of file to search for, e.g. java/lang/String.java
+ * @param name
+ * name of file to search for, e.g. java/lang/String.java
* @return full (canonical) path for file
*/
- public String getPath( String name ) throws IOException {
+ public String getPath(String name) throws IOException {
final int index = name.lastIndexOf('.');
String suffix = "";
if (index > 0) {
@@ -347,200 +734,82 @@ public class ClassPath {
return getPath(name, suffix);
}
-
/**
- * @param name name of file to search for, e.g. java/lang/String
- * @param suffix file name suffix, e.g. .java
+ * @param name
+ * name of file to search for, e.g. java/lang/String
+ * @param suffix
+ * file name suffix, e.g. .java
* @return full (canonical) path for file, if it exists
*/
- public String getPath( final String name, final String suffix ) throws IOException {
+ public String getPath(final String name, final String suffix) throws IOException {
return getClassFile(name, suffix).getPath();
}
- private abstract static class PathEntry {
-
- abstract ClassFile getClassFile( String name, String suffix ) throws IOException;
- abstract URL getResource(String name);
- abstract InputStream getResourceAsStream(String name);
- }
-
- /** Contains information about file/ZIP entry of the Java class.
+ /**
+ * @param name
+ * fully qualified resource name, e.g. java/lang/String.class
+ * @return URL supplying the resource, or null if no resource with that name.
+ * @since 6.0
*/
- public interface ClassFile {
-
- /** @return input stream for class file.
- */
- InputStream getInputStream() throws IOException;
-
-
- /** @return canonical path to class file.
- */
- String getPath();
-
-
- /** @return base path of found class, i.e. class is contained relative
- * to that path, which may either denote a directory, or zip file
- */
- String getBase();
-
-
- /** @return modification time of class file.
- */
- long getTime();
-
-
- /** @return size of class file.
- */
- long getSize();
- }
-
- private static class Dir extends PathEntry {
-
- private final String dir;
-
-
- Dir(final String d) {
- dir = d;
- }
-
- @Override
- URL getResource(final String name) {
- // Resource specification uses '/' whatever the platform
- final File file = new File(dir + File.separatorChar + name.replace('/', File.separatorChar));
- try {
- return file.exists() ? file.toURI().toURL() : null;
- } catch (final MalformedURLException e) {
- return null;
+ public URL getResource(final String name) {
+ for (final AbstractPathEntry path : paths) {
+ URL url;
+ if ((url = path.getResource(name)) != null) {
+ return url;
}
}
+ return null;
+ }
- @Override
- InputStream getResourceAsStream(final String name) {
- // Resource specification uses '/' whatever the platform
- final File file = new File(dir + File.separatorChar + name.replace('/', File.separatorChar));
- try {
- return file.exists() ? new FileInputStream(file) : null;
- } catch (final IOException e) {
- return null;
+ /**
+ * @param name
+ * fully qualified resource name, e.g. java/lang/String.class
+ * @return InputStream supplying the resource, or null if no resource with that name.
+ * @since 6.0
+ */
+ public InputStream getResourceAsStream(final String name) {
+ for (final AbstractPathEntry path : paths) {
+ InputStream is;
+ if ((is = path.getResourceAsStream(name)) != null) {
+ return is;
}
}
-
- @Override
- ClassFile getClassFile( final String name, final String suffix ) throws IOException {
- final File file = new File(dir + File.separatorChar
- + name.replace('.', File.separatorChar) + suffix);
- return file.exists() ? new ClassFile() {
-
- @Override
- public InputStream getInputStream() throws IOException {
- return new FileInputStream(file);
- }
-
-
- @Override
- public String getPath() {
- try {
- return file.getCanonicalPath();
- } catch (final IOException e) {
- return null;
- }
- }
-
-
- @Override
- public long getTime() {
- return file.lastModified();
- }
-
-
- @Override
- public long getSize() {
- return file.length();
- }
-
-
- @Override
- public String getBase() {
- return dir;
- }
- } : null;
- }
-
-
- @Override
- public String toString() {
- return dir;
- }
+ return null;
}
- private static class Zip extends PathEntry {
-
- private final ZipFile zip;
-
-
- Zip(final ZipFile z) {
- zip = z;
- }
-
- @Override
- URL getResource(final String name) {
- final ZipEntry entry = zip.getEntry(name);
- try {
- return (entry != null) ? new URL("jar:file:" + zip.getName() + "!/" + name) : null;
- } catch (final MalformedURLException e) {
- return null;
- }
- }
-
- @Override
- InputStream getResourceAsStream(final String name) {
- final ZipEntry entry = zip.getEntry(name);
- try {
- return (entry != null) ? zip.getInputStream(entry) : null;
- } catch (final IOException e) {
- return null;
+ /**
+ * @param name
+ * fully qualified resource name, e.g. java/lang/String.class
+ * @return An Enumeration of URLs supplying the resource, or an empty Enumeration if no resource with that name.
+ * @since 6.0
+ */
+ public Enumeration<URL> getResources(final String name) {
+ final Vector<URL> results = new Vector<>();
+ for (final AbstractPathEntry path : paths) {
+ URL url;
+ if ((url = path.getResource(name)) != null) {
+ results.add(url);
}
}
+ return results.elements();
+ }
- @Override
- ClassFile getClassFile( final String name, final String suffix ) throws IOException {
- final ZipEntry entry = zip.getEntry(name.replace('.', '/') + suffix);
-
- if (entry == null) {
- return null;
- }
-
- return new ClassFile() {
-
- @Override
- public InputStream getInputStream() throws IOException {
- return zip.getInputStream(entry);
- }
-
-
- @Override
- public String getPath() {
- return entry.toString();
- }
-
-
- @Override
- public long getTime() {
- return entry.getTime();
- }
-
-
- @Override
- public long getSize() {
- return entry.getSize();
- }
-
+ @Override
+ public int hashCode() {
+ if (parent != null) {
+ return classPath.hashCode() + parent.hashCode();
+ }
+ return classPath.hashCode();
+ }
- @Override
- public String getBase() {
- return zip.getName();
- }
- };
+ /**
+ * @return used class path string
+ */
+ @Override
+ public String toString() {
+ if (parent != null) {
+ return parent + File.pathSeparator + classPath;
}
+ return classPath;
}
}
diff --git a/src/main/java/org/apache/bcel/util/ModularRuntimeImage.java b/src/main/java/org/apache/bcel/util/ModularRuntimeImage.java
new file mode 100644
index 00000000..e684f835
--- /dev/null
+++ b/src/main/java/org/apache/bcel/util/ModularRuntimeImage.java
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.bcel.util;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Wraps a Java 9 JEP 220 modular runtime image. Requires the JRT NIO file system.
+ *
+ * @since 6.3
+ */
+public class ModularRuntimeImage implements Closeable {
+
+ static final String MODULES_PATH = File.separator + "modules";
+ static final String PACKAGES_PATH = File.separator + "packages";
+
+ private final URLClassLoader classLoader;
+ private final FileSystem fileSystem;
+
+ /**
+ * Constructs a default instance.
+ *
+ * @throws IOException
+ * an I/O error occurs accessing the file system
+ */
+ public ModularRuntimeImage() throws IOException {
+ this(null, FileSystems.getFileSystem(URI.create("jrt:/")));
+ }
+
+ /**
+ * Constructs an instance using the JRT file system implementation from a specific Java Home.
+ *
+ * @param javaHome
+ * Path to a Java 9 or greater home.
+ *
+ * @throws IOException
+ * an I/O error occurs accessing the file system
+ */
+ public ModularRuntimeImage(final String javaHome) throws IOException {
+ final Map<String, ?> emptyMap = Collections.emptyMap();
+ final Path jrePath = Paths.get(javaHome);
+ final Path jrtFsPath = jrePath.resolve("lib").resolve("jrt-fs.jar");
+ this.classLoader = new URLClassLoader(new URL[] {jrtFsPath.toUri().toURL() });
+ this.fileSystem = FileSystems.newFileSystem(URI.create("jrt:/"), emptyMap, classLoader);
+ }
+
+ private ModularRuntimeImage(final URLClassLoader cl, final FileSystem fs) {
+ this.classLoader = cl;
+ this.fileSystem = fs;
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (classLoader != null) {
+ if (classLoader != null) {
+ classLoader.close();
+ }
+ if (fileSystem != null) {
+ fileSystem.close();
+ }
+ }
+ }
+
+ /**
+ * Lists all entries in the given directory.
+ *
+ * @param dirPath
+ * directory path.
+ * @return a list of dir entries if an I/O error occurs
+ * @throws IOException
+ * an I/O error occurs accessing the file system
+ */
+ public List<Path> list(final Path dirPath) throws IOException {
+ final List<Path> list = new ArrayList<>();
+ try (DirectoryStream<Path> ds = Files.newDirectoryStream(dirPath)) {
+ final Iterator<Path> iterator = ds.iterator();
+ while (iterator.hasNext()) {
+ list.add(iterator.next());
+ }
+ }
+ return list;
+ }
+
+ /**
+ * Lists all entries in the given directory.
+ *
+ * @param dirName
+ * directory path.
+ * @return a list of dir entries if an I/O error occurs
+ * @throws IOException
+ * an I/O error occurs accessing the file system
+ */
+ public List<Path> list(final String dirName) throws IOException {
+ return list(fileSystem.getPath(dirName));
+ }
+
+ /**
+ * Lists all modules.
+ *
+ * @return a list of modules
+ * @throws IOException
+ * an I/O error occurs accessing the file system
+ */
+ public List<Path> modules() throws IOException {
+ return list(MODULES_PATH);
+ }
+
+ /**
+ * Lists all packages.
+ *
+ * @return a list of modules
+ * @throws IOException
+ * an I/O error occurs accessing the file system
+ */
+ public List<Path> packages() throws IOException {
+ return list(PACKAGES_PATH);
+ }
+
+ public FileSystem getFileSystem() {
+ return fileSystem;
+ }
+
+}
diff --git a/src/main/java/org/apache/bcel/util/Repository.java b/src/main/java/org/apache/bcel/util/Repository.java
index 66cc50e8..58e3bb08 100644
--- a/src/main/java/org/apache/bcel/util/Repository.java
+++ b/src/main/java/org/apache/bcel/util/Repository.java
@@ -30,43 +30,45 @@ import org.apache.bcel.classfile.JavaClass;
public interface Repository {
/**
- * Store the provided class under "clazz.getClassName()"
+ * Stores the provided class under "clazz.getClassName()"
*/
void storeClass( JavaClass clazz );
/**
- * Remove class from repository
+ * Removes class from repository
*/
void removeClass( JavaClass clazz );
/**
- * Find the class with the name provided, if the class
+ * Finds the class with the name provided, if the class
* isn't there, return NULL.
*/
JavaClass findClass( String className );
/**
- * Find the class with the name provided, if the class
+ * Finds the class with the name provided, if the class
* isn't there, make an attempt to load it.
*/
JavaClass loadClass( String className ) throws java.lang.ClassNotFoundException;
/**
- * Find the JavaClass instance for the given run-time class object
+ * Finds the JavaClass instance for the given run-time class object
*/
JavaClass loadClass( Class<?> clazz ) throws java.lang.ClassNotFoundException;
- /** Clear all entries from cache.
+ /**
+ * Clears all entries from cache.
*/
void clear();
- /** Get the ClassPath associated with this Repository
+ /**
+ * Gets the ClassPath associated with this Repository
*/
ClassPath getClassPath();
}
diff --git a/src/site/resources/bcel5-bcel6-clirr-report.html b/src/site/resources/bcel5-bcel6-clirr-report.html
index 672198ef..ff01e7b6 100644
--- a/src/site/resources/bcel5-bcel6-clirr-report.html
+++ b/src/site/resources/bcel5-bcel6-clirr-report.html
@@ -160,8 +160,8 @@ limitations under the License.
JIRA Report</a>
</li>
<li class="none">
- <a href="apidocs/index.html" title="JavaDocs">
- JavaDocs</a>
+ <a href="apidocs/index.html" title="Javadocs">
+ Javadocs</a>
</li>
<li class="none">
<a href="xref/index.html" title="Source Xref">
diff --git a/src/site/xdoc/download_bcel.xml b/src/site/xdoc/download_bcel.xml
index a235d54f..0ebd983d 100644
--- a/src/site/xdoc/download_bcel.xml
+++ b/src/site/xdoc/download_bcel.xml
@@ -26,22 +26,24 @@ limitations under the License.
| commons-build-plugin/trunk/src/main/resources/commons-xdoc-templates |
+======================================================================+
| |
- | 1) Re-generate using: mvn commons:download-page |
+ | 1) Re-generate using: mvn commons-build:download-page |
| |
| 2) Set the following properties in the component's pom: |
- | - commons.componentid (required, alphabetic, lower case) |
+ | - commons.componentid (required, alphabetic, lower case) |
| - commons.release.version (required) |
| - commons.release.name (required) |
| - commons.binary.suffix (optional) |
| (defaults to "-bin", set to "" for pre-maven2 releases) |
| - commons.release.desc (optional) |
| - commons.release.subdir (optional) |
+ | - commons.release.hash (optional, lowercase, default sha256) |
| |
- | - commons.release.2/3.version (conditional) |
- | - commons.release.2/3.name (conditional) |
- | - commons.release.2/3.binary.suffix (optional) |
- | - commons.release.2/3.desc (optional) |
- | - commons.release.2/3.subdir (optional) |
+ | - commons.release.[234].version (conditional) |
+ | - commons.release.[234].name (conditional) |
+ | - commons.release.[234].binary.suffix (optional) |
+ | - commons.release.[234].desc (optional) |
+ | - commons.release.[234].subdir (optional) |
+ | - commons.release.[234].hash (optional, lowercase, [sha256])|
| |
| 3) Example Properties |
| (commons.release.name inherited by parent: |
@@ -102,7 +104,7 @@ limitations under the License.
It is essential that you
<a href="https://www.apache.org/info/verification.html">verify the integrity</a>
of downloaded files, preferably using the <code>PGP</code> signature (<code>*.asc</code> files);
- failing that using the <code>MD5</code> hash (<code>*.md5</code> checksum files).
+ failing that using the <code>SHA256</code> hash (<code>*.sha256</code> checksum files).
</p>
<p>
The <a href="https://www.apache.org/dist/commons/KEYS">KEYS</a>
@@ -111,32 +113,32 @@ limitations under the License.
</p>
</subsection>
</section>
- <section name="Apache Commons BCEL 6.2 (Java 7+)">
+ <section name="Apache Commons BCEL 6.3 (Java 8)">
<subsection name="Binaries">
<table>
<tr>
- <td><a href="[preferred]/commons/bcel/binaries/bcel-6.2-bin.tar.gz">bcel-6.2-bin.tar.gz</a></td>
- <td><a href="https://www.apache.org/dist/commons/bcel/binaries/bcel-6.2-bin.tar.gz.md5">md5</a></td>
- <td><a href="https://www.apache.org/dist/commons/bcel/binaries/bcel-6.2-bin.tar.gz.asc">pgp</a></td>
+ <td><a href="[preferred]/commons/bcel/binaries/bcel-6.3-bin.tar.gz">bcel-6.3-bin.tar.gz</a></td>
+ <td><a href="https://www.apache.org/dist/commons/bcel/binaries/bcel-6.3-bin.tar.gz.sha256">sha256</a></td>
+ <td><a href="https://www.apache.org/dist/commons/bcel/binaries/bcel-6.3-bin.tar.gz.asc">pgp</a></td>
</tr>
<tr>
- <td><a href="[preferred]/commons/bcel/binaries/bcel-6.2-bin.zip">bcel-6.2-bin.zip</a></td>
- <td><a href="https://www.apache.org/dist/commons/bcel/binaries/bcel-6.2-bin.zip.md5">md5</a></td>
- <td><a href="https://www.apache.org/dist/commons/bcel/binaries/bcel-6.2-bin.zip.asc">pgp</a></td>
+ <td><a href="[preferred]/commons/bcel/binaries/bcel-6.3-bin.zip">bcel-6.3-bin.zip</a></td>
+ <td><a href="https://www.apache.org/dist/commons/bcel/binaries/bcel-6.3-bin.zip.sha256">sha256</a></td>
+ <td><a href="https://www.apache.org/dist/commons/bcel/binaries/bcel-6.3-bin.zip.asc">pgp</a></td>
</tr>
</table>
</subsection>
<subsection name="Source">
<table>
<tr>
- <td><a href="[preferred]/commons/bcel/source/bcel-6.2-src.tar.gz">bcel-6.2-src.tar.gz</a></td>
- <td><a href="https://www.apache.org/dist/commons/bcel/source/bcel-6.2-src.tar.gz.md5">md5</a></td>
- <td><a href="https://www.apache.org/dist/commons/bcel/source/bcel-6.2-src.tar.gz.asc">pgp</a></td>
+ <td><a href="[preferred]/commons/bcel/source/bcel-6.3-src.tar.gz">bcel-6.3-src.tar.gz</a></td>
+ <td><a href="https://www.apache.org/dist/commons/bcel/source/bcel-6.3-src.tar.gz.sha256">sha256</a></td>
+ <td><a href="https://www.apache.org/dist/commons/bcel/source/bcel-6.3-src.tar.gz.asc">pgp</a></td>
</tr>
<tr>
- <td><a href="[preferred]/commons/bcel/source/bcel-6.2-src.zip">bcel-6.2-src.zip</a></td>
- <td><a href="https://www.apache.org/dist/commons/bcel/source/bcel-6.2-src.zip.md5">md5</a></td>
- <td><a href="https://www.apache.org/dist/commons/bcel/source/bcel-6.2-src.zip.asc">pgp</a></td>
+ <td><a href="[preferred]/commons/bcel/source/bcel-6.3-src.zip">bcel-6.3-src.zip</a></td>
+ <td><a href="https://www.apache.org/dist/commons/bcel/source/bcel-6.3-src.zip.sha256">sha256</a></td>
+ <td><a href="https://www.apache.org/dist/commons/bcel/source/bcel-6.3-src.zip.asc">pgp</a></td>
</tr>
</table>
</subsection>
diff --git a/src/site/xdoc/index.xml b/src/site/xdoc/index.xml
index fd205898..c4471f56 100644
--- a/src/site/xdoc/index.xml
+++ b/src/site/xdoc/index.xml
@@ -61,11 +61,11 @@
<section name="Documentation">
<p>
- The package descriptions in the <a href="javadocs/api-release/index.html">JavaDoc</a> give an overview of the available features
+ The package descriptions in the <a href="javadocs/api-release/index.html">Javadoc</a> give an overview of the available features
and various <a href="project-reports.html">project reports</a> are provided.
</p>
<p>
- The JavaDoc API documents are available online:
+ The Javadoc API documents are available online:
</p>
<ul>
<li>The <a href="apidocs/index.html">current stable release</a></li>
@@ -77,11 +77,11 @@
</section>
<!-- ================================================== -->
<section name="Release Information">
- <p>The latest stable release of BCEL is 6.1. You may: </p>
+ <p>The latest stable release of BCEL is here, you may: </p>
<ul>
- <li>Download <a href="https://commons.apache.org/proper/commons-bcel/download_bcel.cgi">6.1</a></li>
- <li>Read the <a href="https://www.apache.org/dist/commons/bcel/RELEASE-NOTES.txt">6.1 release notes</a></li>
- <li>Inspect the <a href="bcel5-bcel6-clirr-report.html">extended Clirr report</a> comparing 5.2 with 6.0</li>
+ <li><a href="https://commons.apache.org/proper/commons-bcel/download_bcel.cgi">Download</a></li>
+ <li>Read the <a href="https://www.apache.org/dist/commons/bcel/RELEASE-NOTES.txt">release notes</a></li>
+ <li>Inspect the <a href="bcel5-bcel6-clirr-report.html">extended Clirr report</a> comparing 5.2 with 6.x</li>
</ul>
<p>
Alternatively you can pull it from the central Maven repositories:
@@ -89,7 +89,7 @@
&lt;dependency&gt;
&lt;groupId&gt;org.apache.bcel&lt;/groupId&gt;
&lt;artifactId&gt;bcel&lt;/artifactId&gt;
- &lt;version&gt;6.1&lt;/version&gt;
+ &lt;version&gt;6.3&lt;/version&gt;
&lt;/dependency&gt;
</pre>
</p>
diff --git a/src/site/xdoc/issue-tracking.xml b/src/site/xdoc/issue-tracking.xml
index 55b4840c..872f104a 100644
--- a/src/site/xdoc/issue-tracking.xml
+++ b/src/site/xdoc/issue-tracking.xml
@@ -26,7 +26,7 @@ limitations under the License.
| commons-build-plugin/trunk/src/main/resources/commons-xdoc-templates |
+======================================================================+
| |
- | 1) Re-generate using: mvn commons:jira-page |
+ | 1) Re-generate using: mvn commons-build:jira-page |
| |
| 2) Set the following properties in the component's pom: |
| - commons.jira.id (required, alphabetic, upper case) |
diff --git a/src/site/xdoc/mail-lists.xml b/src/site/xdoc/mail-lists.xml
index 0f0aac90..a2381f87 100644
--- a/src/site/xdoc/mail-lists.xml
+++ b/src/site/xdoc/mail-lists.xml
@@ -26,7 +26,7 @@ limitations under the License.
| commons-build-plugin/trunk/src/main/resources/commons-xdoc-templates |
+======================================================================+
| |
- | 1) Re-generate using: mvn commons:mail-page |
+ | 1) Re-generate using: mvn commons-build:mail-page |
| |
| 2) Set the following properties in the component's pom: |
| - commons.componentid (required, alphabetic, lower case) |
diff --git a/src/test/java/org/apache/bcel/generic/JDKGenericDumpTestCase.java b/src/test/java/org/apache/bcel/generic/JdkGenericDumpTestCase.java
index 14ee279e..5e739b91 100644
--- a/src/test/java/org/apache/bcel/generic/JDKGenericDumpTestCase.java
+++ b/src/test/java/org/apache/bcel/generic/JdkGenericDumpTestCase.java
@@ -23,10 +23,20 @@ import static org.junit.Assert.fail;
import java.io.File;
import java.io.FileFilter;
+import java.io.IOException;
import java.io.InputStream;
+import java.nio.file.FileSystems;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.PathMatcher;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@@ -35,8 +45,12 @@ import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.Code;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
+import org.apache.bcel.util.ModularRuntimeImage;
+import org.apache.commons.lang3.JavaVersion;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
+import org.junit.Assert;
+import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -49,7 +63,46 @@ import com.sun.jna.platform.win32.Advapi32Util;
* the instructions. The output bytes should be the same as the input.
*/
@RunWith(Parameterized.class)
-public class JDKGenericDumpTestCase {
+public class JdkGenericDumpTestCase {
+
+ private static class ClassParserFilesVisitor extends SimpleFileVisitor<Path> {
+
+ private final PathMatcher matcher;
+
+ ClassParserFilesVisitor(final String pattern) {
+ matcher = FileSystems.getDefault().getPathMatcher("glob:" + pattern);
+ }
+
+ private void find(final Path path) throws IOException {
+ final Path name = path.getFileName();
+ if (name != null && matcher.matches(name)) {
+ try (final InputStream inputStream = Files.newInputStream(path)) {
+ final ClassParser parser = new ClassParser(inputStream, name.toAbsolutePath().toString());
+ final JavaClass jc = parser.parse();
+ Assert.assertNotNull(jc);
+ }
+
+ }
+ }
+
+ @Override
+ public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) throws IOException {
+ find(dir);
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
+ find(file);
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFileFailed(final Path file, final IOException e) {
+ System.err.println(e);
+ return FileVisitResult.CONTINUE;
+ }
+ }
private static final char[] hexArray = "0123456789ABCDEF".toCharArray();
@@ -62,7 +115,9 @@ public class JDKGenericDumpTestCase {
private static final String KEY_JRE_9 = "SOFTWARE\\JavaSoft\\JRE";
private static void addAllJavaHomesOnWindows(final String keyJre, final Set<String> javaHomes) {
- javaHomes.addAll(findJavaHomesOnWindows(keyJre, Advapi32Util.registryGetKeys(HKEY_LOCAL_MACHINE, keyJre)));
+ if (Advapi32Util.registryKeyExists(HKEY_LOCAL_MACHINE, keyJre)) {
+ javaHomes.addAll(findJavaHomesOnWindows(keyJre, Advapi32Util.registryGetKeys(HKEY_LOCAL_MACHINE, keyJre)));
+ }
}
private static String bytesToHex(final byte[] bytes) {
@@ -97,10 +152,21 @@ public class JDKGenericDumpTestCase {
addAllJavaHomesOnWindows(KEY_JRE_9, javaHomes);
addAllJavaHomesOnWindows(KEY_JDK, javaHomes);
addAllJavaHomesOnWindows(KEY_JDK_9, javaHomes);
+ addAllJavaHomes("ExtraJavaHomes", javaHomes);
return javaHomes;
}
- private static Set<String> findJavaHomesOnWindows(final String keyJavaHome, final String[] keys) {
+ private static void addAllJavaHomes(String extraJavaHomesProp, Set<String> javaHomes) {
+ String path = System.getProperty(extraJavaHomesProp);
+ if (StringUtils.isEmpty(path)) {
+ return;
+ }
+ String[] paths = path.split(File.pathSeparator);
+ javaHomes.addAll(Arrays.asList(paths));
+
+ }
+
+ private static Set<String> findJavaHomesOnWindows(final String keyJavaHome, final String[] keys) {
final Set<String> javaHomes = new HashSet<>(keys.length);
for (final String key : keys) {
if (Advapi32Util.registryKeyExists(HKEY_LOCAL_MACHINE, keyJavaHome + "\\" + key)) {
@@ -118,7 +184,7 @@ public class JDKGenericDumpTestCase {
private final String javaHome;
- public JDKGenericDumpTestCase(final String javaHome) {
+ public JdkGenericDumpTestCase(final String javaHome) {
this.javaHome = javaHome;
}
@@ -144,7 +210,7 @@ public class JDKGenericDumpTestCase {
}
}
- private File[] listJDKjars() throws Exception {
+ private File[] listJdkJars() throws Exception {
final File javaLib = new File(javaHome, "lib");
return javaLib.listFiles(new FileFilter() {
@Override
@@ -154,6 +220,16 @@ public class JDKGenericDumpTestCase {
});
}
+ private File[] listJdkModules() throws Exception {
+ final File javaLib = new File(javaHome, "jmods");
+ return javaLib.listFiles(new FileFilter() {
+ @Override
+ public boolean accept(final File file) {
+ return file.getName().endsWith(".jmod");
+ }
+ });
+ }
+
private void testJar(final File file) throws Exception {
System.out.println(file);
try (JarFile jar = new JarFile(file)) {
@@ -176,12 +252,35 @@ public class JDKGenericDumpTestCase {
}
@Test
- public void testJDKjars() throws Exception {
- final File[] jars = listJDKjars();
+ public void testJdkJars() throws Exception {
+ final File[] jars = listJdkJars();
if (jars != null) {
for (final File file : jars) {
testJar(file);
}
}
}
+
+ @Test
+ public void testJdkModules() throws Exception {
+ final File[] jmods = listJdkModules();
+ if (jmods != null) {
+ for (final File file : jmods) {
+ testJar(file);
+ }
+ }
+ }
+
+ @Test
+ public void testJreModules() throws Exception {
+ Assume.assumeTrue(SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_9));
+ try (final ModularRuntimeImage mri = new ModularRuntimeImage(javaHome)) {
+ final List<Path> modules = mri.modules();
+ Assert.assertFalse(modules.isEmpty());
+ for (final Path path : modules) {
+ Files.walkFileTree(path, new ClassParserFilesVisitor("*.class"));
+ }
+ }
+ }
+
}
diff --git a/src/test/java/org/apache/bcel/util/ClassPathTestCase.java b/src/test/java/org/apache/bcel/util/ClassPathTestCase.java
new file mode 100644
index 00000000..0e8057d8
--- /dev/null
+++ b/src/test/java/org/apache/bcel/util/ClassPathTestCase.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.bcel.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.bcel.AbstractTestCase;
+import org.junit.Assert;
+
+public class ClassPathTestCase extends AbstractTestCase {
+
+ public void testGetClassFile() throws IOException {
+ Assert.assertNotNull(ClassPath.SYSTEM_CLASS_PATH.getClassFile("java.lang.String"));
+ }
+
+ public void testGetResource() throws IOException {
+ Assert.assertNotNull(ClassPath.SYSTEM_CLASS_PATH.getResource("java/lang/String.class"));
+ }
+
+ public void testGetResourceAsStream() throws IOException {
+ try (final InputStream inputStream = ClassPath.SYSTEM_CLASS_PATH
+ .getResourceAsStream("java/lang/String.class")) {
+ Assert.assertNotNull(inputStream);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/test/java/org/apache/bcel/util/ModularRuntimeImageTestCase.java b/src/test/java/org/apache/bcel/util/ModularRuntimeImageTestCase.java
new file mode 100644
index 00000000..33dc6da8
--- /dev/null
+++ b/src/test/java/org/apache/bcel/util/ModularRuntimeImageTestCase.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.bcel.util;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.bcel.generic.JdkGenericDumpTestCase;
+import org.apache.commons.lang3.JavaVersion;
+import org.apache.commons.lang3.SystemUtils;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ * Tests {@link ModularRuntimeImage}.
+ */
+@RunWith(Parameterized.class)
+public class ModularRuntimeImageTestCase {
+
+ @Parameters(name = "{0}")
+ public static Collection<String> data() {
+ return JdkGenericDumpTestCase.data();
+ }
+
+ private final String javaHome;
+ private final ModularRuntimeImage modularRuntimeImage;
+
+ public ModularRuntimeImageTestCase(final String javaHome) throws IOException {
+ this.javaHome = javaHome;
+ Assume.assumeTrue(SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_9));
+ this.modularRuntimeImage = new ModularRuntimeImage(javaHome);
+ }
+
+ @Test
+ public void testListJreModules() throws IOException {
+ final List<Path> listEntries = modularRuntimeImage.list(ModularRuntimeImage.MODULES_PATH);
+ Assert.assertFalse(listEntries.isEmpty());
+ Assert.assertTrue(listEntries.toString().indexOf("/java.base") > -1);
+ }
+
+ @Test
+ public void testListJreModule() throws IOException {
+ final List<Path> listEntries = modularRuntimeImage.list(ModularRuntimeImage.MODULES_PATH + "/java.base");
+ Assert.assertFalse(listEntries.isEmpty());
+ Assert.assertTrue(listEntries.toString().indexOf("/java.base") > -1);
+ }
+
+ @Test
+ public void testListJreModulePackageDir() throws IOException {
+ final List<Path> listEntries = modularRuntimeImage
+ .list(ModularRuntimeImage.MODULES_PATH + "/java.base/java/lang");
+ Assert.assertFalse(listEntries.isEmpty());
+ Assert.assertTrue(listEntries.toString().indexOf("/java.base/java/lang/String.class") > -1);
+ }
+
+ @Test
+ public void testListJrePackages() throws IOException {
+ final List<Path> listEntries = modularRuntimeImage.list(ModularRuntimeImage.PACKAGES_PATH);
+ Assert.assertFalse(listEntries.isEmpty());
+ Assert.assertTrue(listEntries.toString().indexOf("java.lang") > -1);
+ }
+}
diff --git a/src/test/java/org/apache/bcel/visitors/CounterVisitor.java b/src/test/java/org/apache/bcel/visitors/CounterVisitor.java
index 68a03352..3b2a22b7 100644
--- a/src/test/java/org/apache/bcel/visitors/CounterVisitor.java
+++ b/src/test/java/org/apache/bcel/visitors/CounterVisitor.java
@@ -26,6 +26,7 @@ import org.apache.bcel.classfile.Code;
import org.apache.bcel.classfile.CodeException;
import org.apache.bcel.classfile.ConstantClass;
import org.apache.bcel.classfile.ConstantDouble;
+import org.apache.bcel.classfile.ConstantDynamic;
import org.apache.bcel.classfile.ConstantFieldref;
import org.apache.bcel.classfile.ConstantFloat;
import org.apache.bcel.classfile.ConstantInteger;
@@ -159,6 +160,9 @@ public class CounterVisitor implements Visitor
/** @since 6.1 */
public int constantPackageCount = 0;
+
+ /** @since 6.3 */
+ public int constantDynamicCount = 0;
// CHECKSTYLE:ON
@@ -440,4 +444,10 @@ public class CounterVisitor implements Visitor
public void visitConstantModule(final ConstantModule constantModule) {
constantModuleCount++;
}
+
+ /** @since 6.3 */
+ @Override
+ public void visitConstantDynamic(final ConstantDynamic constantDynamic) {
+ constantDynamicCount++;
+ }
}