@SuppressWarnings( "unchecked" ) private static <T> Lifecycle newInstance( KernelContext kernelContext, KernelExtensionFactory<T> factory, Object dependencies ) { return factory.newInstance( kernelContext, (T)dependencies ); } }
@Override public void handle( KernelExtensionFactory kernelExtensionFactory, UnsatisfiedDependencyException e ) { wrap( kernelExtensionFactory, e ).printStackTrace( out ); }
@Override public Lifecycle newInstance( KernelContext context, TestingDependencies dependencies ) { return new TestingExtension( dependencies.jobScheduler() ); } }
@Override public void init() { for ( KernelExtensionFactory<?> kernelExtensionFactory : kernelExtensionFactories ) { try { Object kernelExtensionDependencies = getKernelExtensionDependencies( kernelExtensionFactory ); Lifecycle dependency = newInstance( kernelContext, kernelExtensionFactory, kernelExtensionDependencies ); Objects.requireNonNull( dependency, kernelExtensionFactory.toString() + " returned a null KernelExtension" ); life.add( dependencies.satisfyDependency( dependency ) ); } catch ( UnsatisfiedDependencyException exception ) { kernelExtensionFailureStrategy.handle( kernelExtensionFactory, exception ); } catch ( Throwable throwable ) { kernelExtensionFailureStrategy.handle( kernelExtensionFactory, throwable ); } } life.init(); }
@Test public void shouldConsultUnsatisfiedDependencyHandlerOnFailingDependencyClasses() { // GIVEN KernelContext context = mock( KernelContext.class ); KernelExtensionFailureStrategy handler = mock( KernelExtensionFailureStrategy.class ); Dependencies dependencies = new Dependencies(); // that hasn't got anything. UninitializableKernelExtensionFactory extensionFactory = new UninitializableKernelExtensionFactory(); GlobalKernelExtensions extensions = new GlobalKernelExtensions( context, iterable( extensionFactory ), dependencies, handler ); // WHEN LifeSupport life = new LifeSupport(); life.add( extensions ); try { life.start(); // THEN verify( handler ).handle( eq( extensionFactory ), any( IllegalArgumentException.class ) ); } finally { life.shutdown(); } }
@Test public void shouldConsultUnsatisfiedDependencyHandlerOnMissingDependencies() { // GIVEN KernelContext context = mock( KernelContext.class ); KernelExtensionFailureStrategy handler = mock( KernelExtensionFailureStrategy.class ); Dependencies dependencies = new Dependencies(); // that hasn't got anything. TestingExtensionFactory extensionFactory = new TestingExtensionFactory(); GlobalKernelExtensions extensions = new GlobalKernelExtensions( context, iterable( extensionFactory ), dependencies, handler ); // WHEN LifeSupport life = new LifeSupport(); life.add( extensions ); try { life.start(); // THEN verify( handler ).handle( eq( extensionFactory ), any( UnsatisfiedDependencyException.class ) ); } finally { life.shutdown(); } }
@SuppressWarnings( "unchecked" ) public static DatabaseKernelExtensions instantiateKernelExtensions( File databaseDirectory, FileSystemAbstraction fileSystem, Config config, LogService logService, PageCache pageCache, JobScheduler jobScheduler, RecoveryCleanupWorkCollector recoveryCollector, DatabaseInfo databaseInfo, Monitors monitors, TokenHolders tokenHolders ) { Dependencies deps = new Dependencies(); deps.satisfyDependencies( fileSystem, config, logService, pageCache, recoveryCollector, monitors, jobScheduler, tokenHolders ); @SuppressWarnings( "rawtypes" ) Iterable kernelExtensions = Service.load( KernelExtensionFactory.class ); KernelContext kernelContext = new SimpleKernelContext( databaseDirectory, databaseInfo, deps ); return new DatabaseKernelExtensions( kernelContext, kernelExtensions, deps, KernelExtensionFailureStrategies.ignore() ); } }
private LifeSupport initializeExtensions( Dependencies dependencies ) { LifeSupport extensionsLife = new LifeSupport(); extensionsLife.add( new DatabaseKernelExtensions( new SimpleKernelContext( databaseLayout.databaseDirectory(), databaseInfo, dependencies ), kernelExtensionFactories, dependencies, fail() ) ); indexProviderMap = extensionsLife.add( new DefaultIndexProviderMap( dependencies, config ) ); dependencies.satisfyDependency( indexProviderMap ); extensionsLife.init(); return extensionsLife; }
@Test public void differentInstancesShouldHaveEqualHashCodesAndBeEqual() { KernelExtensionFactory<?> one = newInstance(); KernelExtensionFactory<?> two = newInstance(); assertEquals( "new instances have different hash codes", one.hashCode(), two.hashCode() ); assertEquals( "new instances are not equals", one, two ); one = loadInstance(); two = loadInstance(); assertEquals( "loaded instances have different hash codes", one.hashCode(), two.hashCode() ); assertEquals( "loaded instances are not equals", one, two ); one = loadInstance(); two = newInstance(); assertEquals( "loaded instance and new instance have different hash codes", one.hashCode(), two.hashCode() ); assertEquals( "loaded instance and new instance are not equals", one, two ); }
private static FailedToBuildKernelExtensionException wrap( KernelExtensionFactory kernelExtensionFactory, UnsatisfiedDependencyException e ) { return new FailedToBuildKernelExtensionException( "Failed to build kernel extension " + kernelExtensionFactory + " due to a missing dependency: " + e.getMessage(), e ); }
@Override public String toString() { return "KernelExtension:" + getClass().getSimpleName() + getKeys(); }
@Override public <T> T resolveDependency( Class<T> type, SelectionStrategy selector ) throws IllegalArgumentException { Iterable<? extends T> typeDependencies = resolveTypeDependencies( type ); return selector.select( type, typeDependencies ); }
AbstractKernelExtensions( KernelContext kernelContext, Iterable<KernelExtensionFactory<?>> kernelExtensionFactories, Dependencies dependencies, KernelExtensionFailureStrategy kernelExtensionFailureStrategy, ExtensionType extensionType ) { this.kernelContext = kernelContext; this.kernelExtensionFailureStrategy = kernelExtensionFailureStrategy; this.kernelExtensionFactories = stream( kernelExtensionFactories ).filter( e -> e.getExtensionType() == extensionType ).collect( toList() ); this.dependencies = dependencies; }
private static void appendKernelExtensionsList( File file, StringBuilder to, String separator ) { try ( BufferedReader reader = new BufferedReader( new FileReader( file ) ) ) { String line; while ( (line = reader.readLine()) != null ) { boolean exists = tryLoadClass( line ); to.append( separator ).append( line ).append( " (" ).append( exists ? "exists" : "DOES NOT exist" ).append( ')' ); } } catch ( IOException e ) { to.append( "Couldn't read due to " ).append( e.getMessage() ); } }
@Test public void extensionShouldHavePublicNoArgConstructor() { KernelExtensionFactory<?> instance = null; try { instance = newInstance(); } catch ( IllegalArgumentException failure ) { failure.printStackTrace(); fail( "Contract violation: extension class must have public no-arg constructor (Exception in stderr)" ); } assertNotNull( instance ); }
protected GraphDatabaseAPI graphDb( int instance ) { Map<String, String> config = configuration( instance ); return (GraphDatabaseAPI) new TestGraphDatabaseFactory().newImpermanentDatabaseBuilder().setConfig( config ).newGraphDatabase(); }
@Test public void shouldBeAbleToLoadExtensionAsAServiceProvider() { KernelExtensionFactory<?> instance = null; try { instance = loadInstance(); } catch ( ClassCastException failure ) { failure.printStackTrace(); fail( "Loaded instance does not match the extension class (Exception in stderr)" ); } assertNotNull( "Could not load the kernel extension with the provided key", instance ); assertSame( "Class of the loaded instance is a subclass of the extension class", instance.getClass(), extClass ); }
/** * Check that lifecycle status of extension is SHUTDOWN */ @Test public void shouldBeShutdown() { GraphDatabaseAPI graphdb = graphDb( 0 ); graphdb.shutdown(); assertEquals( LifecycleStatus.SHUTDOWN, graphdb.getDependencyResolver().resolveDependency( GlobalKernelExtensions .class ).resolveDependency( DummyExtension.class ).getStatus() ); } }
@Override public void handle( KernelExtensionFactory kernelExtensionFactory, Throwable e ) { wrap( kernelExtensionFactory, e ).printStackTrace( out ); } };
private static FailedToBuildKernelExtensionException wrap( KernelExtensionFactory kernelExtensionFactory, Throwable e ) { StringBuilder message = new StringBuilder( "Failed to build kernel extension " ).append( kernelExtensionFactory ); if ( e instanceof LinkageError || e instanceof ReflectiveOperationException ) { if ( e instanceof LinkageError ) { message.append( " because it is compiled with a reference to a class, method, or field, that is not in the class path: " ); } else { message.append( " because it a reflective access to a class, method, or field, that is not in the class path: " ); } message.append( '\'' ).append( e.getMessage() ).append( '\'' ); message.append( ". The most common cause of this problem, is that Neo4j has been upgraded without also upgrading all" ); message.append( "installed extensions, such as APOC. " ); message.append( "Make sure that all of your extensions are build against your specific version of Neo4j." ); } else { message.append( " because of an unanticipated error: '" ).append( e.getMessage() ).append( "'." ); } return new FailedToBuildKernelExtensionException( message.toString(), e ); }