Index: oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugSecurityProvider.java
===================================================================
--- oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugSecurityProvider.java (revision 1702510)
+++ oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugSecurityProvider.java (working copy)
@@ -33,12 +33,8 @@
composite.setDefaultConfig(authorizationConfiguration);
composite.addConfiguration(new CugConfiguration(this));
composite.addConfiguration(authorizationConfiguration);
- ((CugSecurityProvider) this).bindAuthorizationConfiguration(composite);
+ setAuthorizationConfiguration(composite);
}
}
- @Override
- protected void bindAuthorizationConfiguration(@Nonnull AuthorizationConfiguration reference) {
- super.bindAuthorizationConfiguration(reference);
- }
}
\ No newline at end of file
Index: oak-core/src/main/java/org/apache/jackrabbit/oak/security/Preconditions.java
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/security/Preconditions.java (revision 0)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/security/Preconditions.java (working copy)
@@ -0,0 +1,112 @@
+/*
+ * 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.jackrabbit.oak.security;
+
+import java.util.Set;
+
+import static com.google.common.collect.Sets.newHashSet;
+
+/**
+ * Represents a preconditions set that may be satisfied by adding the right
+ * candidates.
+ *
+ * Initially, a set of preconditions is empty. An empty set of preconditions is
+ * always satisfied. If candidates are added, but the precondition set is empty,
+ * the preconditions are considered satisfied.
+ *
+ * When some preconditions are added, the preconditions set may enter into the
+ * unsatisfied state. In this case, the preconditions set may be come satisfied
+ * again only with the addition of the right candidates.
+ *
+ * This class doesn't admit duplicates for preconditions or candidates. Adding
+ * the same precondition (or candidate) twice doesn't have any effect on the
+ * state of the preconditions set.
+ */
+class Preconditions {
+
+ private final Set preconditions = newHashSet();
+
+ private final Set candidates = newHashSet();
+
+ private boolean dirty = false;
+
+ private boolean satisfied = true;
+
+ /**
+ * Add a precondition to this preconditions set. If the precondition already
+ * belongs to this set, this operation has no effect.
+ *
+ * @param precondition The precondition to be added.
+ */
+ public void addPrecondition(String precondition) {
+ if (preconditions.add(precondition)) {
+ dirty = true;
+ }
+ }
+
+ /**
+ * Remove all the preconditions to this set. This makes the set of
+ * preconditions empty and, as such, satisfied.
+ */
+ public void clearPreconditions() {
+ preconditions.clear();
+ dirty = false;
+ satisfied = true;
+ }
+
+ /**
+ * Add a candidate to this preconditions set. If the candidate already
+ * belongs to this set, this operation has no effect.
+ *
+ * @param candidate The candidate to be added.
+ */
+ public void addCandidate(String candidate) {
+ if (candidates.add(candidate)) {
+ dirty = true;
+ }
+ }
+
+ /**
+ * Remove a candidate from this preconditions set. If the candidate doesn't
+ * belong to this set, this operation has no effect.
+ *
+ * @param candidate The candidate to be removed.
+ */
+ public void removeCandidate(String candidate) {
+ if (candidates.remove(candidate)) {
+ dirty = false;
+ }
+ }
+
+ /**
+ * Check if the preconditions set are satisfied.
+ *
+ * @return {@code true} if the preconditions set is satisfied, {@code false}
+ * otherwise.
+ */
+ public boolean areSatisfied() {
+ if (dirty) {
+ Set unsatisfied = newHashSet(preconditions);
+ unsatisfied.removeAll(candidates);
+ satisfied = unsatisfied.isEmpty();
+ dirty = false;
+ }
+
+ return satisfied;
+ }
+
+}
Property changes on: oak-core/src/main/java/org/apache/jackrabbit/oak/security/Preconditions.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java (revision 1702510)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java (working copy)
@@ -16,118 +16,96 @@
*/
package org.apache.jackrabbit.oak.security;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import com.google.common.collect.ImmutableMap;
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.ReferencePolicy;
-import org.apache.felix.scr.annotations.Service;
-import org.apache.jackrabbit.oak.osgi.OsgiWhiteboard;
import org.apache.jackrabbit.oak.security.authentication.AuthenticationConfigurationImpl;
import org.apache.jackrabbit.oak.security.authentication.token.TokenConfigurationImpl;
import org.apache.jackrabbit.oak.security.authorization.AuthorizationConfigurationImpl;
import org.apache.jackrabbit.oak.security.principal.PrincipalConfigurationImpl;
import org.apache.jackrabbit.oak.security.privilege.PrivilegeConfigurationImpl;
import org.apache.jackrabbit.oak.security.user.UserConfigurationImpl;
-import org.apache.jackrabbit.oak.spi.security.ConfigurationBase;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.SecurityConfiguration;
import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
import org.apache.jackrabbit.oak.spi.security.authentication.AuthenticationConfiguration;
-import org.apache.jackrabbit.oak.spi.security.authentication.token.CompositeTokenConfiguration;
import org.apache.jackrabbit.oak.spi.security.authentication.token.TokenConfiguration;
import org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
-import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants;
-import org.apache.jackrabbit.oak.spi.security.principal.CompositePrincipalConfiguration;
import org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfiguration;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConfiguration;
import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
-import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
-import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardAuthorizableActionProvider;
-import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardAuthorizableNodeName;
import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardAware;
-import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardRestrictionProvider;
-import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUserAuthenticationFactory;
-import org.osgi.framework.BundleContext;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Sets.newHashSet;
-@Component
-@Service(value = {SecurityProvider.class})
public class SecurityProviderImpl implements SecurityProvider, WhiteboardAware {
- @Reference
- private volatile AuthorizationConfiguration authorizationConfiguration;
+ private AuthenticationConfiguration authenticationConfiguration;
- @Reference
- private volatile AuthenticationConfiguration authenticationConfiguration;
+ private AuthorizationConfiguration authorizationConfiguration;
- @Reference
- private volatile PrivilegeConfiguration privilegeConfiguration;
+ private UserConfiguration userConfiguration;
- @Reference
- private volatile UserConfiguration userConfiguration;
+ private PrincipalConfiguration principalConfiguration;
- @Reference(referenceInterface = PrincipalConfiguration.class,
- name = "principalConfiguration",
- bind = "bindPrincipalConfiguration",
- unbind = "unbindPrincipalConfiguration",
- policy = ReferencePolicy.DYNAMIC,
- cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE)
- private final CompositePrincipalConfiguration principalConfiguration = new CompositePrincipalConfiguration(this);
+ private PrivilegeConfiguration privilegeConfiguration;
- @Reference(referenceInterface = TokenConfiguration.class,
- name = "tokenConfiguration",
- bind = "bindTokenConfiguration",
- unbind = "unbindTokenConfiguration",
- policy = ReferencePolicy.DYNAMIC,
- cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE)
- private final CompositeTokenConfiguration tokenConfiguration = new CompositeTokenConfiguration(this);
+ private TokenConfiguration tokenConfiguration;
- private final WhiteboardAuthorizableNodeName authorizableNodeName = new WhiteboardAuthorizableNodeName();
- private final WhiteboardAuthorizableActionProvider authorizableActionProvider = new WhiteboardAuthorizableActionProvider();
- private final WhiteboardRestrictionProvider restrictionProvider = new WhiteboardRestrictionProvider();
- private final WhiteboardUserAuthenticationFactory userAuthenticationFactory = new WhiteboardUserAuthenticationFactory(UserConfigurationImpl.getDefaultAuthenticationFactory());
-
private ConfigurationParameters configuration;
private Whiteboard whiteboard;
/**
- * Default constructor used in OSGi environments.
+ * Default constructor using an empty configuration and default
+ * implementations for the security configurations.
*/
public SecurityProviderImpl() {
this(ConfigurationParameters.EMPTY);
}
/**
- * Create a new {@code SecurityProvider} instance with the given configuration
- * parameters.
+ * Create a new {@code SecurityProvider} instance with the given
+ * configuration parameters.
*
* @param configuration security configuration
*/
public SecurityProviderImpl(@Nonnull ConfigurationParameters configuration) {
- checkNotNull(configuration);
- this.configuration = configuration;
+ this.configuration = checkNotNull(configuration);
+ this.authenticationConfiguration = new AuthenticationConfigurationImpl(this);
+ this.authorizationConfiguration = new AuthorizationConfigurationImpl(this);
+ this.userConfiguration = new UserConfigurationImpl(this);
+ this.principalConfiguration = new PrincipalConfigurationImpl(this);
+ this.privilegeConfiguration = new PrivilegeConfigurationImpl();
+ this.tokenConfiguration = new TokenConfigurationImpl(this);
+ }
- authenticationConfiguration = new AuthenticationConfigurationImpl(this);
- authorizationConfiguration = new AuthorizationConfigurationImpl(this);
- userConfiguration = new UserConfigurationImpl(this);
- privilegeConfiguration = new PrivilegeConfigurationImpl();
+ protected void setAuthenticationConfiguration(AuthenticationConfiguration authenticationConfiguration) {
+ this.authenticationConfiguration = checkNotNull(authenticationConfiguration);
+ }
- principalConfiguration.setDefaultConfig(new PrincipalConfigurationImpl(this));
- tokenConfiguration.setDefaultConfig(new TokenConfigurationImpl(this));
+ protected void setAuthorizationConfiguration(AuthorizationConfiguration authorizationConfiguration) {
+ this.authorizationConfiguration = authorizationConfiguration;
}
+ protected void setUserConfiguration(UserConfiguration userConfiguration) {
+ this.userConfiguration = userConfiguration;
+ }
+
+ protected void setPrincipalConfiguration(PrincipalConfiguration principalConfiguration) {
+ this.principalConfiguration = principalConfiguration;
+ }
+
+ protected void setPrivilegeConfiguration(PrivilegeConfiguration privilegeConfiguration) {
+ this.privilegeConfiguration = privilegeConfiguration;
+ }
+
+ protected void setTokenConfiguration(TokenConfiguration tokenConfiguration) {
+ this.tokenConfiguration = tokenConfiguration;
+ }
+
@Override
public void setWhiteboard(@Nonnull Whiteboard whiteboard) {
this.whiteboard = whiteboard;
@@ -144,7 +122,9 @@
if (name == null) {
return configuration;
}
+
ConfigurationParameters params = configuration.getConfigValue(name, ConfigurationParameters.EMPTY);
+
for (SecurityConfiguration sc : getConfigurations()) {
if (sc != null && sc.getName().equals(name)) {
return ConfigurationParameters.of(params, sc.getParameters());
@@ -156,14 +136,14 @@
@Nonnull
@Override
public Iterable extends SecurityConfiguration> getConfigurations() {
- Set scs = new HashSet();
- scs.add(authenticationConfiguration);
- scs.add(authorizationConfiguration);
- scs.add(userConfiguration);
- scs.add(principalConfiguration);
- scs.add(privilegeConfiguration);
- scs.add(tokenConfiguration);
- return scs;
+ return newHashSet(
+ authenticationConfiguration,
+ authorizationConfiguration,
+ userConfiguration,
+ principalConfiguration,
+ privilegeConfiguration,
+ tokenConfiguration
+ );
}
@SuppressWarnings("unchecked")
@@ -187,89 +167,4 @@
}
}
- //----------------------------------------------------------------< SCR >---
- @Activate
- protected void activate(BundleContext context) {
- whiteboard = new OsgiWhiteboard(context);
- authorizableActionProvider.start(whiteboard);
- authorizableNodeName.start(whiteboard);
- restrictionProvider.start(whiteboard);
- userAuthenticationFactory.start(whiteboard);
-
- initializeConfigurations();
- }
-
- @Deactivate
- protected void deactivate() {
- authorizableActionProvider.stop();
- authorizableNodeName.stop();
- restrictionProvider.stop();
- userAuthenticationFactory.stop();
- }
-
- @SuppressWarnings("UnusedDeclaration")
- protected void bindPrincipalConfiguration(@Nonnull PrincipalConfiguration reference) {
- principalConfiguration.addConfiguration(initConfiguration(reference));
- }
-
- @SuppressWarnings("UnusedDeclaration")
- protected void unbindPrincipalConfiguration(@Nonnull PrincipalConfiguration reference) {
- principalConfiguration.removeConfiguration(reference);
- }
-
- @SuppressWarnings("UnusedDeclaration")
- protected void bindTokenConfiguration(@Nonnull TokenConfiguration reference) {
- tokenConfiguration.addConfiguration(initConfiguration(reference));
- }
-
- @SuppressWarnings("UnusedDeclaration")
- protected void unbindTokenConfiguration(@Nonnull TokenConfiguration reference) {
- tokenConfiguration.removeConfiguration(reference);
- }
-
- @SuppressWarnings("UnusedDeclaration")
- protected void bindAuthorizationConfiguration(@Nonnull AuthorizationConfiguration reference) {
- authorizationConfiguration = initConfiguration(reference);
- // TODO (OAK-1268): authorizationConfiguration.addConfiguration(initConfiguration(reference));
- }
-
- @SuppressWarnings("UnusedDeclaration")
- protected void unbindAuthorizationConfiguration(@Nonnull AuthorizationConfiguration reference) {
- authorizationConfiguration = new AuthorizationConfigurationImpl(this);
- // TODO (OAK-1268): authorizationConfiguration.removeConfiguration(reference);
- }
-
- //------------------------------------------------------------< private >---
- private void initializeConfigurations() {
- initConfiguration(authorizationConfiguration, ConfigurationParameters.of(
- AccessControlConstants.PARAM_RESTRICTION_PROVIDER, restrictionProvider)
- );
-
- Map userMap = ImmutableMap.of(
- UserConstants.PARAM_AUTHORIZABLE_ACTION_PROVIDER, authorizableActionProvider,
- UserConstants.PARAM_AUTHORIZABLE_NODE_NAME, authorizableNodeName,
- UserConstants.PARAM_USER_AUTHENTICATION_FACTORY, userAuthenticationFactory);
- initConfiguration(userConfiguration, ConfigurationParameters.of(userMap));
-
- initConfiguration(authenticationConfiguration);
- initConfiguration(privilegeConfiguration);
- }
-
- private T initConfiguration(@Nonnull T config) {
- if (config instanceof ConfigurationBase) {
- ConfigurationBase cfg = (ConfigurationBase) config;
- cfg.setSecurityProvider(this);
- cfg.setParameters(ConfigurationParameters.of(ConfigurationParameters.EMPTY, cfg.getParameters()));
- }
- return config;
- }
-
- private T initConfiguration(@Nonnull T config, @Nonnull ConfigurationParameters params) {
- if (config instanceof ConfigurationBase) {
- ConfigurationBase cfg = (ConfigurationBase) config;
- cfg.setSecurityProvider(this);
- cfg.setParameters(ConfigurationParameters.of(params, cfg.getParameters()));
- }
- return config;
- }
}
Index: oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderRegistration.java
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderRegistration.java (revision 0)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderRegistration.java (working copy)
@@ -0,0 +1,622 @@
+/*
+ * 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.jackrabbit.oak.security;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.PropertyUnbounded;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.ReferencePolicy;
+import org.apache.felix.scr.annotations.References;
+import org.apache.jackrabbit.oak.commons.PropertiesUtil;
+import org.apache.jackrabbit.oak.security.user.UserConfigurationImpl;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationBase;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+import org.apache.jackrabbit.oak.spi.security.SecurityConfiguration;
+import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
+import org.apache.jackrabbit.oak.spi.security.authentication.AuthenticationConfiguration;
+import org.apache.jackrabbit.oak.spi.security.authentication.token.CompositeTokenConfiguration;
+import org.apache.jackrabbit.oak.spi.security.authentication.token.TokenConfiguration;
+import org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
+import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants;
+import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
+import org.apache.jackrabbit.oak.spi.security.principal.CompositePrincipalConfiguration;
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfiguration;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConfiguration;
+import org.apache.jackrabbit.oak.spi.security.user.AuthorizableNodeName;
+import org.apache.jackrabbit.oak.spi.security.user.UserAuthenticationFactory;
+import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.apache.jackrabbit.oak.spi.security.user.action.AuthorizableActionProvider;
+import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardAuthorizableActionProvider;
+import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardAuthorizableNodeName;
+import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardRestrictionProvider;
+import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUserAuthenticationFactory;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.util.List;
+import java.util.Map;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Lists.newArrayList;
+
+@Component(
+ immediate = true,
+ metatype = true
+)
+@Properties({
+ @Property(
+ name = "requiredConfigurationPids",
+ unbounded = PropertyUnbounded.ARRAY
+ )
+})
+@References({
+ @Reference(
+ name = "principalConfiguration",
+ referenceInterface = PrincipalConfiguration.class,
+ cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
+ policy = ReferencePolicy.DYNAMIC
+ ),
+ @Reference(
+ name = "tokenConfiguration",
+ referenceInterface = TokenConfiguration.class,
+ cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
+ policy = ReferencePolicy.DYNAMIC
+ ),
+ @Reference(
+ name = "authorizableNodeName",
+ referenceInterface = TokenConfiguration.class,
+ cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
+ policy = ReferencePolicy.DYNAMIC
+ ),
+ @Reference(
+ name = "authorizableActionProvider",
+ referenceInterface = AuthorizableActionProvider.class,
+ cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
+ policy = ReferencePolicy.DYNAMIC
+ ),
+ @Reference(
+ name = "restrictionProvider",
+ referenceInterface = RestrictionProvider.class,
+ cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
+ policy = ReferencePolicy.DYNAMIC
+ ),
+ @Reference(
+ name = "userAuthenticationFactory",
+ referenceInterface = UserAuthenticationFactory.class,
+ cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
+ policy = ReferencePolicy.DYNAMIC
+ )
+})
+public class SecurityProviderRegistration {
+
+ @Reference
+ private AuthorizationConfiguration authorizationConfiguration;
+
+ @Reference
+ private AuthenticationConfiguration authenticationConfiguration;
+
+ @Reference
+ private PrivilegeConfiguration privilegeConfiguration;
+
+ @Reference
+ private UserConfiguration userConfiguration;
+
+ private BundleContext context;
+
+ private ServiceRegistration registration;
+
+ private SecurityProvider securityProvider;
+
+ private final Preconditions preconditions = new Preconditions();
+
+ private final List principalConfigurations = newArrayList();
+
+ private final List tokenConfigurations = newArrayList();
+
+ private final List authorizableNodeNames = newArrayList();
+
+ private final List authorizableActionProviders = newArrayList();
+
+ private final List restrictionProviders = newArrayList();
+
+ private final List userAuthenticationFactories = newArrayList();
+
+ @Activate
+ public synchronized void activate(BundleContext context, Map configuration) {
+ for (String pid : getRequiredConfigurationPids(configuration)) {
+ preconditions.addPrecondition(pid);
+ }
+
+ this.context = context;
+
+ maybeActivate();
+ }
+
+ @Deactivate
+ public synchronized void deactivate() {
+ doDeactivate();
+ preconditions.clearPreconditions();
+ context = null;
+ }
+
+ public void bindAuthorizationConfiguration(AuthorizationConfiguration authorizationConfiguration) {
+ this.authorizationConfiguration = initializeConfiguration(authorizationConfiguration);
+ }
+
+ public void unbindAuthorizationConfiguration() {
+ this.authorizationConfiguration = null;
+ }
+
+ public void bindAuthenticationConfiguration(AuthenticationConfiguration authenticationConfiguration) {
+ this.authenticationConfiguration = initializeConfiguration(authenticationConfiguration);
+ }
+
+ public void unbindAuthenticationConfiguration() {
+ this.authenticationConfiguration = null;
+ }
+
+ public void bindPrivilegeConfiguration(PrivilegeConfiguration privilegeConfiguration) {
+ this.privilegeConfiguration = initializeConfiguration(privilegeConfiguration);
+ }
+
+ public void unbindPrivilegeConfiguration() {
+ this.privilegeConfiguration = null;
+ }
+
+ public void bindUserConfiguration(UserConfiguration userConfiguration) {
+ this.userConfiguration = initializeConfiguration(userConfiguration);
+ }
+
+ public void unbindUserConfiguration() {
+ this.userConfiguration = null;
+ }
+
+ public synchronized void bindPrincipalConfiguration(PrincipalConfiguration principalConfiguration, Map properties) {
+ principalConfigurations.add(initializeConfiguration(principalConfiguration));
+ preconditions.addCandidate(getPid(properties));
+ maybeActivate();
+ }
+
+ public synchronized void unbindPrincipalConfiguration(PrincipalConfiguration principalConfiguration, Map properties) {
+ principalConfigurations.remove(principalConfiguration);
+ preconditions.removeCandidate(getPid(properties));
+ maybeDeactivate();
+ }
+
+ public synchronized void bindTokenConfiguration(TokenConfiguration tokenConfiguration, Map properties) {
+ tokenConfigurations.add(initializeConfiguration(tokenConfiguration));
+ preconditions.addCandidate(getPid(properties));
+ maybeActivate();
+ }
+
+ public synchronized void unbindTokenConfiguration(TokenConfiguration tokenConfiguration, Map properties) {
+ tokenConfigurations.remove(tokenConfiguration);
+ preconditions.removeCandidate(getPid(properties));
+ maybeDeactivate();
+ }
+
+ public synchronized void bindAuthorizableNodeName(AuthorizableNodeName authorizableNodeName, Map properties) {
+ authorizableNodeNames.add(authorizableNodeName);
+ preconditions.addCandidate(getPid(properties));
+ maybeActivate();
+ }
+
+ public synchronized void unbindAuthorizableNodeName(AuthorizableNodeName authorizableNodeName, Map properties) {
+ authorizableNodeNames.remove(authorizableNodeName);
+ preconditions.removeCandidate(getPid(properties));
+ maybeDeactivate();
+ }
+
+ public synchronized void bindAuthorizableActionProvider(AuthorizableActionProvider authorizableActionProvider, Map properties) {
+ authorizableActionProviders.add(authorizableActionProvider);
+ preconditions.addCandidate(getPid(properties));
+ maybeActivate();
+ }
+
+ public synchronized void unbindAuthorizableActionProvider(AuthorizableActionProvider authorizableActionProvider, Map properties) {
+ authorizableActionProviders.remove(authorizableActionProvider);
+ preconditions.removeCandidate(getPid(properties));
+ maybeDeactivate();
+ }
+
+ public synchronized void bindRestrictionProvider(RestrictionProvider restrictionProvider, Map properties) {
+ restrictionProviders.add(restrictionProvider);
+ preconditions.addCandidate(getPid(properties));
+ maybeActivate();
+ }
+
+ public synchronized void unbindRestrictionProvider(RestrictionProvider restrictionProvider, Map properties) {
+ restrictionProviders.remove(restrictionProvider);
+ preconditions.removeCandidate(getPid(properties));
+ maybeDeactivate();
+ }
+
+ public synchronized void bindUserAuthenticationFactory(UserAuthenticationFactory userAuthenticationFactory, Map properties) {
+ userAuthenticationFactories.add(userAuthenticationFactory);
+ preconditions.addCandidate(getPid(properties));
+ maybeActivate();
+ }
+
+ public synchronized void unbindUserAuthenticationFactory(UserAuthenticationFactory userAuthenticationFactory, Map properties) {
+ userAuthenticationFactories.remove(userAuthenticationFactory);
+ preconditions.removeCandidate(getPid(properties));
+ maybeDeactivate();
+ }
+
+ /**
+ * Create a new instance of {@code SecurityProvider} and register it as a
+ * service if some conditions hold.
+ *
+ * A new service is registered if (1) this component is activated, (2) the
+ * preconditions specified via OSGi configuration are satisfied, and (3) a
+ * {@code SecurityProvider} service was not already registered by a previous
+ * invocation of this method.
+ */
+ private void maybeActivate() {
+
+ // The component is not activated, yet. We have no means of registering
+ // the SecurityProvider. This method will be called again after
+ // activation completes.
+
+ if (context == null) {
+ return;
+ }
+
+ // The preconditions are not satisifed. This may happen when this
+ // component is activated but not enough mandatory services are bound
+ // to it.
+
+ if (!preconditions.areSatisfied()) {
+ return;
+ }
+
+ // The SecurityProvider is already registered. This may happen when a
+ // new dependency is added to this component, but the requirements are
+ // already satisfied.
+
+ if (registration != null) {
+ return;
+ }
+
+ // Create a new instance of the SecurityProvider.
+
+ securityProvider = createSecurityProvider();
+
+ // Register the SecurityProvider.
+
+ registration = context.registerService(SecurityProvider.class.getName(), securityProvider, null);
+ }
+
+ /**
+ * Unregister a previously registered {@code SecurityProvider} service if
+ * the preconditions specified via OSGi configuration are satisfied.
+ */
+ private void maybeDeactivate() {
+
+ // If there is nothing to register, we obviously have nothing to do.
+
+ if (registration == null) {
+ return;
+ }
+
+ // The preconditions are not satisfied. This may happen when a
+ // dependency is unbound from the current component.
+
+ if (preconditions.areSatisfied()) {
+ return;
+ }
+
+ // Deregister the SecurityProvider.
+
+ doDeactivate();
+ }
+
+ /**
+ * Unregister a previously registered {@code SecurityProvider} service.
+ */
+ private void doDeactivate() {
+ securityProvider = null;
+
+ registration.unregister();
+ registration = null;
+ }
+
+ /**
+ * Initialize a referenced {@code AuthorizationConfiguration} service. The
+ * service will be linked to the {@code SecurityProvider} managed by this
+ * component and to the {@code RestrictionProvider} services registered into
+ * the framework.
+ *
+ * @param authorizationConfiguration A {@code AuthorizationConfiguration}
+ * service referenced by this component.
+ * @return The same {@code AuthorizationConfiguration} service passed as a
+ * parameter after being initialized.
+ */
+ private AuthorizationConfiguration initializeConfiguration(AuthorizationConfiguration authorizationConfiguration) {
+ return initializeConfiguration(authorizationConfiguration, ConfigurationParameters.of(
+ AccessControlConstants.PARAM_RESTRICTION_PROVIDER, createDelegatingRestrictionProvider()
+ ));
+ }
+
+ /**
+ * Initialize a referenced {@code UserConfiguration} service. The service
+ * will be linked to the {@code SecurityProvider} managed by this component
+ * and to the {@code AuthorizableActionProvider}, {@code
+ * AuthorizableNodeName} and {@code UserAuthenticationFactory} registered
+ * into the framework.
+ *
+ * @param userConfiguration A {@code UserConfiguration} service referenced
+ * by this component.
+ * @return The same {@code UserConfiguration} service passed as a parameter
+ * after being initialized.
+ */
+ private UserConfiguration initializeConfiguration(UserConfiguration userConfiguration) {
+ return initializeConfiguration(userConfiguration, ConfigurationParameters.of(
+ ConfigurationParameters.of(UserConstants.PARAM_AUTHORIZABLE_ACTION_PROVIDER, createDelegatingAuthorizableActionProvider()),
+ ConfigurationParameters.of(UserConstants.PARAM_AUTHORIZABLE_NODE_NAME, createDelegatingAuthorizableNodeName()),
+ ConfigurationParameters.of(UserConstants.PARAM_USER_AUTHENTICATION_FACTORY, createDelegatingUserAuthenticationFactory())
+ ));
+ }
+
+
+ private T initializeConfiguration(T configuration) {
+ return initializeConfiguration(configuration, ConfigurationParameters.EMPTY);
+ }
+
+ /**
+ * Initialize a referenced {@code SecurityConfiguration} services. The
+ * service will be linked to the {@code SecurityProvider} managed by this
+ * component, and its parameters will be merged with the parameters passed
+ * to this method.
+ *
+ * @param configuration An instance of {@code SecurityConfiguration} to
+ * initialize.
+ * @param parameters The parameters to merge with the ones already hold
+ * by the configuration.
+ * @param The type of the {@code SecurityConfiguration}
+ * instance.
+ * @return The same {@code SecurityConfiguration} after being initialized.
+ */
+ private T initializeConfiguration(T configuration, ConfigurationParameters parameters) {
+ if (configuration instanceof ConfigurationBase) {
+ ConfigurationBase base = (ConfigurationBase) configuration;
+ base.setSecurityProvider(createDelegatingSecurityProvider());
+ base.setParameters(ConfigurationParameters.of(parameters, base.getParameters()));
+ }
+
+ return configuration;
+ }
+
+ /**
+ * Create a {@code SecurityProvider} that references its configurations from
+ * the OSGi framework.
+ *
+ * @return An instance of {@code SecurityProvider}.
+ */
+ private SecurityProvider createSecurityProvider() {
+ SecurityProviderImpl securityProvider = new SecurityProviderImpl();
+
+ securityProvider.setAuthenticationConfiguration(authenticationConfiguration);
+ securityProvider.setAuthorizationConfiguration(authorizationConfiguration);
+ securityProvider.setUserConfiguration(userConfiguration);
+ securityProvider.setPrivilegeConfiguration(privilegeConfiguration);
+ securityProvider.setPrincipalConfiguration(createDelegatingPrincipalConfiguration());
+ securityProvider.setTokenConfiguration(createDelegatingTokenConfiguration());
+
+ return securityProvider;
+ }
+
+ /**
+ * Create a {@code PrincipalConfiguration} that aggregates every {@code
+ * PrincipalConfiguration} service referenced by this component.
+ *
+ * @return An instance of {@code PrincipalConfiguration}.
+ */
+ private PrincipalConfiguration createDelegatingPrincipalConfiguration() {
+ return new CompositePrincipalConfiguration(createDelegatingSecurityProvider()) {
+
+ @Override
+ protected List getConfigurations() {
+ synchronized (SecurityProviderRegistration.this) {
+ return newArrayList(principalConfigurations);
+ }
+ }
+
+ };
+ }
+
+ /**
+ * Create a {@code TokenConfiguration} that aggregates every {@code
+ * TokenConfiguration} service referenced by this component.
+ *
+ * @return An instance of {@code TokenConfiguration}.
+ */
+ private TokenConfiguration createDelegatingTokenConfiguration() {
+ return new CompositeTokenConfiguration(createDelegatingSecurityProvider()) {
+
+ @Override
+ protected List getConfigurations() {
+ synchronized (SecurityProviderRegistration.this) {
+ return newArrayList(tokenConfigurations);
+ }
+ }
+
+ };
+ }
+
+ /**
+ * Create an instance of {@code SecurityProvider} that delegates its call to
+ * the {@code SecurityProvider} registered by this component. If no {@code
+ * SecurityProvider} is registered yet, the returned instance will just
+ * throw {@code IllegalStateException}.
+ *
+ * This delegate is necessary because some configurations require a {@code
+ * SecurityProvider} at construction time. The delegate can be considered a
+ * "promise" that a {@code SecurityProvider} will be registered when the
+ * right conditions are met.
+ *
+ * @return An instance of {@code SecurityProvider}
+ */
+ private SecurityProvider createDelegatingSecurityProvider() {
+ return new SecurityProvider() {
+
+ @Nonnull
+ @Override
+ public ConfigurationParameters getParameters(@Nullable String name) {
+ SecurityProvider delegate;
+
+ synchronized (SecurityProviderRegistration.this) {
+ delegate = securityProvider;
+ }
+
+ checkState(delegate != null);
+
+ return delegate.getParameters(name);
+ }
+
+ @Nonnull
+ @Override
+ public Iterable extends SecurityConfiguration> getConfigurations() {
+ SecurityProvider delegate;
+
+ synchronized (SecurityProviderRegistration.this) {
+ delegate = securityProvider;
+ }
+
+ checkState(delegate != null);
+
+ return delegate.getConfigurations();
+ }
+
+ @Nonnull
+ @Override
+ public T getConfiguration(@Nonnull Class configClass) {
+ SecurityProvider delegate;
+
+ synchronized (SecurityProviderRegistration.this) {
+ delegate = securityProvider;
+ }
+
+ checkState(delegate != null);
+
+ return checkNotNull(delegate).getConfiguration(configClass);
+ }
+
+ };
+ }
+
+ /**
+ * Create a {@code RestrictionProvider} that aggregates every {@code
+ * RestrictionProvider} service referenced by this component.
+ *
+ * @return An instance of {@code RestrictionProvider}.
+ */
+ private RestrictionProvider createDelegatingRestrictionProvider() {
+ return new WhiteboardRestrictionProvider() {
+
+ @Override
+ protected List getServices() {
+ synchronized (SecurityProviderRegistration.this) {
+ return newArrayList(restrictionProviders);
+ }
+ }
+
+ };
+ }
+
+ /**
+ * Create a {@code AuthorizableActionProvider} that aggregates every {@code
+ * AuthorizableActionProvider} service referenced by this component.
+ *
+ * @return An instance of {@code RestrictionProvider}.
+ */
+ private AuthorizableActionProvider createDelegatingAuthorizableActionProvider() {
+ return new WhiteboardAuthorizableActionProvider() {
+
+ @Override
+ protected List getServices() {
+ synchronized (SecurityProviderRegistration.this) {
+ return newArrayList(authorizableActionProviders);
+ }
+ }
+
+ };
+ }
+
+ /**
+ * Create a {@code AuthorizableNodeName} that aggregates every {@code
+ * AuthorizableNodeName} service referenced by this component.
+ *
+ * @return An instance of {@code AuthorizableNodeName}.
+ */
+ private AuthorizableNodeName createDelegatingAuthorizableNodeName() {
+ return new WhiteboardAuthorizableNodeName() {
+
+ @Override
+ protected List getServices() {
+ synchronized (SecurityProviderRegistration.this) {
+ return newArrayList(authorizableNodeNames);
+ }
+ }
+
+ };
+ }
+
+ /**
+ * Create a {@code UserAuthenticationFactory} that aggregates every {@code
+ * UserAuthenticationFactory} service referenced by this component.
+ *
+ * @return An instance of {@code UserAuthenticationFactory}.
+ */
+ private UserAuthenticationFactory createDelegatingUserAuthenticationFactory() {
+ return new WhiteboardUserAuthenticationFactory(UserConfigurationImpl.getDefaultAuthenticationFactory()) {
+
+ @Override
+ protected List getServices() {
+ synchronized (SecurityProviderRegistration.this) {
+ return newArrayList(userAuthenticationFactories);
+ }
+ }
+
+ };
+ }
+
+ private String getPid(Map properties) {
+ String pid = PropertiesUtil.toString(properties.get(Constants.SERVICE_PID), null);
+
+ if (pid == null) {
+ throw new IllegalArgumentException("Unable to find the service PID");
+ }
+
+ return pid;
+ }
+
+ private String[] getRequiredConfigurationPids(Map configuration) {
+ return PropertiesUtil.toStringArray(configuration.get("requiredConfigurationPids"), new String[]{});
+ }
+
+}
Property changes on: oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderRegistration.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: oak-core/src/main/java/org/apache/jackrabbit/oak/security/package-info.java
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/security/package-info.java (revision 1702510)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/security/package-info.java (working copy)
@@ -20,7 +20,7 @@
*
* See README.md for more details.
*/
-@Version("1.0.1")
+@Version("2.0.0")
@Export(optional = "provide:=true")
package org.apache.jackrabbit.oak.security;
Index: oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/token/CompositeTokenConfiguration.java
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/token/CompositeTokenConfiguration.java (revision 1702510)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/token/CompositeTokenConfiguration.java (working copy)
@@ -28,7 +28,7 @@
/**
* {@link TokenConfiguration} that combines different token provider implementations.
*/
-public final class CompositeTokenConfiguration extends CompositeConfiguration implements TokenConfiguration {
+public class CompositeTokenConfiguration extends CompositeConfiguration implements TokenConfiguration {
public CompositeTokenConfiguration(@Nonnull SecurityProvider securityProvider) {
super(TokenConfiguration.NAME, securityProvider);
Index: oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/token/package-info.java
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/token/package-info.java (revision 1702510)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/token/package-info.java (working copy)
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@Version("1.1.0")
+@Version("1.2.0")
@Export(optional = "provide:=true")
package org.apache.jackrabbit.oak.spi.security.authentication.token;
Index: oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/CompositePrincipalConfiguration.java
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/CompositePrincipalConfiguration.java (revision 1702510)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/CompositePrincipalConfiguration.java (working copy)
@@ -30,7 +30,7 @@
* {@link PrincipalConfiguration} that combines different principal provider
* implementations that share a common principal manager implementation.
*/
-public final class CompositePrincipalConfiguration extends CompositeConfiguration implements PrincipalConfiguration {
+public class CompositePrincipalConfiguration extends CompositeConfiguration implements PrincipalConfiguration {
public CompositePrincipalConfiguration(@Nonnull SecurityProvider securityProvider) {
super(PrincipalConfiguration.NAME, securityProvider);
Index: oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/package-info.java
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/package-info.java (revision 1702510)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/package-info.java (working copy)
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@Version("1.0")
+@Version("1.1.0")
@Export(optional = "provide:=true")
package org.apache.jackrabbit.oak.spi.security.principal;