1 package org.apache.archiva.metadata.repository.jcr;
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
22 import com.google.common.collect.ImmutableList;
23 import com.google.common.collect.ImmutableSet;
24 import org.apache.commons.lang.time.StopWatch;
25 import org.apache.jackrabbit.oak.api.Type;
26 import org.apache.jackrabbit.oak.jcr.Jcr;
27 import org.apache.jackrabbit.oak.plugins.index.AsyncIndexInfoService;
28 import org.apache.jackrabbit.oak.plugins.index.AsyncIndexInfoServiceImpl;
29 import org.apache.jackrabbit.oak.plugins.index.IndexInfoProvider;
30 import org.apache.jackrabbit.oak.plugins.index.IndexPathService;
31 import org.apache.jackrabbit.oak.plugins.index.IndexPathServiceImpl;
32 import org.apache.jackrabbit.oak.plugins.index.IndexUtils;
33 import org.apache.jackrabbit.oak.plugins.index.aggregate.SimpleNodeAggregator;
34 import org.apache.jackrabbit.oak.plugins.index.lucene.IndexAugmentorFactory;
35 import org.apache.jackrabbit.oak.plugins.index.lucene.IndexCopier;
36 import org.apache.jackrabbit.oak.plugins.index.lucene.IndexTracker;
37 import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexEditorProvider;
38 import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexInfoProvider;
39 import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexProvider;
40 import org.apache.jackrabbit.oak.plugins.index.lucene.directory.ActiveDeletedBlobCollectorFactory;
41 import org.apache.jackrabbit.oak.plugins.index.lucene.directory.BufferedOakDirectory;
42 import org.apache.jackrabbit.oak.plugins.index.lucene.directory.LuceneIndexImporter;
43 import org.apache.jackrabbit.oak.plugins.index.lucene.hybrid.DocumentQueue;
44 import org.apache.jackrabbit.oak.plugins.index.lucene.hybrid.ExternalObserverBuilder;
45 import org.apache.jackrabbit.oak.plugins.index.lucene.hybrid.LocalIndexObserver;
46 import org.apache.jackrabbit.oak.plugins.index.lucene.hybrid.NRTIndexFactory;
47 import org.apache.jackrabbit.oak.plugins.index.lucene.property.PropertyIndexCleaner;
48 import org.apache.jackrabbit.oak.plugins.index.lucene.reader.DefaultIndexReaderFactory;
49 import org.apache.jackrabbit.oak.plugins.index.lucene.score.ScorerProviderFactory;
50 import org.apache.jackrabbit.oak.plugins.index.lucene.score.impl.ScorerProviderFactoryImpl;
51 import org.apache.jackrabbit.oak.plugins.index.lucene.util.IndexDefinitionBuilder;
52 import org.apache.jackrabbit.oak.plugins.index.search.ExtractedTextCache;
53 import org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants;
54 import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore;
55 import org.apache.jackrabbit.oak.plugins.name.Namespaces;
56 import org.apache.jackrabbit.oak.segment.SegmentNodeStoreBuilders;
57 import org.apache.jackrabbit.oak.segment.file.FileStore;
58 import org.apache.jackrabbit.oak.segment.file.FileStoreBuilder;
59 import org.apache.jackrabbit.oak.segment.file.InvalidFileStoreVersionException;
60 import org.apache.jackrabbit.oak.spi.blob.FileBlobStore;
61 import org.apache.jackrabbit.oak.spi.blob.GarbageCollectableBlobStore;
62 import org.apache.jackrabbit.oak.spi.commit.BackgroundObserver;
63 import org.apache.jackrabbit.oak.spi.commit.Observer;
64 import org.apache.jackrabbit.oak.spi.lifecycle.RepositoryInitializer;
65 import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
66 import org.apache.jackrabbit.oak.spi.mount.Mounts;
67 import org.apache.jackrabbit.oak.spi.namespace.NamespaceConstants;
68 import org.apache.jackrabbit.oak.spi.query.QueryIndex;
69 import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider;
70 import org.apache.jackrabbit.oak.spi.state.Clusterable;
71 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
72 import org.apache.jackrabbit.oak.spi.state.NodeStore;
73 import org.apache.jackrabbit.oak.stats.StatisticsProvider;
74 import org.jetbrains.annotations.NotNull;
75 import org.slf4j.Logger;
76 import org.slf4j.LoggerFactory;
78 import javax.annotation.Nonnull;
79 import javax.jcr.Repository;
80 import java.io.Closeable;
81 import java.io.IOException;
82 import java.nio.file.Files;
83 import java.nio.file.Path;
84 import java.nio.file.Paths;
85 import java.util.concurrent.ExecutorService;
86 import java.util.concurrent.LinkedBlockingQueue;
87 import java.util.concurrent.ThreadFactory;
88 import java.util.concurrent.ThreadPoolExecutor;
89 import java.util.concurrent.TimeUnit;
90 import java.util.concurrent.atomic.AtomicInteger;
92 import static com.google.common.base.Preconditions.checkNotNull;
93 import static org.apache.archiva.metadata.repository.jcr.OakRepositoryFactory.StoreType.IN_MEMORY_TYPE;
94 import static org.apache.archiva.metadata.repository.jcr.OakRepositoryFactory.StoreType.SEGMENT_FILE_TYPE;
95 import static org.apache.commons.io.FileUtils.ONE_MB;
96 import static org.apache.jackrabbit.JcrConstants.*;
97 import static org.apache.jackrabbit.oak.api.Type.NAME;
98 import static org.apache.archiva.metadata.repository.jcr.JcrConstants.*;
99 import static org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils.registerMBean;
100 import static org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils.scheduleWithFixedDelay;
103 * Created by martin on 14.06.17.
105 * @author Martin Stockhammer
108 public class OakRepositoryFactory
111 private Logger log = LoggerFactory.getLogger( OakRepositoryFactory.class );
113 private FileStore fileStore;
115 private NodeStore nodeStore;
117 private IndexTracker tracker;
119 private DocumentQueue documentQueue;
121 private NRTIndexFactory nrtIndexFactory;
123 private IndexCopier indexCopier;
125 private ExecutorService executorService;
126 private ExtractedTextCache extractedTextCache;
128 private boolean hybridIndex = true;
129 private boolean prefetchEnabled = true;
130 private boolean enableAsyncIndexOpen = true;
131 int queueSize = 10000;
132 int cleanerInterval = 10*60;
133 boolean enableCopyOnWrite = true;
134 boolean enableCopyOnRead = true;
135 int cacheSizeInMB = 20;
136 int cacheExpiryInSecs = 300;
137 int threadPoolSize = 5;
139 private StatisticsProvider statisticsProvider;
141 private MountInfoProvider mountInfoProvider = Mounts.defaultMountInfoProvider();
143 private AsyncIndexInfoService asyncIndexInfoService = null;
145 private LuceneIndexProvider indexProvider;
147 private ScorerProviderFactory scorerFactory = new ScorerProviderFactoryImpl( );
148 private IndexAugmentorFactory augmentorFactory = new IndexAugmentorFactory( );
150 private ActiveDeletedBlobCollectorFactory.ActiveDeletedBlobCollector activeDeletedBlobCollector = ActiveDeletedBlobCollectorFactory.NOOP;
152 private QueryIndex.NodeAggregator nodeAggregator = new SimpleNodeAggregator( );
154 private BackgroundObserver backgroundObserver;
156 private BackgroundObserver externalIndexObserver;
158 private GarbageCollectableBlobStore blobStore;
160 private PropertyIndexCleaner cleaner;
162 private IndexPathService indexPathService;
164 private LuceneIndexEditorProvider editorProvider;
166 private Path indexDir;
168 public enum StoreType
174 private StoreType storeType = SEGMENT_FILE_TYPE;
176 private Path repositoryPath = Paths.get( "repository" );
178 public OakRepositoryFactory() {
179 final OakRepositoryFactory repositoryFactory = this;
180 Runtime.getRuntime().addShutdownHook( new Thread( ( ) -> {
181 if (repositoryFactory!=null)
183 repositoryFactory.close( );
188 private void initializeExtractedTextCache( StatisticsProvider statisticsProvider) {
189 boolean alwaysUsePreExtractedCache = false;
191 extractedTextCache = new ExtractedTextCache(
192 cacheSizeInMB * ONE_MB,
194 alwaysUsePreExtractedCache,
195 indexDir.toFile(), statisticsProvider);
198 private IndexTracker createTracker() throws IOException {
199 IndexTracker tracker;
200 if (enableCopyOnRead){
201 initializeIndexCopier();
202 log.info("Enabling CopyOnRead support. Index files would be copied under {}", indexDir.toAbsolutePath());
204 nrtIndexFactory = new NRTIndexFactory(indexCopier, statisticsProvider);
206 tracker = new IndexTracker(new DefaultIndexReaderFactory(mountInfoProvider, indexCopier), nrtIndexFactory);
208 tracker = new IndexTracker(new DefaultIndexReaderFactory(mountInfoProvider, null));
211 tracker.setAsyncIndexInfoService(asyncIndexInfoService);
216 private void initializeIndexCopier() throws IOException {
217 if(indexCopier != null){
221 if (prefetchEnabled){
222 log.info("Prefetching of index files enabled. Index would be opened after copying all new files locally");
225 indexCopier = new IndexCopier(getExecutorService(), indexDir.toFile(), prefetchEnabled);
229 ExecutorService getExecutorService(){
230 if (executorService == null){
231 executorService = createExecutor();
233 return executorService;
236 private ExecutorService createExecutor() {
237 ThreadPoolExecutor executor = new ThreadPoolExecutor(threadPoolSize, threadPoolSize, 60L, TimeUnit.SECONDS,
238 new LinkedBlockingQueue<Runnable>(), new ThreadFactory() {
239 private final AtomicInteger counter = new AtomicInteger();
240 private final Thread.UncaughtExceptionHandler handler = new Thread.UncaughtExceptionHandler() {
242 public void uncaughtException(Thread t, Throwable e) {
243 log.warn("Error occurred in asynchronous processing ", e);
247 public Thread newThread(@NotNull Runnable r) {
248 Thread thread = new Thread(r, createName());
249 thread.setDaemon(true);
250 thread.setPriority(Thread.MIN_PRIORITY);
251 thread.setUncaughtExceptionHandler(handler);
255 private String createName() {
256 return "oak-lucene-" + counter.getAndIncrement();
259 executor.setKeepAliveTime(1, TimeUnit.MINUTES);
260 executor.allowCoreThreadTimeOut(true);
264 private void initialize(){
265 if(indexProvider == null){
269 if(nodeAggregator != null){
270 log.debug("Using NodeAggregator {}", nodeAggregator.getClass());
273 indexProvider.setAggregator(nodeAggregator);
276 private void registerObserver() {
277 Observer observer = indexProvider;
278 if (enableAsyncIndexOpen) {
279 backgroundObserver = new BackgroundObserver(indexProvider, getExecutorService(), 5);
280 log.info("Registering the LuceneIndexProvider as a BackgroundObserver");
284 private void registerLocalIndexObserver(IndexTracker tracker) {
286 log.info("Hybrid indexing feature disabled");
289 documentQueue = new DocumentQueue( queueSize, tracker, getExecutorService(), statisticsProvider);
290 LocalIndexObserver localIndexObserver = new LocalIndexObserver(documentQueue, statisticsProvider);
292 int observerQueueSize = 1000;
293 int builderMaxSize = 5000;
294 // regs.add(bundleContext.registerService(JournalPropertyService.class.getName(),
295 // new LuceneJournalPropertyService(builderMaxSize), null));
296 ExternalObserverBuilder builder = new ExternalObserverBuilder(documentQueue, tracker, statisticsProvider,
297 getExecutorService(), observerQueueSize);
298 log.info("Configured JournalPropertyBuilder with max size {} and backed by BackgroundObserver " +
299 "with queue size {}", builderMaxSize, observerQueueSize);
301 Observer observer = builder.build();
302 externalIndexObserver = builder.getBackgroundObserver();
303 log.info("Hybrid indexing enabled for configured indexes with queue size of {}", queueSize );
306 private IndexInfoProvider registerIndexInfoProvider() {
307 return new LuceneIndexInfoProvider(nodeStore, asyncIndexInfoService, getIndexCheckDir().toFile());
310 private Path getIndexCheckDir() {
311 return checkNotNull(indexDir).resolve("indexCheckDir");
314 private LuceneIndexImporter registerIndexImporterProvider() {
315 return new LuceneIndexImporter(blobStore);
318 private void registerPropertyIndexCleaner( ) {
320 if (cleanerInterval <= 0) {
321 log.info("Property index cleaner would not be registered");
325 cleaner = new PropertyIndexCleaner(nodeStore, indexPathService, asyncIndexInfoService, statisticsProvider);
327 //Proxy check for DocumentNodeStore
328 if (nodeStore instanceof Clusterable ) {
329 cleaner.setRecursiveDelete(true);
330 log.info("PropertyIndexCleaner configured to perform recursive delete");
332 log.info("Property index cleaner configured to run every [{}] seconds", cleanerInterval);
335 private void registerIndexEditor( IndexTracker tracker) throws IOException {
336 boolean enableCopyOnWrite = true;
337 if (enableCopyOnWrite){
338 initializeIndexCopier();
339 editorProvider = new LuceneIndexEditorProvider(indexCopier, tracker, extractedTextCache,
340 augmentorFactory, mountInfoProvider, activeDeletedBlobCollector, null, statisticsProvider);
341 log.info("Enabling CopyOnWrite support. Index files would be copied under {}", indexDir.toAbsolutePath());
343 editorProvider = new LuceneIndexEditorProvider(null, tracker, extractedTextCache, augmentorFactory,
344 mountInfoProvider, activeDeletedBlobCollector, null, statisticsProvider);
346 editorProvider.setBlobStore(blobStore);
349 editorProvider.setIndexingQueue(checkNotNull(documentQueue));
355 public Repository createRepository()
356 throws IOException, InvalidFileStoreVersionException
359 indexDir = repositoryPath.resolve( ".index-lucene" );
360 if (!Files.exists( indexDir )) {
361 Files.createDirectories( indexDir );
363 blobStore = new FileBlobStore( indexDir.resolve( "blobs" ).toAbsolutePath().toString() );
365 statisticsProvider = StatisticsProvider.NOOP;
367 if ( SEGMENT_FILE_TYPE == storeType )
369 fileStore = FileStoreBuilder.fileStoreBuilder( repositoryPath.toFile() )
370 .withStatisticsProvider( statisticsProvider )
372 nodeStore = SegmentNodeStoreBuilders.builder( fileStore ) //
373 .withStatisticsProvider( statisticsProvider ) //
376 else if ( IN_MEMORY_TYPE == storeType )
378 nodeStore = new MemoryNodeStore( );
382 throw new IllegalArgumentException( "Store type " + storeType + " not recognized" );
385 asyncIndexInfoService = new AsyncIndexInfoServiceImpl( nodeStore );
387 indexPathService = new IndexPathServiceImpl( nodeStore, mountInfoProvider );
389 BufferedOakDirectory.setEnableWritingSingleBlobIndexFile( true );
391 initializeExtractedTextCache( statisticsProvider );
393 tracker = createTracker();
395 indexProvider = new LuceneIndexProvider(tracker, scorerFactory, augmentorFactory);
399 registerLocalIndexObserver(tracker);
400 registerIndexInfoProvider();
401 registerIndexImporterProvider();
402 registerPropertyIndexCleaner();
404 registerIndexEditor(tracker);
408 RepositoryInitializer repoInitializer = new RepositoryInitializer( )
410 private IndexDefinitionBuilder.PropertyRule initRegexAll( IndexDefinitionBuilder.IndexRule rule ) {
413 .property(JCR_LASTMODIFIED ).propertyIndex().type( "Date" ).ordered()
414 .property(JCR_PRIMARYTYPE).propertyIndex()
415 .property(JCR_MIXINTYPES).propertyIndex()
416 .property(JCR_PATH).propertyIndex().ordered()
417 .property( FulltextIndexConstants.REGEX_ALL_PROPS, true )
418 .propertyIndex().analyzed( ).nodeScopeIndex();
421 private IndexDefinitionBuilder.PropertyRule initBaseRule( IndexDefinitionBuilder.IndexRule rule ) {
424 .property(JCR_CREATED).propertyIndex().type("Date").ordered()
425 .property(JCR_LASTMODIFIED ).propertyIndex().type( "Date" ).ordered()
426 .property(JCR_PRIMARYTYPE).propertyIndex()
427 .property(JCR_MIXINTYPES).propertyIndex()
428 .property(JCR_PATH).propertyIndex().ordered()
429 .property( "id" ).propertyIndex().analyzed( );
433 public void initialize( @Nonnull NodeBuilder root )
435 NodeBuilder namespaces;
436 if ( !root.hasChildNode( NamespaceConstants.REP_NAMESPACES ) )
438 namespaces = Namespaces.createStandardMappings( root );
439 Namespaces.buildIndexNode( namespaces ); // index node for faster lookup
443 namespaces = root.getChildNode( NamespaceConstants.REP_NAMESPACES );
445 Namespaces.addCustomMapping( namespaces, "http://archiva.apache.org/jcr/", "archiva" );
447 log.info( "Creating index " );
449 NodeBuilder oakIdx = IndexUtils.getOrCreateOakIndex( root );
450 if (!oakIdx.hasChildNode( "repo-lucene" ))
452 NodeBuilder lucene = oakIdx.child( "repo-lucene" );
453 lucene.setProperty( JCR_PRIMARYTYPE, "oak:QueryIndexDefinition", NAME );
455 lucene.setProperty( "compatVersion", 2 );
456 lucene.setProperty( "type", "lucene" );
457 // lucene.setProperty("async", "async");
458 // lucene.setProperty( INCLUDE_PROPERTY_TYPES, ImmutableSet.of( ), Type.STRINGS );
459 // lucene.setProperty("refresh",true);
460 NodeBuilder rules = lucene.child( "indexRules" ).
461 setProperty( JCR_PRIMARYTYPE, NT_UNSTRUCTURED, NAME );
462 rules.setProperty( ":childOrder", ImmutableSet.of(
463 REPOSITORY_NODE_TYPE,
464 NAMESPACE_NODE_TYPE, //
466 PROJECT_VERSION_NODE_TYPE, //
467 ARTIFACT_NODE_TYPE, //
470 IndexDefinitionBuilder idxBuilder = new IndexDefinitionBuilder( lucene );
471 idxBuilder.async( "async", "nrt", "sync" ).includedPaths( "/repositories" ).evaluatePathRestrictions();
473 initBaseRule(idxBuilder.indexRule( REPOSITORY_NODE_TYPE ));
474 initBaseRule(idxBuilder.indexRule( NAMESPACE_NODE_TYPE ))
475 .property( "namespace" ).propertyIndex().analyzed();
476 initBaseRule(idxBuilder.indexRule( PROJECT_NODE_TYPE ))
477 .property( "name" ).propertyIndex().analyzed().notNullCheckEnabled().nullCheckEnabled();
478 initBaseRule( idxBuilder.indexRule( PROJECT_VERSION_NODE_TYPE ) )
479 .property("name").propertyIndex().analyzed().notNullCheckEnabled().nullCheckEnabled()
480 .property("description").propertyIndex().analyzed().notNullCheckEnabled().nullCheckEnabled()
481 .property("url").propertyIndex().analyzed( ).notNullCheckEnabled().nullCheckEnabled()
482 .property("incomplete").type("Boolean").propertyIndex()
483 .property("mailinglist/name").propertyIndex().analyzed()
484 .property("license/license.name").propertyIndex().analyzed();
485 initBaseRule(idxBuilder.indexRule( ARTIFACT_NODE_TYPE ))
486 .property( "whenGathered" ).type("Date").propertyIndex().analyzed().ordered()
487 .property("size").type("Long").propertyIndex().analyzed().ordered()
488 .property("version").propertyIndex().analyzed().ordered()
489 .property("checksums/*/value").propertyIndex();
491 initBaseRule( idxBuilder.indexRule( CHECKSUM_NODE_TYPE ) )
492 .property("type").propertyIndex()
493 .property("value").propertyIndex();
495 initRegexAll( idxBuilder.indexRule( FACET_NODE_TYPE ) )
496 .property("archiva:facetId").propertyIndex().analyzed().ordered()
497 .property("archiva:name").propertyIndex().analyzed().ordered();
500 idxBuilder.indexRule( MIXIN_META_SCM )
501 .property( "scm.connection" ).propertyIndex()
502 .property( "scm.developerConnection" ).propertyIndex()
503 .property( "scm.url").type("URI").propertyIndex().analyzed();
504 idxBuilder.indexRule( MIXIN_META_CI )
505 .property( "ci.system" ).propertyIndex( )
506 .property( "ci.ur" ).propertyIndex( ).analyzed( );
507 idxBuilder.indexRule( MIXIN_META_ISSUE )
508 .property( "issue.system").propertyIndex()
509 .property("issue.url").propertyIndex().analyzed();
510 idxBuilder.indexRule( MIXIN_META_ORGANIZATION )
511 .property( "org.name" ).propertyIndex( ).analyzed( )
512 .property( "org.url" ).propertyIndex( ).analyzed( );
513 idxBuilder.indexRule( MIXIN_META_LICENSE )
514 .property( "license.name" ).propertyIndex( ).analyzed( )
515 .property( "license.url" ).propertyIndex( ).analyzed( );
516 idxBuilder.indexRule( MIXIN_META_MAILINGLIST )
517 .property( "name" ).propertyIndex().analyzed();
518 initBaseRule(idxBuilder.indexRule( DEPENDENCY_NODE_TYPE ))
519 .property( "groupId" ).propertyIndex().analyzed().ordered()
520 .property( "artifactId").propertyIndex().analyzed().ordered()
521 .property("version").propertyIndex().analyzed().ordered()
522 .property("type").propertyIndex().analyzed().ordered()
523 .property( "classifier" ).propertyIndex().ordered()
524 .property("scope").propertyIndex()
525 .property("systemPath").propertyIndex().analyzed()
526 .property("optional").type("Boolean").propertyIndex();
528 idxBuilder.aggregateRule( PROJECT_VERSION_NODE_TYPE ).include( "dependencies")
529 .path("dependencies/*" ).relativeNode();
533 IndexUtils.createIndexDefinition( oakIdx, "baseIndexes", true, false, ImmutableList.of( "jcr:uuid", "rep:principalName" ), null );
535 log.info( "Index: {} repo-lucene: {}", lucene, lucene.getChildNode( "repo-lucene" ) );
536 log.info( "repo-lucene Properties: {}", lucene.getChildNode( "repo-lucene" ).getProperties( ) );
538 log.info( "No Index update" );
540 // IndexUtils.createIndexDefinition( )
545 // ExternalObserverBuilder builder = new ExternalObserverBuilder(queue, tracker, statsProvider,
546 // executorService, queueSize);
547 // Observer observer = builder.build();
548 // builder.getBackgroundObserver();
552 log.info( "Starting Jcr repo with nodeStore {}", nodeStore );
553 Jcr jcr = new Jcr( nodeStore ).with( editorProvider ) //
554 .with( backgroundObserver ) //
555 .with( externalIndexObserver )
557 .with( (QueryIndexProvider) indexProvider )
558 .with (repoInitializer)
559 .withAsyncIndexing( "async", 5 );
561 //.withAsyncIndexing( "async", 5 );
562 StopWatch stopWatch = new StopWatch();
564 Repository r = jcr.createRepository();
566 log.info( "time to create jcr repository: {} ms", stopWatch.getTime() );
573 private void closeSilently( Closeable service) {
579 catch ( Throwable e )
588 log.info( "Closing JCR RepositoryFactory" );
589 closeSilently( fileStore );
590 closeSilently( backgroundObserver );
591 closeSilently( externalIndexObserver );
592 closeSilently( indexProvider );
593 indexProvider = null;
594 closeSilently( documentQueue );
595 closeSilently( nrtIndexFactory );
596 closeSilently( indexCopier );
598 if (executorService != null){
599 executorService.shutdown();
602 executorService.awaitTermination(1, TimeUnit.MINUTES);
604 catch ( InterruptedException e )
606 e.printStackTrace( );
610 if (extractedTextCache != null) {
611 extractedTextCache.close();
616 public StoreType getStoreType()
621 public void setStoreType( StoreType storeType )
623 this.storeType = storeType;
626 public Path getRepositoryPath()
628 return repositoryPath;
631 public void setRepositoryPath( Path repositoryPath )
633 this.repositoryPath = repositoryPath;
636 public void setRepositoryPath( String repositoryPath )
638 this.repositoryPath = Paths.get( repositoryPath );
639 if ( !Files.exists( this.repositoryPath ) )
643 Files.createDirectories( this.repositoryPath );
645 catch ( IOException e )
647 log.error( e.getMessage(), e );
648 throw new IllegalArgumentException( "cannot create directory:" + repositoryPath, e );