RuntimeEnvironment.java revision 456
0N/A/*
0N/A * CDDL HEADER START
0N/A *
0N/A * The contents of this file are subject to the terms of the
0N/A * Common Development and Distribution License (the "License").
0N/A * You may not use this file except in compliance with the License.
0N/A *
0N/A * See LICENSE.txt included in this distribution for the specific
0N/A * language governing permissions and limitations under the License.
0N/A *
0N/A * When distributing Covered Code, include this CDDL HEADER in each
0N/A * file and include the License file at LICENSE.txt.
0N/A * If applicable, add the following below this CDDL HEADER, with the
0N/A * fields enclosed by brackets "[]" replaced with your own identifying
0N/A * information: Portions Copyright [yyyy] [name of copyright owner]
0N/A *
0N/A * CDDL HEADER END
0N/A */
0N/A
0N/A/*
119N/A * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
0N/A * Use is subject to license terms.
0N/A */
0N/Apackage org.opensolaris.opengrok.configuration;
65N/A
0N/Aimport java.beans.XMLDecoder;
125N/Aimport java.beans.XMLEncoder;
125N/Aimport java.io.BufferedInputStream;
125N/Aimport java.io.BufferedReader;
125N/Aimport java.io.File;
58N/Aimport java.io.IOException;
77N/Aimport java.io.InputStreamReader;
125N/Aimport java.net.InetAddress;
125N/Aimport java.net.ServerSocket;
125N/Aimport java.net.Socket;
125N/Aimport java.net.SocketAddress;
261N/Aimport java.net.UnknownHostException;
261N/Aimport java.util.Date;
126N/Aimport java.util.List;
58N/Aimport java.util.Map;
8N/Aimport java.util.logging.Level;
30N/Aimport java.util.logging.Logger;
0N/Aimport org.opensolaris.opengrok.history.Repository;
77N/Aimport org.opensolaris.opengrok.index.IgnoredNames;
0N/A
0N/A/**
0N/A * The RuntimeEnvironment class is used as a placeholder for the current
0N/A * configuration this execution context (classloader) is using.
0N/A */
0N/Apublic final class RuntimeEnvironment {
0N/A private Configuration configuration;
65N/A private final ThreadLocal<Configuration> threadConfig;
65N/A
65N/A private static final Logger log = Logger.getLogger(RuntimeEnvironment.class.getName());
65N/A
0N/A private static RuntimeEnvironment instance = new RuntimeEnvironment();
30N/A
58N/A /**
260N/A * Get the one and only instance of the RuntimeEnvironment
112N/A * @return the one and only instance of the RuntimeEnvironment
0N/A */
0N/A public static RuntimeEnvironment getInstance() {
0N/A return instance;
260N/A }
0N/A
0N/A /**
0N/A * Creates a new instance of RuntimeEnvironment. Private to ensure a
0N/A * singleton pattern.
0N/A */
11N/A private RuntimeEnvironment() {
0N/A configuration = new Configuration();
240N/A threadConfig = new ThreadLocal<Configuration>() {
58N/A @Override protected Configuration initialValue() {
58N/A return configuration;
58N/A }
58N/A };
77N/A }
207N/A
207N/A /**
261N/A * Get the path to the where the index database is stored
260N/A * @return the path to the index database
77N/A */
260N/A public String getDataRootPath() {
112N/A return threadConfig.get().getDataRoot();
77N/A }
77N/A
77N/A /**
77N/A * Get a file representing the index database
260N/A * @return the index database
77N/A */
77N/A public File getDataRootFile() {
77N/A File ret = null;
0N/A String file = getDataRootPath();
77N/A if (file != null) {
111N/A ret = new File(file);
111N/A }
111N/A
111N/A return ret;
111N/A }
111N/A
111N/A /**
111N/A * Set the path to where the index database is stored
111N/A * @param data the index database
111N/A * @throws IOException if the path cannot be resolved
111N/A */
111N/A public void setDataRoot(File data) throws IOException {
77N/A threadConfig.get().setDataRoot(data.getCanonicalPath());
77N/A }
77N/A
207N/A /**
207N/A * Set the path to where the index database is stored
77N/A * @param dataRoot the index database
77N/A */
99N/A public void setDataRoot(String dataRoot) {
77N/A threadConfig.get().setDataRoot(dataRoot);
77N/A }
77N/A
77N/A /**
77N/A * Get the path to where the sources are located
77N/A * @return path to where the sources are located
77N/A */
77N/A public String getSourceRootPath() {
0N/A return threadConfig.get().getSourceRoot();
77N/A }
77N/A
77N/A /**
77N/A * Get a file representing the directory where the sources are located
77N/A * @return A file representing the directory where the sources are located
77N/A */
77N/A public File getSourceRootFile() {
77N/A File ret = null;
77N/A String file = getSourceRootPath();
77N/A if (file != null) {
77N/A ret = new File(file);
111N/A }
111N/A
77N/A return ret;
77N/A }
77N/A
240N/A /**
173N/A * Specify the source root
173N/A * @param source the location of the sources
173N/A * @throws IOException if the name cannot be resolved
173N/A */
254N/A public void setSourceRootFile(File source) throws IOException {
173N/A threadConfig.get().setSourceRoot(source.getCanonicalPath());
173N/A }
173N/A
254N/A /**
173N/A * Specify the source root
173N/A * @param sourceRoot the location of the sources
173N/A */
253N/A public void setSourceRoot(String sourceRoot) {
253N/A threadConfig.get().setSourceRoot(sourceRoot);
253N/A }
253N/A
253N/A /**
253N/A * Do we have projects?
253N/A * @return true if we have projects
253N/A */
253N/A public boolean hasProjects() {
253N/A List<Project> proj = getProjects();
253N/A return (proj != null && !proj.isEmpty());
253N/A }
99N/A
77N/A /**
77N/A * Get all of the projects
77N/A * @return a list containing all of the projects (may be null)
77N/A */
77N/A public List<Project> getProjects() {
0N/A return threadConfig.get().getProjects();
0N/A }
77N/A
125N/A /**
77N/A * Set the list of the projects
77N/A * @param projects the list of projects to use
205N/A */
205N/A public void setProjects(List<Project> projects) {
205N/A threadConfig.get().setProjects(projects);
112N/A }
112N/A
112N/A /**
77N/A * Register this thread in the thread/configuration map (so that all
106N/A * subsequent calls to the RuntimeEnvironment from this thread will use
119N/A * the same configuration
106N/A */
119N/A public void register() {
106N/A threadConfig.set(configuration);
119N/A }
119N/A
119N/A /**
119N/A * Get the context name of the web application
106N/A * @return the web applications context name
106N/A */
106N/A public String getUrlPrefix() {
99N/A return threadConfig.get().getUrlPrefix();
99N/A }
99N/A
99N/A /**
99N/A * Set the web context name
99N/A * @param urlPrefix the web applications context name
99N/A */
99N/A public void setUrlPrefix(String urlPrefix) {
99N/A threadConfig.get().setUrlPrefix(urlPrefix);
125N/A }
125N/A
125N/A /**
125N/A * Get the name of the ctags program in use
125N/A * @return the name of the ctags program in use
125N/A */
125N/A public String getCtags() {
125N/A return threadConfig.get().getCtags();
125N/A }
126N/A
125N/A /**
125N/A * Specify the CTags program to use
125N/A * @param ctags the ctags program to use
126N/A */
126N/A public void setCtags(String ctags) {
126N/A threadConfig.get().setCtags(ctags);
126N/A }
126N/A
126N/A /**
126N/A * Validate that I have a Exuberant ctags program I may use
126N/A * @return true if success, false otherwise
126N/A */
126N/A public boolean validateExuberantCtags() {
126N/A String ctags = getCtags();
126N/A
126N/A //Check if exub ctags is available
126N/A Process ctagsProcess = null;
126N/A try {
126N/A ctagsProcess = Runtime.getRuntime().exec(new String[] {ctags, "--version" });
126N/A } catch (Exception e) {
126N/A }
126N/A if (ctagsProcess == null) {
210N/A log.severe("Error: executing " + ctags + "! " +
210N/A "\nPlease use option -c to specify path to a good Exuberant Ctags program");
210N/A return false;
210N/A }
210N/A try {
210N/A BufferedReader cin = new BufferedReader(new InputStreamReader(ctagsProcess.getInputStream()));
210N/A try {
126N/A String ctagOut;
126N/A if (!((ctagOut = cin.readLine()) != null && ctagOut.startsWith("Exuberant Ctags"))) {
126N/A log.severe("Error: No Exuberant Ctags found in PATH!\n" +
126N/A "(tried running " + ctags + ")\n" +
144N/A "Please use option -c to specify path to a good Exuberant Ctags program");
144N/A return false;
144N/A }
261N/A } finally {
261N/A cin.close();
261N/A }
261N/A } catch (Exception e) {
261N/A log.severe("Error: executing " + ctags + "! " +e.getLocalizedMessage() +
261N/A "\nPlease use option -c to specify path to a good Exuberant Ctags program");
261N/A return false;
261N/A }
296N/A
296N/A // reap the child process..
296N/A try {
296N/A int ret;
296N/A if ((ret = ctagsProcess.exitValue()) != 0) {
296N/A log.severe("Error: ctags returned " + ret);
296N/A return false;
296N/A }
296N/A } catch (IllegalThreadStateException exp) {
296N/A // the process is still running??? just kill it..
296N/A ctagsProcess.destroy();
293N/A return true;
293N/A }
293N/A return true;
293N/A }
293N/A
77N/A /**
293N/A * Get the max time a SMC operation may use to avoid beeing cached
0N/A * @return the max time
0N/A */
0N/A public int getHistoryReaderTimeLimit() {
77N/A return threadConfig.get().getHistoryCacheTime();
77N/A }
205N/A
77N/A /**
77N/A * Specify the maximum time a SCM operation should take before it will
77N/A * be cached (in ms)
77N/A * @param historyReaderTimeLimit the max time in ms before it is cached
77N/A */
58N/A public void setHistoryReaderTimeLimit(int historyReaderTimeLimit) {
58N/A threadConfig.get().setHistoryCacheTime(historyReaderTimeLimit);
77N/A }
260N/A
0N/A /**
0N/A * Is history cache currently enabled?
77N/A * @return true if history cache is enabled
58N/A */
58N/A public boolean useHistoryCache() {
58N/A return threadConfig.get().isHistoryCache();
0N/A }
0N/A
0N/A /**
58N/A * Specify if we should use history cache or not
0N/A * @param useHistoryCache set false if you do not want to use history cache
0N/A */
0N/A public void setUseHistoryCache(boolean useHistoryCache) {
0N/A threadConfig.get().setHistoryCache(useHistoryCache);
58N/A }
0N/A
260N/A /**
0N/A * Should we generate HTML or not during the indexing phase
0N/A * @return true if HTML should be generated during the indexing phase
58N/A */
77N/A public boolean isGenerateHtml() {
58N/A return threadConfig.get().isGenerateHtml();
58N/A }
260N/A
0N/A /**
0N/A * Specify if we should generate HTML or not during the indexing phase
0N/A * @param generateHtml set this to true to pregenerate HTML
77N/A */
99N/A public void setGenerateHtml(boolean generateHtml) {
0N/A threadConfig.get().setGenerateHtml(generateHtml);
0N/A }
77N/A
11N/A /**
99N/A * Set if we should compress the xref files or not
99N/A * @param compressXref set to true if the generated html files should be
99N/A * compressed
99N/A */
11N/A public void setCompressXref(boolean compressXref) {
290N/A threadConfig.get().setCompressXref(compressXref);
11N/A }
99N/A
99N/A /**
99N/A * Are we using copressed HTML files?
11N/A * @return true if the html-files should be compressed. false otherwise
77N/A */
58N/A public boolean isCompressXref() {
77N/A return threadConfig.get().isCompressXref();
70N/A }
70N/A
58N/A public boolean isQuickContextScan() {
77N/A return threadConfig.get().isQuickContextScan();
70N/A }
58N/A
58N/A public void setQuickContextScan(boolean quickContextScan) {
77N/A threadConfig.get().setQuickContextScan(quickContextScan);
77N/A }
99N/A
99N/A /**
99N/A * Get the map of external SCM repositories available
99N/A * @return A map containing all available SCMs
77N/A */
77N/A public Map<String, Repository> getRepositories() {
77N/A return threadConfig.get().getRepositories();
77N/A }
77N/A
77N/A /**
77N/A * Set the map of external SCM repositories
77N/A * @param repositories the repositories to use
77N/A */
77N/A public void setRepositories(Map<String, Repository> repositories) {
58N/A threadConfig.get().setRepositories(repositories);
77N/A }
77N/A
77N/A /**
77N/A * Set the project that is specified to be the default project to use. The
77N/A * default project is the project you will search (from the web application)
77N/A * if the page request didn't contain the cookie..
77N/A * @param defaultProject The default project to use
77N/A */
77N/A public void setDefaultProject(Project defaultProject) {
99N/A threadConfig.get().setDefaultProject(defaultProject);
58N/A }
99N/A
99N/A /**
99N/A * Get the project that is specified to be the default project to use. The
99N/A * default project is the project you will search (from the web application)
58N/A * if the page request didn't contain the cookie..
99N/A * @return the default project (may be null if not specified)
99N/A */
99N/A public Project getDefaultProject() {
99N/A return threadConfig.get().getDefaultProject();
58N/A }
112N/A
58N/A /**
203N/A * Chandan wrote the following answer on the opengrok-discuss list:
240N/A * "Traditionally search engines (specially spiders) think that large files
240N/A * are junk. Large files tend to be multimedia files etc., which text
58N/A * search spiders do not want to chew. So they ignore the contents of
58N/A * the file after a cutoff length. Lucene does this by number of words,
207N/A * which is by default is 10,000."
207N/A * By default OpenGrok will increase this limit to 60000, but it may be
207N/A * overridden in the configuration file
207N/A * @return The maximum words to index
207N/A */
207N/A public int getIndexWordLimit() {
207N/A return threadConfig.get().getIndexWordLimit();
207N/A }
270N/A
270N/A /**
270N/A * Set the number of words in a file Lucene will index.
270N/A * See getIndexWordLimit for a better description.
270N/A * @param indexWordLimit the number of words to index in a single file
264N/A */
270N/A public void setIndexWordLimit(int indexWordLimit) {
270N/A threadConfig.get().setIndexWordLimit(indexWordLimit);
270N/A }
270N/A
274N/A /**
274N/A * Is the verbosity flag turned on?
270N/A * @return true if we can print extra information
270N/A */
297N/A public boolean isVerbose() {
270N/A return threadConfig.get().isVerbose();
270N/A }
297N/A
297N/A /**
297N/A * Set the verbosity flag (to add extra debug information in output)
297N/A * @param verbose new value
297N/A */
297N/A public void setVerbose(boolean verbose) {
274N/A threadConfig.get().setVerbose(verbose);
274N/A }
274N/A
274N/A /**
274N/A * Specify if a search may start with a wildcard. Note that queries
274N/A * that start with a wildcard will give a significant impact on the
274N/A * search performace.
274N/A * @param allowLeadingWildcard set to true to activate (disabled by default)
274N/A */
274N/A public void setAllowLeadingWildcard(boolean allowLeadingWildcard) {
274N/A threadConfig.get().setAllowLeadingWildcard(allowLeadingWildcard);
274N/A }
274N/A
274N/A /**
274N/A * Is leading wildcards allowed?
274N/A * @return true if a search may start with a wildcard
270N/A */
270N/A public boolean isAllowLeadingWildcard() {
270N/A return threadConfig.get().isAllowLeadingWildcard();
270N/A }
261N/A
270N/A public IgnoredNames getIgnoredNames() {
270N/A return threadConfig.get().getIgnoredNames();
270N/A }
264N/A
270N/A public void setIgnoredNames(IgnoredNames ignoredNames) {
270N/A threadConfig.get().setIgnoredNames(ignoredNames);
261N/A }
270N/A
270N/A /**
264N/A * Returns the user page for the history listing
270N/A * @return the URL string fragment preceeding the username
274N/A */
270N/A public String getUserPage() {
270N/A return threadConfig.get().getUserPage();
270N/A }
270N/A
270N/A /**
270N/A * Sets the user page for the history listing
270N/A * @param userPage the URL fragment preceeding the username from history
270N/A */
270N/A public void setUserPage(String userPage) {
264N/A threadConfig.get().setUserPage(userPage);
264N/A }
58N/A
58N/A /**
58N/A * Returns the bug page for the history listing
99N/A * @return the URL string fragment preceeding the bug ID
99N/A */
99N/A public String getBugPage() {
58N/A return threadConfig.get().getBugPage();
58N/A }
58N/A
58N/A /**
58N/A * Sets the bug page for the history listing
58N/A * @param bugPage the URL fragment preceeding the bug ID
58N/A */
58N/A public void setBugPage(String bugPage) {
58N/A threadConfig.get().setBugPage(bugPage);
58N/A }
58N/A
58N/A /**
58N/A * Returns the bug regex for the history listing
58N/A * @return the regex that is looked for in history comments
58N/A */
58N/A public String getBugPattern() {
99N/A return threadConfig.get().getBugPattern();
99N/A }
99N/A
58N/A /**
58N/A * Sets the bug regex for the history listing
0N/A * @param bugPattern the regex to search history comments
260N/A */
260N/A public void setBugPattern(String bugPattern) {
260N/A threadConfig.get().setBugPattern(bugPattern);
0N/A }
0N/A
0N/A
0N/A /**
260N/A * Returns the review(ARC) page for the history listing
260N/A * @return the URL string fragment preceeding the review page ID
260N/A */
0N/A public String getReviewPage() {
return threadConfig.get().getReviewPage();
}
/**
* Sets the review(ARC) page for the history listing
* @param reviewPage the URL fragment preceeding the review page ID
*/
public void setReviewPage(String reviewPage) {
threadConfig.get().setReviewPage(reviewPage);
}
/**
* Returns the review(ARC) regex for the history listing
* @return the regex that is looked for in history comments
*/
public String getReviewPattern() {
return threadConfig.get().getReviewPattern();
}
/**
* Sets the review(ARC) regex for the history listing
* @param reviewPattern the regex to search history comments
*/
public void setReviewPattern(String reviewPattern) {
threadConfig.get().setReviewPattern(reviewPattern);
}
public String getWebappLAF() {
return threadConfig.get().getWebappLAF();
}
public void setWebappLAF(String laf) {
threadConfig.get().setWebappLAF(laf);
}
public boolean isRemoteScmSupported() {
return threadConfig.get().isRemoteScmSupported();
}
public void setRemoteScmSupported(boolean supported) {
threadConfig.get().setRemoteScmSupported(supported);
}
public boolean isOptimizeDatabase() {
return threadConfig.get().isOptimizeDatabase();
}
public void setOptimizeDatabase(boolean optimizeDatabase) {
threadConfig.get().setOptimizeDatabase(optimizeDatabase);
}
public boolean isUsingLuceneLocking() {
return threadConfig.get().isUsingLuceneLocking();
}
public void setUsingLuceneLocking(boolean useLuceneLocking) {
threadConfig.get().setUsingLuceneLocking(useLuceneLocking);
}
/**
* Read an configuration file and set it as the current configuration.
* @param file the file to read
* @throws IOException if an error occurs
*/
public void readConfiguration(File file) throws IOException {
configuration = Configuration.read(file);
register();
}
/**
* Write the current configuration to a file
* @param file the file to write the configuration into
* @throws IOException if an error occurs
*/
public void writeConfiguration(File file) throws IOException {
threadConfig.get().write(file);
}
/**
* 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
*/
public void writeConfiguration(InetAddress host, int port) throws IOException {
Socket sock = new Socket(host, port);
XMLEncoder e = new XMLEncoder(sock.getOutputStream());
e.writeObject(threadConfig.get());
e.close();
try {
sock.close();
} catch (Exception ex) {
log.log(Level.INFO, "Couldn't close socket after writing configuration.", ex);
}
}
public void setConfiguration(Configuration configuration) {
this.configuration = configuration;
register();
}
private ServerSocket configServerSocket;
/**
* Try to stop the configuration listener thread
*/
public void stopConfigurationListenerThread() {
try {
configServerSocket.close();
} catch (Exception e) { log.log(Level.FINE, "Stopping config listener thread: ", e); }
}
/**
* 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)
*/
public boolean startConfigurationListenerThread(SocketAddress endpoint) {
boolean ret = false;
try {
configServerSocket = new ServerSocket();
configServerSocket.bind(endpoint);
ret = true;
final ServerSocket sock = configServerSocket;
Thread t = new Thread(new Runnable() {
public void run() {
Socket s = null;
while (!sock.isClosed()) {
try {
s = sock.accept();
log.info((new Date()).toString() + " OpenGrok: Got request from " + s.getInetAddress().getHostAddress());
String line;
BufferedInputStream in = new BufferedInputStream(s.getInputStream());
XMLDecoder d = new XMLDecoder(new BufferedInputStream(in));
Object obj = d.readObject();
d.close();
if (obj instanceof Configuration) {
configuration = (Configuration)obj;
log.info("Configuration updated: " + configuration.getSourceRoot());
}
} catch (IOException e) {
log.log(Level.FINE,"Error reading config file: ",e);
} finally {
try { s.close(); } catch (Exception ex) { log.log(Level.FINE, "Interrupt closing config listener reader socket: ", ex); }
}
}
}
});
t.start();
} catch (UnknownHostException ex) {
log.log(Level.FINE,"Problem resolving sender: ",ex);
} catch (IOException ex) {
log.log(Level.FINE,"I/O error when waiting for config: ",ex);
}
if (!ret && configServerSocket != null) {
try {
configServerSocket.close();
} catch (IOException ex) {
log.log(Level.FINE,"I/O problem closing reader config socket: ",ex);
}
}
return ret;
}
}