/*
* Copyright 2005 Joe Walker
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.directwebremoting.server.jetty;
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.nio.SelectChannelConnector;
import org.mortbay.jetty.webapp.WebAppContext;
import org.mortbay.log.Log;
import org.mortbay.util.Scanner;
/**
* Launch Jetty embedded. Do not use this outside of DWR it is not supported.
* It's also worth looking at the Eclipse Jetty Runner as an alternative
* http://code.google.com/p/run-jetty-run/wiki/GettingStarted
* @author Joe Walker [joe at getahead dot org]
*/
public class JettyLauncherBase
{
/**
* Sets up the server.
* @param contextHome Path (can be relative) to the web application
* (aka context) This directory should contain a WEB-INF/web.xml file
* @param contextPath URL component to which we deploy the application,
* as in: http://example.com/CONTEXT_PATH/path_in_the_webapp
* @param port The TCP port to listen on
*/
@SuppressWarnings("unchecked")
public JettyLauncherBase(String contextHome, final String contextPath, int port)
{
server = new Server();
SelectChannelConnector connector = new SelectChannelConnector();
connector.setPort(port);
server.addConnector(connector);
server.setStopAtShutdown(true);
/*
// Adding a security realm
HashUserRealm realm = new HashUserRealm("TestRealm");
realm.put("username", "password");
realm.addUserToRole("username", "manager");
server.addUserRealm(realm);
*/
final File contextRoot = new File(contextHome);
File webXml = new File(contextRoot, "WEB-INF/web.xml");
if (!webXml.isFile())
{
Log.warn("Warning: Failed to find web application. Missing web.xml: " + webXml.getAbsolutePath());
Log.warn("- Alter " + this.getClass().getName() + ".CONTEXT_HOME, or hack the source to remove this warning.");
}
List<File> scanList = new ArrayList<File>();
scanList.add(webXml);
findFiles("", new File(contextRoot, "WEB-INF"), scanList);
Log.info("Scanning files: " + scanList);
scanner = new Scanner();
scanner.setScanInterval(5);
scanner.setScanDirs(scanList);
scanner.setReportExistingFilesOnStartup(false);
Log.info("#### Initializing context: " + contextPath);
final WebAppContext context = new WebAppContext(contextRoot.getAbsolutePath(), contextPath);
server.addHandler(context);
// This should prevent Jetty from using memory mapped buffers (which
// causes file locking on windows). If we discover that it doesn't then
// we need to investigate this more:
// http://docs.codehaus.org/display/JETTY/Files+locked+on+Windows
context.getInitParams().put("useFileMappedBuffer", "false");
//context.setCopyWebDir(true);
scanner.addListener(new Scanner.BulkListener()
{
public void filesChanged(List changedFiles)
{
try
{
Log.info("#### Stopping context: " + contextPath + " from " + contextRoot.getAbsolutePath());
context.stop();
Log.info("#### Starting context: " + contextPath + " from " + contextRoot.getAbsolutePath());
context.start();
}
catch (Exception ex)
{
throw new RuntimeException(ex);
}
}
});
Log.info("Visit http://localhost:" + port + contextPath + "/ to get started.");
}
/**
* Start the web serving/file scanning threads
*/
public void start() throws Exception
{
scanner.start();
server.start();
server.join();
}
/**
* Find all the files with a given <code>extension</code> recursively under
* <code>baseDir</code> and place them into <code>found</code>.
* Warning: If you're doing anything funky with directory loops, then life
* ends here. There is no depth protection.
*/
private void findFiles(final String extension, File baseDir, final Collection<File> found)
{
baseDir.listFiles(new FileFilter()
{
public boolean accept(File pathname)
{
if (pathname.isDirectory())
{
findFiles(extension, pathname, found);
}
else if (pathname.getName().endsWith(extension))
{
found.add(pathname);
}
return false;
}
});
}
/**
* The Jetty web server
*/
private final Server server;
/**
* The file change scanner
*/
private final Scanner scanner;
}