All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.neo4j.driver.internal.DriverFactory Maven / Gradle / Ivy

There is a newer version: 5.27.0
Show newest version
/*
 * Copyright (c) 2002-2017 "Neo Technology,"
 * Network Engine for Objects in Lund AB [http://neotechnology.com]
 *
 * This file is part of Neo4j.
 *
 * 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 org.neo4j.driver.internal;

import java.io.IOException;
import java.net.URI;
import java.security.GeneralSecurityException;

import org.neo4j.driver.internal.cluster.LoadBalancer;
import org.neo4j.driver.internal.cluster.RoutingSettings;
import org.neo4j.driver.internal.net.BoltServerAddress;
import org.neo4j.driver.internal.net.SocketConnector;
import org.neo4j.driver.internal.net.pooling.PoolSettings;
import org.neo4j.driver.internal.net.pooling.SocketConnectionPool;
import org.neo4j.driver.internal.retry.ExponentialBackoffRetryLogic;
import org.neo4j.driver.internal.retry.RetryLogic;
import org.neo4j.driver.internal.retry.RetrySettings;
import org.neo4j.driver.internal.security.SecurityPlan;
import org.neo4j.driver.internal.spi.ConnectionPool;
import org.neo4j.driver.internal.spi.ConnectionProvider;
import org.neo4j.driver.internal.spi.Connector;
import org.neo4j.driver.internal.util.Clock;
import org.neo4j.driver.v1.AuthToken;
import org.neo4j.driver.v1.AuthTokens;
import org.neo4j.driver.v1.Config;
import org.neo4j.driver.v1.Driver;
import org.neo4j.driver.v1.Logger;
import org.neo4j.driver.v1.Logging;
import org.neo4j.driver.v1.exceptions.ClientException;

import static java.lang.String.format;
import static org.neo4j.driver.internal.security.SecurityPlan.insecure;
import static org.neo4j.driver.v1.Config.EncryptionLevel.REQUIRED;

public class DriverFactory
{
    public final Driver newInstance( URI uri, AuthToken authToken, RoutingSettings routingSettings,
            RetrySettings retrySettings, Config config )
    {
        BoltServerAddress address = BoltServerAddress.from( uri );
        SecurityPlan securityPlan = createSecurityPlan( address, config );
        ConnectionPool connectionPool = createConnectionPool( authToken, securityPlan, config );
        RetryLogic retryLogic = createRetryLogic( retrySettings, config.logging() );

        try
        {
            return createDriver( address, uri.getScheme(), connectionPool, config, routingSettings, securityPlan,
                    retryLogic );
        }
        catch ( Throwable driverError )
        {
            // we need to close the connection pool if driver creation threw exception
            try
            {
                connectionPool.close();
            }
            catch ( Throwable closeError )
            {
                driverError.addSuppressed( closeError );
            }
            throw driverError;
        }
    }

    private Driver createDriver( BoltServerAddress address, String scheme, ConnectionPool connectionPool,
            Config config, RoutingSettings routingSettings, SecurityPlan securityPlan, RetryLogic retryLogic )
    {
        switch ( scheme.toLowerCase() )
        {
        case "bolt":
            return createDirectDriver( address, connectionPool, config, securityPlan, retryLogic );
        case "bolt+routing":
            return createRoutingDriver( address, connectionPool, config, routingSettings, securityPlan, retryLogic );
        default:
            throw new ClientException( format( "Unsupported URI scheme: %s", scheme ) );
        }
    }

    /**
     * Creates a new driver for "bolt" scheme.
     * 

* This method is protected only for testing */ protected Driver createDirectDriver( BoltServerAddress address, ConnectionPool connectionPool, Config config, SecurityPlan securityPlan, RetryLogic retryLogic ) { ConnectionProvider connectionProvider = new DirectConnectionProvider( address, connectionPool ); SessionFactory sessionFactory = createSessionFactory( connectionProvider, retryLogic, config ); return createDriver( config, securityPlan, sessionFactory ); } /** * Creates new a new driver for "bolt+routing" scheme. *

* This method is protected only for testing */ protected Driver createRoutingDriver( BoltServerAddress address, ConnectionPool connectionPool, Config config, RoutingSettings routingSettings, SecurityPlan securityPlan, RetryLogic retryLogic ) { if ( !securityPlan.isRoutingCompatible() ) { throw new IllegalArgumentException( "The chosen security plan is not compatible with a routing driver" ); } ConnectionProvider connectionProvider = createLoadBalancer( address, connectionPool, config, routingSettings ); SessionFactory sessionFactory = createSessionFactory( connectionProvider, retryLogic, config ); return createDriver( config, securityPlan, sessionFactory ); } /** * Creates new {@link Driver}. *

* This method is protected only for testing */ protected InternalDriver createDriver( Config config, SecurityPlan securityPlan, SessionFactory sessionFactory ) { return new InternalDriver( securityPlan, sessionFactory, config.logging() ); } /** * Creates new {@link LoadBalancer} for the routing driver. *

* This method is protected only for testing */ protected LoadBalancer createLoadBalancer( BoltServerAddress address, ConnectionPool connectionPool, Config config, RoutingSettings routingSettings ) { return new LoadBalancer( address, routingSettings, connectionPool, createClock(), config.logging() ); } /** * Creates new {@link ConnectionPool}. *

* This method is protected only for testing */ protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Config config ) { authToken = authToken == null ? AuthTokens.none() : authToken; ConnectionSettings connectionSettings = new ConnectionSettings( authToken, config.connectionTimeoutMillis() ); PoolSettings poolSettings = new PoolSettings( config.maxIdleConnectionPoolSize(), config.idleTimeBeforeConnectionTest() ); Connector connector = createConnector( connectionSettings, securityPlan, config.logging() ); return new SocketConnectionPool( poolSettings, connector, createClock(), config.logging() ); } /** * Creates new {@link Clock}. *

* This method is protected only for testing */ protected Clock createClock() { return Clock.SYSTEM; } /** * Creates new {@link Connector}. *

* This method is protected only for testing */ protected Connector createConnector( ConnectionSettings connectionSettings, SecurityPlan securityPlan, Logging logging ) { return new SocketConnector( connectionSettings, securityPlan, logging ); } /** * Creates new {@link SessionFactory}. *

* This method is protected only for testing */ protected SessionFactory createSessionFactory( ConnectionProvider connectionProvider, RetryLogic retryLogic, Config config ) { return new SessionFactoryImpl( connectionProvider, retryLogic, config ); } /** * Creates new {@link RetryLogic >}. *

* This method is protected only for testing */ protected RetryLogic createRetryLogic( RetrySettings settings, Logging logging ) { return new ExponentialBackoffRetryLogic( settings, createClock(), logging ); } private static SecurityPlan createSecurityPlan( BoltServerAddress address, Config config ) { try { return createSecurityPlanImpl( address, config ); } catch ( GeneralSecurityException | IOException ex ) { throw new ClientException( "Unable to establish SSL parameters", ex ); } } /* * Establish a complete SecurityPlan based on the details provided for * driver construction. */ @SuppressWarnings( "deprecation" ) private static SecurityPlan createSecurityPlanImpl( BoltServerAddress address, Config config ) throws GeneralSecurityException, IOException { Config.EncryptionLevel encryptionLevel = config.encryptionLevel(); boolean requiresEncryption = encryptionLevel.equals( REQUIRED ); if ( requiresEncryption ) { Logger logger = config.logging().getLog( "SecurityPlan" ); switch ( config.trustStrategy().strategy() ) { // DEPRECATED CASES // case TRUST_ON_FIRST_USE: logger.warn( "Option `TRUST_ON_FIRST_USE` has been deprecated and will be removed in a future " + "version of the driver. Please switch to use `TRUST_ALL_CERTIFICATES` instead." ); return SecurityPlan.forTrustOnFirstUse( config.trustStrategy().certFile(), address, logger ); case TRUST_SIGNED_CERTIFICATES: logger.warn( "Option `TRUST_SIGNED_CERTIFICATE` has been deprecated and will be removed in a future " + "version of the driver. Please switch to use `TRUST_CUSTOM_CA_SIGNED_CERTIFICATES` instead." ); // intentional fallthrough // END OF DEPRECATED CASES // case TRUST_CUSTOM_CA_SIGNED_CERTIFICATES: return SecurityPlan.forCustomCASignedCertificates( config.trustStrategy().certFile() ); case TRUST_SYSTEM_CA_SIGNED_CERTIFICATES: return SecurityPlan.forSystemCASignedCertificates(); case TRUST_ALL_CERTIFICATES: return SecurityPlan.forAllCertificates(); default: throw new ClientException( "Unknown TLS authentication strategy: " + config.trustStrategy().strategy().name() ); } } else { return insecure(); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy