diff options
author | Sorin Basca <sorinbasca@google.com> | 2024-05-24 08:44:36 +0100 |
---|---|---|
committer | Sorin Basca <sorinbasca@google.com> | 2024-05-24 08:44:36 +0100 |
commit | 72f6971b327429551fb7543bf17e36ef9d8a8343 (patch) | |
tree | 62fa812797c731460c4accaea211e0212fcddb33 | |
parent | 76d2a11286542b37dcc583942b23abbd69efca2e (diff) | |
parent | 3ba11f51e948be042a593ffe919727be68e67de7 (diff) | |
download | apache-commons-bcel-master.tar.gz |
Generated by merging to commit 3ba11f51 from
aosp/upstream-master.
Bug: 335612268
Test: TreeHugger
Change-Id: I3b36fe5a6de9b40dcb4c35e611a9403e5c5e340e
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
@@ -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/). @@ -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 @@ -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 @@ <dependency> <groupId>org.apache.bcel</groupId> <artifactId>bcel</artifactId> - <version>6.1</version> + <version>6.3</version> </dependency> </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++; + } } |