forked from Azure/azure-sdk-for-java
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Support for Java 9 in Multi-Release JAR for azure-core (Azure#23835)
Add Support for Java 9 in Multi-Release JAR for azure-core
- Loading branch information
1 parent
3108ad8
commit 173670a
Showing
11 changed files
with
224 additions
and
91 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
sdk/core/azure-core/src/main/java/com/azure/core/implementation/ReflectionUtilsApi.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
package com.azure.core.implementation; | ||
|
||
import java.lang.invoke.MethodHandles; | ||
|
||
/** | ||
* API for {@link ReflectionUtils}. | ||
*/ | ||
public interface ReflectionUtilsApi { | ||
ReflectionUtilsApi INSTANCE = new ReflectionUtils(); | ||
|
||
/** | ||
* Gets the {@link MethodHandles.Lookup} to use based on the target {@link Class}. | ||
* | ||
* @param targetClass The target {@link Class}. | ||
* @return The {@link MethodHandles.Lookup} to use. | ||
* @throws Throwable If an error occurs while attempting to find the lookup. | ||
*/ | ||
MethodHandles.Lookup getLookupToUse(Class<?> targetClass) throws Throwable; | ||
|
||
/** | ||
* Gets the Java implementation major version. | ||
* | ||
* @return The Java implementation major version. | ||
*/ | ||
default int getJavaImplementationMajorVersion() { | ||
return 8; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
69 changes: 69 additions & 0 deletions
69
sdk/core/azure-core/src/main/java9/com/azure/core/implementation/ReflectionUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
package com.azure.core.implementation; | ||
|
||
import java.lang.invoke.MethodHandles; | ||
|
||
/** | ||
* Utility methods that aid in performing reflective operations. | ||
*/ | ||
final class ReflectionUtils implements ReflectionUtilsApi { | ||
// This lookup is specific to the com.azure.core module, specifically this class. | ||
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); | ||
|
||
// Convenience pointer to the com.azure.core module. | ||
private static final Module CORE_MODULE = ReflectionUtils.class.getModule(); | ||
|
||
/** | ||
* Gets the {@link MethodHandles.Lookup} to use when performing reflective operations. | ||
* <p> | ||
* If Java 8 is being used this will always return {@link MethodHandles.Lookup#publicLookup()} as Java 8 doesn't | ||
* have module boundaries that will prevent reflective access to the {@code targetClass}. | ||
* <p> | ||
* If Java 9 or above is being used this will return a {@link MethodHandles.Lookup} based on whether the module | ||
* containing the {@code targetClass} exports the package containing the class. Otherwise, the {@link | ||
* MethodHandles.Lookup} associated to {@code com.azure.core} will attempt to read the module containing {@code | ||
* targetClass}. | ||
* | ||
* @param targetClass The {@link Class} that will need to be reflectively accessed. | ||
* @return The {@link MethodHandles.Lookup} that will allow {@code com.azure.core} to access the {@code targetClass} | ||
* reflectively. | ||
* @throws Throwable If the underlying reflective calls throw an exception. | ||
*/ | ||
public MethodHandles.Lookup getLookupToUse(Class<?> targetClass) throws Throwable { | ||
Module responseModule = targetClass.getModule(); | ||
|
||
/* | ||
* First check if the response class's module is exported to all unnamed modules. If it is we will use | ||
* MethodHandles.publicLookup() which is meant for creating MethodHandle instances for publicly accessible | ||
* classes. | ||
*/ | ||
if (responseModule.isExported("")) { | ||
return MethodHandles.publicLookup(); | ||
} | ||
|
||
/* | ||
* Otherwise, we use the MethodHandles.Lookup which is associated to this (com.azure.core) module, and more | ||
* specifically, is tied to this class (ReflectionUtils). But, in order to use this lookup we need to ensure | ||
* that the com.azure.core module reads the response class's module as the lookup won't have permissions | ||
* necessary to create the MethodHandle instance without it. | ||
* | ||
* This logic is safe due to the fact that any SDK module calling into this code path will already need to open | ||
* to com.azure.core as it needs to perform other reflective operations on classes in the module. Adding the | ||
* com.azure.core reads is handling specifically required by MethodHandle. | ||
*/ | ||
if (!CORE_MODULE.canRead(responseModule)) { | ||
CORE_MODULE.addReads(responseModule); | ||
} | ||
|
||
return LOOKUP; | ||
} | ||
|
||
public int getJavaImplementationMajorVersion() { | ||
return 9; | ||
} | ||
|
||
ReflectionUtils() { | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
sdk/core/azure-core/src/main/java9/com/azure/core/implementation/package-info.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
/** | ||
* Package containing implementation-specific APIs that should not be used by end-users. | ||
*/ | ||
package com.azure.core.implementation; |
28 changes: 28 additions & 0 deletions
28
sdk/core/azure-core/src/test/java/com/azure/core/implementation/ReflectionUtilsIT.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
package com.azure.core.implementation; | ||
|
||
import org.junit.jupiter.api.Test; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
|
||
/** | ||
* Integration tests for {@link ReflectionUtils}. | ||
*/ | ||
public class ReflectionUtilsIT { | ||
/* | ||
* This is an integration test instead of a unit test because integration tests use the generated JAR, with | ||
* multi-release support, instead of the class files in Maven's output directory. Given that, the integration tests | ||
* will hook into the different Java version implementations. | ||
*/ | ||
@Test | ||
public void validateImplementationVersion() { | ||
String javaSpecificationVersion = System.getProperty("java.specification.version"); | ||
if (javaSpecificationVersion.equals("1.8")) { | ||
assertEquals(8, ReflectionUtilsApi.INSTANCE.getJavaImplementationMajorVersion()); | ||
} else { | ||
assertEquals(9, ReflectionUtilsApi.INSTANCE.getJavaImplementationMajorVersion()); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.