Skip to content

Commit

Permalink
8243596: ModuleLayer::parents should return an unmodifiable list
Browse files Browse the repository at this point in the history
Reviewed-by: mchung
  • Loading branch information
Alan Bateman committed May 7, 2020
1 parent 93b0516 commit f6dda95
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 30 deletions.
17 changes: 8 additions & 9 deletions src/java.base/share/classes/java/lang/ModuleLayer.java
@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -489,7 +489,7 @@ public static Controller defineModulesWithOneLoader(Configuration cf,
List<ModuleLayer> parentLayers, List<ModuleLayer> parentLayers,
ClassLoader parentLoader) ClassLoader parentLoader)
{ {
List<ModuleLayer> parents = new ArrayList<>(parentLayers); List<ModuleLayer> parents = List.copyOf(parentLayers);
checkConfiguration(cf, parents); checkConfiguration(cf, parents);


checkCreateClassLoaderPermission(); checkCreateClassLoaderPermission();
Expand Down Expand Up @@ -565,7 +565,7 @@ public static Controller defineModulesWithManyLoaders(Configuration cf,
List<ModuleLayer> parentLayers, List<ModuleLayer> parentLayers,
ClassLoader parentLoader) ClassLoader parentLoader)
{ {
List<ModuleLayer> parents = new ArrayList<>(parentLayers); List<ModuleLayer> parents = List.copyOf(parentLayers);
checkConfiguration(cf, parents); checkConfiguration(cf, parents);


checkCreateClassLoaderPermission(); checkCreateClassLoaderPermission();
Expand Down Expand Up @@ -649,7 +649,7 @@ public static Controller defineModules(Configuration cf,
List<ModuleLayer> parentLayers, List<ModuleLayer> parentLayers,
Function<String, ClassLoader> clf) Function<String, ClassLoader> clf)
{ {
List<ModuleLayer> parents = new ArrayList<>(parentLayers); List<ModuleLayer> parents = List.copyOf(parentLayers);
checkConfiguration(cf, parents); checkConfiguration(cf, parents);
Objects.requireNonNull(clf); Objects.requireNonNull(clf);


Expand Down Expand Up @@ -752,13 +752,12 @@ public Configuration configuration() {
return cf; return cf;
} }



/** /**
* Returns the list of this layer's parents unless this is the * Returns an unmodifiable list of this layer's parents, in search
* {@linkplain #empty empty layer}, which has no parents and so an * order. If this is the {@linkplain #empty() empty layer} then an
* empty list is returned. * empty list is returned.
* *
* @return The list of this layer's parents * @return A possibly-empty unmodifiable list of this layer's parents
*/ */
public List<ModuleLayer> parents() { public List<ModuleLayer> parents() {
return parents; return parents;
Expand Down Expand Up @@ -803,7 +802,7 @@ Stream<ModuleLayer> layers() {
private volatile List<ModuleLayer> allLayers; private volatile List<ModuleLayer> allLayers;


/** /**
* Returns the set of the modules in this layer. * Returns an unmodifiable set of the modules in this layer.
* *
* @return A possibly-empty unmodifiable set of the modules in this layer * @return A possibly-empty unmodifiable set of the modules in this layer
*/ */
Expand Down
@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -509,7 +509,7 @@ public static Configuration empty() {


/** /**
* Returns an unmodifiable list of this configuration's parents, in search * Returns an unmodifiable list of this configuration's parents, in search
* order. If this is the {@linkplain #empty empty configuration} then an * order. If this is the {@linkplain #empty() empty configuration} then an
* empty list is returned. * empty list is returned.
* *
* @return A possibly-empty unmodifiable list of this parent configurations * @return A possibly-empty unmodifiable list of this parent configurations
Expand All @@ -520,7 +520,7 @@ public List<Configuration> parents() {




/** /**
* Returns an immutable set of the resolved modules in this configuration. * Returns an unmodifiable set of the resolved modules in this configuration.
* *
* @return A possibly-empty unmodifiable set of the resolved modules * @return A possibly-empty unmodifiable set of the resolved modules
* in this configuration * in this configuration
Expand Down
46 changes: 40 additions & 6 deletions test/jdk/java/lang/ModuleLayer/BasicLayerTest.java
@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -1195,14 +1195,48 @@ public void testFindLoaderWithNull() {
} }




// immutable sets // unmodifiable collections


@Test(expectedExceptions = { UnsupportedOperationException.class }) @DataProvider(name = "layers")
public void testImmutableSet() { public Object[][] layers() {
Module base = Object.class.getModule(); Configuration cf = resolve(ModuleFinder.of());
ModuleLayer.boot().modules().add(base); ModuleLayer layer1 = ModuleLayer.empty().defineModulesWithOneLoader(cf, null);
ModuleLayer layer2 = ModuleLayer.empty().defineModulesWithManyLoaders(cf, null);
ModuleLayer layer3 = ModuleLayer.empty().defineModules(cf, mn -> null);

// empty, boot, and custom layers
return new Object[][] {
{ ModuleLayer.empty(), null },
{ ModuleLayer.boot(), null },
{ layer1, null },
{ layer2, null },
{ layer3, null },
};
} }


@Test(dataProvider = "layers",
expectedExceptions = { UnsupportedOperationException.class })
public void testUnmodifiableParents1(ModuleLayer layer, Object ignore) {
layer.parents().add(ModuleLayer.empty());
}

@Test(dataProvider = "layers",
expectedExceptions = { UnsupportedOperationException.class })
public void testUnmodifiableParents2(ModuleLayer layer, Object ignore) {
layer.parents().remove(ModuleLayer.empty());
}

@Test(dataProvider = "layers",
expectedExceptions = { UnsupportedOperationException.class })
public void testUnmodifiableModules1(ModuleLayer layer, Object ignore) {
layer.modules().add(Object.class.getModule());
}

@Test(dataProvider = "layers",
expectedExceptions = { UnsupportedOperationException.class })
public void testUnmodifiableModules2(ModuleLayer layer, Object ignore) {
layer.modules().remove(Object.class.getModule());
}


/** /**
* Resolve the given modules, by name, and returns the resulting * Resolve the given modules, by name, and returns the resulting
Expand Down
51 changes: 39 additions & 12 deletions test/jdk/java/lang/module/ConfigurationTest.java
@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -2033,22 +2033,49 @@ public void testFindModuleWithNull() {
Configuration.empty().findModule(null); Configuration.empty().findModule(null);
} }


// immutable sets // unmodifiable collections


@Test(expectedExceptions = { UnsupportedOperationException.class }) @DataProvider(name = "configurations")
public void testImmutableSet1() { public Object[][] configurations() {
Configuration cf = ModuleLayer.boot().configuration(); // empty, boot, and custom configurations
ResolvedModule base = cf.findModule("java.base").get(); return new Object[][] {
cf.modules().add(base); { Configuration.empty(), null },
{ ModuleLayer.boot().configuration(), null },
{ resolve(ModuleFinder.of()), null },
};
} }


@Test(expectedExceptions = { UnsupportedOperationException.class }) @Test(dataProvider = "configurations",
public void testImmutableSet2() { expectedExceptions = { UnsupportedOperationException.class })
Configuration cf = ModuleLayer.boot().configuration(); public void testUnmodifiableParents1(Configuration cf, Object ignore) {
ResolvedModule base = cf.findModule("java.base").get(); cf.parents().add(Configuration.empty());
base.reads().add(base);
} }


@Test(dataProvider = "configurations",
expectedExceptions = { UnsupportedOperationException.class })
public void testUnmodifiableParents2(Configuration cf, Object ignore) {
cf.parents().remove(Configuration.empty());
}

@Test(dataProvider = "configurations",
expectedExceptions = { UnsupportedOperationException.class })
public void testUnmodifiableModules1(Configuration cf, Object ignore) {
ResolvedModule module = ModuleLayer.boot()
.configuration()
.findModule("java.base")
.orElseThrow();
cf.modules().add(module);
}

@Test(dataProvider = "configurations",
expectedExceptions = { UnsupportedOperationException.class })
public void testUnmodifiableModules2(Configuration cf, Object ignore) {
ResolvedModule module = ModuleLayer.boot()
.configuration()
.findModule("java.base")
.orElseThrow();
cf.modules().remove(module);
}


/** /**
* Invokes parent.resolve(...) * Invokes parent.resolve(...)
Expand Down

0 comments on commit f6dda95

Please sign in to comment.