diff --git a/.gitignore b/.gitignore index 11a721777fdd7..940d90fcccc71 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ .project target node_modules +.settings + diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/Exports.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/Exports.java index a981bbde293b0..791ed56f87555 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/Exports.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/Exports.java @@ -15,10 +15,14 @@ package com.microsoft.windowsazure.services.media; import com.microsoft.windowsazure.services.core.Builder; +import com.microsoft.windowsazure.services.media.implementation.MediaExceptionProcessor; +import com.microsoft.windowsazure.services.media.implementation.MediaRestProxy; import com.microsoft.windowsazure.services.media.implementation.OAuthContract; import com.microsoft.windowsazure.services.media.implementation.OAuthFilter; import com.microsoft.windowsazure.services.media.implementation.OAuthRestProxy; import com.microsoft.windowsazure.services.media.implementation.OAuthTokenManager; +import com.microsoft.windowsazure.services.media.implementation.RedirectFilter; +import com.microsoft.windowsazure.services.media.implementation.ResourceLocationManager; public class Exports implements Builder.Exports { @@ -27,9 +31,14 @@ public class Exports implements Builder.Exports { */ @Override public void register(Builder.Registry registry) { + registry.add(MediaContract.class, MediaExceptionProcessor.class); + registry.add(MediaExceptionProcessor.class); + registry.add(MediaRestProxy.class); registry.add(OAuthContract.class, OAuthRestProxy.class); registry.add(OAuthTokenManager.class); registry.add(OAuthFilter.class); + registry.add(ResourceLocationManager.class); + registry.add(RedirectFilter.class); } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/MediaConfiguration.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/MediaConfiguration.java index 0c4c703fb1dd7..ac7464c570018 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/MediaConfiguration.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/MediaConfiguration.java @@ -17,7 +17,7 @@ import com.microsoft.windowsazure.services.core.Configuration; /** - * Provides functionality to create a service bus configuration. + * Provides functionality to create a media services configuration. * */ public class MediaConfiguration { diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/MediaContract.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/MediaContract.java new file mode 100644 index 0000000000000..3e92ac300dae0 --- /dev/null +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/MediaContract.java @@ -0,0 +1,28 @@ +/** + * Copyright 2011 Microsoft Corporation + * + * Licensed 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 com.microsoft.windowsazure.services.media; + +import com.microsoft.windowsazure.services.core.FilterableService; + +/** + * + * Defines the methods available for Windows Azure Media Services + * + */ +public interface MediaContract extends FilterableService { + + // Will fill in as we implement the various Media Services entities + +} diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/MediaService.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/MediaService.java new file mode 100644 index 0000000000000..413dae44c8d41 --- /dev/null +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/MediaService.java @@ -0,0 +1,67 @@ +/** + * Copyright 2011 Microsoft Corporation + * + * Licensed 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 com.microsoft.windowsazure.services.media; + +import com.microsoft.windowsazure.services.core.Configuration; + +/** + * + * Access media services functionality. This class cannot + * be instantiated. + * + */ +public class MediaService { + + private MediaService() { + } + + /** + * Creates an instance of the MediaServicesContract API. + * + */ + public static MediaContract create() { + return Configuration.getInstance().create(MediaContract.class); + } + + /** + * Creates an instance of the MediaServicesContract API using the specified configuration. + * + * @param config + * A Configuration object that represents the configuration for the service bus service. + * + */ + public static MediaContract create(Configuration config) { + return config.create(MediaContract.class); + } + + /** + * Creates an instance of the MediaServicesContract API. + * + */ + public static MediaContract create(String profile) { + return Configuration.getInstance().create(profile, MediaContract.class); + } + + /** + * Creates an instance of the MediaServicesContract API using the specified configuration. + * + * @param config + * A Configuration object that represents the configuration for the service bus service. + * + */ + public static MediaContract create(String profile, Configuration config) { + return config.create(profile, MediaContract.class); + } +} diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/MediaExceptionProcessor.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/MediaExceptionProcessor.java new file mode 100644 index 0000000000000..d9c3141d52064 --- /dev/null +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/MediaExceptionProcessor.java @@ -0,0 +1,57 @@ +/** + * Copyright 2011 Microsoft Corporation + * + * Licensed 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 com.microsoft.windowsazure.services.media.implementation; + +import javax.inject.Inject; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.microsoft.windowsazure.services.core.ServiceException; +import com.microsoft.windowsazure.services.core.ServiceFilter; +import com.microsoft.windowsazure.services.core.utils.ServiceExceptionFactory; +import com.microsoft.windowsazure.services.media.MediaContract; + +/** + * Wrapper implementation of MediaServicesContract that + * translates exceptions into ServiceExceptions. + * + */ +public class MediaExceptionProcessor implements MediaContract { + + private final MediaContract next; + static Log log = LogFactory.getLog(MediaContract.class); + + public MediaExceptionProcessor(MediaContract next) { + this.next = next; + } + + @Inject + public MediaExceptionProcessor(MediaRestProxy next) { + this.next = next; + } + + @Override + public MediaContract withFilter(ServiceFilter filter) { + return new MediaExceptionProcessor(next.withFilter(filter)); + } + + private ServiceException processCatch(ServiceException e) { + log.warn(e.getMessage(), e.getCause()); + return ServiceExceptionFactory.process("MediaServices", e); + } + +} diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/MediaRestProxy.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/MediaRestProxy.java new file mode 100644 index 0000000000000..9b1dfc25e5a60 --- /dev/null +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/MediaRestProxy.java @@ -0,0 +1,74 @@ +/** + * Copyright 2011 Microsoft Corporation + * + * Licensed 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 com.microsoft.windowsazure.services.media.implementation; + +import java.util.Arrays; + +import javax.inject.Inject; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.microsoft.windowsazure.services.core.ServiceFilter; +import com.microsoft.windowsazure.services.core.utils.pipeline.ClientFilterAdapter; +import com.microsoft.windowsazure.services.media.MediaContract; +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.WebResource; + +public class MediaRestProxy implements MediaContract { + + private Client channel; + static Log log = LogFactory.getLog(MediaContract.class); + + ServiceFilter[] filters; + + @Inject + public MediaRestProxy(Client channel, OAuthFilter authFilter, RedirectFilter redirectFilter) { + this.channel = channel; + this.filters = new ServiceFilter[0]; + channel.addFilter(redirectFilter); + channel.addFilter(authFilter); + } + + public MediaRestProxy(Client channel, ServiceFilter[] filters) { + this.channel = channel; + this.filters = filters; + } + + @Override + public MediaContract withFilter(ServiceFilter filter) { + ServiceFilter[] newFilters = Arrays.copyOf(filters, filters.length + 1); + newFilters[filters.length] = filter; + return new MediaRestProxy(channel, newFilters); + } + + public Client getChannel() { + return channel; + } + + public void setChannel(Client channel) { + this.channel = channel; + } + + private WebResource getResource(String entityName) { + WebResource resource = getChannel().resource(entityName); + for (ServiceFilter filter : filters) { + resource.addFilter(new ClientFilterAdapter(filter)); + } + return resource; + } + +} diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthTokenManager.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthTokenManager.java index 9a5ffcf59afb3..473bd9d60bb60 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthTokenManager.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthTokenManager.java @@ -19,10 +19,12 @@ import java.net.URISyntaxException; import java.util.Date; +import javax.inject.Named; import javax.management.timer.Timer; import com.microsoft.windowsazure.services.core.ServiceException; import com.microsoft.windowsazure.services.core.utils.DateFactory; +import com.microsoft.windowsazure.services.media.MediaConfiguration; /** * An OAuth token manager class. @@ -59,8 +61,11 @@ public class OAuthTokenManager { * A String object instance that represents the client secret. * */ - public OAuthTokenManager(OAuthContract contract, DateFactory dateFactory, URI acsBaseUri, String clientId, - String clientSecret, String scope) { + public OAuthTokenManager(OAuthContract contract, DateFactory dateFactory, + @Named(MediaConfiguration.OAUTH_URI) URI acsBaseUri, + @Named(MediaConfiguration.OAUTH_CLIENT_ID) String clientId, + @Named(MediaConfiguration.OAUTH_CLIENT_SECRET) String clientSecret, + @Named(MediaConfiguration.OAUTH_SCOPE) String scope) { this.contract = contract; this.dateFactory = dateFactory; this.acsBaseUri = acsBaseUri; diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/ResourceLocationManager.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/ResourceLocationManager.java index 773b6c27847d1..75b5c12ad6dc6 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/ResourceLocationManager.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/ResourceLocationManager.java @@ -18,12 +18,15 @@ import java.net.URI; import java.net.URISyntaxException; +import javax.inject.Named; import javax.ws.rs.core.UriBuilder; +import com.microsoft.windowsazure.services.media.MediaConfiguration; + public class ResourceLocationManager { private URI baseURI; - public ResourceLocationManager(String baseUri) throws URISyntaxException { + public ResourceLocationManager(@Named(MediaConfiguration.URI) String baseUri) throws URISyntaxException { this.baseURI = new URI(baseUri); } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/models/AccessPolicyPermission.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/models/AccessPolicyPermission.java new file mode 100644 index 0000000000000..a1abc4a25587b --- /dev/null +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/models/AccessPolicyPermission.java @@ -0,0 +1,79 @@ +/** + * Copyright 2011 Microsoft Corporation + * + * Licensed 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 com.microsoft.windowsazure.services.media.models; + +import java.util.EnumSet; + +/** + * Permissions available to an access policy + * + */ +public enum AccessPolicyPermission { + NONE(0), READ(1), WRITE(2), DELETE(4), LIST(8); + + private int flagValue; + + private AccessPolicyPermission(int value) { + flagValue = value; + } + + /** + * Get the flag bit value associated with this permission + * + * @return The integer permission value + */ + public int getFlagValue() { + return flagValue; + } + + /** + * Given an integer representing the permissions as a bit vector, + * convert it into an EnumSet<AccessPolicyPermission> object containing the correct permissions + * * + * + * @param bits + * The bit vector of permissions + * @return The set of permissions in an EnumSet object. + */ + public static EnumSet permissionsFromBits(int bits) { + EnumSet perms = EnumSet.of(AccessPolicyPermission.NONE); + + for (AccessPolicyPermission p : AccessPolicyPermission.values()) { + if ((bits & p.getFlagValue()) != 0) { + perms.remove(AccessPolicyPermission.NONE); + perms.add(p); + } + } + + return perms; + } + + /** + * Convert an EnumSet containing permissions into the + * corresponding integer bit vector to be passed to Media services. + * + * @param perms + * The permissions + * @return The bit vector to go out over the wire. + */ + public static int bitsFromPermissions(EnumSet perms) { + int result = 0; + for (AccessPolicyPermission p : perms) { + result |= p.getFlagValue(); + } + + return result; + } +} diff --git a/microsoft-azure-api/src/main/resources/META-INF/services/com.microsoft.windowsazure.services.core.Builder$Exports b/microsoft-azure-api/src/main/resources/META-INF/services/com.microsoft.windowsazure.services.core.Builder$Exports index 07fdb1c4e7b67..e49188d4c09af 100644 --- a/microsoft-azure-api/src/main/resources/META-INF/services/com.microsoft.windowsazure.services.core.Builder$Exports +++ b/microsoft-azure-api/src/main/resources/META-INF/services/com.microsoft.windowsazure.services.core.Builder$Exports @@ -5,3 +5,5 @@ com.microsoft.windowsazure.services.serviceBus.Exports com.microsoft.windowsazure.services.serviceBus.implementation.Exports com.microsoft.windowsazure.services.core.utils.Exports com.microsoft.windowsazure.services.core.utils.pipeline.Exports +com.microsoft.windowsazure.services.media.Exports + diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/ExportsTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/ExportsTest.java new file mode 100644 index 0000000000000..c21063c48e261 --- /dev/null +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/ExportsTest.java @@ -0,0 +1,32 @@ +package com.microsoft.windowsazure.services.media; + +import static org.junit.Assert.*; + +import java.net.URI; + +import org.junit.Test; + +import com.microsoft.windowsazure.services.media.implementation.RedirectFilter; +import com.microsoft.windowsazure.services.media.implementation.ResourceLocationManager; + +/** + * Tests to verify the items exported from media services + * can be resolved from configuration. + * + */ +public class ExportsTest extends IntegrationTestBase { + + @Test + public void canResolveLocationManagerFromConfig() throws Exception { + ResourceLocationManager rlm = config.create(ResourceLocationManager.class); + URI rootUri = new URI((String) config.getProperty(MediaConfiguration.URI)); + + assertEquals(rootUri, rlm.getBaseURI()); + } + + @Test + public void canResolveRedirectFilterFromConfig() throws Exception { + RedirectFilter filter = config.create(RedirectFilter.class); + assertNotNull(filter); + } +} diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/IntegrationTestBase.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/IntegrationTestBase.java new file mode 100644 index 0000000000000..113d1ff2b2c50 --- /dev/null +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/IntegrationTestBase.java @@ -0,0 +1,26 @@ +package com.microsoft.windowsazure.services.media; + +import org.junit.Before; + +import com.microsoft.windowsazure.services.core.Configuration; + +public abstract class IntegrationTestBase { + protected Configuration config; + + @Before + public void beforeEachTest() { + config = Configuration.getInstance(); + overrideWithEnv(config, MediaConfiguration.URI); + overrideWithEnv(config, MediaConfiguration.OAUTH_URI); + overrideWithEnv(config, MediaConfiguration.OAUTH_CLIENT_ID); + overrideWithEnv(config, MediaConfiguration.OAUTH_CLIENT_SECRET); + } + + protected static void overrideWithEnv(Configuration config, String key) { + String value = System.getenv(key); + if (value == null) + return; + + config.setProperty(key, value); + } +} diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/implementation/OAuthRestProxyIntegrationTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/implementation/OAuthRestProxyIntegrationTest.java index da1153cae4015..13bede0a0db30 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/implementation/OAuthRestProxyIntegrationTest.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/implementation/OAuthRestProxyIntegrationTest.java @@ -20,18 +20,14 @@ import org.junit.Test; -import com.microsoft.windowsazure.services.core.Configuration; +import com.microsoft.windowsazure.services.media.IntegrationTestBase; import com.microsoft.windowsazure.services.media.MediaConfiguration; import com.sun.jersey.api.client.Client; -public class OAuthRestProxyIntegrationTest { +public class OAuthRestProxyIntegrationTest extends IntegrationTestBase { @Test public void serviceCanBeCalledToCreateAccessToken() throws Exception { // Arrange - Configuration config = Configuration.getInstance(); - overrideWithEnv(config, MediaConfiguration.OAUTH_URI); - overrideWithEnv(config, MediaConfiguration.OAUTH_CLIENT_ID); - overrideWithEnv(config, MediaConfiguration.OAUTH_CLIENT_SECRET); OAuthContract oAuthContract = new OAuthRestProxy(config.create(Client.class)); // Act @@ -45,12 +41,4 @@ public void serviceCanBeCalledToCreateAccessToken() throws Exception { assertNotNull(result); assertNotNull(result.getAccessToken()); } - - private static void overrideWithEnv(Configuration config, String key) { - String value = System.getenv(key); - if (value == null) - return; - - config.setProperty(key, value); - } } diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/models/AccessPolicyPermissionTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/models/AccessPolicyPermissionTest.java new file mode 100644 index 0000000000000..2ff5a68665294 --- /dev/null +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/models/AccessPolicyPermissionTest.java @@ -0,0 +1,79 @@ +package com.microsoft.windowsazure.services.media.models; + +import static org.junit.Assert.*; + +import java.util.EnumSet; + +import org.junit.Test; + +public class AccessPolicyPermissionTest { + + @Test + public void testGetFlagValue() { + assertEquals(0, AccessPolicyPermission.NONE.getFlagValue()); + assertEquals(1, AccessPolicyPermission.READ.getFlagValue()); + assertEquals(2, AccessPolicyPermission.WRITE.getFlagValue()); + assertEquals(4, AccessPolicyPermission.DELETE.getFlagValue()); + assertEquals(8, AccessPolicyPermission.LIST.getFlagValue()); + } + + @Test + public void testZeroResultsInNonePermission() { + EnumSet perms = AccessPolicyPermission.permissionsFromBits(0); + assertTrue(perms.contains(AccessPolicyPermission.NONE)); + } + + @Test + public void testAllBitsSetResultsInAllPermissions() { + EnumSet perms = AccessPolicyPermission.permissionsFromBits(1 + 2 + 4 + 8); + + assertFalse(perms.contains(AccessPolicyPermission.NONE)); + assertTrue(perms.contains(AccessPolicyPermission.READ)); + assertTrue(perms.contains(AccessPolicyPermission.WRITE)); + assertTrue(perms.contains(AccessPolicyPermission.DELETE)); + assertTrue(perms.contains(AccessPolicyPermission.LIST)); + } + + @Test + public void testWriteBitsResultsInOnlyWritePermissions() { + EnumSet perms = AccessPolicyPermission.permissionsFromBits(2); + + assertFalse(perms.contains(AccessPolicyPermission.NONE)); + assertFalse(perms.contains(AccessPolicyPermission.READ)); + assertTrue(perms.contains(AccessPolicyPermission.WRITE)); + assertFalse(perms.contains(AccessPolicyPermission.DELETE)); + assertFalse(perms.contains(AccessPolicyPermission.LIST)); + } + + @Test + public void testEmptyPermissionsResultsInZeroBits() { + EnumSet perms = EnumSet.noneOf(AccessPolicyPermission.class); + int bits = AccessPolicyPermission.bitsFromPermissions(perms); + + assertEquals(0, bits); + } + + @Test + public void allPermissionsInSetResultsInCorrectValue() { + EnumSet perms = EnumSet.of(AccessPolicyPermission.READ, AccessPolicyPermission.WRITE, + AccessPolicyPermission.DELETE, AccessPolicyPermission.LIST, AccessPolicyPermission.NONE); + int bits = AccessPolicyPermission.bitsFromPermissions(perms); + + assertEquals(1 + 2 + 4 + 8, bits); + } + + @Test + public void writePermissionsInSetResultsInCorrectValue() { + EnumSet perms = EnumSet.of(AccessPolicyPermission.WRITE); + int bits = AccessPolicyPermission.bitsFromPermissions(perms); + + assertEquals(2, bits); + } + + @Test + public void unknownPermissionBitsAreIgnored() { + EnumSet perms = AccessPolicyPermission.permissionsFromBits(16 + 32); + + assertTrue(perms.contains(AccessPolicyPermission.NONE)); + } +}