commit
0ae3eafe10
15 changed files with 561 additions and 8 deletions
|
@ -2,6 +2,7 @@ package org.keycloak.representations.idm;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bburke@redhat.com">Bill Burke</a>
|
||||
|
@ -9,7 +10,7 @@ import java.util.Map;
|
|||
public class UserFederationProviderFactoryRepresentation {
|
||||
|
||||
private String id;
|
||||
private List<String> options;
|
||||
private Set<String> options;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
|
@ -19,11 +20,11 @@ public class UserFederationProviderFactoryRepresentation {
|
|||
this.id = id;
|
||||
}
|
||||
|
||||
public List<String> getOptions() {
|
||||
public Set<String> getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public void setOptions(List<String> options) {
|
||||
public void setOptions(Set<String> options) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
|
|
48
examples/providers/federation-provider/pom.xml
Executable file
48
examples/providers/federation-provider/pom.xml
Executable file
|
@ -0,0 +1,48 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>examples-providers-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.0-beta-4-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Properties Authentication Provider Example</name>
|
||||
<description/>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>federation-properties-example</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-model-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>federation-properties-example</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,76 @@
|
|||
package org.keycloak.examples.federation.properties;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.UserFederationProvider;
|
||||
import org.keycloak.models.UserFederationProviderFactory;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashSet;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public abstract class BasePropertiesFederationFactory implements UserFederationProviderFactory {
|
||||
static final Set<String> configOptions = new HashSet<String>();
|
||||
protected ConcurrentHashMap<String, Properties> files = new ConcurrentHashMap<String, Properties>();
|
||||
|
||||
static {
|
||||
configOptions.add("path");
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserFederationProvider getInstance(KeycloakSession session, UserFederationProviderModel model) {
|
||||
String path = model.getConfig().get("path");
|
||||
if (path == null) {
|
||||
throw new IllegalStateException("Path attribute not configured for provider");
|
||||
}
|
||||
Properties props = files.get(path);
|
||||
if (props != null) return createProvider(session, model, props);
|
||||
|
||||
|
||||
props = new Properties();
|
||||
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
|
||||
if (is == null) {
|
||||
throw new IllegalStateException("Path attribute not configured for provider");
|
||||
|
||||
}
|
||||
try {
|
||||
props.load(is);
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
props.put(path, props);
|
||||
return createProvider(session, model, props);
|
||||
}
|
||||
|
||||
protected abstract BasePropertiesFederationProvider createProvider(KeycloakSession session, UserFederationProviderModel model, Properties props);
|
||||
|
||||
|
||||
@Override
|
||||
public Set<String> getConfigurationOptions() {
|
||||
return configOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserFederationProvider create(KeycloakSession session) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
package org.keycloak.examples.federation.properties;
|
||||
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserFederationProvider;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public abstract class BasePropertiesFederationProvider implements UserFederationProvider {
|
||||
protected static final Set<String> supportedCredentialTypes = new HashSet<String>();
|
||||
protected KeycloakSession session;
|
||||
protected Properties properties;
|
||||
protected UserFederationProviderModel model;
|
||||
|
||||
public BasePropertiesFederationProvider(KeycloakSession session, UserFederationProviderModel model, Properties properties) {
|
||||
this.session = session;
|
||||
this.model = model;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public static Set<String> getSupportedCredentialTypes() {
|
||||
return supportedCredentialTypes;
|
||||
}
|
||||
|
||||
static
|
||||
{
|
||||
supportedCredentialTypes.add(UserCredentialModel.PASSWORD);
|
||||
}
|
||||
|
||||
|
||||
public KeycloakSession getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
public Properties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public UserFederationProviderModel getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserByUsername(RealmModel realm, String username) {
|
||||
String password = properties.getProperty(username);
|
||||
if (password != null) {
|
||||
UserModel userModel = session.userStorage().addUser(realm, username);
|
||||
userModel.updateCredential(UserCredentialModel.password(password));
|
||||
return userModel;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserByEmail(RealmModel realm, String email) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchByAttributes(Map<String, String> attributes, RealmModel realm, int maxResults) {
|
||||
if (attributes.containsKey(USERNAME)) {
|
||||
UserModel user = getUserByUsername(realm, attributes.get(USERNAME));
|
||||
if (user != null) {
|
||||
List<UserModel> list = new ArrayList<UserModel>(1);
|
||||
list.add(user);
|
||||
return list;
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, RoleModel role) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(UserModel local) {
|
||||
return properties.containsKey(local.getUsername());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getSupportedCredentialTypes(UserModel user) {
|
||||
return supportedCredentialTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
|
||||
for (UserCredentialModel cred : input) {
|
||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
String password = properties.getProperty(user.getUsername());
|
||||
if (password == null) return false;
|
||||
return password.equals(cred.getValue());
|
||||
} else {
|
||||
return false; // invalid cred type
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
|
||||
for (UserCredentialModel cred : input) {
|
||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
String password = properties.getProperty(user.getUsername());
|
||||
if (password == null) return false;
|
||||
return password.equals(cred.getValue());
|
||||
} else {
|
||||
return false; // invalid cred type
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package org.keycloak.examples.federation.properties;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.UserFederationProvider;
|
||||
import org.keycloak.models.UserFederationProviderFactory;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ClasspathPropertiesFederationFactory extends BasePropertiesFederationFactory {
|
||||
|
||||
@Override
|
||||
protected BasePropertiesFederationProvider createProvider(KeycloakSession session, UserFederationProviderModel model, Properties props) {
|
||||
return new ClasspathPropertiesFederationProvider(session, model, props);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "classpath-properties";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package org.keycloak.examples.federation.properties;
|
||||
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserFederationProvider;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ClasspathPropertiesFederationProvider extends BasePropertiesFederationProvider {
|
||||
|
||||
public ClasspathPropertiesFederationProvider(KeycloakSession session, UserFederationProviderModel model, Properties properties) {
|
||||
super(session, model, properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel proxy(UserModel local) {
|
||||
return new ReadonlyUserModelProxy(local);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean synchronizeRegistrations() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel register(RealmModel realm, UserModel user) {
|
||||
throw new IllegalStateException("Registration not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeUser(RealmModel realm, UserModel user) {
|
||||
throw new IllegalStateException("Remove not supported");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package org.keycloak.examples.federation.properties;
|
||||
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class FilePropertiesFederationFactory extends BasePropertiesFederationFactory {
|
||||
|
||||
@Override
|
||||
protected BasePropertiesFederationProvider createProvider(KeycloakSession session, UserFederationProviderModel model, Properties props) {
|
||||
return new FilePropertiesFederationProvider(session, props, model);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "file-properties";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package org.keycloak.examples.federation.properties;
|
||||
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserFederationProvider;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class FilePropertiesFederationProvider extends BasePropertiesFederationProvider {
|
||||
|
||||
public FilePropertiesFederationProvider(KeycloakSession session, Properties properties, UserFederationProviderModel model) {
|
||||
super(session, model, properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel proxy(UserModel local) {
|
||||
return new WritableUserModelProxy(local, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean synchronizeRegistrations() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void save() {
|
||||
String path = getModel().getConfig().get("path");
|
||||
try {
|
||||
FileOutputStream fos = new FileOutputStream(path);
|
||||
properties.store(fos, "");
|
||||
fos.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel register(RealmModel realm, UserModel user) {
|
||||
synchronized (properties) {
|
||||
properties.setProperty(user.getUsername(), "");
|
||||
save();
|
||||
}
|
||||
return proxy(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeUser(RealmModel realm, UserModel user) {
|
||||
synchronized (properties) {
|
||||
if (properties.remove(user.getUsername()) == null) return false;
|
||||
save();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package org.keycloak.examples.federation.properties;
|
||||
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserCredentialValueModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.UserModelDelegate;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ReadonlyUserModelProxy extends UserModelDelegate {
|
||||
|
||||
public ReadonlyUserModelProxy(UserModel delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUsername(String username) {
|
||||
throw new IllegalStateException("Username is readonly");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredentialDirectly(UserCredentialValueModel cred) {
|
||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
throw new IllegalStateException("Passwords are readonly");
|
||||
}
|
||||
super.updateCredentialDirectly(cred);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredential(UserCredentialModel cred) {
|
||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
throw new IllegalStateException("Passwords are readonly");
|
||||
}
|
||||
super.updateCredential(cred);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package org.keycloak.examples.federation.properties;
|
||||
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserCredentialValueModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.UserModelDelegate;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class WritableUserModelProxy extends UserModelDelegate {
|
||||
protected FilePropertiesFederationProvider provider;
|
||||
|
||||
public WritableUserModelProxy(UserModel delegate, FilePropertiesFederationProvider provider) {
|
||||
super(delegate);
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUsername(String username) {
|
||||
if (delegate.getUsername().equals(username)) return;
|
||||
delegate.setUsername(username);
|
||||
Properties properties = provider.getProperties();
|
||||
synchronized (properties) {
|
||||
if (properties.containsKey(username)) {
|
||||
throw new IllegalStateException("Can't change username to existing user");
|
||||
}
|
||||
String password = (String) properties.remove(username);
|
||||
if (password == null) {
|
||||
throw new IllegalStateException("User doesn't exist");
|
||||
}
|
||||
properties.setProperty(username, password);
|
||||
provider.save();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredentialDirectly(UserCredentialValueModel cred) {
|
||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
throw new IllegalStateException("Shouldn't be using this method");
|
||||
}
|
||||
super.updateCredentialDirectly(cred);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredential(UserCredentialModel cred) {
|
||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
|
||||
} else {
|
||||
super.updateCredential(cred);
|
||||
synchronized (provider.getProperties()) {
|
||||
if (!provider.getProperties().containsKey(delegate.getUsername())) {
|
||||
throw new IllegalStateException("no user of that in properties file");
|
||||
}
|
||||
provider.getProperties().put(delegate.getUsername(), cred.getValue());
|
||||
provider.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
org.keycloak.examples.federation.properties.ClasspathPropertiesFederationFactory
|
||||
org.keycloak.examples.federation.properties.FilePropertiesFederationFactory
|
|
@ -27,5 +27,6 @@
|
|||
<modules>
|
||||
<module>audit-listener-sysout</module>
|
||||
<module>audit-provider-mem</module>
|
||||
<module>federation-provider</module>
|
||||
</modules>
|
||||
</project>
|
||||
|
|
|
@ -9,6 +9,7 @@ import org.picketlink.idm.PartitionManager;
|
|||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
|
@ -46,7 +47,7 @@ public class LDAPFederationProviderFactory implements UserFederationProviderFact
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> getConfigurationOptions() {
|
||||
return Collections.emptyList();
|
||||
public Set<String> getConfigurationOptions() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.keycloak.models;
|
|||
import org.keycloak.provider.ProviderFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -16,5 +17,5 @@ public interface UserFederationProviderFactory extends ProviderFactory<UserFeder
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
List<String> getConfigurationOptions();
|
||||
Set<String> getConfigurationOptions();
|
||||
}
|
||||
|
|
|
@ -7,7 +7,9 @@ import org.keycloak.models.UserFederationProviderFactory;
|
|||
import org.keycloak.models.UserFederationProviderModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -20,8 +22,8 @@ public class DummyUserFederationProviderFactory implements UserFederationProvide
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> getConfigurationOptions() {
|
||||
List<String> list = new ArrayList<String>();
|
||||
public Set<String> getConfigurationOptions() {
|
||||
Set<String> list = new HashSet<String>();
|
||||
list.add("important.config");
|
||||
return list;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue