<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>osgi.cmpn</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>mdsal-binding-api</artifactId>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
</dependencies>
<build>
<Export-Package>
org.opendaylight.aaa.impl.password.service.DefaultPasswordHashService
</Export-Package>
+ <_dsannotations-options>norequirements</_dsannotations-options>
</instructions>
</configuration>
</plugin>
--- /dev/null
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.aaa.impl.password.service;
+
+import org.opendaylight.aaa.api.password.service.PasswordHash;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.password.service.config.rev170619.PasswordServiceConfig;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+
+@Component(immediate = true, service = PasswordHashService.class, property = "type=default")
+public final class OSGiPasswordHashService implements PasswordHashService {
+ private volatile DefaultPasswordHashService delegate = null;
+
+ @Override
+ public PasswordHash getPasswordHash(final String password) {
+ return delegate.getPasswordHash(password);
+ }
+
+ @Override
+ public PasswordHash getPasswordHash(final String password, final String salt) {
+ return delegate.getPasswordHash(password, salt);
+ }
+
+ @Override
+ public boolean passwordsMatch(final String plaintext, final String stored, final String salt) {
+ return delegate.passwordsMatch(plaintext, stored, salt);
+ }
+
+ @Reference(policy = ReferencePolicy.DYNAMIC, cardinality = ReferenceCardinality.MANDATORY)
+ void bindConfig(final PasswordServiceConfig config) {
+ updatedConfig(config);
+ }
+
+ void unbindConfig(final PasswordServiceConfig config) {
+ delegate = null;
+ }
+
+ void updatedConfig(final PasswordServiceConfig config) {
+ delegate = new DefaultPasswordHashService(config);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.aaa.impl.password.service;
+
+import static com.google.common.base.Verify.verifyNotNull;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ForwardingObject;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Map;
+import org.gaul.modernizer_maven_annotations.SuppressModernizer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.password.service.config.rev170619.PasswordServiceConfig;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+
+@Beta
+@Component(factory = OSGiPasswordServiceConfig.FACTORY_NAME)
+public final class OSGiPasswordServiceConfig extends ForwardingObject implements PasswordServiceConfig {
+ // OSGi DS Component Factory name
+ static final String FACTORY_NAME = "org.opendaylight.aaa.impl.password.service.OSGiPasswordServiceConfig";
+
+ // Keys to for activation properties
+ @VisibleForTesting
+ static final String DELEGATE = ".delegate";
+
+ private PasswordServiceConfig delegate;
+
+ @Override
+ public Map<Class<? extends Augmentation<PasswordServiceConfig>>, Augmentation<PasswordServiceConfig>>
+ augmentations() {
+ return delegate().augmentations();
+ }
+
+ @Override
+ public String getAlgorithm() {
+ return delegate().getAlgorithm();
+ }
+
+ @Override
+ public Integer getIterations() {
+ return delegate().getIterations();
+ }
+
+ @Override
+ public String getPrivateSalt() {
+ return delegate().getPrivateSalt();
+ }
+
+ @Override
+ public int hashCode() {
+ return delegate().hashCode();
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ return delegate().equals(obj);
+ }
+
+ @Override
+ protected PasswordServiceConfig delegate() {
+ return verifyNotNull(delegate);
+ }
+
+ @Activate
+ void activate(final Map<String, ?> properties) {
+ delegate = (PasswordServiceConfig) verifyNotNull(properties.get(DELEGATE));
+ }
+
+ @Deactivate
+ void deactivate() {
+ delegate = null;
+ }
+
+ @SuppressModernizer
+ static Dictionary<String, ?> props(final PasswordServiceConfig delegate) {
+ final Dictionary<String, Object> ret = new Hashtable<>(2);
+ ret.put(DELEGATE, requireNonNull(delegate));
+ return ret;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.aaa.impl.password.service;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.Iterables;
+import java.util.Collection;
+import org.checkerframework.checker.lock.qual.Holding;
+import org.opendaylight.mdsal.binding.api.ClusteredDataTreeChangeListener;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
+import org.opendaylight.mdsal.binding.api.DataTreeModification;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.password.service.config.rev170619.PasswordServiceConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.password.service.config.rev170619.PasswordServiceConfigBuilder;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.osgi.service.component.ComponentFactory;
+import org.osgi.service.component.ComponentInstance;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Beta
+@Component(immediate = true)
+public final class OSGiPasswordServiceConfigBootstrap
+ implements ClusteredDataTreeChangeListener<PasswordServiceConfig> {
+ private static final Logger LOG = LoggerFactory.getLogger(OSGiPasswordServiceConfigBootstrap.class);
+
+ @Reference
+ DataBroker dataBroker = null;
+
+ @Reference(target = "(component.factory=" + OSGiPasswordServiceConfig.FACTORY_NAME + ")")
+ ComponentFactory configFactory = null;
+
+ private ListenerRegistration<?> registration;
+ private ComponentInstance instance;
+
+ @Activate
+ synchronized void activate() {
+ registration = dataBroker.registerDataTreeChangeListener(
+ DataTreeIdentifier.create(LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.create(PasswordServiceConfig.class)), this);
+ LOG.info("Listening for password service configuration");
+ }
+
+ @Deactivate
+ synchronized void deactivate() {
+ registration.close();
+ registration = null;
+ if (instance != null) {
+ instance.dispose();
+ instance = null;
+ }
+ LOG.info("No longer listening for password service configuration");
+ }
+
+ @Override
+ public synchronized void onInitialData() {
+ updateInstance(null);
+ }
+
+ @Override
+ public synchronized void onDataTreeChanged(final Collection<DataTreeModification<PasswordServiceConfig>> changes) {
+ // FIXME: at this point we need to populate default values -- from the XML file
+ updateInstance(Iterables.getLast(changes).getRootNode().getDataAfter());
+ }
+
+ @Holding("this")
+ private void updateInstance(final PasswordServiceConfig config) {
+ if (registration != null) {
+ final ComponentInstance newInstance = configFactory.newInstance(
+ OSGiPasswordServiceConfig.props(config != null ? config : new PasswordServiceConfigBuilder().build()));
+ if (instance != null) {
+ instance.dispose();
+ }
+ instance = newInstance;
+ }
+ }
+}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- vi: set et smarttab sw=4 tabstop=4: -->
-<!--
-Copyright © 2018 Inocybe Technologies and others. All rights reserved.
-
-This program and the accompanying materials are made available under the
-terms of the Eclipse Public License v1.0 which accompanies this distribution,
-and is available at http://www.eclipse.org/legal/epl-v10.html
--->
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
- xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
- odl:use-default-for-reference-types="true">
-
- <odl:clustered-app-config
- binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.password.service.config.rev170619.PasswordServiceConfig"
- id="passwordServiceConfig" default-config-file-name="aaa-password-service-config.xml" />
-
- <bean id="passwordService" class="org.opendaylight.aaa.impl.password.service.DefaultPasswordHashService">
- <argument ref="passwordServiceConfig" />
- </bean>
- <service ref="passwordService" interface="org.opendaylight.aaa.api.password.service.PasswordHashService"
- odl:type="default"/>
-
-</blueprint>
binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.app.config.rev170619.DatastoreConfig" />
<reference id="authService" interface="org.opendaylight.aaa.api.AuthenticationService"/>
- <reference id="passwordService" interface="org.opendaylight.aaa.api.password.service.PasswordHashService"
- odl:type="default"/>
+ <reference id="passwordService" interface="org.opendaylight.aaa.api.password.service.PasswordHashService"/>
<bean id="idmStore" class="org.opendaylight.aaa.datastore.h2.H2Store">
<argument value="${dbUsername}" />