RuntimeEnvironment.java revision e8a20bc0a36e5885fa67503ba58be9c29ef96500
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* See LICENSE.txt included in this distribution for the specific
* language governing permissions and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at LICENSE.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
/**
* The RuntimeEnvironment class is used as a placeholder for the current
* configuration this execution context (classloader) is using.
*/
public final class RuntimeEnvironment {
private Configuration configuration;
/* Get thread pool used for top-level repository history generation. */
public static synchronized ExecutorService getHistoryExecutor() {
if (historyExecutor == null) {
try {
} catch (Throwable t) {
+ "cache threads to use for cache creation", t);
}
}
new ThreadFactory() {
return thread;
}
});
}
return historyExecutor;
}
/* Get thread pool used for history generation of renamed files. */
public static synchronized ExecutorService getHistoryRenamedExecutor() {
if (historyRenamedExecutor == null) {
try {
} catch (Throwable t) {
+ "cache threads to use for cache creation of renamed files", t);
}
}
new ThreadFactory() {
return thread;
}
});
}
return historyRenamedExecutor;
}
/* Get thread pool used for multi-project searches. */
public synchronized ExecutorService getSearchExecutor() {
if (searchExecutor == null) {
this.getMaxSearchThreadCount(),
new ThreadFactory() {
return thread;
}
});
}
return searchExecutor;
}
public static synchronized void freeHistoryExecutor() {
}
public static synchronized void destroyRenamedHistoryExecutor() throws InterruptedException {
if (historyRenamedExecutor != null) {
// All the jobs should be completed by now however for testing
// we would like to make sure the threads are gone.
}
}
/**
* Get the one and only instance of the RuntimeEnvironment
*
* @return the one and only instance of the RuntimeEnvironment
*/
public static RuntimeEnvironment getInstance() {
return instance;
}
/**
* Creates a new instance of RuntimeEnvironment. Private to ensure a
* singleton pattern.
*/
private RuntimeEnvironment() {
configuration = new Configuration();
protected Configuration initialValue() {
return configuration;
}
};
}
try {
return s;
}
return file.getCanonicalPath();
} catch (IOException ex) {
return s;
}
}
public int getScanningDepth() {
}
public void setScanningDepth(int scanningDepth) {
}
public int getCommandTimeout() {
}
public void setCommandTimeout(int timeout) {
}
public int getIndexRefreshPeriod() {
}
public void setIndexRefreshPeriod(int seconds) {
}
/**
* Get the path to the where the index database is stored
*
* @return the path to the index database
*/
public String getDataRootPath() {
}
/**
* Get a file representing the index database
*
* @return the index database
*/
public File getDataRootFile() {
}
return ret;
}
/**
* Set the path to where the index database is stored
*
* @param dataRoot the index database
*/
}
/**
* Get the path to where the sources are located
*
* @return path to where the sources are located
*/
public String getSourceRootPath() {
return configuration.getSourceRoot();
}
/**
* Get a file representing the directory where the sources are located
*
* @return A file representing the directory where the sources are located
*/
public File getSourceRootFile() {
}
return ret;
}
/**
* Specify the source root
*
* @param sourceRoot the location of the sources
*/
}
/**
* Returns a path relative to source root. This would just be a simple
* substring operation, except we need to support symlinks outside the
* source root.
*
* @param file A file to resolve
* @param stripCount Number of characters past source root to strip
* @throws IOException If an IO error occurs
* @throws FileNotFoundException If the file is not relative to source root
* @return Path relative to source root
*/
}
+ stripCount);
}
}
}
/**
* Do we have projects?
*
* @return true if we have projects
*/
public boolean hasProjects() {
}
/**
* Get all of the projects
*
* @return a list containing all of the projects (may be null)
*/
}
/**
* Set the list of the projects
*
* @param projects the list of projects to use
*/
}
/**
* Do we have groups?
*
* @return true if we have groups
*/
public boolean hasGroups() {
}
/**
* Get all of the groups
*
* @return a set containing all of the groups (may be null)
*/
}
/**
* Set the list of the groups
*
* @param groups the set of groups to use
*/
}
/**
* Register this thread in the thread/configuration map (so that all
* subsequent calls to the RuntimeEnvironment from this thread will use the
* same configuration
*
* @return this instance
*/
public RuntimeEnvironment register() {
return this;
}
/**
* Returns constructed project - repositories map.
*
* @return the map
* @see #generateProjectRepositoriesMap
*/
return repository_map;
}
/**
* Get the context name of the web application
*
* @return the web applications context name
*/
public String getUrlPrefix() {
}
/**
* Set the web context name
*
* @param urlPrefix the web applications context name
*/
}
/**
* Get the name of the ctags program in use
*
* @return the name of the ctags program in use
*/
}
/**
* Specify the CTags program to use
*
* @param ctags the ctags program to use
*/
}
public int getCachePages() {
}
public void setCachePages(int cachePages) {
}
public int getHitsPerPage() {
}
public void setHitsPerPage(int hitsPerPage) {
}
// cache these tests instead of reruning them for every call
private transient Boolean exCtagsFound;
private transient Boolean isUniversalCtagsVal;
/**
* Validate that I have a Exuberant ctags program I may use
*
* @return true if success, false otherwise
*/
public boolean validateExuberantCtags() {
if (exCtagsFound == null) {
+ "(tried running " + "{0}" + ")\n"
+ "Please use option -c to specify path to a good "
+ "Exuberant Ctags program.\n"
+ "Or set it in java property "
+ "org.opensolaris.opengrok.analysis.Ctags", getCtags());
exCtagsFound = false;
} else {
if (isUnivCtags) {
isUniversalCtagsVal = true;
}
exCtagsFound = true;
}
}
return exCtagsFound;
}
/**
* Are we using Universal ctags?
*
* @return true if we are using Universal ctags
*/
public boolean isUniversalCtags() {
if (isUniversalCtagsVal == null) {
isUniversalCtagsVal = false;
isUniversalCtagsVal = true;
}
}
return isUniversalCtagsVal;
}
/**
* Get the max time a SMC operation may use to avoid being cached
*
* @return the max time
*/
public int getHistoryReaderTimeLimit() {
}
/**
* Specify the maximum time a SCM operation should take before it will be
* cached (in ms)
*
* @param historyReaderTimeLimit the max time in ms before it is cached
*/
public void setHistoryReaderTimeLimit(int historyReaderTimeLimit) {
}
/**
* Is history cache currently enabled?
*
* @return true if history cache is enabled
*/
public boolean useHistoryCache() {
}
/**
* Specify if we should use history cache or not
*
* @param useHistoryCache set false if you do not want to use history cache
*/
public void setUseHistoryCache(boolean useHistoryCache) {
}
/**
* Should the history cache be stored in a database instead of in XML files?
*
* @return {@code true} if the cache should be stored in a database
*/
public boolean storeHistoryCacheInDB() {
}
/**
* Set whether the history cache should be stored in a database.
*
* @param store {@code true} if the cache should be stored in a database
*/
public void setStoreHistoryCacheInDB(boolean store) {
}
/**
* Should we generate HTML or not during the indexing phase
*
* @return true if HTML should be generated during the indexing phase
*/
public boolean isGenerateHtml() {
}
/**
* Specify if we should generate HTML or not during the indexing phase
*
* @param generateHtml set this to true to pregenerate HTML
*/
public void setGenerateHtml(boolean generateHtml) {
}
/**
* Set if we should compress the xref files or not
*
* @param compressXref set to true if the generated html files should be
* compressed
*/
public void setCompressXref(boolean compressXref) {
}
/**
* Are we using compressed HTML files?
*
* @return {@code true} if the html-files should be compressed.
*/
public boolean isCompressXref() {
}
public boolean isQuickContextScan() {
}
public void setQuickContextScan(boolean quickContextScan) {
}
}
/**
* Set the map of external SCM repositories
*
* @param repositories the repositories to use
*/
}
/**
* Set the project that is specified to be the default project to use. The
* default project is the project you will search (from the web application)
* if the page request didn't contain the cookie..
*
* @param defaultProject The default project to use
*/
}
/**
* Get the project that is specified to be the default project to use. The
* default project is the project you will search (from the web application)
* if the page request didn't contain the cookie..
*
* @return the default project (may be null if not specified)
*/
public Project getDefaultProject() {
}
/**
*
* @return at what size (in MB) we should flush the buffer
*/
public double getRamBufferSize() {
}
/**
* Set the size of buffer which will determine when the docs are flushed to
* disk. Specify size in MB please. 16MB is default note that this is per
* thread (lucene uses 8 threads by default in 4.x)
*
* @param ramBufferSize the size(in MB) when we should flush the docs
*/
public void setRamBufferSize(double ramBufferSize) {
}
}
public String getPluginDirectory() {
}
/**
* Is the verbosity flag turned on?
*
* @return true if we can print extra information
*/
public boolean isVerbose() {
}
/**
* Set the verbosity flag (to add extra debug information in output)
*
* @param verbose new value
*/
public void setVerbose(boolean verbose) {
}
/**
* Is the progress print flag turned on?
*
* @return true if we can print per project progress %
*/
public boolean isPrintProgress() {
}
/**
* Set the printing of progress % flag (user convenience)
*
* @param printP new value
*/
public void setPrintProgress(boolean printP) {
}
/**
* Specify if a search may start with a wildcard. Note that queries that
* start with a wildcard will give a significant impact on the search
* performance.
*
* @param allowLeadingWildcard set to true to activate (disabled by default)
*/
public void setAllowLeadingWildcard(boolean allowLeadingWildcard) {
}
/**
* Is leading wildcards allowed?
*
* @return true if a search may start with a wildcard
*/
public boolean isAllowLeadingWildcard() {
}
public IgnoredNames getIgnoredNames() {
}
}
public Filter getIncludedNames() {
}
}
/**
* Returns the user page for the history listing
*
* @return the URL string fragment preceeding the username
*/
public String getUserPage() {
}
/**
* Get the client command to use to access the repository for the given
* fully qualified classname.
*
* @param clazzName name of the targeting class
* @return {@code null} if not yet set, the client command otherwise.
*/
}
/**
* Set the client command to use to access the repository for the given
* fully quallified classname.
*
* @param clazzName name of the targeting class. If {@code null} this method
* does nothing.
* @param cmd the client command to use. If {@code null} the corresponding
* entry for the given clazzName get removed.
* @return the client command previously set, which might be {@code null}.
*/
}
/**
* Sets the user page for the history listing
*
* @param userPage the URL fragment preceeding the username from history
*/
}
/**
* Returns the user page suffix for the history listing
*
* @return the URL string fragment following the username
*/
public String getUserPageSuffix() {
}
/**
* Sets the user page suffix for the history listing
*
* @param userPageSuffix the URL fragment following the username from
* history
*/
}
/**
* Returns the bug page for the history listing
*
* @return the URL string fragment preceeding the bug ID
*/
public String getBugPage() {
}
/**
* Sets the bug page for the history listing
*
* @param bugPage the URL fragment preceeding the bug ID
*/
}
/**
* Returns the bug regex for the history listing
*
* @return the regex that is looked for in history comments
*/
public String getBugPattern() {
}
/**
* Sets the bug regex for the history listing
*
* @param bugPattern the regex to search history comments
*/
}
/**
* Returns the review(ARC) page for the history listing
*
* @return the URL string fragment preceeding the review page ID
*/
public String getReviewPage() {
}
/**
* Sets the review(ARC) page for the history listing
*
* @param reviewPage the URL fragment preceeding the review page ID
*/
}
/**
* Returns the review(ARC) regex for the history listing
*
* @return the regex that is looked for in history comments
*/
public String getReviewPattern() {
}
/**
* Sets the review(ARC) regex for the history listing
*
* @param reviewPattern the regex to search history comments
*/
}
public String getWebappLAF() {
}
}
}
}
public boolean isOptimizeDatabase() {
}
public void setOptimizeDatabase(boolean optimizeDatabase) {
}
public boolean isUsingLuceneLocking() {
}
public void setUsingLuceneLocking(boolean useLuceneLocking) {
}
public boolean isIndexVersionedFilesOnly() {
}
public void setIndexVersionedFilesOnly(boolean indexVersionedFilesOnly) {
}
public boolean isTagsEnabled() {
}
public void setTagsEnabled(boolean tagsEnabled) {
}
public boolean isScopesEnabled() {
}
public void setScopesEnabled(boolean scopesEnabled) {
}
public boolean isFoldingEnabled() {
}
public void setFoldingEnabled(boolean foldingEnabled) {
}
public Date getDateForLastIndexRun() {
}
public String getDatabaseDriver() {
}
}
public String getDatabaseUrl() {
}
}
public String getCTagsExtraOptionsFile() {
}
}
}
}
/**
* Return whether e-mail addresses should be obfuscated in the xref.
* @return if we obfuscate emails
*/
public boolean isObfuscatingEMailAddresses() {
}
/**
* Set whether e-mail addresses should be obfuscated in the xref.
* @param obfuscate should we obfuscate emails?
*/
public void setObfuscatingEMailAddresses(boolean obfuscate) {
}
/**
* Should status.jsp print internal settings, like paths and database URLs?
*
* @return {@code true} if status.jsp should show the configuration,
* {@code false} otherwise
*/
public boolean isChattyStatusPage() {
}
/**
* Set whether status.jsp should print internal settings.
*
* @param chatty {@code true} if internal settings should be printed,
* {@code false} otherwise
*/
public void setChattyStatusPage(boolean chatty) {
}
public void setFetchHistoryWhenNotInCache(boolean nofetch) {
}
public boolean isFetchHistoryWhenNotInCache() {
}
public void setHandleHistoryOfRenamedFiles(boolean enable) {
}
public boolean isHandleHistoryOfRenamedFiles() {
}
public void setRevisionMessageCollapseThreshold(int threshold) {
}
public int getRevisionMessageCollapseThreshold() {
}
public void setMaxSearchThreadCount(int count) {
}
public int getMaxSearchThreadCount() {
}
/**
* Read an configuration file and set it as the current configuration.
*
* @param file the file to read
* @throws IOException if an error occurs
*/
}
/**
* Write the current configuration to a file
*
* @param file the file to write the configuration into
* @throws IOException if an error occurs
*/
}
/**
* Write the current configuration to a socket
*
* @param host the host address to receive the configuration
* @param port the port to use on the host
* @throws IOException if an error occurs
*/
}
}
protected void writeConfiguration() throws IOException {
}
/**
* Generate a TreeMap of projects with corresponding repository information.
*
* Project with some repository information is considered as a repository
* otherwise it is just a simple project.
*/
private void generateProjectRepositoriesMap() throws IOException {
}
}
}
}
/**
* Classifies projects and puts them in their groups.
*/
return;
}
// filterProjects only groups which match project's description
}
});
// add project to the groups
} else {
}
}
}
}
/**
* Sets the configuration and performs necessary actions.
*
* Mainly it classifies the projects in their groups and generates project -
* repositories map
*
* @param configuration what configuration to use
*/
this.configuration = configuration;
try {
} catch (IOException ex) {
}
register();
}
this.configuration = configuration;
try {
} catch (IOException ex) {
}
register();
}
public Configuration getConfiguration() {
return this.threadConfig.get();
}
private ServerSocket configServerSocket;
/**
* Try to stop the configuration listener thread
*/
public void stopConfigurationListenerThread() {
}
private Thread configurationListenerThread;
/**
* Start a thread to listen on a socket to receive new configurations to
* use.
*
* @param endpoint The socket address to listen on
* @return true if the endpoint was available (and the thread was started)
*/
boolean ret = false;
try {
configServerSocket = new ServerSocket();
ret = true;
public void run() {
s.getInetAddress().getHostAddress());
byte[] buf = new byte[1024];
int len;
}
}
obj = d.readObject();
}
if (obj instanceof Configuration) {
//force timestamp to update itself upon new config arrival
// We are assuming that each update of configuration
// means reindex. If dedicated thread is introduced
// in the future solely for the purpose of getting
// the event of reindex, the 2 calls below should
// be moved there.
}
} catch (IOException e) {
} catch (RuntimeException e) {
}
}
}
}, "configurationListener");
} catch (UnknownHostException ex) {
} catch (IOException ex) {
}
}
return ret;
}
private Thread watchDogThread;
private WatchService watchDogWatcher;
public static final int THREAD_SLEEP_TIME = 2000;
/**
* Starts a watch dog service for a directory. It automatically reloads the
* AuthorizationFramework if there was a change.
*
* You can control start of this service by context-parameter in web.xml
* param-name: enableAuthorizationWatchDog
*
* @param directory root directory for plugins
*/
return;
}
public void run() {
try {
// attach monitor
return CONTINUE;
}
});
try {
} catch (ClosedWatchServiceException x) {
break;
}
boolean reload = false;
if (kind == ENTRY_CREATE) {
reload = true;
} else if (kind == ENTRY_DELETE) {
reload = true;
} else if (kind == ENTRY_MODIFY) {
reload = true;
}
}
if (reload) {
}
break;
}
}
}
}
}, "watchDogService");
}
/**
* Stops the watch dog service.
*/
public void stopWatchDogService() {
if (watchDogWatcher != null) {
try {
} catch (IOException ex) {
}
}
if (watchDogThread != null) {
try {
} catch (InterruptedException ex) {
}
}
}
private Thread indexReopenThread;
public void maybeRefreshIndexSearchers() {
try {
} catch (IOException ex) {
}
}
}
/**
* Call maybeRefresh() on each SearcherManager object from dedicated thread
* periodically.
* If the corresponding index has changed in the meantime, it will be safely
* reopened, i.e. without impacting existing IndexSearcher/IndexReader
* objects, thus not disrupting searches in progress.
*/
public void startIndexReopenThread() {
public void run() {
try {
} catch (InterruptedException ex) {
}
}
}
}, "indexReopenThread");
}
public void stopIndexReopenThread() {
if (indexReopenThread != null) {
try {
} catch (InterruptedException ex) {
}
}
}
/**
* Get IndexSearcher for given project.
* Each IndexSearcher is born from a SearcherManager object. There is
* one SearcherManager for every project.
* This schema makes it possible to reuse IndexSearcher/IndexReader objects
* so the heavy lifting (esp. system calls) performed in FSDirectory
* and DirectoryReader happens only once for a project.
* The caller has to make sure that the IndexSearcher is returned back
* to the SearcherManager. This is done with returnIndexSearcher().
* The return of the IndexSearcher should happen only after the search
* result data are read fully.
*
* @param proj project
* @return SearcherManager for given project
*/
try {
} catch (IOException ex) {
}
} else {
}
return searcher;
}
/**
* Return IndexSearcher object back to corresponding SearcherManager.
* @param proj project name which belongs to the searcher
* @param searcher searcher object to release
*/
try {
} catch (IOException ex) {
}
} else {
}
}
/**
* After new configuration is put into place, the set of projects might
* change so we go through the SearcherManager objects and close those where
* the corresponding project is no longer present.
*/
private void refreshSearcherManagerMap() {
try {
// If a project is gone, close the corresponding SearcherManager
// so that it cannot produce new IndexSearcher objects.
// XXX Ideally we would like to remove the entry from the map here.
// However, if some thread acquired an IndexSearcher and then reindex happened
// and the corresponding searcherManager was removed from the map,
// returnIndexSearcher() will have no place to return the indexSearcher to.
// This would likely lead to leaks.
// So, we cannot remove searcherManager from the map until all threads
// are done with it. However, there does not seem to be any way how
// to know this without implementing yet another layer of reference counting.
// For the time being, simply let the map to grow.
}
}
} catch (IOException ex) {
}
}
}
/**
* Return collection of IndexReader objects as MultiReader object
* for given list of projects.
* The caller is responsible for releasing the IndexSearcher objects
* so we add them to the map.
*
* @param projects list of projects
* @param map each IndexSearcher produced will be put into this map
* @return MultiReader for the projects
*/
int ii = 0;
// TODO might need to rewrite to Project instead of
// String , need changes in projects.jspf too
try {
} catch (IOException ex) {
}
}
try {
} catch (IOException ex) {
"cannot construct MultiReader for set of projects", ex);
}
return multiReader;
}
/**
* Helper method for the consumers of getMultiReader() to be called when
* destroying search context. This will make sure all indexSearcher
* objects are properly released.
*
* @param map map of project to indexSearcher
*/
}
}
}
}