mirror of
https://github.com/jenkinsci/jenkins.git
synced 2026-11-08 01:26:03 +00:00
git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@5706 71c3de6d-444a-0410-be80-ed276b4c234a
226 lines
8.5 KiB
Java
226 lines
8.5 KiB
Java
package hudson;
|
|
|
|
import com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider;
|
|
import com.thoughtworks.xstream.core.JVM;
|
|
import hudson.model.Hudson;
|
|
import hudson.model.User;
|
|
import hudson.triggers.Trigger;
|
|
import hudson.triggers.SafeTimerTask;
|
|
import hudson.util.*;
|
|
|
|
import javax.naming.Context;
|
|
import javax.naming.InitialContext;
|
|
import javax.naming.NamingException;
|
|
import javax.servlet.ServletContext;
|
|
import javax.servlet.ServletContextEvent;
|
|
import javax.servlet.ServletContextListener;
|
|
import javax.servlet.ServletResponse;
|
|
import javax.xml.transform.TransformerFactory;
|
|
import javax.xml.transform.TransformerFactoryConfigurationError;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.util.Properties;
|
|
import java.util.logging.Level;
|
|
import java.util.logging.Logger;
|
|
import java.net.URLClassLoader;
|
|
import java.net.URL;
|
|
|
|
/**
|
|
* Entry point when Hudson is used as a webapp.
|
|
*
|
|
* @author Kohsuke Kawaguchi
|
|
*/
|
|
public class WebAppMain implements ServletContextListener {
|
|
private final RingBufferLogHandler handler = new RingBufferLogHandler();
|
|
private static final String APP = "app";
|
|
|
|
/**
|
|
* Creates the sole instance of {@link Hudson} and register it to the {@link ServletContext}.
|
|
*/
|
|
public void contextInitialized(ServletContextEvent event) {
|
|
try {
|
|
final ServletContext context = event.getServletContext();
|
|
|
|
// quick check to see if we (seem to) have enough permissions to run. (see #719)
|
|
JVM jvm;
|
|
try {
|
|
jvm = new JVM();
|
|
new URLClassLoader(new URL[0],getClass().getClassLoader());
|
|
} catch(SecurityException e) {
|
|
context.setAttribute(APP,new InsufficientPermissionDetected(e));
|
|
return;
|
|
}
|
|
|
|
installLogger();
|
|
|
|
final File home = getHomeDir(event).getAbsoluteFile();
|
|
home.mkdirs();
|
|
System.out.println("hudson home directory: "+home);
|
|
|
|
// check that home exists (as mkdirs could have failed silently), otherwise throw a meaningful error
|
|
if (! home.exists()) {
|
|
context.setAttribute(APP,new NoHomeDir(home));
|
|
return;
|
|
}
|
|
|
|
// make sure that we are using XStream in the "enhanced" (JVM-specific) mode
|
|
if(jvm.bestReflectionProvider().getClass()==PureJavaReflectionProvider.class) {
|
|
// nope
|
|
context.setAttribute(APP,new IncompatibleVMDetected());
|
|
return;
|
|
}
|
|
|
|
// make sure this is servlet 2.4 container or above
|
|
try {
|
|
ServletResponse.class.getMethod("setCharacterEncoding",String.class);
|
|
} catch (NoSuchMethodException e) {
|
|
context.setAttribute(APP,new IncompatibleServletVersionDetected(ServletResponse.class));
|
|
return;
|
|
}
|
|
|
|
// Tomcat breaks XSLT with JDK 5.0 and onward. Check if that's the case, and if so,
|
|
// try to correct it
|
|
try {
|
|
TransformerFactory.newInstance();
|
|
// if this works we are all happy
|
|
} catch (TransformerFactoryConfigurationError x) {
|
|
// no it didn't.
|
|
Logger logger = Logger.getLogger(WebAppMain.class.getName());
|
|
|
|
logger.log(Level.WARNING, "XSLT not configured correctly. Hudson will try to fix this. See http://issues.apache.org/bugzilla/show_bug.cgi?id=40895 for more details",x);
|
|
System.setProperty(TransformerFactory.class.getName(),"com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
|
|
try {
|
|
TransformerFactory.newInstance();
|
|
logger.info("XSLT is set to the JAXP RI in JRE");
|
|
} catch(TransformerFactoryConfigurationError y) {
|
|
logger.log(Level.SEVERE, "Failed to correct the problem.");
|
|
}
|
|
}
|
|
|
|
context.setAttribute(APP,new HudsonIsLoading());
|
|
|
|
new Thread("hudson initialization thread") {
|
|
public void run() {
|
|
try {
|
|
computeVersion(context);
|
|
|
|
try {
|
|
context.setAttribute(APP,new Hudson(home,context));
|
|
} catch( IOException e ) {
|
|
throw new Error(e);
|
|
}
|
|
|
|
Trigger.init(); // start running trigger
|
|
|
|
// trigger the loading of changelogs in the background,
|
|
// but give the system 10 seconds so that the first page
|
|
// can be served quickly
|
|
Trigger.timer.schedule(new SafeTimerTask() {
|
|
public void doRun() {
|
|
User.get("nobody").getBuilds();
|
|
}
|
|
}, 1000*10);
|
|
} catch (Error e) {
|
|
LOGGER.log(Level.SEVERE, "Failed to initialize Hudson",e);
|
|
throw e;
|
|
} catch (RuntimeException e) {
|
|
LOGGER.log(Level.SEVERE, "Failed to initialize Hudson",e);
|
|
throw e;
|
|
}
|
|
}
|
|
}.start();
|
|
} catch (Error e) {
|
|
LOGGER.log(Level.SEVERE, "Failed to initialize Hudson",e);
|
|
throw e;
|
|
} catch (RuntimeException e) {
|
|
LOGGER.log(Level.SEVERE, "Failed to initialize Hudson",e);
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
protected void computeVersion(ServletContext context) {
|
|
// set the version
|
|
Properties props = new Properties();
|
|
try {
|
|
InputStream is = getClass().getResourceAsStream("hudson-version.properties");
|
|
if(is!=null)
|
|
props.load(is);
|
|
} catch (IOException e) {
|
|
e.printStackTrace(); // if the version properties is missing, that's OK.
|
|
}
|
|
String ver = props.getProperty("version");
|
|
if(ver==null) ver="?";
|
|
Hudson.VERSION = ver;
|
|
context.setAttribute("version",ver);
|
|
|
|
if(ver.equals("?"))
|
|
Hudson.RESOURCE_PATH = "";
|
|
else
|
|
Hudson.RESOURCE_PATH = "/static/"+Util.getDigestOf(ver).substring(0,8);
|
|
}
|
|
|
|
/**
|
|
* Installs log handler to monitor all Hudson logs.
|
|
*/
|
|
private void installLogger() {
|
|
Hudson.logRecords = handler.getView();
|
|
Logger.getLogger("hudson").addHandler(handler);
|
|
}
|
|
|
|
/**
|
|
* Determines the home directory for Hudson.
|
|
*
|
|
* People makes configuration mistakes, so we are trying to be nice
|
|
* with those by doing {@link String#trim()}.
|
|
*/
|
|
private File getHomeDir(ServletContextEvent event) {
|
|
// check JNDI for the home directory first
|
|
try {
|
|
Context env = (Context) new InitialContext().lookup("java:comp/env");
|
|
String value = (String) env.lookup("HUDSON_HOME");
|
|
if(value!=null && value.trim().length()>0)
|
|
return new File(value.trim());
|
|
} catch (NamingException e) {
|
|
// ignore
|
|
}
|
|
|
|
// look at the env var next
|
|
String env = EnvVars.masterEnvVars.get("HUDSON_HOME");
|
|
if(env!=null)
|
|
return new File(env.trim()).getAbsoluteFile();
|
|
|
|
// finally check the system property
|
|
String sysProp = System.getProperty("HUDSON_HOME");
|
|
if(sysProp!=null)
|
|
return new File(sysProp.trim());
|
|
|
|
// otherwise pick a place by ourselves
|
|
|
|
String root = event.getServletContext().getRealPath("/WEB-INF/workspace");
|
|
if(root!=null) {
|
|
File ws = new File(root.trim());
|
|
if(ws.exists())
|
|
// Hudson <1.42 used to prefer this before ~/.hudson, so
|
|
// check the existence and if it's there, use it.
|
|
// otherwise if this is a new installation, prefer ~/.hudson
|
|
return ws;
|
|
}
|
|
|
|
// if for some reason we can't put it within the webapp, use home directory.
|
|
return new File(new File(System.getProperty("user.home")),".hudson");
|
|
}
|
|
|
|
public void contextDestroyed(ServletContextEvent event) {
|
|
Hudson instance = Hudson.getInstance();
|
|
if(instance!=null)
|
|
instance.cleanUp();
|
|
|
|
// Logger is in the system classloader, so if we don't do this
|
|
// the whole web app will never be undepoyed.
|
|
Logger.getLogger("hudson").removeHandler(handler);
|
|
}
|
|
|
|
private static final Logger LOGGER = Logger.getLogger(WebAppMain.class.getName());
|
|
}
|