Skip to content

Commit f0ce436

Browse files
Refactor test and apply suggestions
1 parent 91d82f1 commit f0ce436

File tree

5 files changed

+105
-72
lines changed

5 files changed

+105
-72
lines changed

hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/Constants.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,19 +1363,19 @@ private Constants() {
13631363

13641364

13651365
/**
1366-
* To use the same classloader that loaded S3AFileSystem to al
1367-
* load the user extensions, such as {{fs.s3a.aws.credentials.provider}}.
1366+
* To use the same classloader that loaded S3AFileSystem to load
1367+
* user extensions, such as {{fs.s3a.aws.credentials.provider}}.
13681368
* It is useful to turn this off for Apache Spark applications that
13691369
* might load S3AFileSystem from the Spark distribution (Launcher classloader)
13701370
* while users might want to provide custom extensions (loaded by Spark MutableClassloader).
13711371
* Default value: true.
13721372
*/
1373-
public static final String AWS_S3_EXTENSIONS_ISOLATED_CLASSLOADER =
1374-
"fs.s3a.extensions.isolated.classloader";
1373+
public static final String AWS_S3_CLASSLOADER_ISOLATION =
1374+
"fs.s3a.classloader.isolation";
13751375

13761376

13771377
/**
1378-
* Default value for {{fs.s3a.extensions.isolated.classloader}}.
1378+
* Default value for {{fs.s3a.classloader.isolation}}.
13791379
*/
1380-
public static final boolean DEFAULT_AWS_S3_EXTENSIONS_ISOLATED_CLASSLOADER = true;
1380+
public static final boolean DEFAULT_AWS_S3_CLASSLOADER_ISOLATION = true;
13811381
}

hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AFileSystem.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -718,9 +718,17 @@ public void initialize(URI name, Configuration originalConf)
718718
}
719719
}
720720

721-
void isolateClassloader(Configuration conf, ClassLoader classLoader) {
722-
if (conf.getBoolean(Constants.AWS_S3_EXTENSIONS_ISOLATED_CLASSLOADER,
723-
Constants.DEFAULT_AWS_S3_EXTENSIONS_ISOLATED_CLASSLOADER)) {
721+
/**
722+
* If classloader isolation is {{true}}
723+
* (through {@link Constants#AWS_S3_EXTENSIONS_ISOLATED_CLASSLOADER}) or not
724+
* explicitly set, then the classLoader of the input configuration object
725+
* will be set to the input classloader, otherwise nothing will happen.
726+
* @param conf configuration object.
727+
* @param classLoader isolated classLoader.
728+
*/
729+
private void isolateClassloader(Configuration conf, ClassLoader classLoader) {
730+
if (conf.getBoolean(Constants.AWS_S3_CLASSLOADER_ISOLATION,
731+
Constants.DEFAULT_AWS_S3_CLASSLOADER_ISOLATION)) {
724732
LOG.debug("Configuration classloader set to S3AFileSystem classloader: {}", classLoader);
725733
conf.setClassLoader(classLoader);
726734
} else {

hadoop-tools/hadoop-aws/src/site/markdown/tools/hadoop-aws/index.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,8 @@ This AWS credential provider is enabled in S3A by default.
564564
## Custom AWS Credential Providers and Apache Spark
565565

566566
Apache Spark employs two class loaders, one that loads "distribution" (Spark + Hadoop) classes and one that
567-
loads custom user classes. If the user wants to load custom implementations of AWS Credential Providers
567+
loads custom user classes. If the user wants to load custom implementations of AWS credential providers,
568+
custom signers, delegation token providers or any other dynamically loaded extension class
568569
through user provided jars will need to set the following configuration:
569570

570571
```xml
@@ -579,7 +580,7 @@ through user provided jars will need to set the following configuration:
579580

580581
```
581582

582-
If the following property is not set or set to true, the following exception will be thrown:
583+
If the following property is not set or set to `true`, the following exception will be thrown:
583584

584585
```
585586
java.io.IOException: From option fs.s3a.aws.credentials.provider java.lang.ClassNotFoundException: Class CustomCredentialsProvider not found
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.hadoop.fs.s3a;
20+
21+
import java.io.IOException;
22+
import java.lang.reflect.Constructor;
23+
import java.lang.reflect.InvocationTargetException;
24+
25+
import org.apache.hadoop.conf.Configuration;
26+
import static org.assertj.core.api.Assertions.*;
27+
import org.junit.Test;
28+
29+
public class ITestS3AFileSystemIsolatedClassloader extends AbstractS3ATestBase {
30+
31+
public static class CustomClassLoader extends ClassLoader {
32+
}
33+
34+
private final ClassLoader customClassLoader = new CustomClassLoader();
35+
36+
private <T> T createClass(ClassLoader clsLoader, Class<T> toLoad) {
37+
try {
38+
Class<?> cls = clsLoader.loadClass(toLoad.getCanonicalName());
39+
Constructor<?> constructor = cls.getConstructor();
40+
return (T) constructor.newInstance();
41+
} catch(ClassNotFoundException | InstantiationException | IllegalAccessException |
42+
IllegalArgumentException | InvocationTargetException | NoSuchMethodException |
43+
SecurityException e) {
44+
throw new RuntimeException(e);
45+
}
46+
}
47+
48+
@Test
49+
public void isolatedClassloader() throws IOException {
50+
try (S3AFileSystem fs = getFileSystem()) {
51+
Configuration conf = createClass(customClassLoader, Configuration.class);
52+
assertEquals(fs.getConf().getClassLoader(), customClassLoader);
53+
conf.setBoolean(Constants.AWS_S3_CLASSLOADER_ISOLATION, true);
54+
assertNotEquals(fs.getClass().getClassLoader(), customClassLoader);
55+
fs.initialize(fs.getUri(), conf);
56+
assertEquals(fs.getConf().getClassLoader(), fs.getClass().getClassLoader());
57+
assertNotEquals(fs.getConf().getClassLoader(), customClassLoader);
58+
}
59+
}
60+
61+
@Test
62+
public void isolatedClassloaderDefault() throws IOException {
63+
try (S3AFileSystem fs = getFileSystem()) {
64+
Configuration conf = createClass(customClassLoader, Configuration.class);
65+
assertEquals(fs.getConf().getClassLoader(), customClassLoader);
66+
assertNotEquals(fs.getClass().getClassLoader(), customClassLoader);
67+
fs.initialize(fs.getUri(), conf);
68+
assertEquals(fs.getConf().getClassLoader(), fs.getClass().getClassLoader());
69+
assertNotEquals(fs.getConf().getClassLoader(), customClassLoader);
70+
}
71+
}
72+
73+
@Test
74+
public void notIsolatedClassloader() throws IOException {
75+
try (S3AFileSystem fs = getFileSystem()) {
76+
Configuration conf = createClass(customClassLoader, Configuration.class);
77+
assertEquals(fs.getConf().getClassLoader(), customClassLoader);
78+
conf.setBoolean(Constants.AWS_S3_CLASSLOADER_ISOLATION, false);
79+
assertNotEquals(fs.getClass().getClassLoader(), customClassLoader);
80+
fs.initialize(fs.getUri(), conf);
81+
assertNotEquals(fs.getConf().getClassLoader(), fs.getClass().getClassLoader());
82+
assertEquals(fs.getConf().getClassLoader(), customClassLoader);
83+
}
84+
}
85+
}

hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/TestS3AFileSystemIsolatedClassloader.java

Lines changed: 0 additions & 61 deletions
This file was deleted.

0 commit comments

Comments
 (0)