1b5840353SAdam Hornáček /* 2b5840353SAdam Hornáček * CDDL HEADER START 3b5840353SAdam Hornáček * 4b5840353SAdam Hornáček * The contents of this file are subject to the terms of the 5b5840353SAdam Hornáček * Common Development and Distribution License (the "License"). 6b5840353SAdam Hornáček * You may not use this file except in compliance with the License. 7b5840353SAdam Hornáček * 8b5840353SAdam Hornáček * See LICENSE.txt included in this distribution for the specific 9b5840353SAdam Hornáček * language governing permissions and limitations under the License. 10b5840353SAdam Hornáček * 11b5840353SAdam Hornáček * When distributing Covered Code, include this CDDL HEADER in each 12b5840353SAdam Hornáček * file and include the License file at LICENSE.txt. 13b5840353SAdam Hornáček * If applicable, add the following below this CDDL HEADER, with the 14b5840353SAdam Hornáček * fields enclosed by brackets "[]" replaced with your own identifying 15b5840353SAdam Hornáček * information: Portions Copyright [yyyy] [name of copyright owner] 16b5840353SAdam Hornáček * 17b5840353SAdam Hornáček * CDDL HEADER END 18b5840353SAdam Hornáček */ 19b5840353SAdam Hornáček 20b5840353SAdam Hornáček /* 216bfa9427SVladimir Kotal * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved. 225d9f3aa0SAdam Hornáček * Portions Copyright (c) 2017, 2020, Chris Fraire <cfraire@me.com>. 23b5840353SAdam Hornáček */ 249805b761SAdam Hornáček package org.opengrok.indexer.configuration; 25b5840353SAdam Hornáček 2668830e6dSKryštof Tulinger import static org.opengrok.indexer.configuration.Configuration.makeXMLStringAsConfiguration; 27f1e34e10SVladimir Kotal import static org.opengrok.indexer.index.IndexerUtil.getWebAppHeaders; 282ffbb0cfSVladimir Kotal 29b5840353SAdam Hornáček import java.io.File; 30b5840353SAdam Hornáček import java.io.FileNotFoundException; 31b5840353SAdam Hornáček import java.io.IOException; 32b5840353SAdam Hornáček import java.nio.file.Path; 336d9d3df9SAnatoly Akkerman import java.nio.file.Paths; 34b5840353SAdam Hornáček import java.util.ArrayList; 35937bd40dSVladimir Kotal import java.util.Arrays; 361b935619SVladimir Kotal import java.util.Collection; 372ffbb0cfSVladimir Kotal import java.util.Collections; 38b5840353SAdam Hornáček import java.util.Date; 39fadf9080SVladimir Kotal import java.util.HashMap; 409c92ca95SChris Fraire import java.util.HashSet; 41b5840353SAdam Hornáček import java.util.List; 42b5840353SAdam Hornáček import java.util.Map; 43b5840353SAdam Hornáček import java.util.Set; 44b5840353SAdam Hornáček import java.util.SortedSet; 45b5840353SAdam Hornáček import java.util.TreeSet; 46b5840353SAdam Hornáček import java.util.concurrent.ConcurrentHashMap; 47e9a23d1eSAdam Hornáček import java.util.concurrent.CopyOnWriteArraySet; 48b5840353SAdam Hornáček import java.util.concurrent.ExecutorService; 49b5840353SAdam Hornáček import java.util.concurrent.Executors; 50fb531549SVladimir Kotal import java.util.concurrent.TimeUnit; 514151dbf5SChris Fraire import java.util.function.Function; 52b5840353SAdam Hornáček import java.util.logging.Level; 53b5840353SAdam Hornáček import java.util.logging.Logger; 54b5840353SAdam Hornáček import java.util.stream.Collectors; 55aa6abf42SAdam Hornacek 56aa6abf42SAdam Hornacek import jakarta.ws.rs.client.ClientBuilder; 57aa6abf42SAdam Hornacek import jakarta.ws.rs.client.Entity; 58aa6abf42SAdam Hornacek import jakarta.ws.rs.core.Response; 5968830e6dSKryštof Tulinger import org.apache.lucene.index.IndexReader; 6068830e6dSKryštof Tulinger import org.apache.lucene.index.MultiReader; 6168830e6dSKryštof Tulinger import org.apache.lucene.search.SearcherManager; 6268830e6dSKryštof Tulinger import org.apache.lucene.store.AlreadyClosedException; 6368830e6dSKryštof Tulinger import org.apache.lucene.store.Directory; 6468830e6dSKryštof Tulinger import org.apache.lucene.store.FSDirectory; 65fb531549SVladimir Kotal import org.apache.lucene.util.NamedThreadFactory; 6632b4cd63SVladimir Kotal import org.jetbrains.annotations.VisibleForTesting; 6768830e6dSKryštof Tulinger import org.opengrok.indexer.authorization.AuthorizationFramework; 6868830e6dSKryštof Tulinger import org.opengrok.indexer.authorization.AuthorizationStack; 69fadf9080SVladimir Kotal import org.opengrok.indexer.history.FileCollector; 7068830e6dSKryštof Tulinger import org.opengrok.indexer.history.HistoryGuru; 7168830e6dSKryštof Tulinger import org.opengrok.indexer.history.RepositoryInfo; 7268830e6dSKryštof Tulinger import org.opengrok.indexer.index.IndexDatabase; 73e829566cSChris Fraire import org.opengrok.indexer.index.IndexerParallelizer; 7468830e6dSKryštof Tulinger import org.opengrok.indexer.logger.LoggerFactory; 754151dbf5SChris Fraire import org.opengrok.indexer.util.CloseableReentrantReadWriteLock; 7668830e6dSKryštof Tulinger import org.opengrok.indexer.util.CtagsUtil; 7768830e6dSKryštof Tulinger import org.opengrok.indexer.util.ForbiddenSymlinkException; 78e829566cSChris Fraire import org.opengrok.indexer.util.LazilyInstantiate; 7968830e6dSKryštof Tulinger import org.opengrok.indexer.util.PathUtils; 804151dbf5SChris Fraire import org.opengrok.indexer.util.ResourceLock; 816068c59cSVladimir Kotal import org.opengrok.indexer.util.Statistics; 82cce4eb5fSVladimir Kotal import org.opengrok.indexer.web.ApiUtils; 8368830e6dSKryštof Tulinger import org.opengrok.indexer.web.Prefix; 84369f83fbSVladimir Kotal import org.opengrok.indexer.web.Util; 8568830e6dSKryštof Tulinger import org.opengrok.indexer.web.messages.Message; 8668830e6dSKryštof Tulinger import org.opengrok.indexer.web.messages.MessagesContainer; 8768830e6dSKryštof Tulinger import org.opengrok.indexer.web.messages.MessagesContainer.AcceptedMessage; 884ce4e2b9SAdam Hornáček 89b5840353SAdam Hornáček /** 90b5840353SAdam Hornáček * The RuntimeEnvironment class is used as a placeholder for the current 91b5840353SAdam Hornáček * configuration this execution context (classloader) is using. 92b5840353SAdam Hornáček */ 93b5840353SAdam Hornáček public final class RuntimeEnvironment { 94b5840353SAdam Hornáček 95b5840353SAdam Hornáček private static final Logger LOGGER = LoggerFactory.getLogger(RuntimeEnvironment.class); 96b5840353SAdam Hornáček 97b5840353SAdam Hornáček private static final String URL_PREFIX = "/source" + Prefix.SEARCH_R + "?"; 98b5840353SAdam Hornáček 99b5840353SAdam Hornáček private Configuration configuration; 1004151dbf5SChris Fraire private final CloseableReentrantReadWriteLock configLock; 101e829566cSChris Fraire private final LazilyInstantiate<IndexerParallelizer> lzIndexerParallelizer; 102e829566cSChris Fraire private final LazilyInstantiate<ExecutorService> lzSearchExecutor; 103fb531549SVladimir Kotal private final LazilyInstantiate<ExecutorService> lzRevisionExecutor; 104b5840353SAdam Hornáček private static final RuntimeEnvironment instance = new RuntimeEnvironment(); 105b5840353SAdam Hornáček 106b5840353SAdam Hornáček private final Map<Project, List<RepositoryInfo>> repository_map = new ConcurrentHashMap<>(); 107b5840353SAdam Hornáček private final Map<String, SearcherManager> searcherManagerMap = new ConcurrentHashMap<>(); 108b5840353SAdam Hornáček 10955402125SVladimir Kotal private String configURI; 1104151dbf5SChris Fraire IncludeFiles includeFiles = new IncludeFiles(); 1114ce4e2b9SAdam Hornáček private final MessagesContainer messagesContainer = new MessagesContainer(); 1124ce4e2b9SAdam Hornáček 113b5840353SAdam Hornáček private static final IndexTimestamp indexTime = new IndexTimestamp(); 114b5840353SAdam Hornáček 115b5840353SAdam Hornáček /** 116b5840353SAdam Hornáček * Stores a transient value when 117b5840353SAdam Hornáček * {@link #setCtags(java.lang.String)} is called -- i.e. the 118b5840353SAdam Hornáček * value is not mediated to {@link Configuration}. 119b5840353SAdam Hornáček */ 120b5840353SAdam Hornáček private String ctags; 121b5840353SAdam Hornáček /** 122b5840353SAdam Hornáček * Stores a transient value when 123b5840353SAdam Hornáček * {@link #setMandoc(java.lang.String)} is called -- i.e. the 124b5840353SAdam Hornáček * value is not mediated to {@link Configuration}. 125b5840353SAdam Hornáček */ 126b5840353SAdam Hornáček private String mandoc; 127b5840353SAdam Hornáček 1282ffbb0cfSVladimir Kotal private transient File dtagsEftar = null; 1292ffbb0cfSVladimir Kotal 1309c92ca95SChris Fraire private transient volatile Boolean ctagsFound; 1319c92ca95SChris Fraire private final transient Set<String> ctagsLanguages = new HashSet<>(); 1329c92ca95SChris Fraire 13323287255SVladimir Kotal private final WatchDogService watchDog; 1349c92ca95SChris Fraire 135e9a23d1eSAdam Hornáček private final Set<ConfigurationChangedListener> listeners = new CopyOnWriteArraySet<>(); 136e9a23d1eSAdam Hornáček getSubFiles()1370d7ace53SVladimir Kotal public List<String> getSubFiles() { 1380d7ace53SVladimir Kotal return subFiles; 1390d7ace53SVladimir Kotal } 1400d7ace53SVladimir Kotal 141c6f0939bSAdam Hornacek private final List<String> subFiles = new ArrayList<>(); 1420d7ace53SVladimir Kotal 143b5840353SAdam Hornáček /** 144fadf9080SVladimir Kotal * Maps project name to FileCollector object. This is used to pass the list of files acquired when 145fadf9080SVladimir Kotal * generating history cache in the first phase of indexing to the second phase of indexing. 146fadf9080SVladimir Kotal */ 147fadf9080SVladimir Kotal private final Map<String, FileCollector> fileCollectorMap = new HashMap<>(); 148fadf9080SVladimir Kotal 149fadf9080SVladimir Kotal /** 1502ffbb0cfSVladimir Kotal * Creates a new instance of RuntimeEnvironment. Private to ensure a 1512ffbb0cfSVladimir Kotal * singleton anti-pattern. 152b5840353SAdam Hornáček */ RuntimeEnvironment()1532ffbb0cfSVladimir Kotal private RuntimeEnvironment() { 1542ffbb0cfSVladimir Kotal configuration = new Configuration(); 1554151dbf5SChris Fraire configLock = new CloseableReentrantReadWriteLock(); 1562ffbb0cfSVladimir Kotal watchDog = new WatchDogService(); 157e829566cSChris Fraire lzIndexerParallelizer = LazilyInstantiate.using(() -> 158e829566cSChris Fraire new IndexerParallelizer(this)); 159c6f0939bSAdam Hornacek lzSearchExecutor = LazilyInstantiate.using(this::newSearchExecutor); 160c6f0939bSAdam Hornacek lzRevisionExecutor = LazilyInstantiate.using(this::newRevisionExecutor); 1612ffbb0cfSVladimir Kotal } 1622ffbb0cfSVladimir Kotal 1631cbb0597SVladimir Kotal // Instance of authorization framework and its lock. 164b5840353SAdam Hornáček private AuthorizationFramework authFramework; 1651cbb0597SVladimir Kotal private final Object authFrameworkLock = new Object(); 166b5840353SAdam Hornáček 1670d7ace53SVladimir Kotal private boolean indexer; 1680d7ace53SVladimir Kotal isIndexer()1690d7ace53SVladimir Kotal public boolean isIndexer() { 1700d7ace53SVladimir Kotal return indexer; 1710d7ace53SVladimir Kotal } 1720d7ace53SVladimir Kotal setIndexer(boolean indexer)1730d7ace53SVladimir Kotal public void setIndexer(boolean indexer) { 1740d7ace53SVladimir Kotal this.indexer = indexer; 1750d7ace53SVladimir Kotal } 1760d7ace53SVladimir Kotal 17723287255SVladimir Kotal /** 17823287255SVladimir Kotal * @return {@code WatchDogService} instance 17923287255SVladimir Kotal */ getWatchDog()18023287255SVladimir Kotal public WatchDogService getWatchDog() { 18123287255SVladimir Kotal return watchDog; 18223287255SVladimir Kotal } 18323287255SVladimir Kotal 184e829566cSChris Fraire /** Gets the thread pool used for multi-project searches. */ getSearchExecutor()185e829566cSChris Fraire public ExecutorService getSearchExecutor() { 186e829566cSChris Fraire return lzSearchExecutor.get(); 187b5840353SAdam Hornáček } 188b5840353SAdam Hornáček newSearchExecutor()189e829566cSChris Fraire private ExecutorService newSearchExecutor() { 190e829566cSChris Fraire return Executors.newFixedThreadPool( 191b5840353SAdam Hornáček this.getMaxSearchThreadCount(), 192c6f0939bSAdam Hornacek runnable -> { 193b5840353SAdam Hornáček Thread thread = Executors.defaultThreadFactory().newThread(runnable); 194b5840353SAdam Hornáček thread.setName("search-" + thread.getId()); 195b5840353SAdam Hornáček return thread; 196b5840353SAdam Hornáček }); 197b5840353SAdam Hornáček } 198b5840353SAdam Hornáček getRevisionExecutor()199fb531549SVladimir Kotal public ExecutorService getRevisionExecutor() { 200fb531549SVladimir Kotal return lzRevisionExecutor.get(); 201fb531549SVladimir Kotal } 202fb531549SVladimir Kotal newRevisionExecutor()203fb531549SVladimir Kotal private ExecutorService newRevisionExecutor() { 204fb531549SVladimir Kotal return Executors.newFixedThreadPool(this.getMaxRevisionThreadCount(), 205fb531549SVladimir Kotal new NamedThreadFactory("get-revision")); 206fb531549SVladimir Kotal } 207fb531549SVladimir Kotal shutdownRevisionExecutor()208fb531549SVladimir Kotal public void shutdownRevisionExecutor() throws InterruptedException { 209fb531549SVladimir Kotal getRevisionExecutor().shutdownNow(); 210a904b83aSVladimir Kotal getRevisionExecutor().awaitTermination(getIndexerCommandTimeout(), TimeUnit.SECONDS); 211fb531549SVladimir Kotal } 212fb531549SVladimir Kotal 213b5840353SAdam Hornáček /** 214ff44f24aSAdam Hornáček * Get the one and only instance of the RuntimeEnvironment. 215b5840353SAdam Hornáček * 216b5840353SAdam Hornáček * @return the one and only instance of the RuntimeEnvironment 217b5840353SAdam Hornáček */ getInstance()218b5840353SAdam Hornáček public static RuntimeEnvironment getInstance() { 219b5840353SAdam Hornáček return instance; 220b5840353SAdam Hornáček } 221b5840353SAdam Hornáček getIndexerParallelizer()222e829566cSChris Fraire public IndexerParallelizer getIndexerParallelizer() { 223e829566cSChris Fraire return lzIndexerParallelizer.get(); 224e829566cSChris Fraire } 225e829566cSChris Fraire 22640669eceSChris Fraire /** 22740669eceSChris Fraire * Gets an instance associated to this environment. 22840669eceSChris Fraire */ getPathAccepter()22940669eceSChris Fraire public PathAccepter getPathAccepter() { 23040669eceSChris Fraire return new PathAccepter(getIgnoredNames(), getIncludedNames()); 23140669eceSChris Fraire } 23240669eceSChris Fraire getCanonicalPath(String s)233b5840353SAdam Hornáček private String getCanonicalPath(String s) { 234ff44f24aSAdam Hornáček if (s == null) { 235ff44f24aSAdam Hornáček return null; 236ff44f24aSAdam Hornáček } 237b5840353SAdam Hornáček try { 238b5840353SAdam Hornáček File file = new File(s); 239b5840353SAdam Hornáček if (!file.exists()) { 240b5840353SAdam Hornáček return s; 241b5840353SAdam Hornáček } 242b5840353SAdam Hornáček return file.getCanonicalPath(); 243b5840353SAdam Hornáček } catch (IOException ex) { 244b5840353SAdam Hornáček LOGGER.log(Level.SEVERE, "Failed to get canonical path", ex); 245b5840353SAdam Hornáček return s; 246b5840353SAdam Hornáček } 247b5840353SAdam Hornáček } 248b5840353SAdam Hornáček getScanningDepth()249b5840353SAdam Hornáček public int getScanningDepth() { 2504151dbf5SChris Fraire return syncReadConfiguration(Configuration::getScanningDepth); 251b5840353SAdam Hornáček } 252b5840353SAdam Hornáček setScanningDepth(int scanningDepth)253b5840353SAdam Hornáček public void setScanningDepth(int scanningDepth) { 254754ebdfbSChris Fraire syncWriteConfiguration(scanningDepth, Configuration::setScanningDepth); 255b5840353SAdam Hornáček } 256b5840353SAdam Hornáček getNestingMaximum()2572402fe1cSChris Fraire public int getNestingMaximum() { 2582402fe1cSChris Fraire return syncReadConfiguration(Configuration::getNestingMaximum); 2592402fe1cSChris Fraire } 2602402fe1cSChris Fraire setNestingMaximum(int nestingMaximum)2612402fe1cSChris Fraire public void setNestingMaximum(int nestingMaximum) { 2622402fe1cSChris Fraire syncWriteConfiguration(nestingMaximum, Configuration::setNestingMaximum); 2632402fe1cSChris Fraire } 2642402fe1cSChris Fraire getCommandTimeout(CommandTimeoutType cmdType)265a904b83aSVladimir Kotal public int getCommandTimeout(CommandTimeoutType cmdType) { 266a904b83aSVladimir Kotal switch (cmdType) { 267a904b83aSVladimir Kotal case INDEXER: 268a904b83aSVladimir Kotal return getIndexerCommandTimeout(); 269a904b83aSVladimir Kotal case INTERACTIVE: 270a904b83aSVladimir Kotal return getInteractiveCommandTimeout(); 271a904b83aSVladimir Kotal case WEBAPP_START: 272a904b83aSVladimir Kotal return getWebappStartCommandTimeout(); 273a904b83aSVladimir Kotal case RESTFUL: 274a904b83aSVladimir Kotal return getRestfulCommandTimeout(); 275b5840353SAdam Hornáček } 276b5840353SAdam Hornáček 2778b57b0e7SVladimir Kotal throw new IllegalArgumentException("invalid command timeout type"); 278a904b83aSVladimir Kotal } 279a904b83aSVladimir Kotal getRestfulCommandTimeout()280a904b83aSVladimir Kotal public int getRestfulCommandTimeout() { 281a904b83aSVladimir Kotal return syncReadConfiguration(Configuration::getRestfulCommandTimeout); 282a904b83aSVladimir Kotal } 283a904b83aSVladimir Kotal setRestfulCommandTimeout(int timeout)284a904b83aSVladimir Kotal public void setRestfulCommandTimeout(int timeout) { 285a904b83aSVladimir Kotal syncWriteConfiguration(timeout, Configuration::setWebappStartCommandTimeout); 286a904b83aSVladimir Kotal } 287a904b83aSVladimir Kotal getWebappStartCommandTimeout()288a904b83aSVladimir Kotal public int getWebappStartCommandTimeout() { 289a904b83aSVladimir Kotal return syncReadConfiguration(Configuration::getWebappStartCommandTimeout); 290a904b83aSVladimir Kotal } 291a904b83aSVladimir Kotal setWebappStartCommandTimeout(int timeout)292a904b83aSVladimir Kotal public void setWebappStartCommandTimeout(int timeout) { 293a904b83aSVladimir Kotal syncWriteConfiguration(timeout, Configuration::setWebappStartCommandTimeout); 294a904b83aSVladimir Kotal } 295a904b83aSVladimir Kotal getIndexerCommandTimeout()296a904b83aSVladimir Kotal public int getIndexerCommandTimeout() { 297a904b83aSVladimir Kotal return syncReadConfiguration(Configuration::getIndexerCommandTimeout); 298a904b83aSVladimir Kotal } 299a904b83aSVladimir Kotal setIndexerCommandTimeout(int timeout)300a904b83aSVladimir Kotal public void setIndexerCommandTimeout(int timeout) { 301a904b83aSVladimir Kotal syncWriteConfiguration(timeout, Configuration::setIndexerCommandTimeout); 302b5840353SAdam Hornáček } 303b5840353SAdam Hornáček getInteractiveCommandTimeout()304b5840353SAdam Hornáček public int getInteractiveCommandTimeout() { 3054151dbf5SChris Fraire return syncReadConfiguration(Configuration::getInteractiveCommandTimeout); 306b5840353SAdam Hornáček } 307b5840353SAdam Hornáček setInteractiveCommandTimeout(int timeout)308a904b83aSVladimir Kotal public void setInteractiveCommandTimeout(int timeout) { 309a904b83aSVladimir Kotal syncWriteConfiguration(timeout, Configuration::setInteractiveCommandTimeout); 310b5840353SAdam Hornáček } 311b82c5e9dSVladimir Kotal getCtagsTimeout()312b124dbe6SVladimir Kotal public long getCtagsTimeout() { 3134151dbf5SChris Fraire return syncReadConfiguration(Configuration::getCtagsTimeout); 314b82c5e9dSVladimir Kotal } 315b82c5e9dSVladimir Kotal setCtagsTimeout(long timeout)316a904b83aSVladimir Kotal public void setCtagsTimeout(long timeout) { 317a904b83aSVladimir Kotal syncWriteConfiguration(timeout, Configuration::setCtagsTimeout); 318b82c5e9dSVladimir Kotal } 319b5840353SAdam Hornáček getXrefTimeout()320e92cec67SVladimir Kotal public long getXrefTimeout() { 321e92cec67SVladimir Kotal return syncReadConfiguration(Configuration::getXrefTimeout); 322e92cec67SVladimir Kotal } 323e92cec67SVladimir Kotal setXrefTimeout(long timeout)324e92cec67SVladimir Kotal public void setXrefTimeout(long timeout) { 325e92cec67SVladimir Kotal syncWriteConfiguration(timeout, Configuration::setXrefTimeout); 326e92cec67SVladimir Kotal } 327e92cec67SVladimir Kotal setLastEditedDisplayMode(boolean lastEditedDisplayMode)328b5840353SAdam Hornáček public void setLastEditedDisplayMode(boolean lastEditedDisplayMode) { 329754ebdfbSChris Fraire syncWriteConfiguration(lastEditedDisplayMode, Configuration::setLastEditedDisplayMode); 330b5840353SAdam Hornáček } 331b5840353SAdam Hornáček isLastEditedDisplayMode()332b5840353SAdam Hornáček public boolean isLastEditedDisplayMode() { 3334151dbf5SChris Fraire return syncReadConfiguration(Configuration::isLastEditedDisplayMode); 334b5840353SAdam Hornáček } 335b5840353SAdam Hornáček 336b5840353SAdam Hornáček /** 337ff44f24aSAdam Hornáček * Get the path to the where the web application includes are stored. 338a03922c4SAdam Hornáček * 339a03922c4SAdam Hornáček * @return the path to the web application include files 340a03922c4SAdam Hornáček */ getIncludeRootPath()341a03922c4SAdam Hornáček public String getIncludeRootPath() { 3424151dbf5SChris Fraire return syncReadConfiguration(Configuration::getIncludeRoot); 343a03922c4SAdam Hornáček } 344a03922c4SAdam Hornáček 345a03922c4SAdam Hornáček /** 346ff44f24aSAdam Hornáček * Set include root path. 3476630f04dSVladimir Kotal * @param includeRoot path 3486630f04dSVladimir Kotal */ setIncludeRoot(String includeRoot)3496630f04dSVladimir Kotal public void setIncludeRoot(String includeRoot) { 350754ebdfbSChris Fraire syncWriteConfiguration(getCanonicalPath(includeRoot), Configuration::setIncludeRoot); 3516630f04dSVladimir Kotal } 3526630f04dSVladimir Kotal 3536630f04dSVladimir Kotal /** 354ff44f24aSAdam Hornáček * Get the path to the where the index database is stored. 355b5840353SAdam Hornáček * 356b5840353SAdam Hornáček * @return the path to the index database 357b5840353SAdam Hornáček */ getDataRootPath()358b5840353SAdam Hornáček public String getDataRootPath() { 3594151dbf5SChris Fraire return syncReadConfiguration(Configuration::getDataRoot); 360b5840353SAdam Hornáček } 361b5840353SAdam Hornáček 362b5840353SAdam Hornáček /** 363ff44f24aSAdam Hornáček * Get a file representing the index database. 364b5840353SAdam Hornáček * 365b5840353SAdam Hornáček * @return the index database 366b5840353SAdam Hornáček */ getDataRootFile()367b5840353SAdam Hornáček public File getDataRootFile() { 368b5840353SAdam Hornáček File ret = null; 369b5840353SAdam Hornáček String file = getDataRootPath(); 370b5840353SAdam Hornáček if (file != null) { 371b5840353SAdam Hornáček ret = new File(file); 372b5840353SAdam Hornáček } 373b5840353SAdam Hornáček 374b5840353SAdam Hornáček return ret; 375b5840353SAdam Hornáček } 376b5840353SAdam Hornáček 377b5840353SAdam Hornáček /** 378ff44f24aSAdam Hornáček * Set the path to where the index database is stored. 379b5840353SAdam Hornáček * 380b5840353SAdam Hornáček * @param dataRoot the index database 381b5840353SAdam Hornáček */ setDataRoot(String dataRoot)382b5840353SAdam Hornáček public void setDataRoot(String dataRoot) { 383754ebdfbSChris Fraire syncWriteConfiguration(getCanonicalPath(dataRoot), Configuration::setDataRoot); 384b5840353SAdam Hornáček } 385b5840353SAdam Hornáček 386b5840353SAdam Hornáček /** 387ff44f24aSAdam Hornáček * Get the path to where the sources are located. 388b5840353SAdam Hornáček * 389b5840353SAdam Hornáček * @return path to where the sources are located 390b5840353SAdam Hornáček */ getSourceRootPath()391b5840353SAdam Hornáček public String getSourceRootPath() { 3924151dbf5SChris Fraire return syncReadConfiguration(Configuration::getSourceRoot); 393b5840353SAdam Hornáček } 394b5840353SAdam Hornáček 395b5840353SAdam Hornáček /** 396ff44f24aSAdam Hornáček * Get a file representing the directory where the sources are located. 397b5840353SAdam Hornáček * 398b5840353SAdam Hornáček * @return A file representing the directory where the sources are located 399b5840353SAdam Hornáček */ getSourceRootFile()400b5840353SAdam Hornáček public File getSourceRootFile() { 401b5840353SAdam Hornáček File ret = null; 402b5840353SAdam Hornáček String file = getSourceRootPath(); 403b5840353SAdam Hornáček if (file != null) { 404b5840353SAdam Hornáček ret = new File(file); 405b5840353SAdam Hornáček } 406b5840353SAdam Hornáček 407b5840353SAdam Hornáček return ret; 408b5840353SAdam Hornáček } 409b5840353SAdam Hornáček 410b5840353SAdam Hornáček /** 411ff44f24aSAdam Hornáček * Specify the source root. 412b5840353SAdam Hornáček * 413b5840353SAdam Hornáček * @param sourceRoot the location of the sources 414b5840353SAdam Hornáček */ setSourceRoot(String sourceRoot)415b5840353SAdam Hornáček public void setSourceRoot(String sourceRoot) { 416754ebdfbSChris Fraire syncWriteConfiguration(getCanonicalPath(sourceRoot), Configuration::setSourceRoot); 417b5840353SAdam Hornáček } 418b5840353SAdam Hornáček 419b5840353SAdam Hornáček /** 420b5840353SAdam Hornáček * Returns a path relative to source root. This would just be a simple 421b5840353SAdam Hornáček * substring operation, except we need to support symlinks outside the 422b5840353SAdam Hornáček * source root. 423b5840353SAdam Hornáček * 424b5840353SAdam Hornáček * @param file A file to resolve 425b5840353SAdam Hornáček * @return Path relative to source root 426b5840353SAdam Hornáček * @throws IOException If an IO error occurs 427b5840353SAdam Hornáček * @throws FileNotFoundException if the file is not relative to source root 4282738be5eSChris Fraire * or if {@code sourceRoot} is not defined 429b5840353SAdam Hornáček * @throws ForbiddenSymlinkException if symbolic-link checking encounters 430b5840353SAdam Hornáček * an ineligible link 431b5840353SAdam Hornáček */ getPathRelativeToSourceRoot(File file)432b5840353SAdam Hornáček public String getPathRelativeToSourceRoot(File file) 433b5840353SAdam Hornáček throws IOException, ForbiddenSymlinkException { 4342738be5eSChris Fraire String sourceRoot = getSourceRootPath(); 4352738be5eSChris Fraire if (sourceRoot == null) { 4362738be5eSChris Fraire throw new FileNotFoundException("sourceRoot is not defined"); 4372738be5eSChris Fraire } 4382738be5eSChris Fraire 4396d9d3df9SAnatoly Akkerman String maybeRelPath = PathUtils.getRelativeToCanonical(file.toPath(), 4406d9d3df9SAnatoly Akkerman Paths.get(sourceRoot), getAllowedSymlinks(), getCanonicalRoots()); 4412738be5eSChris Fraire File maybeRelFile = new File(maybeRelPath); 4422738be5eSChris Fraire if (!maybeRelFile.isAbsolute()) { 4432738be5eSChris Fraire /* 4442738be5eSChris Fraire * N.b. OpenGrok has a weird convention that source-root "relative" 4452738be5eSChris Fraire * paths must start with a '/' as they are elsewhere directly 4462738be5eSChris Fraire * appended to getSourceRootPath() and also stored as such. 4472738be5eSChris Fraire */ 4482738be5eSChris Fraire maybeRelPath = File.separator + maybeRelPath; 4492738be5eSChris Fraire return maybeRelPath; 4502738be5eSChris Fraire } 4512738be5eSChris Fraire 4522738be5eSChris Fraire throw new FileNotFoundException("Failed to resolve [" + file.getPath() 4532738be5eSChris Fraire + "] relative to source root [" + sourceRoot + "]"); 454b5840353SAdam Hornáček } 455b5840353SAdam Hornáček 456b5840353SAdam Hornáček /** 457b5840353SAdam Hornáček * Do we have any projects ? 458b5840353SAdam Hornáček * 459b5840353SAdam Hornáček * @return true if we have projects 460b5840353SAdam Hornáček */ hasProjects()461b5840353SAdam Hornáček public boolean hasProjects() { 462b5840353SAdam Hornáček return (this.isProjectsEnabled() && getProjects().size() > 0); 463b5840353SAdam Hornáček } 464b5840353SAdam Hornáček 465b5840353SAdam Hornáček /** 466b5840353SAdam Hornáček * Get list of projects. 467b5840353SAdam Hornáček * 468fa055da0SVladimir Kotal * @return a list containing all the projects 469b5840353SAdam Hornáček */ getProjectList()470b5840353SAdam Hornáček public List<Project> getProjectList() { 4712ffbb0cfSVladimir Kotal return new ArrayList<>(getProjects().values()); 472b5840353SAdam Hornáček } 473b5840353SAdam Hornáček 474b5840353SAdam Hornáček /** 475b5840353SAdam Hornáček * Get project map. 476b5840353SAdam Hornáček * 4777e740a87SVladimir Kotal * @return a Map with all the projects 478b5840353SAdam Hornáček */ getProjects()479b5840353SAdam Hornáček public Map<String, Project> getProjects() { 4804151dbf5SChris Fraire return syncReadConfiguration(Configuration::getProjects); 481b5840353SAdam Hornáček } 482b5840353SAdam Hornáček 483b5840353SAdam Hornáček /** 484b5840353SAdam Hornáček * Get names of all projects. 485b5840353SAdam Hornáček * 486b5840353SAdam Hornáček * @return a list containing names of all projects. 487b5840353SAdam Hornáček */ getProjectNames()488b5840353SAdam Hornáček public List<String> getProjectNames() { 4892ffbb0cfSVladimir Kotal return getProjectList().stream().map(Project::getName).collect(Collectors.toList()); 490b5840353SAdam Hornáček } 491b5840353SAdam Hornáček 492b5840353SAdam Hornáček /** 493ff44f24aSAdam Hornáček * Set the list of the projects. 494b5840353SAdam Hornáček * 495b5840353SAdam Hornáček * @param projects the map of projects to use 496b5840353SAdam Hornáček */ setProjects(Map<String, Project> projects)497b5840353SAdam Hornáček public void setProjects(Map<String, Project> projects) { 498754ebdfbSChris Fraire syncWriteConfiguration(projects, (c, p) -> { 4994151dbf5SChris Fraire if (p != null) { 5004151dbf5SChris Fraire populateGroups(getGroups(), new TreeSet<>(p.values())); 501b5840353SAdam Hornáček } 5024151dbf5SChris Fraire c.setProjects(p); 503754ebdfbSChris Fraire }); 504b5840353SAdam Hornáček } 505b5840353SAdam Hornáček 506b5840353SAdam Hornáček /** 507b5840353SAdam Hornáček * Do we have groups? 508b5840353SAdam Hornáček * 509b5840353SAdam Hornáček * @return true if we have groups 510b5840353SAdam Hornáček */ hasGroups()511b5840353SAdam Hornáček public boolean hasGroups() { 512b5840353SAdam Hornáček return (getGroups() != null && !getGroups().isEmpty()); 513b5840353SAdam Hornáček } 514b5840353SAdam Hornáček 515b5840353SAdam Hornáček /** 516ff44f24aSAdam Hornáček * Get all of the groups. 517b5840353SAdam Hornáček * 518b5840353SAdam Hornáček * @return a set containing all of the groups (may be null) 519b5840353SAdam Hornáček */ getGroups()520b5840353SAdam Hornáček public Set<Group> getGroups() { 5214151dbf5SChris Fraire return syncReadConfiguration(Configuration::getGroups); 522b5840353SAdam Hornáček } 523b5840353SAdam Hornáček 524b5840353SAdam Hornáček /** 525ff44f24aSAdam Hornáček * Set the list of the groups. 526b5840353SAdam Hornáček * 527b5840353SAdam Hornáček * @param groups the set of groups to use 528b5840353SAdam Hornáček */ setGroups(Set<Group> groups)529b5840353SAdam Hornáček public void setGroups(Set<Group> groups) { 530754ebdfbSChris Fraire syncWriteConfiguration(groups, (c, g) -> { 5314151dbf5SChris Fraire populateGroups(g, new TreeSet<>(getProjects().values())); 5324151dbf5SChris Fraire c.setGroups(g); 533754ebdfbSChris Fraire }); 534b5840353SAdam Hornáček } 535b5840353SAdam Hornáček 536b5840353SAdam Hornáček /** 537b5840353SAdam Hornáček * Returns constructed project - repositories map. 538b5840353SAdam Hornáček * 539b5840353SAdam Hornáček * @return the map 540b5840353SAdam Hornáček * @see #generateProjectRepositoriesMap 541b5840353SAdam Hornáček */ getProjectRepositoriesMap()542b5840353SAdam Hornáček public Map<Project, List<RepositoryInfo>> getProjectRepositoriesMap() { 543b5840353SAdam Hornáček return repository_map; 544b5840353SAdam Hornáček } 545b5840353SAdam Hornáček 546b5840353SAdam Hornáček /** 547b5840353SAdam Hornáček * Gets a static placeholder for the web application context name that is 548b5840353SAdam Hornáček * translated to the true servlet {@code contextPath} on demand. 549b5840353SAdam Hornáček * @return {@code "/source"} + {@link Prefix#SEARCH_R} + {@code "?"} 550b5840353SAdam Hornáček */ getUrlPrefix()551b5840353SAdam Hornáček public String getUrlPrefix() { 552b5840353SAdam Hornáček return URL_PREFIX; 553b5840353SAdam Hornáček } 554b5840353SAdam Hornáček 555b5840353SAdam Hornáček /** 556b5840353SAdam Hornáček * Gets the name of the ctags program to use: either the last value passed 557b5840353SAdam Hornáček * successfully to {@link #setCtags(java.lang.String)}, or 558b5840353SAdam Hornáček * {@link Configuration#getCtags()}, or the system property for 5599805b761SAdam Hornáček * {@code "org.opengrok.indexer.analysis.Ctags"}, or "ctags" as a 560b5840353SAdam Hornáček * default. 561b5840353SAdam Hornáček * @return a defined value 562b5840353SAdam Hornáček */ getCtags()563b5840353SAdam Hornáček public String getCtags() { 5644151dbf5SChris Fraire if (ctags != null) { 5654151dbf5SChris Fraire return ctags; 5664151dbf5SChris Fraire } 5674151dbf5SChris Fraire 5684151dbf5SChris Fraire String value = syncReadConfiguration(Configuration::getCtags); 5694151dbf5SChris Fraire return value != null ? value : 5702ffbb0cfSVladimir Kotal System.getProperty(CtagsUtil.SYSTEM_CTAGS_PROPERTY, "ctags"); 571b5840353SAdam Hornáček } 572b5840353SAdam Hornáček 573b5840353SAdam Hornáček /** 574b5840353SAdam Hornáček * Sets the name of the ctags program to use, or resets to use the fallbacks 575b5840353SAdam Hornáček * documented for {@link #getCtags()}. 576b5840353SAdam Hornáček * <p> 577b5840353SAdam Hornáček * N.b. the value is not mediated to {@link Configuration}. 578b5840353SAdam Hornáček * 579b5840353SAdam Hornáček * @param ctags a defined value or {@code null} to reset to use the 580b5840353SAdam Hornáček * {@link Configuration#getCtags()} fallbacks 581b5840353SAdam Hornáček * @see #getCtags() 582b5840353SAdam Hornáček */ setCtags(String ctags)583b5840353SAdam Hornáček public void setCtags(String ctags) { 584b5840353SAdam Hornáček this.ctags = ctags; 585b5840353SAdam Hornáček } 586b5840353SAdam Hornáček 587b5840353SAdam Hornáček /** 588b5840353SAdam Hornáček * Gets the name of the mandoc program to use: either the last value passed 589b5840353SAdam Hornáček * successfully to {@link #setMandoc(java.lang.String)}, or 590b5840353SAdam Hornáček * {@link Configuration#getMandoc()}, or the system property for 5919805b761SAdam Hornáček * {@code "org.opengrok.indexer.analysis.Mandoc"}, or {@code null} as a 592b5840353SAdam Hornáček * default. 593b5840353SAdam Hornáček * @return a defined instance or {@code null} 594b5840353SAdam Hornáček */ getMandoc()595b5840353SAdam Hornáček public String getMandoc() { 5964151dbf5SChris Fraire if (mandoc != null) { 5974151dbf5SChris Fraire return mandoc; 5984151dbf5SChris Fraire } 5994151dbf5SChris Fraire 6004151dbf5SChris Fraire String value = syncReadConfiguration(Configuration::getMandoc); 6014151dbf5SChris Fraire return value != null ? value : 6029805b761SAdam Hornáček System.getProperty("org.opengrok.indexer.analysis.Mandoc"); 603b5840353SAdam Hornáček } 604b5840353SAdam Hornáček 605b5840353SAdam Hornáček /** 606b5840353SAdam Hornáček * Sets the name of the mandoc program to use, or resets to use the 607b5840353SAdam Hornáček * fallbacks documented for {@link #getMandoc()}. 608b5840353SAdam Hornáček * <p> 609b5840353SAdam Hornáček * N.b. the value is not mediated to {@link Configuration}. 610b5840353SAdam Hornáček * 611b5840353SAdam Hornáček * @param value a defined value or {@code null} to reset to use the 612b5840353SAdam Hornáček * {@link Configuration#getMandoc()} fallbacks 613b5840353SAdam Hornáček * @see #getMandoc() 614b5840353SAdam Hornáček */ setMandoc(String value)615b5840353SAdam Hornáček public void setMandoc(String value) { 616b5840353SAdam Hornáček this.mandoc = value; 617b5840353SAdam Hornáček } 618b5840353SAdam Hornáček getCachePages()619b5840353SAdam Hornáček public int getCachePages() { 6204151dbf5SChris Fraire return syncReadConfiguration(Configuration::getCachePages); 621b5840353SAdam Hornáček } 622b5840353SAdam Hornáček setCachePages(int cachePages)623b5840353SAdam Hornáček public void setCachePages(int cachePages) { 624754ebdfbSChris Fraire syncWriteConfiguration(cachePages, Configuration::setCachePages); 625b5840353SAdam Hornáček } 626b5840353SAdam Hornáček getHitsPerPage()627b5840353SAdam Hornáček public int getHitsPerPage() { 6284151dbf5SChris Fraire return syncReadConfiguration(Configuration::getHitsPerPage); 629b5840353SAdam Hornáček } 630b5840353SAdam Hornáček setHitsPerPage(int hitsPerPage)631b5840353SAdam Hornáček public void setHitsPerPage(int hitsPerPage) { 632754ebdfbSChris Fraire syncWriteConfiguration(hitsPerPage, Configuration::setHitsPerPage); 633b5840353SAdam Hornáček } 634b5840353SAdam Hornáček 635b5840353SAdam Hornáček /** 6362a63f72dSVladimir Kotal * Validate that there is a Universal ctags program. 637b5840353SAdam Hornáček * 638b5840353SAdam Hornáček * @return true if success, false otherwise 639b5840353SAdam Hornáček */ validateUniversalCtags()6402a63f72dSVladimir Kotal public boolean validateUniversalCtags() { 6412a63f72dSVladimir Kotal if (ctagsFound == null) { 6429c92ca95SChris Fraire String ctagsBinary = getCtags(); 6434151dbf5SChris Fraire try (ResourceLock resourceLock = configLock.writeLockAsResource()) { 6444151dbf5SChris Fraire //noinspection ConstantConditions to avoid warning of no reference to auto-closeable 6454151dbf5SChris Fraire assert resourceLock != null; 6469c92ca95SChris Fraire if (ctagsFound == null) { 6479c92ca95SChris Fraire ctagsFound = CtagsUtil.validate(ctagsBinary); 6489c92ca95SChris Fraire if (ctagsFound) { 6499c92ca95SChris Fraire List<String> languages = CtagsUtil.getLanguages(ctagsBinary); 6509c92ca95SChris Fraire if (languages != null) { 6519c92ca95SChris Fraire ctagsLanguages.addAll(languages); 6529c92ca95SChris Fraire } 6539c92ca95SChris Fraire } 6549c92ca95SChris Fraire } 655b5840353SAdam Hornáček } 656b5840353SAdam Hornáček } 6572a63f72dSVladimir Kotal return ctagsFound; 658b5840353SAdam Hornáček } 659b5840353SAdam Hornáček 660b5840353SAdam Hornáček /** 6619c92ca95SChris Fraire * Gets the base set of supported Ctags languages. 6629c92ca95SChris Fraire * @return a defined set which may be empty if 6639c92ca95SChris Fraire * {@link #validateUniversalCtags()} has not yet been called or if the call 6649c92ca95SChris Fraire * fails 6659c92ca95SChris Fraire */ getCtagsLanguages()6669c92ca95SChris Fraire public Set<String> getCtagsLanguages() { 6679c92ca95SChris Fraire return Collections.unmodifiableSet(ctagsLanguages); 6689c92ca95SChris Fraire } 6699c92ca95SChris Fraire 6709c92ca95SChris Fraire /** 671b5840353SAdam Hornáček * Is history cache currently enabled? 672b5840353SAdam Hornáček * 673b5840353SAdam Hornáček * @return true if history cache is enabled 674b5840353SAdam Hornáček */ useHistoryCache()675b5840353SAdam Hornáček public boolean useHistoryCache() { 6764151dbf5SChris Fraire return syncReadConfiguration(Configuration::isHistoryCache); 677b5840353SAdam Hornáček } 678b5840353SAdam Hornáček 679b5840353SAdam Hornáček /** 680ff44f24aSAdam Hornáček * Specify if we should use history cache or not. 681b5840353SAdam Hornáček * 682b5840353SAdam Hornáček * @param useHistoryCache set false if you do not want to use history cache 683b5840353SAdam Hornáček */ setUseHistoryCache(boolean useHistoryCache)684b5840353SAdam Hornáček public void setUseHistoryCache(boolean useHistoryCache) { 685754ebdfbSChris Fraire syncWriteConfiguration(useHistoryCache, Configuration::setHistoryCache); 686b5840353SAdam Hornáček } 687b5840353SAdam Hornáček 688b5840353SAdam Hornáček /** 689ff44f24aSAdam Hornáček * Should we generate HTML or not during the indexing phase. 690b5840353SAdam Hornáček * 691b5840353SAdam Hornáček * @return true if HTML should be generated during the indexing phase 692b5840353SAdam Hornáček */ isGenerateHtml()693b5840353SAdam Hornáček public boolean isGenerateHtml() { 6944151dbf5SChris Fraire return syncReadConfiguration(Configuration::isGenerateHtml); 695b5840353SAdam Hornáček } 696b5840353SAdam Hornáček 697b5840353SAdam Hornáček /** 698ff44f24aSAdam Hornáček * Specify if we should generate HTML or not during the indexing phase. 699b5840353SAdam Hornáček * 700b5840353SAdam Hornáček * @param generateHtml set this to true to pregenerate HTML 701b5840353SAdam Hornáček */ setGenerateHtml(boolean generateHtml)702b5840353SAdam Hornáček public void setGenerateHtml(boolean generateHtml) { 703754ebdfbSChris Fraire syncWriteConfiguration(generateHtml, Configuration::setGenerateHtml); 704b5840353SAdam Hornáček } 705b5840353SAdam Hornáček 706b5840353SAdam Hornáček /** 707ff44f24aSAdam Hornáček * Set if we should compress the xref files or not. 708b5840353SAdam Hornáček * 709b5840353SAdam Hornáček * @param compressXref set to true if the generated html files should be 710b5840353SAdam Hornáček * compressed 711b5840353SAdam Hornáček */ setCompressXref(boolean compressXref)712b5840353SAdam Hornáček public void setCompressXref(boolean compressXref) { 713754ebdfbSChris Fraire syncWriteConfiguration(compressXref, Configuration::setCompressXref); 714b5840353SAdam Hornáček } 715b5840353SAdam Hornáček 716b5840353SAdam Hornáček /** 717b5840353SAdam Hornáček * Are we using compressed HTML files? 718b5840353SAdam Hornáček * 719b5840353SAdam Hornáček * @return {@code true} if the html-files should be compressed. 720b5840353SAdam Hornáček */ isCompressXref()721b5840353SAdam Hornáček public boolean isCompressXref() { 7224151dbf5SChris Fraire return syncReadConfiguration(Configuration::isCompressXref); 723b5840353SAdam Hornáček } 724b5840353SAdam Hornáček isQuickContextScan()725b5840353SAdam Hornáček public boolean isQuickContextScan() { 7264151dbf5SChris Fraire return syncReadConfiguration(Configuration::isQuickContextScan); 727b5840353SAdam Hornáček } 728b5840353SAdam Hornáček setQuickContextScan(boolean quickContextScan)729b5840353SAdam Hornáček public void setQuickContextScan(boolean quickContextScan) { 730754ebdfbSChris Fraire syncWriteConfiguration(quickContextScan, Configuration::setQuickContextScan); 731b5840353SAdam Hornáček } 732b5840353SAdam Hornáček getRepositories()733b5840353SAdam Hornáček public List<RepositoryInfo> getRepositories() { 7344151dbf5SChris Fraire return syncReadConfiguration(Configuration::getRepositories); 735b5840353SAdam Hornáček } 736b5840353SAdam Hornáček 737b5840353SAdam Hornáček /** 738b5840353SAdam Hornáček * Set the list of repositories. 739b5840353SAdam Hornáček * 740b5840353SAdam Hornáček * @param repositories the repositories to use 741b5840353SAdam Hornáček */ setRepositories(List<RepositoryInfo> repositories)742b5840353SAdam Hornáček public void setRepositories(List<RepositoryInfo> repositories) { 743754ebdfbSChris Fraire syncWriteConfiguration(repositories, Configuration::setRepositories); 744b5840353SAdam Hornáček } 745b5840353SAdam Hornáček removeRepositories()746b5840353SAdam Hornáček public void removeRepositories() { 747754ebdfbSChris Fraire syncWriteConfiguration(null, Configuration::setRepositories); 748b5840353SAdam Hornáček } 749b5840353SAdam Hornáček 750b5840353SAdam Hornáček /** 751b5840353SAdam Hornáček * Search through the directory for repositories and use the result to replace 752b5840353SAdam Hornáček * the lists of repositories in both RuntimeEnvironment/Configuration and HistoryGuru. 753b5840353SAdam Hornáček * 754937bd40dSVladimir Kotal * @param dir the directories to start the search in 755b5840353SAdam Hornáček */ setRepositories(String... dir)756937bd40dSVladimir Kotal public void setRepositories(String... dir) { 757b5840353SAdam Hornáček List<RepositoryInfo> repos = new ArrayList<>(HistoryGuru.getInstance(). 75840669eceSChris Fraire addRepositories(Arrays.stream(dir).map(File::new).toArray(File[]::new))); 7594151dbf5SChris Fraire setRepositories(repos); 760b5840353SAdam Hornáček } 761b5840353SAdam Hornáček 762b5840353SAdam Hornáček /** 763b5840353SAdam Hornáček * Add repositories to the list. 764b5840353SAdam Hornáček * @param repositories list of repositories 765b5840353SAdam Hornáček */ addRepositories(List<RepositoryInfo> repositories)766b5840353SAdam Hornáček public void addRepositories(List<RepositoryInfo> repositories) { 767754ebdfbSChris Fraire syncWriteConfiguration(repositories, Configuration::addRepositories); 768b5840353SAdam Hornáček } 769b5840353SAdam Hornáček 770b5840353SAdam Hornáček /** 771369f83fbSVladimir Kotal * Set the specified projects as default in the configuration. 772369f83fbSVladimir Kotal * This method should be called only after projects were discovered and became part of the configuration, 773369f83fbSVladimir Kotal * i.e. after {@link org.opengrok.indexer.index.Indexer#prepareIndexer} was called. 774369f83fbSVladimir Kotal * 775369f83fbSVladimir Kotal * @param defaultProjects The default project to use 776369f83fbSVladimir Kotal * @see #setDefaultProjects 777369f83fbSVladimir Kotal */ setDefaultProjectsFromNames(Set<String> defaultProjects)778369f83fbSVladimir Kotal public void setDefaultProjectsFromNames(Set<String> defaultProjects) { 779369f83fbSVladimir Kotal if (defaultProjects != null && !defaultProjects.isEmpty()) { 780369f83fbSVladimir Kotal Set<Project> projects = new TreeSet<>(); 781369f83fbSVladimir Kotal for (String projectPath : defaultProjects) { 782369f83fbSVladimir Kotal if (projectPath.equals("__all__")) { 783369f83fbSVladimir Kotal projects.addAll(getProjects().values()); 784369f83fbSVladimir Kotal break; 785369f83fbSVladimir Kotal } 786369f83fbSVladimir Kotal for (Project p : getProjectList()) { 787369f83fbSVladimir Kotal if (p.getPath().equals(Util.fixPathIfWindows(projectPath))) { 788369f83fbSVladimir Kotal projects.add(p); 789369f83fbSVladimir Kotal break; 790369f83fbSVladimir Kotal } 791369f83fbSVladimir Kotal } 792369f83fbSVladimir Kotal } 793369f83fbSVladimir Kotal if (!projects.isEmpty()) { 794369f83fbSVladimir Kotal setDefaultProjects(projects); 795369f83fbSVladimir Kotal } 796369f83fbSVladimir Kotal } 797369f83fbSVladimir Kotal } 798369f83fbSVladimir Kotal 799369f83fbSVladimir Kotal /** 800b5840353SAdam Hornáček * Set the projects that are specified to be the default projects to use. 801b5840353SAdam Hornáček * The default projects are the projects you will search (from the web 802b5840353SAdam Hornáček * application) if the page request didn't contain the cookie.. 803b5840353SAdam Hornáček * 8042ffbb0cfSVladimir Kotal * @param defaultProjects The default project to use 805b5840353SAdam Hornáček */ setDefaultProjects(Set<Project> defaultProjects)8062ffbb0cfSVladimir Kotal public void setDefaultProjects(Set<Project> defaultProjects) { 807754ebdfbSChris Fraire syncWriteConfiguration(defaultProjects, Configuration::setDefaultProjects); 808b5840353SAdam Hornáček } 809b5840353SAdam Hornáček 810b5840353SAdam Hornáček /** 811b5840353SAdam Hornáček * Get the projects that are specified to be the default projects to use. 812b5840353SAdam Hornáček * The default projects are the projects you will search (from the web 813b5840353SAdam Hornáček * application) if the page request didn't contain the cookie.. 814b5840353SAdam Hornáček * 815b5840353SAdam Hornáček * @return the default projects (may be null if not specified) 816b5840353SAdam Hornáček */ getDefaultProjects()817b5840353SAdam Hornáček public Set<Project> getDefaultProjects() { 8184151dbf5SChris Fraire Set<Project> projects = syncReadConfiguration(Configuration::getDefaultProjects); 8192ffbb0cfSVladimir Kotal if (projects == null) { 8202ffbb0cfSVladimir Kotal return null; 8212ffbb0cfSVladimir Kotal } 8222ffbb0cfSVladimir Kotal return Collections.unmodifiableSet(projects); 823b5840353SAdam Hornáček } 824b5840353SAdam Hornáček 825b5840353SAdam Hornáček /** 826b5840353SAdam Hornáček * 827b5840353SAdam Hornáček * @return at what size (in MB) we should flush the buffer 828b5840353SAdam Hornáček */ getRamBufferSize()829b5840353SAdam Hornáček public double getRamBufferSize() { 8304151dbf5SChris Fraire return syncReadConfiguration(Configuration::getRamBufferSize); 831b5840353SAdam Hornáček } 832b5840353SAdam Hornáček 833b5840353SAdam Hornáček /** 834b5840353SAdam Hornáček * Set the size of buffer which will determine when the docs are flushed to 835b5840353SAdam Hornáček * disk. Specify size in MB please. 16MB is default note that this is per 836b5840353SAdam Hornáček * thread (lucene uses 8 threads by default in 4.x) 837b5840353SAdam Hornáček * 838b5840353SAdam Hornáček * @param ramBufferSize the size(in MB) when we should flush the docs 839b5840353SAdam Hornáček */ setRamBufferSize(double ramBufferSize)840b5840353SAdam Hornáček public void setRamBufferSize(double ramBufferSize) { 841754ebdfbSChris Fraire syncWriteConfiguration(ramBufferSize, Configuration::setRamBufferSize); 842b5840353SAdam Hornáček } 843b5840353SAdam Hornáček setPluginDirectory(String pluginDirectory)844b5840353SAdam Hornáček public void setPluginDirectory(String pluginDirectory) { 845754ebdfbSChris Fraire syncWriteConfiguration(pluginDirectory, Configuration::setPluginDirectory); 846b5840353SAdam Hornáček } 847b5840353SAdam Hornáček getPluginDirectory()848b5840353SAdam Hornáček public String getPluginDirectory() { 8494151dbf5SChris Fraire return syncReadConfiguration(Configuration::getPluginDirectory); 850b5840353SAdam Hornáček } 851b5840353SAdam Hornáček isAuthorizationWatchdog()852b5840353SAdam Hornáček public boolean isAuthorizationWatchdog() { 8534151dbf5SChris Fraire return syncReadConfiguration(Configuration::isAuthorizationWatchdogEnabled); 854b5840353SAdam Hornáček } 855b5840353SAdam Hornáček setAuthorizationWatchdog(boolean authorizationWatchdogEnabled)856b5840353SAdam Hornáček public void setAuthorizationWatchdog(boolean authorizationWatchdogEnabled) { 857754ebdfbSChris Fraire syncWriteConfiguration(authorizationWatchdogEnabled, 858754ebdfbSChris Fraire Configuration::setAuthorizationWatchdogEnabled); 859b5840353SAdam Hornáček } 860b5840353SAdam Hornáček getPluginStack()861b5840353SAdam Hornáček public AuthorizationStack getPluginStack() { 8624151dbf5SChris Fraire return syncReadConfiguration(Configuration::getPluginStack); 863b5840353SAdam Hornáček } 864b5840353SAdam Hornáček setPluginStack(AuthorizationStack pluginStack)865b5840353SAdam Hornáček public void setPluginStack(AuthorizationStack pluginStack) { 866754ebdfbSChris Fraire syncWriteConfiguration(pluginStack, Configuration::setPluginStack); 867b5840353SAdam Hornáček } 868b5840353SAdam Hornáček 869b5840353SAdam Hornáček /** 870b5840353SAdam Hornáček * Is the progress print flag turned on? 871b5840353SAdam Hornáček * 872b5840353SAdam Hornáček * @return true if we can print per project progress % 873b5840353SAdam Hornáček */ isPrintProgress()874b5840353SAdam Hornáček public boolean isPrintProgress() { 8754151dbf5SChris Fraire return syncReadConfiguration(Configuration::isPrintProgress); 876b5840353SAdam Hornáček } 877b5840353SAdam Hornáček 878b5840353SAdam Hornáček /** 879ff44f24aSAdam Hornáček * Set the printing of progress % flag (user convenience). 880b5840353SAdam Hornáček * 8812ffbb0cfSVladimir Kotal * @param printProgress new value 882b5840353SAdam Hornáček */ setPrintProgress(boolean printProgress)8832ffbb0cfSVladimir Kotal public void setPrintProgress(boolean printProgress) { 884754ebdfbSChris Fraire syncWriteConfiguration(printProgress, Configuration::setPrintProgress); 885b5840353SAdam Hornáček } 886b5840353SAdam Hornáček 887b5840353SAdam Hornáček /** 888b5840353SAdam Hornáček * Specify if a search may start with a wildcard. Note that queries that 889b5840353SAdam Hornáček * start with a wildcard will give a significant impact on the search 890b5840353SAdam Hornáček * performance. 891b5840353SAdam Hornáček * 892b5840353SAdam Hornáček * @param allowLeadingWildcard set to true to activate (disabled by default) 893b5840353SAdam Hornáček */ setAllowLeadingWildcard(boolean allowLeadingWildcard)894b5840353SAdam Hornáček public void setAllowLeadingWildcard(boolean allowLeadingWildcard) { 895754ebdfbSChris Fraire syncWriteConfiguration(allowLeadingWildcard, Configuration::setAllowLeadingWildcard); 896b5840353SAdam Hornáček } 897b5840353SAdam Hornáček 898b5840353SAdam Hornáček /** 899b5840353SAdam Hornáček * Is leading wildcards allowed? 900b5840353SAdam Hornáček * 901b5840353SAdam Hornáček * @return true if a search may start with a wildcard 902b5840353SAdam Hornáček */ isAllowLeadingWildcard()903b5840353SAdam Hornáček public boolean isAllowLeadingWildcard() { 9044151dbf5SChris Fraire return syncReadConfiguration(Configuration::isAllowLeadingWildcard); 905b5840353SAdam Hornáček } 906b5840353SAdam Hornáček getIgnoredNames()907b5840353SAdam Hornáček public IgnoredNames getIgnoredNames() { 9084151dbf5SChris Fraire return syncReadConfiguration(Configuration::getIgnoredNames); 909b5840353SAdam Hornáček } 910b5840353SAdam Hornáček setIgnoredNames(IgnoredNames ignoredNames)911b5840353SAdam Hornáček public void setIgnoredNames(IgnoredNames ignoredNames) { 912754ebdfbSChris Fraire syncWriteConfiguration(ignoredNames, Configuration::setIgnoredNames); 913b5840353SAdam Hornáček } 914b5840353SAdam Hornáček getIncludedNames()915b5840353SAdam Hornáček public Filter getIncludedNames() { 9164151dbf5SChris Fraire return syncReadConfiguration(Configuration::getIncludedNames); 917b5840353SAdam Hornáček } 918b5840353SAdam Hornáček setIncludedNames(Filter includedNames)919b5840353SAdam Hornáček public void setIncludedNames(Filter includedNames) { 920754ebdfbSChris Fraire syncWriteConfiguration(includedNames, Configuration::setIncludedNames); 921b5840353SAdam Hornáček } 922b5840353SAdam Hornáček 923b5840353SAdam Hornáček /** 924ff44f24aSAdam Hornáček * Returns the user page for the history listing. 925b5840353SAdam Hornáček * 926b5840353SAdam Hornáček * @return the URL string fragment preceeding the username 927b5840353SAdam Hornáček */ getUserPage()928b5840353SAdam Hornáček public String getUserPage() { 9294151dbf5SChris Fraire return syncReadConfiguration(Configuration::getUserPage); 930b5840353SAdam Hornáček } 931b5840353SAdam Hornáček 932b5840353SAdam Hornáček /** 933b5840353SAdam Hornáček * Get the client command to use to access the repository for the given 934b5840353SAdam Hornáček * fully qualified classname. 935b5840353SAdam Hornáček * 936b5840353SAdam Hornáček * @param clazzName name of the targeting class 937b5840353SAdam Hornáček * @return {@code null} if not yet set, the client command otherwise. 938b5840353SAdam Hornáček */ getRepoCmd(String clazzName)939b5840353SAdam Hornáček public String getRepoCmd(String clazzName) { 9404151dbf5SChris Fraire return syncReadConfiguration(c -> c.getRepoCmd(clazzName)); 941b5840353SAdam Hornáček } 942b5840353SAdam Hornáček 943b5840353SAdam Hornáček /** 944b5840353SAdam Hornáček * Set the client command to use to access the repository for the given 945b5840353SAdam Hornáček * fully qualified classname. 946b5840353SAdam Hornáček * 947b5840353SAdam Hornáček * @param clazzName name of the targeting class. If {@code null} this method 948b5840353SAdam Hornáček * does nothing. 949b5840353SAdam Hornáček * @param cmd the client command to use. If {@code null} the corresponding 950b5840353SAdam Hornáček * entry for the given clazzName get removed. 951b5840353SAdam Hornáček * @return the client command previously set, which might be {@code null}. 952b5840353SAdam Hornáček */ setRepoCmd(String clazzName, String cmd)953b5840353SAdam Hornáček public String setRepoCmd(String clazzName, String cmd) { 954754ebdfbSChris Fraire syncWriteConfiguration(null, (c, ignored) -> c.setRepoCmd(clazzName, cmd)); 9552ffbb0cfSVladimir Kotal return cmd; 956b5840353SAdam Hornáček } 957b5840353SAdam Hornáček setRepoCmds(Map<String, String> cmds)95829816c3bSChris Fraire public void setRepoCmds(Map<String, String> cmds) { 959754ebdfbSChris Fraire syncWriteConfiguration(cmds, Configuration::setCmds); 96029816c3bSChris Fraire } 96129816c3bSChris Fraire 962b5840353SAdam Hornáček /** 963ff44f24aSAdam Hornáček * Sets the user page for the history listing. 964b5840353SAdam Hornáček * 965b5840353SAdam Hornáček * @param userPage the URL fragment preceeding the username from history 966b5840353SAdam Hornáček */ setUserPage(String userPage)967b5840353SAdam Hornáček public void setUserPage(String userPage) { 968754ebdfbSChris Fraire syncWriteConfiguration(userPage, Configuration::setUserPage); 969b5840353SAdam Hornáček } 970b5840353SAdam Hornáček 971b5840353SAdam Hornáček /** 972ff44f24aSAdam Hornáček * Returns the user page suffix for the history listing. 973b5840353SAdam Hornáček * 974b5840353SAdam Hornáček * @return the URL string fragment following the username 975b5840353SAdam Hornáček */ getUserPageSuffix()976b5840353SAdam Hornáček public String getUserPageSuffix() { 9774151dbf5SChris Fraire return syncReadConfiguration(Configuration::getUserPageSuffix); 978b5840353SAdam Hornáček } 979b5840353SAdam Hornáček 980b5840353SAdam Hornáček /** 981ff44f24aSAdam Hornáček * Sets the user page suffix for the history listing. 982b5840353SAdam Hornáček * 983b5840353SAdam Hornáček * @param userPageSuffix the URL fragment following the username from 984b5840353SAdam Hornáček * history 985b5840353SAdam Hornáček */ setUserPageSuffix(String userPageSuffix)986b5840353SAdam Hornáček public void setUserPageSuffix(String userPageSuffix) { 987754ebdfbSChris Fraire syncWriteConfiguration(userPageSuffix, Configuration::setUserPageSuffix); 988b5840353SAdam Hornáček } 989b5840353SAdam Hornáček 990b5840353SAdam Hornáček /** 991ff44f24aSAdam Hornáček * Returns the bug page for the history listing. 992b5840353SAdam Hornáček * 993b5840353SAdam Hornáček * @return the URL string fragment preceeding the bug ID 994b5840353SAdam Hornáček */ getBugPage()995b5840353SAdam Hornáček public String getBugPage() { 9964151dbf5SChris Fraire return syncReadConfiguration(Configuration::getBugPage); 997b5840353SAdam Hornáček } 998b5840353SAdam Hornáček 999b5840353SAdam Hornáček /** 1000ff44f24aSAdam Hornáček * Sets the bug page for the history listing. 1001b5840353SAdam Hornáček * 1002b5840353SAdam Hornáček * @param bugPage the URL fragment preceeding the bug ID 1003b5840353SAdam Hornáček */ setBugPage(String bugPage)1004b5840353SAdam Hornáček public void setBugPage(String bugPage) { 1005754ebdfbSChris Fraire syncWriteConfiguration(bugPage, Configuration::setBugPage); 1006b5840353SAdam Hornáček } 1007b5840353SAdam Hornáček 1008b5840353SAdam Hornáček /** 1009ff44f24aSAdam Hornáček * Returns the bug regex for the history listing. 1010b5840353SAdam Hornáček * 1011b5840353SAdam Hornáček * @return the regex that is looked for in history comments 1012b5840353SAdam Hornáček */ getBugPattern()1013b5840353SAdam Hornáček public String getBugPattern() { 10144151dbf5SChris Fraire return syncReadConfiguration(Configuration::getBugPattern); 1015b5840353SAdam Hornáček } 1016b5840353SAdam Hornáček 1017b5840353SAdam Hornáček /** 1018ff44f24aSAdam Hornáček * Sets the bug regex for the history listing. 1019b5840353SAdam Hornáček * 1020b5840353SAdam Hornáček * @param bugPattern the regex to search history comments 1021b5840353SAdam Hornáček */ setBugPattern(String bugPattern)10224151dbf5SChris Fraire public void setBugPattern(String bugPattern) { 1023754ebdfbSChris Fraire syncWriteConfiguration(bugPattern, Configuration::setBugPattern); 1024b5840353SAdam Hornáček } 1025b5840353SAdam Hornáček 1026b5840353SAdam Hornáček /** 1027ff44f24aSAdam Hornáček * Returns the review(ARC) page for the history listing. 1028b5840353SAdam Hornáček * 1029b5840353SAdam Hornáček * @return the URL string fragment preceeding the review page ID 1030b5840353SAdam Hornáček */ getReviewPage()1031b5840353SAdam Hornáček public String getReviewPage() { 10324151dbf5SChris Fraire return syncReadConfiguration(Configuration::getReviewPage); 1033b5840353SAdam Hornáček } 1034b5840353SAdam Hornáček 1035b5840353SAdam Hornáček /** 1036ff44f24aSAdam Hornáček * Sets the review(ARC) page for the history listing. 1037b5840353SAdam Hornáček * 1038b5840353SAdam Hornáček * @param reviewPage the URL fragment preceeding the review page ID 1039b5840353SAdam Hornáček */ setReviewPage(String reviewPage)1040b5840353SAdam Hornáček public void setReviewPage(String reviewPage) { 1041754ebdfbSChris Fraire syncWriteConfiguration(reviewPage, Configuration::setReviewPage); 1042b5840353SAdam Hornáček } 1043b5840353SAdam Hornáček 1044b5840353SAdam Hornáček /** 1045ff44f24aSAdam Hornáček * Returns the review(ARC) regex for the history listing. 1046b5840353SAdam Hornáček * 1047b5840353SAdam Hornáček * @return the regex that is looked for in history comments 1048b5840353SAdam Hornáček */ getReviewPattern()1049b5840353SAdam Hornáček public String getReviewPattern() { 10504151dbf5SChris Fraire return syncReadConfiguration(Configuration::getReviewPattern); 1051b5840353SAdam Hornáček } 1052b5840353SAdam Hornáček 1053b5840353SAdam Hornáček /** 1054ff44f24aSAdam Hornáček * Sets the review(ARC) regex for the history listing. 1055b5840353SAdam Hornáček * 1056b5840353SAdam Hornáček * @param reviewPattern the regex to search history comments 1057b5840353SAdam Hornáček */ setReviewPattern(String reviewPattern)10584151dbf5SChris Fraire public void setReviewPattern(String reviewPattern) { 1059754ebdfbSChris Fraire syncWriteConfiguration(reviewPattern, Configuration::setReviewPattern); 1060b5840353SAdam Hornáček } 1061b5840353SAdam Hornáček getWebappLAF()1062b5840353SAdam Hornáček public String getWebappLAF() { 10634151dbf5SChris Fraire return syncReadConfiguration(Configuration::getWebappLAF); 1064b5840353SAdam Hornáček } 1065b5840353SAdam Hornáček setWebappLAF(String webappLAF)1066754ebdfbSChris Fraire public void setWebappLAF(String webappLAF) { 1067754ebdfbSChris Fraire syncWriteConfiguration(webappLAF, Configuration::setWebappLAF); 1068b5840353SAdam Hornáček } 1069b5840353SAdam Hornáček 1070e829566cSChris Fraire /** 1071e829566cSChris Fraire * Gets a value indicating if the web app should run ctags as necessary. 1072e829566cSChris Fraire * @return the value of {@link Configuration#isWebappCtags()} 1073e829566cSChris Fraire */ isWebappCtags()1074e829566cSChris Fraire public boolean isWebappCtags() { 10754151dbf5SChris Fraire return syncReadConfiguration(Configuration::isWebappCtags); 1076e829566cSChris Fraire } 1077e829566cSChris Fraire getRemoteScmSupported()1078b5840353SAdam Hornáček public Configuration.RemoteSCM getRemoteScmSupported() { 10794151dbf5SChris Fraire return syncReadConfiguration(Configuration::getRemoteScmSupported); 1080b5840353SAdam Hornáček } 1081b5840353SAdam Hornáček setRemoteScmSupported(Configuration.RemoteSCM remoteScmSupported)1082754ebdfbSChris Fraire public void setRemoteScmSupported(Configuration.RemoteSCM remoteScmSupported) { 1083754ebdfbSChris Fraire syncWriteConfiguration(remoteScmSupported, Configuration::setRemoteScmSupported); 1084b5840353SAdam Hornáček } 1085b5840353SAdam Hornáček isOptimizeDatabase()1086b5840353SAdam Hornáček public boolean isOptimizeDatabase() { 10874151dbf5SChris Fraire return syncReadConfiguration(Configuration::isOptimizeDatabase); 1088b5840353SAdam Hornáček } 1089b5840353SAdam Hornáček setOptimizeDatabase(boolean optimizeDatabase)1090b5840353SAdam Hornáček public void setOptimizeDatabase(boolean optimizeDatabase) { 1091754ebdfbSChris Fraire syncWriteConfiguration(optimizeDatabase, Configuration::setOptimizeDatabase); 1092b5840353SAdam Hornáček } 1093b5840353SAdam Hornáček getLuceneLocking()1094b5840353SAdam Hornáček public LuceneLockName getLuceneLocking() { 10954151dbf5SChris Fraire return syncReadConfiguration(Configuration::getLuceneLocking); 1096b5840353SAdam Hornáček } 1097b5840353SAdam Hornáček isIndexVersionedFilesOnly()1098b5840353SAdam Hornáček public boolean isIndexVersionedFilesOnly() { 10994151dbf5SChris Fraire return syncReadConfiguration(Configuration::isIndexVersionedFilesOnly); 1100b5840353SAdam Hornáček } 1101b5840353SAdam Hornáček setIndexVersionedFilesOnly(boolean indexVersionedFilesOnly)1102b5840353SAdam Hornáček public void setIndexVersionedFilesOnly(boolean indexVersionedFilesOnly) { 1103754ebdfbSChris Fraire syncWriteConfiguration(indexVersionedFilesOnly, Configuration::setIndexVersionedFilesOnly); 1104b5840353SAdam Hornáček } 1105b5840353SAdam Hornáček 1106b5840353SAdam Hornáček /** 1107b5840353SAdam Hornáček * Gets the value of {@link Configuration#getIndexingParallelism()} -- or 1108b5840353SAdam Hornáček * if zero, then as a default gets the number of available processors. 1109b5840353SAdam Hornáček * @return a natural number >= 1 1110b5840353SAdam Hornáček */ getIndexingParallelism()1111b5840353SAdam Hornáček public int getIndexingParallelism() { 11124151dbf5SChris Fraire int parallelism = syncReadConfiguration(Configuration::getIndexingParallelism); 1113b5840353SAdam Hornáček return parallelism < 1 ? Runtime.getRuntime().availableProcessors() : 1114b5840353SAdam Hornáček parallelism; 1115b5840353SAdam Hornáček } 1116b5840353SAdam Hornáček 1117b5840353SAdam Hornáček /** 11182123e367SVladimir Kotal * Gets the value of {@link Configuration#getRepositoryInvalidationParallelism()} -- or 11192123e367SVladimir Kotal * if zero, then as a default gets the number of available processors halved. 11202123e367SVladimir Kotal * @return a natural number >= 1 11212123e367SVladimir Kotal */ getRepositoryInvalidationParallelism()11222123e367SVladimir Kotal public int getRepositoryInvalidationParallelism() { 11232123e367SVladimir Kotal int parallelism = syncReadConfiguration(Configuration::getRepositoryInvalidationParallelism); 11242123e367SVladimir Kotal return parallelism < 1 ? (Runtime.getRuntime().availableProcessors() / 2) : parallelism; 11252123e367SVladimir Kotal } 11262123e367SVladimir Kotal 11272123e367SVladimir Kotal /** 1128b5840353SAdam Hornáček * Gets the value of {@link Configuration#getHistoryParallelism()} -- or 1129b5840353SAdam Hornáček * if zero, then as a default gets the number of available processors. 1130b5840353SAdam Hornáček * @return a natural number >= 1 1131b5840353SAdam Hornáček */ getHistoryParallelism()1132b5840353SAdam Hornáček public int getHistoryParallelism() { 11334151dbf5SChris Fraire int parallelism = syncReadConfiguration(Configuration::getHistoryParallelism); 1134b5840353SAdam Hornáček return parallelism < 1 ? Runtime.getRuntime().availableProcessors() : 1135b5840353SAdam Hornáček parallelism; 1136b5840353SAdam Hornáček } 1137b5840353SAdam Hornáček 1138b5840353SAdam Hornáček /** 1139dc607a84SVladimir Kotal * Gets the value of {@link Configuration#getHistoryFileParallelism()} -- or 1140b5840353SAdam Hornáček * if zero, then as a default gets the number of available processors. 1141b5840353SAdam Hornáček * @return a natural number >= 1 1142b5840353SAdam Hornáček */ getHistoryFileParallelism()1143dc607a84SVladimir Kotal public int getHistoryFileParallelism() { 1144dc607a84SVladimir Kotal int parallelism = syncReadConfiguration(Configuration::getHistoryFileParallelism); 1145b5840353SAdam Hornáček return parallelism < 1 ? Runtime.getRuntime().availableProcessors() : 1146b5840353SAdam Hornáček parallelism; 1147b5840353SAdam Hornáček } 1148b5840353SAdam Hornáček isTagsEnabled()1149b5840353SAdam Hornáček public boolean isTagsEnabled() { 11504151dbf5SChris Fraire return syncReadConfiguration(Configuration::isTagsEnabled); 1151b5840353SAdam Hornáček } 1152b5840353SAdam Hornáček setTagsEnabled(boolean tagsEnabled)1153b5840353SAdam Hornáček public void setTagsEnabled(boolean tagsEnabled) { 1154754ebdfbSChris Fraire syncWriteConfiguration(tagsEnabled, Configuration::setTagsEnabled); 1155b5840353SAdam Hornáček } 1156b5840353SAdam Hornáček isScopesEnabled()1157b5840353SAdam Hornáček public boolean isScopesEnabled() { 11584151dbf5SChris Fraire return syncReadConfiguration(Configuration::isScopesEnabled); 1159b5840353SAdam Hornáček } 1160b5840353SAdam Hornáček setScopesEnabled(boolean scopesEnabled)1161b5840353SAdam Hornáček public void setScopesEnabled(boolean scopesEnabled) { 1162754ebdfbSChris Fraire syncWriteConfiguration(scopesEnabled, Configuration::setScopesEnabled); 1163b5840353SAdam Hornáček } 1164b5840353SAdam Hornáček isProjectsEnabled()1165b5840353SAdam Hornáček public boolean isProjectsEnabled() { 11664151dbf5SChris Fraire return syncReadConfiguration(Configuration::isProjectsEnabled); 1167b5840353SAdam Hornáček } 1168b5840353SAdam Hornáček setProjectsEnabled(boolean projectsEnabled)1169b5840353SAdam Hornáček public void setProjectsEnabled(boolean projectsEnabled) { 1170754ebdfbSChris Fraire syncWriteConfiguration(projectsEnabled, Configuration::setProjectsEnabled); 1171b5840353SAdam Hornáček } 1172b5840353SAdam Hornáček isFoldingEnabled()1173b5840353SAdam Hornáček public boolean isFoldingEnabled() { 11744151dbf5SChris Fraire return syncReadConfiguration(Configuration::isFoldingEnabled); 1175b5840353SAdam Hornáček } 1176b5840353SAdam Hornáček setFoldingEnabled(boolean foldingEnabled)1177b5840353SAdam Hornáček public void setFoldingEnabled(boolean foldingEnabled) { 1178754ebdfbSChris Fraire syncWriteConfiguration(foldingEnabled, Configuration::setFoldingEnabled); 1179b5840353SAdam Hornáček } 1180b5840353SAdam Hornáček getDateForLastIndexRun()1181b5840353SAdam Hornáček public Date getDateForLastIndexRun() { 1182b5840353SAdam Hornáček return indexTime.getDateForLastIndexRun(); 1183b5840353SAdam Hornáček } 1184b5840353SAdam Hornáček getCTagsExtraOptionsFile()1185b5840353SAdam Hornáček public String getCTagsExtraOptionsFile() { 11864151dbf5SChris Fraire return syncReadConfiguration(Configuration::getCTagsExtraOptionsFile); 1187b5840353SAdam Hornáček } 1188b5840353SAdam Hornáček setCTagsExtraOptionsFile(String ctagsExtraOptionsFile)1189754ebdfbSChris Fraire public void setCTagsExtraOptionsFile(String ctagsExtraOptionsFile) { 1190754ebdfbSChris Fraire syncWriteConfiguration(ctagsExtraOptionsFile, Configuration::setCTagsExtraOptionsFile); 1191b5840353SAdam Hornáček } 1192b5840353SAdam Hornáček getAllowedSymlinks()1193b5840353SAdam Hornáček public Set<String> getAllowedSymlinks() { 11944151dbf5SChris Fraire return syncReadConfiguration(Configuration::getAllowedSymlinks); 1195b5840353SAdam Hornáček } 1196b5840353SAdam Hornáček setAllowedSymlinks(Set<String> allowedSymlinks)1197b5840353SAdam Hornáček public void setAllowedSymlinks(Set<String> allowedSymlinks) { 1198754ebdfbSChris Fraire syncWriteConfiguration(allowedSymlinks, Configuration::setAllowedSymlinks); 1199b5840353SAdam Hornáček } 1200b5840353SAdam Hornáček getCanonicalRoots()12010e0ac58dSChris Fraire public Set<String> getCanonicalRoots() { 12024151dbf5SChris Fraire return syncReadConfiguration(Configuration::getCanonicalRoots); 12030e0ac58dSChris Fraire } 12040e0ac58dSChris Fraire setCanonicalRoots(Set<String> canonicalRoots)12050e0ac58dSChris Fraire public void setCanonicalRoots(Set<String> canonicalRoots) { 1206754ebdfbSChris Fraire syncWriteConfiguration(canonicalRoots, Configuration::setCanonicalRoots); 12070e0ac58dSChris Fraire } 12080e0ac58dSChris Fraire 1209b5840353SAdam Hornáček /** 1210b5840353SAdam Hornáček * Return whether e-mail addresses should be obfuscated in the xref. 1211b5840353SAdam Hornáček * @return if we obfuscate emails 1212b5840353SAdam Hornáček */ isObfuscatingEMailAddresses()1213b5840353SAdam Hornáček public boolean isObfuscatingEMailAddresses() { 12144151dbf5SChris Fraire return syncReadConfiguration(Configuration::isObfuscatingEMailAddresses); 1215b5840353SAdam Hornáček } 1216b5840353SAdam Hornáček 1217b5840353SAdam Hornáček /** 1218b5840353SAdam Hornáček * Set whether e-mail addresses should be obfuscated in the xref. 1219754ebdfbSChris Fraire * @param obfuscatingEMailAddresses should we obfuscate emails? 1220b5840353SAdam Hornáček */ setObfuscatingEMailAddresses(boolean obfuscatingEMailAddresses)1221754ebdfbSChris Fraire public void setObfuscatingEMailAddresses(boolean obfuscatingEMailAddresses) { 1222754ebdfbSChris Fraire syncWriteConfiguration(obfuscatingEMailAddresses, 1223754ebdfbSChris Fraire Configuration::setObfuscatingEMailAddresses); 1224b5840353SAdam Hornáček } 1225b5840353SAdam Hornáček 1226b5840353SAdam Hornáček /** 1227b5840353SAdam Hornáček * Should status.jsp print internal settings, like paths and database URLs? 1228b5840353SAdam Hornáček * 1229b5840353SAdam Hornáček * @return {@code true} if status.jsp should show the configuration, 1230b5840353SAdam Hornáček * {@code false} otherwise 1231b5840353SAdam Hornáček */ isChattyStatusPage()1232b5840353SAdam Hornáček public boolean isChattyStatusPage() { 12334151dbf5SChris Fraire return syncReadConfiguration(Configuration::isChattyStatusPage); 1234b5840353SAdam Hornáček } 1235b5840353SAdam Hornáček 1236b5840353SAdam Hornáček /** 1237b5840353SAdam Hornáček * Set whether status.jsp should print internal settings. 1238b5840353SAdam Hornáček * 1239754ebdfbSChris Fraire * @param chattyStatusPage {@code true} if internal settings should be printed, 1240b5840353SAdam Hornáček * {@code false} otherwise 1241b5840353SAdam Hornáček */ setChattyStatusPage(boolean chattyStatusPage)1242754ebdfbSChris Fraire public void setChattyStatusPage(boolean chattyStatusPage) { 1243754ebdfbSChris Fraire syncWriteConfiguration(chattyStatusPage, Configuration::setChattyStatusPage); 1244b5840353SAdam Hornáček } 1245b5840353SAdam Hornáček setFetchHistoryWhenNotInCache(boolean fetchHistoryWhenNotInCache)1246754ebdfbSChris Fraire public void setFetchHistoryWhenNotInCache(boolean fetchHistoryWhenNotInCache) { 1247754ebdfbSChris Fraire syncWriteConfiguration(fetchHistoryWhenNotInCache, 1248754ebdfbSChris Fraire Configuration::setFetchHistoryWhenNotInCache); 1249b5840353SAdam Hornáček } 1250b5840353SAdam Hornáček isFetchHistoryWhenNotInCache()1251b5840353SAdam Hornáček public boolean isFetchHistoryWhenNotInCache() { 12524151dbf5SChris Fraire return syncReadConfiguration(Configuration::isFetchHistoryWhenNotInCache); 12532ffbb0cfSVladimir Kotal } 12542ffbb0cfSVladimir Kotal isHistoryCache()12552ffbb0cfSVladimir Kotal public boolean isHistoryCache() { 12564151dbf5SChris Fraire return syncReadConfiguration(Configuration::isHistoryCache); 1257b5840353SAdam Hornáček } 1258b5840353SAdam Hornáček setHandleHistoryOfRenamedFiles(boolean handleHistoryOfRenamedFiles)1259754ebdfbSChris Fraire public void setHandleHistoryOfRenamedFiles(boolean handleHistoryOfRenamedFiles) { 1260754ebdfbSChris Fraire syncWriteConfiguration(handleHistoryOfRenamedFiles, 1261754ebdfbSChris Fraire Configuration::setHandleHistoryOfRenamedFiles); 1262b5840353SAdam Hornáček } 1263b5840353SAdam Hornáček isHandleHistoryOfRenamedFiles()1264b5840353SAdam Hornáček public boolean isHandleHistoryOfRenamedFiles() { 12654151dbf5SChris Fraire return syncReadConfiguration(Configuration::isHandleHistoryOfRenamedFiles); 1266b5840353SAdam Hornáček } 1267b5840353SAdam Hornáček setMergeCommitsEnabled(boolean flag)12688e5e1036SVladimir Kotal public void setMergeCommitsEnabled(boolean flag) { 12698e5e1036SVladimir Kotal syncWriteConfiguration(flag, Configuration::setMergeCommitsEnabled); 12708e5e1036SVladimir Kotal } 12718e5e1036SVladimir Kotal isMergeCommitsEnabled()12728e5e1036SVladimir Kotal public boolean isMergeCommitsEnabled() { 12738e5e1036SVladimir Kotal return syncReadConfiguration(Configuration::isMergeCommitsEnabled); 12748e5e1036SVladimir Kotal } 12758e5e1036SVladimir Kotal setNavigateWindowEnabled(boolean navigateWindowEnabled)1276754ebdfbSChris Fraire public void setNavigateWindowEnabled(boolean navigateWindowEnabled) { 1277754ebdfbSChris Fraire syncWriteConfiguration(navigateWindowEnabled, Configuration::setNavigateWindowEnabled); 1278326dace0SVladimir Kotal } 1279326dace0SVladimir Kotal isNavigateWindowEnabled()1280326dace0SVladimir Kotal public boolean isNavigateWindowEnabled() { 12814151dbf5SChris Fraire return syncReadConfiguration(Configuration::isNavigateWindowEnabled); 1282326dace0SVladimir Kotal } 1283326dace0SVladimir Kotal setRevisionMessageCollapseThreshold(int revisionMessageCollapseThreshold)1284754ebdfbSChris Fraire public void setRevisionMessageCollapseThreshold(int revisionMessageCollapseThreshold) { 1285754ebdfbSChris Fraire syncWriteConfiguration(revisionMessageCollapseThreshold, 1286754ebdfbSChris Fraire Configuration::setRevisionMessageCollapseThreshold); 1287b5840353SAdam Hornáček } 1288b5840353SAdam Hornáček getRevisionMessageCollapseThreshold()1289b5840353SAdam Hornáček public int getRevisionMessageCollapseThreshold() { 12904151dbf5SChris Fraire return syncReadConfiguration(Configuration::getRevisionMessageCollapseThreshold); 1291b5840353SAdam Hornáček } 1292b5840353SAdam Hornáček setMaxSearchThreadCount(int maxSearchThreadCount)1293754ebdfbSChris Fraire public void setMaxSearchThreadCount(int maxSearchThreadCount) { 1294754ebdfbSChris Fraire syncWriteConfiguration(maxSearchThreadCount, Configuration::setMaxSearchThreadCount); 1295b5840353SAdam Hornáček } 1296b5840353SAdam Hornáček getMaxSearchThreadCount()1297b5840353SAdam Hornáček public int getMaxSearchThreadCount() { 12984151dbf5SChris Fraire return syncReadConfiguration(Configuration::getMaxSearchThreadCount); 1299b5840353SAdam Hornáček } 1300b5840353SAdam Hornáček setMaxRevisionThreadCount(int maxRevisionThreadCount)1301754ebdfbSChris Fraire public void setMaxRevisionThreadCount(int maxRevisionThreadCount) { 1302754ebdfbSChris Fraire syncWriteConfiguration(maxRevisionThreadCount, Configuration::setMaxRevisionThreadCount); 1303fb531549SVladimir Kotal } 1304fb531549SVladimir Kotal getMaxRevisionThreadCount()1305fb531549SVladimir Kotal public int getMaxRevisionThreadCount() { 13064151dbf5SChris Fraire return syncReadConfiguration(Configuration::getMaxRevisionThreadCount); 1307fb531549SVladimir Kotal } 1308fb531549SVladimir Kotal getCurrentIndexedCollapseThreshold()1309b5840353SAdam Hornáček public int getCurrentIndexedCollapseThreshold() { 13104151dbf5SChris Fraire return syncReadConfiguration(Configuration::getCurrentIndexedCollapseThreshold); 1311b5840353SAdam Hornáček } 1312b5840353SAdam Hornáček setCurrentIndexedCollapseThreshold(int currentIndexedCollapseThreshold)1313b5840353SAdam Hornáček public void setCurrentIndexedCollapseThreshold(int currentIndexedCollapseThreshold) { 1314754ebdfbSChris Fraire syncWriteConfiguration(currentIndexedCollapseThreshold, 1315754ebdfbSChris Fraire Configuration::setCurrentIndexedCollapseThreshold); 1316b5840353SAdam Hornáček } 1317b5840353SAdam Hornáček getGroupsCollapseThreshold()1318b5840353SAdam Hornáček public int getGroupsCollapseThreshold() { 13194151dbf5SChris Fraire return syncReadConfiguration(Configuration::getGroupsCollapseThreshold); 1320b5840353SAdam Hornáček } 1321b5840353SAdam Hornáček 132255402125SVladimir Kotal // The URI is not necessary to be present in the configuration 1323b5840353SAdam Hornáček // (so that when -U option of the indexer is omitted, the config will not 132455402125SVladimir Kotal // be sent to the webapp) so store it only in the RuntimeEnvironment. setConfigURI(String host)132555402125SVladimir Kotal public void setConfigURI(String host) { 132655402125SVladimir Kotal configURI = host; 1327b5840353SAdam Hornáček } 1328b5840353SAdam Hornáček getConfigURI()132955402125SVladimir Kotal public String getConfigURI() { 133055402125SVladimir Kotal return configURI; 1331b5840353SAdam Hornáček } 1332b5840353SAdam Hornáček isHistoryEnabled()1333b5840353SAdam Hornáček public boolean isHistoryEnabled() { 13344151dbf5SChris Fraire return syncReadConfiguration(Configuration::isHistoryEnabled); 1335b5840353SAdam Hornáček } 1336b5840353SAdam Hornáček setHistoryEnabled(boolean historyEnabled)1337754ebdfbSChris Fraire public void setHistoryEnabled(boolean historyEnabled) { 1338754ebdfbSChris Fraire syncWriteConfiguration(historyEnabled, Configuration::setHistoryEnabled); 1339b5840353SAdam Hornáček } 1340b5840353SAdam Hornáček isDisplayRepositories()1341ad8a45cdSVladimir Kotal public boolean isDisplayRepositories() { 1342ad8a45cdSVladimir Kotal return syncReadConfiguration(Configuration::isDisplayRepositories); 1343b5840353SAdam Hornáček } 1344b5840353SAdam Hornáček setDisplayRepositories(boolean displayRepositories)1345754ebdfbSChris Fraire public void setDisplayRepositories(boolean displayRepositories) { 1346754ebdfbSChris Fraire syncWriteConfiguration(displayRepositories, Configuration::setDisplayRepositories); 1347b5840353SAdam Hornáček } 1348b5840353SAdam Hornáček getListDirsFirst()1349b5840353SAdam Hornáček public boolean getListDirsFirst() { 13504151dbf5SChris Fraire return syncReadConfiguration(Configuration::getListDirsFirst); 1351b5840353SAdam Hornáček } 1352b5840353SAdam Hornáček setListDirsFirst(boolean listDirsFirst)1353754ebdfbSChris Fraire public void setListDirsFirst(boolean listDirsFirst) { 1354754ebdfbSChris Fraire syncWriteConfiguration(listDirsFirst, Configuration::setListDirsFirst); 13552ffbb0cfSVladimir Kotal } 13562ffbb0cfSVladimir Kotal setTabSize(int tabSize)1357754ebdfbSChris Fraire public void setTabSize(int tabSize) { 1358754ebdfbSChris Fraire syncWriteConfiguration(tabSize, Configuration::setTabSize); 13592ffbb0cfSVladimir Kotal } 13602ffbb0cfSVladimir Kotal getTabSize()13612ffbb0cfSVladimir Kotal public int getTabSize() { 13624151dbf5SChris Fraire return syncReadConfiguration(Configuration::getTabSize); 1363b5840353SAdam Hornáček } 1364b5840353SAdam Hornáček 1365b5840353SAdam Hornáček /** 1366ff44f24aSAdam Hornáček * Gets the total number of context lines per file to show. 1367b5840353SAdam Hornáček * @return a value greater than zero 1368b5840353SAdam Hornáček */ getContextLimit()1369b5840353SAdam Hornáček public short getContextLimit() { 13704151dbf5SChris Fraire return syncReadConfiguration(Configuration::getContextLimit); 1371b5840353SAdam Hornáček } 1372b5840353SAdam Hornáček 1373b5840353SAdam Hornáček /** 1374ff44f24aSAdam Hornáček * Gets the number of context lines to show before or after any match. 1375b5840353SAdam Hornáček * @return a value greater than or equal to zero 1376b5840353SAdam Hornáček */ getContextSurround()1377b5840353SAdam Hornáček public short getContextSurround() { 13784151dbf5SChris Fraire return syncReadConfiguration(Configuration::getContextSurround); 1379b5840353SAdam Hornáček } 1380b5840353SAdam Hornáček getHistoryChunkCount()1381a2f09795SVladimir Kotal public int getHistoryChunkCount() { 1382a2f09795SVladimir Kotal return syncReadConfiguration(Configuration::getHistoryChunkCount); 1383a2f09795SVladimir Kotal } 1384a2f09795SVladimir Kotal setHistoryChunkCount(int chunkCount)1385a2f09795SVladimir Kotal public void setHistoryChunkCount(int chunkCount) { 1386a2f09795SVladimir Kotal syncWriteConfiguration(chunkCount, Configuration::setHistoryChunkCount); 1387a2f09795SVladimir Kotal } 1388a2f09795SVladimir Kotal isHistoryCachePerPartesEnabled()13895a635a8eSVladimir Kotal public boolean isHistoryCachePerPartesEnabled() { 13905a635a8eSVladimir Kotal return syncReadConfiguration(Configuration::isHistoryCachePerPartesEnabled); 13915a635a8eSVladimir Kotal } 13925a635a8eSVladimir Kotal setHistoryCachePerPartesEnabled(boolean enabled)13935a635a8eSVladimir Kotal public void setHistoryCachePerPartesEnabled(boolean enabled) { 13945a635a8eSVladimir Kotal syncWriteConfiguration(enabled, Configuration::setHistoryCachePerPartesEnabled); 13955a635a8eSVladimir Kotal } 13965a635a8eSVladimir Kotal getDisabledRepositories()139729816c3bSChris Fraire public Set<String> getDisabledRepositories() { 13984151dbf5SChris Fraire return syncReadConfiguration(Configuration::getDisabledRepositories); 139929816c3bSChris Fraire } 140029816c3bSChris Fraire setDisabledRepositories(Set<String> disabledRepositories)140129816c3bSChris Fraire public void setDisabledRepositories(Set<String> disabledRepositories) { 1402754ebdfbSChris Fraire syncWriteConfiguration(disabledRepositories, Configuration::setDisabledRepositories); 140329816c3bSChris Fraire } 140429816c3bSChris Fraire getServerName()14050516dd21SVladimir Kotal public String getServerName() { 14060516dd21SVladimir Kotal return syncReadConfiguration(Configuration::getServerName); 14070516dd21SVladimir Kotal } 14080516dd21SVladimir Kotal setServerName(String serverName)14090516dd21SVladimir Kotal public void setServerName(String serverName) { 14100516dd21SVladimir Kotal syncWriteConfiguration(serverName, Configuration::setServerName); 14110516dd21SVladimir Kotal } 14120516dd21SVladimir Kotal getApiTimeout()14131c258122SVladimir Kotal public int getApiTimeout() { 14141c258122SVladimir Kotal return syncReadConfiguration(Configuration::getApiTimeout); 14151c258122SVladimir Kotal } 14161c258122SVladimir Kotal setApiTimeout(int apiTimeout)14171c258122SVladimir Kotal public void setApiTimeout(int apiTimeout) { 14181c258122SVladimir Kotal syncWriteConfiguration(apiTimeout, Configuration::setApiTimeout); 14191c258122SVladimir Kotal } 14201c258122SVladimir Kotal getConnectTimeout()14211c258122SVladimir Kotal public int getConnectTimeout() { 14221c258122SVladimir Kotal return syncReadConfiguration(Configuration::getConnectTimeout); 14231c258122SVladimir Kotal } 14241c258122SVladimir Kotal setConnectTimeout(int connectTimeout)14251c258122SVladimir Kotal public void setConnectTimeout(int connectTimeout) { 14261c258122SVladimir Kotal syncWriteConfiguration(connectTimeout, Configuration::setConnectTimeout); 14271c258122SVladimir Kotal } 14281c258122SVladimir Kotal isHistoryBasedReindex()1429f4571972SVladimir Kotal public boolean isHistoryBasedReindex() { 1430f4571972SVladimir Kotal return syncReadConfiguration(Configuration::isHistoryBasedReindex); 143112365fb4SVladimir Kotal } 143212365fb4SVladimir Kotal setHistoryBasedReindex(boolean flag)1433f4571972SVladimir Kotal public void setHistoryBasedReindex(boolean flag) { 1434f4571972SVladimir Kotal syncWriteConfiguration(flag, Configuration::setHistoryBasedReindex); 143512365fb4SVladimir Kotal } 143612365fb4SVladimir Kotal getFileCollector(String name)1437fadf9080SVladimir Kotal public FileCollector getFileCollector(String name) { 1438fadf9080SVladimir Kotal return fileCollectorMap.get(name); 1439fadf9080SVladimir Kotal } 1440fadf9080SVladimir Kotal setFileCollector(String name, FileCollector fileCollector)1441fadf9080SVladimir Kotal public void setFileCollector(String name, FileCollector fileCollector) { 1442fadf9080SVladimir Kotal fileCollectorMap.put(name, fileCollector); 1443fadf9080SVladimir Kotal } 1444fadf9080SVladimir Kotal 1445*5650cf15SVladimir Kotal @VisibleForTesting clearFileCollector()1446*5650cf15SVladimir Kotal public void clearFileCollector() { 1447*5650cf15SVladimir Kotal fileCollectorMap.clear(); 1448*5650cf15SVladimir Kotal } 1449*5650cf15SVladimir Kotal 1450b5840353SAdam Hornáček /** 1451b5840353SAdam Hornáček * Read an configuration file and set it as the current configuration. 1452b5840353SAdam Hornáček * 1453b5840353SAdam Hornáček * @param file the file to read 1454b5840353SAdam Hornáček * @throws IOException if an error occurs 1455b5840353SAdam Hornáček */ readConfiguration(File file)1456b5840353SAdam Hornáček public void readConfiguration(File file) throws IOException { 14574151dbf5SChris Fraire // The following method handles the locking. 1458b5840353SAdam Hornáček setConfiguration(Configuration.read(file)); 1459b5840353SAdam Hornáček } 1460b5840353SAdam Hornáček 1461b5840353SAdam Hornáček /** 1462b5840353SAdam Hornáček * Read configuration from a file and put it into effect. 1463b5840353SAdam Hornáček * @param file the file to read 1464a904b83aSVladimir Kotal * @param cmdType command timeout type 146581b586e6SVladimir Kotal * @throws IOException I/O 1466b5840353SAdam Hornáček */ readConfiguration(File file, CommandTimeoutType cmdType)1467a904b83aSVladimir Kotal public void readConfiguration(File file, CommandTimeoutType cmdType) throws IOException { 14684151dbf5SChris Fraire // The following method handles the locking. 1469a904b83aSVladimir Kotal setConfiguration(Configuration.read(file), null, cmdType); 1470b5840353SAdam Hornáček } 1471b5840353SAdam Hornáček 1472b5840353SAdam Hornáček /** 1473ff44f24aSAdam Hornáček * Write the current configuration to a file. 1474b5840353SAdam Hornáček * 1475b5840353SAdam Hornáček * @param file the file to write the configuration into 1476b5840353SAdam Hornáček * @throws IOException if an error occurs 1477b5840353SAdam Hornáček */ writeConfiguration(File file)1478b5840353SAdam Hornáček public void writeConfiguration(File file) throws IOException { 14794151dbf5SChris Fraire try (ResourceLock resourceLock = configLock.readLockAsResource()) { 14804151dbf5SChris Fraire //noinspection ConstantConditions to avoid warning of no reference to auto-closeable 14814151dbf5SChris Fraire assert resourceLock != null; 14822ffbb0cfSVladimir Kotal configuration.write(file); 14832ffbb0cfSVladimir Kotal } 14842ffbb0cfSVladimir Kotal } 14852ffbb0cfSVladimir Kotal getConfigurationXML()14862ffbb0cfSVladimir Kotal public String getConfigurationXML() { 14874151dbf5SChris Fraire return syncReadConfiguration(Configuration::getXMLRepresentationAsString); 1488b5840353SAdam Hornáček } 1489b5840353SAdam Hornáček 1490b5840353SAdam Hornáček /** 14911c258122SVladimir Kotal * Write the current configuration to a socket and waits for the result. 1492b5840353SAdam Hornáček * 1493b5840353SAdam Hornáček * @param host the host address to receive the configuration 1494b5840353SAdam Hornáček * @throws IOException if an error occurs 1495b5840353SAdam Hornáček */ writeConfiguration(String host)14961c258122SVladimir Kotal public void writeConfiguration(String host) throws IOException, InterruptedException, IllegalArgumentException { 14974151dbf5SChris Fraire String configXML = syncReadConfiguration(Configuration::getXMLRepresentationAsString); 14982ffbb0cfSVladimir Kotal 14991c258122SVladimir Kotal Response response = ClientBuilder.newClient() 15004ce4e2b9SAdam Hornáček .target(host) 15014ce4e2b9SAdam Hornáček .path("api") 15024ce4e2b9SAdam Hornáček .path("v1") 15034ce4e2b9SAdam Hornáček .path("configuration") 15044ce4e2b9SAdam Hornáček .queryParam("reindex", true) 15054ce4e2b9SAdam Hornáček .request() 1506f1e34e10SVladimir Kotal .headers(getWebAppHeaders()) 15072ffbb0cfSVladimir Kotal .put(Entity.xml(configXML)); 1508b5840353SAdam Hornáček 15091c258122SVladimir Kotal if (response.getStatus() == Response.Status.ACCEPTED.getStatusCode()) { 1510cce4eb5fSVladimir Kotal response = ApiUtils.waitForAsyncApi(response); 15111c258122SVladimir Kotal } 15121c258122SVladimir Kotal 15131c258122SVladimir Kotal if (response.getStatusInfo().getFamily() != Response.Status.Family.SUCCESSFUL) { 15141c258122SVladimir Kotal throw new IOException(response.toString()); 1515b5840353SAdam Hornáček } 1516b5840353SAdam Hornáček } 1517b5840353SAdam Hornáček 1518b5840353SAdam Hornáček /** 1519b5840353SAdam Hornáček * Generate a TreeMap of projects with corresponding repository information. 15205f6ae75cSKryštof Tulinger * <p> 1521b5840353SAdam Hornáček * Project with some repository information is considered as a repository 1522b5840353SAdam Hornáček * otherwise it is just a simple project. 1523b5840353SAdam Hornáček */ 152432b4cd63SVladimir Kotal @VisibleForTesting generateProjectRepositoriesMap()152532b4cd63SVladimir Kotal public void generateProjectRepositoriesMap() throws IOException { 1526b5840353SAdam Hornáček repository_map.clear(); 1527b5840353SAdam Hornáček for (RepositoryInfo r : getRepositories()) { 1528b5840353SAdam Hornáček Project proj; 1529b5840353SAdam Hornáček String repoPath; 1530b5840353SAdam Hornáček try { 15312738be5eSChris Fraire repoPath = getPathRelativeToSourceRoot(new File(r.getDirectoryName())); 1532b5840353SAdam Hornáček } catch (ForbiddenSymlinkException e) { 1533b5840353SAdam Hornáček LOGGER.log(Level.FINER, e.getMessage()); 1534b5840353SAdam Hornáček continue; 1535b5840353SAdam Hornáček } 1536b5840353SAdam Hornáček 1537b5840353SAdam Hornáček if ((proj = Project.getProject(repoPath)) != null) { 1538a72324b1SAdam Hornáček List<RepositoryInfo> values = repository_map.computeIfAbsent(proj, k -> new ArrayList<>()); 153968830e6dSKryštof Tulinger // the map is held under the lock because the next call to 154068830e6dSKryštof Tulinger // values.add(r) which should not be called from multiple threads at the same time 1541b5840353SAdam Hornáček values.add(r); 1542b5840353SAdam Hornáček } 1543b5840353SAdam Hornáček } 1544b5840353SAdam Hornáček } 1545b5840353SAdam Hornáček 1546b5840353SAdam Hornáček /** 1547b5840353SAdam Hornáček * Classifies projects and puts them in their groups. 1548ba15b5bdSKryštof Tulinger * <p> 1549ba15b5bdSKryštof Tulinger * If any of the groups contain some projects or repositories already, 1550ba15b5bdSKryštof Tulinger * these get discarded. 1551ba15b5bdSKryštof Tulinger * 1552ba15b5bdSKryštof Tulinger * @param groups set of groups to be filled with matching projects 1553b5840353SAdam Hornáček * @param projects projects to classify 1554b5840353SAdam Hornáček */ populateGroups(Set<Group> groups, Set<Project> projects)1555b5840353SAdam Hornáček public void populateGroups(Set<Group> groups, Set<Project> projects) { 1556b5840353SAdam Hornáček if (projects == null || groups == null) { 1557b5840353SAdam Hornáček return; 1558b5840353SAdam Hornáček } 1559ba15b5bdSKryštof Tulinger 1560ba15b5bdSKryštof Tulinger // clear the groups first if they had something in them 1561ba15b5bdSKryštof Tulinger for (Group group : groups) { 1562ba15b5bdSKryštof Tulinger group.getRepositories().clear(); 1563ba15b5bdSKryštof Tulinger group.getProjects().clear(); 1564ba15b5bdSKryštof Tulinger } 1565ba15b5bdSKryštof Tulinger 1566ba15b5bdSKryštof Tulinger // now fill the groups with appropriate projects 1567b5840353SAdam Hornáček for (Project project : projects) { 1568ba15b5bdSKryštof Tulinger // clear the project's groups 1569ba15b5bdSKryštof Tulinger project.getGroups().clear(); 1570ba15b5bdSKryštof Tulinger 1571ba15b5bdSKryštof Tulinger // filter projects only to groups which match project's name 1572b5840353SAdam Hornáček Set<Group> copy = Group.matching(project, groups); 1573b5840353SAdam Hornáček 1574b5840353SAdam Hornáček // add project to the groups 1575b5840353SAdam Hornáček for (Group group : copy) { 1576b5840353SAdam Hornáček if (repository_map.get(project) == null) { 1577b5840353SAdam Hornáček group.addProject(project); 1578b5840353SAdam Hornáček } else { 1579b5840353SAdam Hornáček group.addRepository(project); 1580b5840353SAdam Hornáček } 1581b5840353SAdam Hornáček project.addGroup(group); 1582b5840353SAdam Hornáček } 1583b5840353SAdam Hornáček } 1584b5840353SAdam Hornáček } 1585b5840353SAdam Hornáček 1586b5840353SAdam Hornáček /** 1587b5840353SAdam Hornáček * Sets the configuration and performs necessary actions. 1588b5840353SAdam Hornáček * 1589b5840353SAdam Hornáček * Mainly it classifies the projects in their groups and generates project - 1590b5840353SAdam Hornáček * repositories map 1591b5840353SAdam Hornáček * 1592b5840353SAdam Hornáček * @param configuration what configuration to use 1593b5840353SAdam Hornáček */ setConfiguration(Configuration configuration)1594b5840353SAdam Hornáček public void setConfiguration(Configuration configuration) { 1595a904b83aSVladimir Kotal setConfiguration(configuration, null, CommandTimeoutType.INDEXER); 1596b5840353SAdam Hornáček } 1597b5840353SAdam Hornáček 1598b5840353SAdam Hornáček /** 1599b5840353SAdam Hornáček * Sets the configuration and performs necessary actions. 1600b5840353SAdam Hornáček * @param configuration new configuration 1601a904b83aSVladimir Kotal * @param cmdType command timeout type 1602b5840353SAdam Hornáček */ setConfiguration(Configuration configuration, CommandTimeoutType cmdType)1603a904b83aSVladimir Kotal public void setConfiguration(Configuration configuration, CommandTimeoutType cmdType) { 1604a904b83aSVladimir Kotal setConfiguration(configuration, null, cmdType); 1605b5840353SAdam Hornáček } 1606b5840353SAdam Hornáček 1607b5840353SAdam Hornáček /** 1608b5840353SAdam Hornáček * Sets the configuration and performs necessary actions. 16095f6ae75cSKryštof Tulinger * 1610b5840353SAdam Hornáček * @param configuration new configuration 16111b935619SVladimir Kotal * @param subFileList collection of repositories 1612a904b83aSVladimir Kotal * @param cmdType command timeout type 1613b5840353SAdam Hornáček */ setConfiguration(Configuration configuration, Collection<String> subFileList, CommandTimeoutType cmdType)16141b935619SVladimir Kotal public synchronized void setConfiguration(Configuration configuration, Collection<String> subFileList, CommandTimeoutType cmdType) { 16154151dbf5SChris Fraire try (ResourceLock resourceLock = configLock.writeLockAsResource()) { 16164151dbf5SChris Fraire //noinspection ConstantConditions to avoid warning of no reference to auto-closeable 16174151dbf5SChris Fraire assert resourceLock != null; 1618b5840353SAdam Hornáček this.configuration = configuration; 16192ffbb0cfSVladimir Kotal } 1620b5840353SAdam Hornáček 16212ffbb0cfSVladimir Kotal // HistoryGuru constructor needs environment properties so no locking is done here. 1622b5840353SAdam Hornáček HistoryGuru histGuru = HistoryGuru.getInstance(); 1623b5840353SAdam Hornáček 16245f6ae75cSKryštof Tulinger // Set the working repositories in HistoryGuru. 16255f6ae75cSKryštof Tulinger if (subFileList != null) { 1626a904b83aSVladimir Kotal histGuru.invalidateRepositories(getRepositories(), subFileList, cmdType); 16275f6ae75cSKryštof Tulinger } else { 1628a904b83aSVladimir Kotal histGuru.invalidateRepositories(getRepositories(), cmdType); 16295f6ae75cSKryštof Tulinger } 16305f6ae75cSKryštof Tulinger 16315f6ae75cSKryštof Tulinger // The invalidation of repositories above might have excluded some 16325f6ae75cSKryštof Tulinger // repositories in HistoryGuru so the configuration needs to reflect that. 16335f6ae75cSKryštof Tulinger setRepositories(new ArrayList<>(histGuru.getRepositories())); 16345f6ae75cSKryštof Tulinger 16355f6ae75cSKryštof Tulinger // generate repository map is dependent on getRepositories() 1636b5840353SAdam Hornáček try { 1637b5840353SAdam Hornáček generateProjectRepositoriesMap(); 1638b5840353SAdam Hornáček } catch (IOException ex) { 1639b5840353SAdam Hornáček LOGGER.log(Level.SEVERE, "Cannot generate project - repository map", ex); 1640b5840353SAdam Hornáček } 1641b5840353SAdam Hornáček 16425f6ae75cSKryštof Tulinger // populate groups is dependent on repositories map 1643b5840353SAdam Hornáček populateGroups(getGroups(), new TreeSet<>(getProjects().values())); 1644b5840353SAdam Hornáček 16452ffbb0cfSVladimir Kotal includeFiles.reloadIncludeFiles(); 1646b5840353SAdam Hornáček } 1647b5840353SAdam Hornáček getIncludeFiles()16482ffbb0cfSVladimir Kotal public IncludeFiles getIncludeFiles() { 16492ffbb0cfSVladimir Kotal return includeFiles; 1650b5840353SAdam Hornáček } 1651b5840353SAdam Hornáček 1652b5840353SAdam Hornáček /** 1653b5840353SAdam Hornáček * Return the authorization framework used in this environment. 1654b5840353SAdam Hornáček * 1655b5840353SAdam Hornáček * @return the framework 1656b5840353SAdam Hornáček */ getAuthorizationFramework()16571cbb0597SVladimir Kotal public AuthorizationFramework getAuthorizationFramework() { 16581cbb0597SVladimir Kotal synchronized (authFrameworkLock) { 1659b5840353SAdam Hornáček if (authFramework == null) { 1660b5840353SAdam Hornáček authFramework = new AuthorizationFramework(getPluginDirectory(), getPluginStack()); 1661b5840353SAdam Hornáček } 1662b5840353SAdam Hornáček return authFramework; 1663b5840353SAdam Hornáček } 16641cbb0597SVladimir Kotal } 1665b5840353SAdam Hornáček 1666b5840353SAdam Hornáček /** 1667b5840353SAdam Hornáček * Set the authorization framework for this environment. Unload all 1668b5840353SAdam Hornáček * previously load plugins. 1669b5840353SAdam Hornáček * 1670b5840353SAdam Hornáček * @param fw the new framework 1671b5840353SAdam Hornáček */ setAuthorizationFramework(AuthorizationFramework fw)16721cbb0597SVladimir Kotal public void setAuthorizationFramework(AuthorizationFramework fw) { 16731cbb0597SVladimir Kotal synchronized (authFrameworkLock) { 1674b5840353SAdam Hornáček if (this.authFramework != null) { 1675b5840353SAdam Hornáček this.authFramework.removeAll(); 1676b5840353SAdam Hornáček } 1677b5840353SAdam Hornáček this.authFramework = fw; 1678b5840353SAdam Hornáček } 16791cbb0597SVladimir Kotal } 1680b5840353SAdam Hornáček 1681b5840353SAdam Hornáček /** 16822ffbb0cfSVladimir Kotal * Re-apply the configuration. 16832ffbb0cfSVladimir Kotal * @param reindex is the message result of reindex 1684a904b83aSVladimir Kotal * @param cmdType command timeout type 1685fa80b070SVladimir Kotal * @see #applyConfig(org.opengrok.indexer.configuration.Configuration, 1686fa80b070SVladimir Kotal * boolean, CommandTimeoutType) applyConfig(config, reindex, cmdType) 16872ffbb0cfSVladimir Kotal */ applyConfig(boolean reindex, CommandTimeoutType cmdType)1688a904b83aSVladimir Kotal public void applyConfig(boolean reindex, CommandTimeoutType cmdType) { 1689a904b83aSVladimir Kotal applyConfig(configuration, reindex, cmdType); 16902ffbb0cfSVladimir Kotal } 16912ffbb0cfSVladimir Kotal 16922ffbb0cfSVladimir Kotal /** 1693b5840353SAdam Hornáček * Set configuration from a message. The message could have come from the 1694b5840353SAdam Hornáček * Indexer (in which case some extra work is needed) or is it just a request 1695b5840353SAdam Hornáček * to set new configuration in place. 1696b5840353SAdam Hornáček * 16972ffbb0cfSVladimir Kotal * @param configuration XML configuration 1698b5840353SAdam Hornáček * @param reindex is the message result of reindex 1699a904b83aSVladimir Kotal * @param cmdType command timeout type 17009805b761SAdam Hornáček * @see #applyConfig(org.opengrok.indexer.configuration.Configuration, 1701a904b83aSVladimir Kotal * boolean, CommandTimeoutType) applyConfig(config, reindex, cmdType) 1702b5840353SAdam Hornáček */ applyConfig(String configuration, boolean reindex, CommandTimeoutType cmdType)1703a904b83aSVladimir Kotal public void applyConfig(String configuration, boolean reindex, CommandTimeoutType cmdType) { 1704b5840353SAdam Hornáček Configuration config; 1705b5840353SAdam Hornáček try { 17064ce4e2b9SAdam Hornáček config = makeXMLStringAsConfiguration(configuration); 1707b5840353SAdam Hornáček } catch (IOException ex) { 1708b5840353SAdam Hornáček LOGGER.log(Level.WARNING, "Configuration decoding failed", ex); 1709b5840353SAdam Hornáček return; 1710b5840353SAdam Hornáček } 1711b5840353SAdam Hornáček 1712a904b83aSVladimir Kotal applyConfig(config, reindex, cmdType); 1713b5840353SAdam Hornáček } 1714b5840353SAdam Hornáček 1715b5840353SAdam Hornáček /** 1716b5840353SAdam Hornáček * Set configuration from the incoming parameter. The configuration could 1717b5840353SAdam Hornáček * have come from the Indexer (in which case some extra work is needed) or 1718b5840353SAdam Hornáček * is it just a request to set new configuration in place. 1719b5840353SAdam Hornáček * 1720fa80b070SVladimir Kotal * The classes that have registered their listener will be pinged here. 1721fa80b070SVladimir Kotal * @see ConfigurationChangedListener 1722fa80b070SVladimir Kotal * 1723b5840353SAdam Hornáček * @param config the incoming configuration 1724b5840353SAdam Hornáček * @param reindex is the message result of reindex 1725a904b83aSVladimir Kotal * @param cmdType command timeout type 1726b5840353SAdam Hornáček */ applyConfig(Configuration config, boolean reindex, CommandTimeoutType cmdType)1727a904b83aSVladimir Kotal public void applyConfig(Configuration config, boolean reindex, CommandTimeoutType cmdType) { 1728a904b83aSVladimir Kotal setConfiguration(config, cmdType); 17292ffbb0cfSVladimir Kotal LOGGER.log(Level.INFO, "Configuration updated"); 1730b5840353SAdam Hornáček 1731b5840353SAdam Hornáček if (reindex) { 17322ffbb0cfSVladimir Kotal // We are assuming that each update of configuration means reindex. If dedicated thread is introduced 17332ffbb0cfSVladimir Kotal // in the future solely for the purpose of getting the event of reindex, the 2 calls below should 1734b5840353SAdam Hornáček // be moved there. 1735b5840353SAdam Hornáček refreshSearcherManagerMap(); 1736b5840353SAdam Hornáček maybeRefreshIndexSearchers(); 1737b5840353SAdam Hornáček // Force timestamp to update itself upon new config arrival. 1738b5840353SAdam Hornáček refreshDateForLastIndexRun(); 1739b5840353SAdam Hornáček } 1740b5840353SAdam Hornáček 17412ffbb0cfSVladimir Kotal // start/stop the watchdog if necessary 17422ffbb0cfSVladimir Kotal if (isAuthorizationWatchdog() && getPluginDirectory() != null) { 17432ffbb0cfSVladimir Kotal watchDog.start(new File(getPluginDirectory())); 1744b5840353SAdam Hornáček } else { 17452ffbb0cfSVladimir Kotal watchDog.stop(); 1746b5840353SAdam Hornáček } 1747b5840353SAdam Hornáček 1748b5840353SAdam Hornáček // set the new plugin directory and reload the authorization framework 17492ffbb0cfSVladimir Kotal getAuthorizationFramework().setPluginDirectory(getPluginDirectory()); 17502ffbb0cfSVladimir Kotal getAuthorizationFramework().setStack(getPluginStack()); 1751b5840353SAdam Hornáček getAuthorizationFramework().reload(); 17524ce4e2b9SAdam Hornáček 17532ffbb0cfSVladimir Kotal messagesContainer.setMessageLimit(getMessageLimit()); 1754e9a23d1eSAdam Hornáček 1755e9a23d1eSAdam Hornáček for (ConfigurationChangedListener l : listeners) { 1756e9a23d1eSAdam Hornáček l.onConfigurationChanged(); 1757e9a23d1eSAdam Hornáček } 17586068c59cSVladimir Kotal 17596068c59cSVladimir Kotal LOGGER.log(Level.INFO, "Done applying configuration"); 1760b5840353SAdam Hornáček } 1761b5840353SAdam Hornáček setIndexTimestamp()1762b5840353SAdam Hornáček public void setIndexTimestamp() throws IOException { 1763b5840353SAdam Hornáček indexTime.stamp(); 1764b5840353SAdam Hornáček } 1765b5840353SAdam Hornáček refreshDateForLastIndexRun()1766b5840353SAdam Hornáček public void refreshDateForLastIndexRun() { 1767b5840353SAdam Hornáček indexTime.refreshDateForLastIndexRun(); 1768b5840353SAdam Hornáček } 1769b5840353SAdam Hornáček maybeRefreshSearcherManager(SearcherManager sm)1770b5840353SAdam Hornáček private void maybeRefreshSearcherManager(SearcherManager sm) { 1771b5840353SAdam Hornáček try { 1772b5840353SAdam Hornáček sm.maybeRefresh(); 1773b5840353SAdam Hornáček } catch (AlreadyClosedException ex) { 17742ffbb0cfSVladimir Kotal // This is a case of removed project. See refreshSearcherManagerMap() for details. 1775b5840353SAdam Hornáček } catch (IOException ex) { 1776b5840353SAdam Hornáček LOGGER.log(Level.SEVERE, "maybeRefresh failed", ex); 1777b5840353SAdam Hornáček } 1778b5840353SAdam Hornáček } 1779b5840353SAdam Hornáček maybeRefreshIndexSearchers(Iterable<String> projects)17804ce4e2b9SAdam Hornáček public void maybeRefreshIndexSearchers(Iterable<String> projects) { 1781b5840353SAdam Hornáček for (String proj : projects) { 1782b5840353SAdam Hornáček if (searcherManagerMap.containsKey(proj)) { 1783b5840353SAdam Hornáček maybeRefreshSearcherManager(searcherManagerMap.get(proj)); 1784b5840353SAdam Hornáček } 1785b5840353SAdam Hornáček } 1786b5840353SAdam Hornáček } 1787b5840353SAdam Hornáček maybeRefreshIndexSearchers()1788b5840353SAdam Hornáček public void maybeRefreshIndexSearchers() { 17896068c59cSVladimir Kotal LOGGER.log(Level.INFO, "refreshing searcher managers"); 17906068c59cSVladimir Kotal Statistics stat = new Statistics(); 1791b5840353SAdam Hornáček for (Map.Entry<String, SearcherManager> entry : searcherManagerMap.entrySet()) { 1792b5840353SAdam Hornáček maybeRefreshSearcherManager(entry.getValue()); 1793b5840353SAdam Hornáček } 17946068c59cSVladimir Kotal stat.report(LOGGER, "Done refreshing searcher managers"); 1795b5840353SAdam Hornáček } 1796b5840353SAdam Hornáček 1797b5840353SAdam Hornáček /** 1798b5840353SAdam Hornáček * Get IndexSearcher for given project. 17992ffbb0cfSVladimir Kotal * Each IndexSearcher is born from a SearcherManager object. There is one SearcherManager for every project. 18002ffbb0cfSVladimir Kotal * This schema makes it possible to reuse IndexSearcher/IndexReader objects so the heavy lifting 18012ffbb0cfSVladimir Kotal * (esp. system calls) performed in FSDirectory and DirectoryReader happens only once for a project. 1802b5840353SAdam Hornáček * The caller has to make sure that the IndexSearcher is returned back 1803b5840353SAdam Hornáček * to the SearcherManager. This is done with returnIndexSearcher(). 18042ffbb0cfSVladimir Kotal * The return of the IndexSearcher should happen only after the search result data are read fully. 1805b5840353SAdam Hornáček * 1806f0df8b60SVladimir Kotal * @param projectName project 1807b5840353SAdam Hornáček * @return SearcherManager for given project 1808b5840353SAdam Hornáček * @throws IOException I/O exception 1809b5840353SAdam Hornáček */ 1810523d6b7bSVladimir Kotal @SuppressWarnings("java:S2095") getIndexSearcher(String projectName)1811f0df8b60SVladimir Kotal public SuperIndexSearcher getIndexSearcher(String projectName) throws IOException { 1812f0df8b60SVladimir Kotal SearcherManager mgr = searcherManagerMap.get(projectName); 1813f0df8b60SVladimir Kotal SuperIndexSearcher searcher; 1814b5840353SAdam Hornáček 1815b5840353SAdam Hornáček if (mgr == null) { 1816b5840353SAdam Hornáček File indexDir = new File(getDataRootPath(), IndexDatabase.INDEX_DIR); 1817f0df8b60SVladimir Kotal Directory dir = FSDirectory.open(new File(indexDir, projectName).toPath()); 1818b5840353SAdam Hornáček mgr = new SearcherManager(dir, new ThreadpoolSearcherFactory()); 1819f0df8b60SVladimir Kotal searcherManagerMap.put(projectName, mgr); 1820b5840353SAdam Hornáček } 1821c6f0939bSAdam Hornacek searcher = (SuperIndexSearcher) mgr.acquire(); 1822c6f0939bSAdam Hornacek searcher.setSearcherManager(mgr); 1823b5840353SAdam Hornáček 1824b5840353SAdam Hornáček return searcher; 1825b5840353SAdam Hornáček } 1826b5840353SAdam Hornáček 1827b5840353SAdam Hornáček /** 1828b5840353SAdam Hornáček * After new configuration is put into place, the set of projects might 1829b5840353SAdam Hornáček * change so we go through the SearcherManager objects and close those where 1830b5840353SAdam Hornáček * the corresponding project is no longer present. 1831b5840353SAdam Hornáček */ refreshSearcherManagerMap()1832b5840353SAdam Hornáček public void refreshSearcherManagerMap() { 1833b5840353SAdam Hornáček ArrayList<String> toRemove = new ArrayList<>(); 1834b5840353SAdam Hornáček 1835b5840353SAdam Hornáček for (Map.Entry<String, SearcherManager> entry : searcherManagerMap.entrySet()) { 1836b5840353SAdam Hornáček // If a project is gone, close the corresponding SearcherManager 1837b5840353SAdam Hornáček // so that it cannot produce new IndexSearcher objects. 1838b5840353SAdam Hornáček if (!getProjectNames().contains(entry.getKey())) { 1839b5840353SAdam Hornáček try { 18406068c59cSVladimir Kotal LOGGER.log(Level.FINE, "closing SearcherManager for project {0}", entry.getKey()); 1841b5840353SAdam Hornáček entry.getValue().close(); 1842b5840353SAdam Hornáček } catch (IOException ex) { 1843b5840353SAdam Hornáček LOGGER.log(Level.SEVERE, 18446068c59cSVladimir Kotal String.format("cannot close SearcherManager for project %s", entry.getKey()), ex); 1845b5840353SAdam Hornáček } 1846b5840353SAdam Hornáček toRemove.add(entry.getKey()); 1847b5840353SAdam Hornáček } 1848b5840353SAdam Hornáček } 1849b5840353SAdam Hornáček 1850b5840353SAdam Hornáček for (String proj : toRemove) { 1851b5840353SAdam Hornáček searcherManagerMap.remove(proj); 1852b5840353SAdam Hornáček } 1853b5840353SAdam Hornáček } 1854b5840353SAdam Hornáček 1855b5840353SAdam Hornáček /** 1856b5840353SAdam Hornáček * Return collection of IndexReader objects as MultiReader object 1857b5840353SAdam Hornáček * for given list of projects. 1858b5840353SAdam Hornáček * The caller is responsible for releasing the IndexSearcher objects 1859b5840353SAdam Hornáček * so we add them to the map. 1860b5840353SAdam Hornáček * 1861b5840353SAdam Hornáček * @param projects list of projects 1862b5840353SAdam Hornáček * @param searcherList each SuperIndexSearcher produced will be put into this list 1863b5840353SAdam Hornáček * @return MultiReader for the projects 1864b5840353SAdam Hornáček */ getMultiReader(SortedSet<String> projects, ArrayList<SuperIndexSearcher> searcherList)1865b5840353SAdam Hornáček public MultiReader getMultiReader(SortedSet<String> projects, 1866b5840353SAdam Hornáček ArrayList<SuperIndexSearcher> searcherList) { 1867b5840353SAdam Hornáček 1868b5840353SAdam Hornáček IndexReader[] subreaders = new IndexReader[projects.size()]; 1869b5840353SAdam Hornáček int ii = 0; 1870b5840353SAdam Hornáček 18712ffbb0cfSVladimir Kotal // TODO might need to rewrite to Project instead of String, need changes in projects.jspf too. 1872b5840353SAdam Hornáček for (String proj : projects) { 1873b5840353SAdam Hornáček try { 18744151dbf5SChris Fraire SuperIndexSearcher searcher = getIndexSearcher(proj); 1875b5840353SAdam Hornáček subreaders[ii++] = searcher.getIndexReader(); 1876b5840353SAdam Hornáček searcherList.add(searcher); 1877a72324b1SAdam Hornáček } catch (IOException | NullPointerException ex) { 1878b5840353SAdam Hornáček LOGGER.log(Level.SEVERE, 1879b5840353SAdam Hornáček "cannot get IndexReader for project " + proj, ex); 1880b5840353SAdam Hornáček return null; 1881b5840353SAdam Hornáček } 1882b5840353SAdam Hornáček } 1883b5840353SAdam Hornáček MultiReader multiReader = null; 1884b5840353SAdam Hornáček try { 1885b5840353SAdam Hornáček multiReader = new MultiReader(subreaders, true); 1886b5840353SAdam Hornáček } catch (IOException ex) { 1887b5840353SAdam Hornáček LOGGER.log(Level.SEVERE, 1888b5840353SAdam Hornáček "cannot construct MultiReader for set of projects", ex); 1889b5840353SAdam Hornáček } 1890b5840353SAdam Hornáček return multiReader; 1891b5840353SAdam Hornáček } 18924ce4e2b9SAdam Hornáček startExpirationTimer()18934ce4e2b9SAdam Hornáček public void startExpirationTimer() { 18944151dbf5SChris Fraire messagesContainer.setMessageLimit(getMessageLimit()); 18954ce4e2b9SAdam Hornáček messagesContainer.startExpirationTimer(); 18964ce4e2b9SAdam Hornáček } 18974ce4e2b9SAdam Hornáček stopExpirationTimer()18984ce4e2b9SAdam Hornáček public void stopExpirationTimer() { 18994ce4e2b9SAdam Hornáček messagesContainer.stopExpirationTimer(); 19004ce4e2b9SAdam Hornáček } 19014ce4e2b9SAdam Hornáček 19024ce4e2b9SAdam Hornáček /** 19034ce4e2b9SAdam Hornáček * Get the default set of messages for the main tag. 19044ce4e2b9SAdam Hornáček * 19054ce4e2b9SAdam Hornáček * @return set of messages 19064ce4e2b9SAdam Hornáček */ getMessages()19074ce4e2b9SAdam Hornáček public SortedSet<AcceptedMessage> getMessages() { 19084ce4e2b9SAdam Hornáček return messagesContainer.getMessages(); 19094ce4e2b9SAdam Hornáček } 19104ce4e2b9SAdam Hornáček 19114ce4e2b9SAdam Hornáček /** 1912ff44f24aSAdam Hornáček * Get the set of messages for the arbitrary tag. 19134ce4e2b9SAdam Hornáček * 19144ce4e2b9SAdam Hornáček * @param tag the message tag 19154ce4e2b9SAdam Hornáček * @return set of messages 19164ce4e2b9SAdam Hornáček */ getMessages(final String tag)19174ce4e2b9SAdam Hornáček public SortedSet<AcceptedMessage> getMessages(final String tag) { 19184ce4e2b9SAdam Hornáček return messagesContainer.getMessages(tag); 19194ce4e2b9SAdam Hornáček } 19204ce4e2b9SAdam Hornáček 19214ce4e2b9SAdam Hornáček /** 19224ce4e2b9SAdam Hornáček * Add a message to the application. 19234ce4e2b9SAdam Hornáček * Also schedules a expiration timer to remove this message after its expiration. 19244ce4e2b9SAdam Hornáček * 19254ce4e2b9SAdam Hornáček * @param message the message 19264ce4e2b9SAdam Hornáček */ addMessage(final Message message)19274ce4e2b9SAdam Hornáček public void addMessage(final Message message) { 19284ce4e2b9SAdam Hornáček messagesContainer.addMessage(message); 19294ce4e2b9SAdam Hornáček } 19304ce4e2b9SAdam Hornáček 19314ce4e2b9SAdam Hornáček /** 19324ce4e2b9SAdam Hornáček * Remove all messages containing at least one of the tags. 19334ce4e2b9SAdam Hornáček * @param tags set of tags 19341d0bbff4SVladimir Kotal * @param text message text (can be null, empty) 19354ce4e2b9SAdam Hornáček */ removeAnyMessage(final Set<String> tags, final String text)19361d0bbff4SVladimir Kotal public void removeAnyMessage(final Set<String> tags, final String text) { 19371d0bbff4SVladimir Kotal messagesContainer.removeAnyMessage(tags, text); 19384ce4e2b9SAdam Hornáček } 19394ce4e2b9SAdam Hornáček 19404ce4e2b9SAdam Hornáček /** 19414ce4e2b9SAdam Hornáček * @return all messages regardless their tag 19424ce4e2b9SAdam Hornáček */ getAllMessages()19434ce4e2b9SAdam Hornáček public Set<AcceptedMessage> getAllMessages() { 19444ce4e2b9SAdam Hornáček return messagesContainer.getAllMessages(); 19454ce4e2b9SAdam Hornáček } 19464ce4e2b9SAdam Hornáček getDtagsEftarPath()19472ffbb0cfSVladimir Kotal public Path getDtagsEftarPath() { 19484151dbf5SChris Fraire return syncReadConfiguration(Configuration::getDtagsEftarPath); 19492ffbb0cfSVladimir Kotal } 19502ffbb0cfSVladimir Kotal 19512ffbb0cfSVladimir Kotal /** 19522ffbb0cfSVladimir Kotal * Get the eftar file, which contains definition tags for path descriptions. 19532ffbb0cfSVladimir Kotal * 19542ffbb0cfSVladimir Kotal * @return {@code null} if there is no such file, the file otherwise. 19552ffbb0cfSVladimir Kotal */ getDtagsEftar()19562ffbb0cfSVladimir Kotal public File getDtagsEftar() { 19572ffbb0cfSVladimir Kotal if (dtagsEftar == null) { 19582ffbb0cfSVladimir Kotal File tmp = getDtagsEftarPath().toFile(); 19592ffbb0cfSVladimir Kotal if (tmp.canRead()) { 19602ffbb0cfSVladimir Kotal dtagsEftar = tmp; 19612ffbb0cfSVladimir Kotal } 19622ffbb0cfSVladimir Kotal } 19632ffbb0cfSVladimir Kotal return dtagsEftar; 19642ffbb0cfSVladimir Kotal } 19652ffbb0cfSVladimir Kotal getSuggesterConfig()19662ffbb0cfSVladimir Kotal public SuggesterConfig getSuggesterConfig() { 19674151dbf5SChris Fraire return syncReadConfiguration(Configuration::getSuggesterConfig); 19682ffbb0cfSVladimir Kotal } 19692ffbb0cfSVladimir Kotal setSuggesterConfig(SuggesterConfig suggesterConfig)1970754ebdfbSChris Fraire public void setSuggesterConfig(SuggesterConfig suggesterConfig) { 1971754ebdfbSChris Fraire syncWriteConfiguration(suggesterConfig, Configuration::setSuggesterConfig); 19722ffbb0cfSVladimir Kotal } 19732ffbb0cfSVladimir Kotal getStatsdConfig()19740d7ace53SVladimir Kotal public StatsdConfig getStatsdConfig() { 19750d7ace53SVladimir Kotal return syncReadConfiguration(Configuration::getStatsdConfig); 19760d7ace53SVladimir Kotal } 19770d7ace53SVladimir Kotal setStatsdConfig(StatsdConfig statsdConfig)19780d7ace53SVladimir Kotal public void setStatsdConfig(StatsdConfig statsdConfig) { 19790d7ace53SVladimir Kotal syncWriteConfiguration(statsdConfig, Configuration::setStatsdConfig); 19800d7ace53SVladimir Kotal } 19810d7ace53SVladimir Kotal 19824151dbf5SChris Fraire /** 19834151dbf5SChris Fraire * Applies the specified function to the runtime configuration, after having 19844151dbf5SChris Fraire * obtained the configuration read-lock (and releasing afterward). 19854151dbf5SChris Fraire * @param function a defined function 19864151dbf5SChris Fraire * @param <R> the type of the result of the function 19874151dbf5SChris Fraire * @return the function result 19884151dbf5SChris Fraire */ syncReadConfiguration(Function<Configuration, R> function)19894151dbf5SChris Fraire public <R> R syncReadConfiguration(Function<Configuration, R> function) { 19904151dbf5SChris Fraire try (ResourceLock resourceLock = configLock.readLockAsResource()) { 1991754ebdfbSChris Fraire //noinspection ConstantConditions to avoid warning of no reference to auto-closeable 19924151dbf5SChris Fraire assert resourceLock != null; 19934151dbf5SChris Fraire return function.apply(configuration); 19944151dbf5SChris Fraire } 19954151dbf5SChris Fraire } 19964151dbf5SChris Fraire 19974151dbf5SChris Fraire /** 19984151dbf5SChris Fraire * Performs the specified operation which is provided the runtime 19994151dbf5SChris Fraire * configuration and the specified argument, after first having obtained the 20004151dbf5SChris Fraire * configuration write-lock (and releasing afterward). 20014151dbf5SChris Fraire * @param <V> the type of the input to the operation 2002754ebdfbSChris Fraire * @param v the input argument 2003754ebdfbSChris Fraire * @param consumer a defined consumer 20044151dbf5SChris Fraire */ syncWriteConfiguration(V v, ConfigurationValueConsumer<V> consumer)2005754ebdfbSChris Fraire public <V> void syncWriteConfiguration(V v, ConfigurationValueConsumer<V> consumer) { 20064151dbf5SChris Fraire try (ResourceLock resourceLock = configLock.writeLockAsResource()) { 2007754ebdfbSChris Fraire //noinspection ConstantConditions to avoid warning of no reference to auto-closeable 20084151dbf5SChris Fraire assert resourceLock != null; 20094151dbf5SChris Fraire consumer.accept(configuration, v); 20104151dbf5SChris Fraire } 20114151dbf5SChris Fraire } 20124151dbf5SChris Fraire getMessageLimit()20134151dbf5SChris Fraire private int getMessageLimit() { 20144151dbf5SChris Fraire return syncReadConfiguration(Configuration::getMessageLimit); 2015ff44f24aSAdam Hornáček } 2016814ddb49SVladimir Kotal getIndexerAuthenticationToken()20178d34347cSVladimir Kotal public String getIndexerAuthenticationToken() { 20188d34347cSVladimir Kotal return syncReadConfiguration(Configuration::getIndexerAuthenticationToken); 20198d34347cSVladimir Kotal } 20208d34347cSVladimir Kotal setIndexerAuthenticationToken(String token)20218d34347cSVladimir Kotal public void setIndexerAuthenticationToken(String token) { 20228d34347cSVladimir Kotal syncWriteConfiguration(token, Configuration::setIndexerAuthenticationToken); 20238d34347cSVladimir Kotal } 20248d34347cSVladimir Kotal getAuthenticationTokens()2025b0a23e73SVladimir Kotal public Set<String> getAuthenticationTokens() { 2026c7dfd267SVladimir Kotal return Collections.unmodifiableSet(syncReadConfiguration(Configuration::getAuthenticationTokens)); 2027b0a23e73SVladimir Kotal } 2028b0a23e73SVladimir Kotal setAuthenticationTokens(Set<String> tokens)2029b0a23e73SVladimir Kotal public void setAuthenticationTokens(Set<String> tokens) { 2030b0a23e73SVladimir Kotal syncWriteConfiguration(tokens, Configuration::setAuthenticationTokens); 2031814ddb49SVladimir Kotal } 2032e9a23d1eSAdam Hornáček isAllowInsecureTokens()203360e45c9fSVladimir Kotal public boolean isAllowInsecureTokens() { 203460e45c9fSVladimir Kotal return syncReadConfiguration(Configuration::isAllowInsecureTokens); 203560e45c9fSVladimir Kotal } 203660e45c9fSVladimir Kotal setAllowInsecureTokens(boolean value)203760e45c9fSVladimir Kotal public void setAllowInsecureTokens(boolean value) { 203860e45c9fSVladimir Kotal syncWriteConfiguration(value, Configuration::setAllowInsecureTokens); 203960e45c9fSVladimir Kotal } 204060e45c9fSVladimir Kotal registerListener(ConfigurationChangedListener listener)2041e9a23d1eSAdam Hornáček public void registerListener(ConfigurationChangedListener listener) { 2042e9a23d1eSAdam Hornáček listeners.add(listener); 2043e9a23d1eSAdam Hornáček } 2044b5840353SAdam Hornáček } 2045