Skip to content

Commit

Permalink
Reduce duplication in connector validators and make them more strict
Browse files Browse the repository at this point in the history
  • Loading branch information
spacecowboy committed Jan 5, 2017
1 parent 41924c9 commit 9b3752a
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 248 deletions.
Expand Up @@ -19,22 +19,14 @@
*/
package org.neo4j.kernel.configuration;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import javax.annotation.Nonnull;

import org.neo4j.graphdb.config.InvalidSettingException;
import org.neo4j.graphdb.config.Setting;
import org.neo4j.helpers.ListenSocketAddress;

import static org.neo4j.kernel.configuration.BoltConnector.EncryptionLevel.OPTIONAL;
import static org.neo4j.kernel.configuration.Connector.ConnectorType.BOLT;
import static org.neo4j.kernel.configuration.Settings.BOOLEAN;
import static org.neo4j.kernel.configuration.Settings.NO_DEFAULT;
import static org.neo4j.kernel.configuration.Settings.advertisedAddress;
import static org.neo4j.kernel.configuration.Settings.listenAddress;
import static org.neo4j.kernel.configuration.Settings.options;
Expand All @@ -49,111 +41,25 @@ public BoltConnectorValidator()

@Override
@Nonnull
public Map<String,String> validate( @Nonnull Map<String,String> rawConfig )
throws InvalidSettingException
protected Optional<Setting> getSettingFor( @Nonnull String settingName, @Nonnull Map<String,String> params )
{
final HashMap<String,String> result = new HashMap<>();
// owns has already verified that 'type' is correct and that this split is possible
String[] parts = settingName.split( "\\." );
final String subsetting = parts[3];

ownedEntries( rawConfig ).forEach( s ->
switch ( subsetting )
{
// owns has already verified that 'type' is correct and that this split is possible
final String subsetting = s.getKey().split( "\\." )[3];

Setting<ListenSocketAddress> las = listenAddress( s.getKey(), 7687 );
switch ( subsetting )
{
case "enabled":
result.putAll( setting( s.getKey(), BOOLEAN, "false" ).validate( rawConfig ) );
break;
case "tls_level":
result.putAll( setting( s.getKey(), options( BoltConnector.EncryptionLevel.class ),
OPTIONAL.name() ).validate( rawConfig ) );
break;
case "address":
case "listen_address":
// Exact default port doesn't matter for validation purposes
result.putAll( las.validate( rawConfig ) );
break;
case "advertised_address":
result.putAll( advertisedAddress( s.getKey(), las ).validate( rawConfig ) );
break;
case "type":
result.putAll( assertTypeIsBolt(
setting( s.getKey(), options( Connector.ConnectorType.class ),
NO_DEFAULT ), rawConfig ) );
break;
default:
throw new InvalidSettingException( String.format( "Unknown configuration passed to %s: %s",
getClass().getName(), s.getKey() ) );
}
} );

return result;
}

@Nonnull
private Map<String,String> assertTypeIsBolt( @Nonnull Setting<?> setting, @Nonnull Map<String,String> rawConfig )
{
Map<String,String> result = setting.validate( rawConfig );

Optional<?> typeValue = Optional.ofNullable( setting.apply( rawConfig::get ) );

if ( typeValue.isPresent() && !BOLT.equals( typeValue.get() ) )
{
throw new InvalidSettingException(
String.format( "'%s' is only allowed to be '%s'; not '%s'",
setting.name(), BOLT, typeValue.get() ) );

case "tls_level":
return Optional.of( setting( settingName, options( BoltConnector.EncryptionLevel.class ),
OPTIONAL.name() ) );
case "address":
case "listen_address":
return Optional.of( listenAddress( settingName, 7687 ) );
case "advertised_address":
return Optional.of( advertisedAddress( settingName,
listenAddress( settingName, 7687 ) ) );
default:
return super.getSettingFor( settingName, params );
}
return result;
}

@Override
@Nonnull
public List<String> subSettings()
{
return Arrays.asList( "type", "enabled", "tls_level", "address", "listen_address", "advertised_address" );
}

@Override
@Nonnull
public Map<String,Object> values( @Nonnull Map<String,String> params )
{
final HashMap<String,Object> result = new HashMap<>();

ownedEntries( params ).forEach( s ->
{
// owns has already verified that 'type' is correct and that this split is possible
String[] parts = s.getKey().split( "\\." );
final String subsetting = parts[3];

Setting<ListenSocketAddress> las = listenAddress( s.getKey(), 7687 );
switch ( subsetting )
{
case "enabled":
result.putAll( setting( s.getKey(), BOOLEAN, "false" ).values( params ) );
break;
case "tls_level":
result.putAll( setting( s.getKey(), options( BoltConnector.EncryptionLevel.class ),
OPTIONAL.name() ).values( params ) );
break;
case "address":
case "listen_address":
result.putAll( las.values( params ) );
break;
case "advertised_address":
result.putAll( advertisedAddress( s.getKey(), las ).values( params ) );
break;
case "type":
result.putAll( setting( s.getKey(), options( Connector.ConnectorType.class ), NO_DEFAULT )
.values( params ) );
break;
default:
throw new InvalidSettingException( String.format( "Unknown configuration passed to %s: %s",
getClass().getName(), s.getKey() ) );
}
} );

return result;
}
}
Expand Up @@ -20,16 +20,24 @@
package org.neo4j.kernel.configuration;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Nonnull;

import org.neo4j.graphdb.config.InvalidSettingException;
import org.neo4j.graphdb.config.Setting;
import org.neo4j.graphdb.config.SettingGroup;

import static org.neo4j.kernel.configuration.Settings.BOOLEAN;
import static org.neo4j.kernel.configuration.Settings.NO_DEFAULT;
import static org.neo4j.kernel.configuration.Settings.options;
import static org.neo4j.kernel.configuration.Settings.setting;

public abstract class ConnectorValidator implements SettingGroup<Object>
{
public static final List<String> validTypes =
Expand All @@ -43,13 +51,6 @@ public ConnectorValidator( @Nonnull Connector.ConnectorType type )
this.type = type;
}

/**
* @return a list of the internal settings of this connector. For example, if this connector is
* "dbms.connector.bolt.*" then this method returns all strings which can replace the final '*'.
*/
@Nonnull
public abstract List<String> subSettings();

/**
* Determine if this instance is responsible for validating a setting.
*
Expand All @@ -62,7 +63,7 @@ public ConnectorValidator( @Nonnull Connector.ConnectorType type )
public boolean owns( @Nonnull String key, @Nonnull Map<String,String> rawConfig ) throws InvalidSettingException
{
String[] parts = key.split( "\\." );
if ( parts.length != 4 )
if ( parts.length < 2 )
{
return false;
}
Expand All @@ -71,11 +72,17 @@ public boolean owns( @Nonnull String key, @Nonnull Map<String,String> rawConfig
return false;
}

if ( !subSettings().contains( parts[3] ) )
// Do not allow invalid settings under 'dbms.connector.**'
if ( parts.length != 4 )
{
return false;
throw new InvalidSettingException( String.format( "Invalid connector setting: %s", key ) );
}

/*if ( !subSettings().contains( parts[3] ) )
{
return false;
}*/

// A type must be specified, or it is not possible to know who owns this setting
String groupKey = parts[2];
String typeKey = String.join( ".", parts[0], parts[1], groupKey, "type" );
Expand Down Expand Up @@ -118,4 +125,53 @@ public Stream<Entry<String,String>> ownedEntries( @Nonnull Map<String,String> pa
return params.entrySet().stream()
.filter( it -> owns( it.getKey(), params ) );
}

@Override
@Nonnull
public Map<String,String> validate( @Nonnull Map<String,String> rawConfig )
throws InvalidSettingException
{
final HashMap<String,String> result = new HashMap<>();

ownedEntries( rawConfig ).forEach( s ->
result.putAll( getSettingFor( s.getKey(), rawConfig )
.orElseThrow( () -> new InvalidSettingException(
String.format( "Invalid connector setting: %s", s.getKey() ) ) )
.validate( rawConfig ) ) );

return result;
}

@Override
@Nonnull
public Map<String,Object> values( @Nonnull Map<String,String> params )
{
final HashMap<String,Object> result = new HashMap<>();

ownedEntries( params ).forEach( s ->
result.putAll( getSettingFor( s.getKey(), params )
.orElseThrow( () -> new InvalidSettingException(
String.format( "Invalid connector setting: %s", s.getKey() ) ) )
.values( params ) ) );

return result;
}

@Nonnull
protected Optional<Setting> getSettingFor( @Nonnull String settingName, @Nonnull Map<String,String> params )
{
// owns has already verified that 'type' is correct and that this split is possible
String[] parts = settingName.split( "\\." );
final String subsetting = parts[3];

switch ( subsetting )
{
case "enabled":
return Optional.of( setting( settingName, BOOLEAN, "false" ) );
case "type":
return Optional.of( setting( settingName, options( Connector.ConnectorType.class ), NO_DEFAULT ) );
default:
return Optional.empty();
}
}
}

0 comments on commit 9b3752a

Please sign in to comment.