blob: f3684fb35737d554bb89b8c401d3f8b37a71e6ad [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.commons.vfs2.provider.webdav.test;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Collections;
import java.util.Enumeration;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.io.IOUtils;
import org.apache.jackrabbit.servlet.jackrabbit.JackrabbitRepositoryServlet;
import org.apache.jackrabbit.standalone.Main;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Layout;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.Priority;
import org.mortbay.jetty.Connector;
import org.mortbay.jetty.NCSARequestLog;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.bio.SocketConnector;
import org.mortbay.jetty.handler.RequestLogHandler;
import org.mortbay.jetty.servlet.ServletHolder;
import org.mortbay.jetty.webapp.WebAppContext;
/**
* Manages a Jackrabbit server instance.
*
* Copied and minimally changed from Jackrabbit's Main class in 1.5.2 to add a shutdown method.
*
* @since 2.1
*/
class JackrabbitMain
{
/**
* @param args
*/
public static void main(final String[] args) throws Exception
{
new JackrabbitMain(args).run();
}
private final Options options = new Options();
private final CommandLine command;
private final RequestLogHandler accessLog = new RequestLogHandler();
private final WebAppContext webapp = new WebAppContext();
private final Connector connector = new SocketConnector();
private final Server server = new Server();
private FileAppender jackrabbitAppender;
private FileAppender jettyAppender;
public JackrabbitMain(final String[] args) throws ParseException
{
options.addOption("?", "help", false, "print this message");
options.addOption("n", "notice", false, "print copyright notices");
options.addOption("l", "license", false, "print license information");
options.addOption("q", "quiet", false, "disable console output");
options.addOption("d", "debug", false, "enable debug logging");
options.addOption("h", "host", true, "IP address of the HTTP server");
options.addOption("p", "port", true, "TCP port of the HTTP server (8080)");
options.addOption("f", "file", true, "location of this jar file");
options.addOption("r", "repo", true, "repository directory (jackrabbit)");
options.addOption("c", "conf", true, "repository configuration file");
command = new GnuParser().parse(options, args);
}
private void copyToOutput(final String resource) throws IOException
{
final InputStream stream = JackrabbitMain.class.getResourceAsStream(resource);
try
{
IOUtils.copy(stream, System.out);
} finally
{
stream.close();
}
}
private void message(final String message)
{
if (!command.hasOption("quiet"))
{
System.out.println(message);
}
}
private void prepareAccessLog(final File log)
{
final NCSARequestLog ncsa = new NCSARequestLog(new File(log, "access.log.yyyy_mm_dd").getPath());
ncsa.setFilenameDateFormat("yyyy-MM-dd");
accessLog.setRequestLog(ncsa);
}
private void prepareConnector()
{
final String port = command.getOptionValue("port", "8080");
connector.setPort(Integer.parseInt(port));
final String host = command.getOptionValue("host");
if (host != null)
{
connector.setHost(host);
}
}
private void prepareServerLog(final File log) throws IOException
{
final Layout layout = new PatternLayout("%d{dd.MM.yyyy HH:mm:ss} *%-5p* %c{1}: %m%n");
final Logger jackrabbitLog = Logger.getRootLogger();
jackrabbitAppender = new FileAppender(layout, new File(log, "jackrabbit.log").getPath());
jackrabbitAppender.setThreshold(Level.ALL);
jackrabbitLog.addAppender(jackrabbitAppender);
final Logger jettyLog = Logger.getLogger("org.mortbay.log");
jettyAppender = new FileAppender(layout, new File(log, "jetty.log").getPath());
jettyAppender.setThreshold(Level.ALL);
jettyLog.addAppender(jettyAppender);
jettyLog.setAdditivity(false);
System.setProperty("derby.stream.error.file", new File(log, "derby.log").getPath());
}
private void prepareShutdown()
{
Runtime.getRuntime().addShutdownHook(new Thread()
{
@Override
public void run()
{
try
{
shutdown();
} catch (final Exception e)
{
e.printStackTrace();
}
}
});
}
private void prepareWebapp(final File file, final File repository, final File tmp)
{
webapp.setContextPath("/");
webapp.setWar(file.getPath());
webapp.setClassLoader(JackrabbitMain.class.getClassLoader());
// we use a modified web.xml which has some servlets remove (which produce random empty directories)
URL res = getResource("/jcrweb.xml");
if (res != null)
webapp.setDescriptor(res.toString());
webapp.setExtractWAR(false);
webapp.setTempDirectory(tmp);
final ServletHolder servlet = new ServletHolder(JackrabbitRepositoryServlet.class);
servlet.setInitOrder(1);
servlet.setInitParameter("repository.home", repository.getAbsolutePath());
final String conf = command.getOptionValue("conf");
if (conf != null)
{
servlet.setInitParameter("repository.config", conf);
}
webapp.addServlet(servlet, "/repository.properties");
}
/** Try to load a resource with various classloaders. */
private URL getResource(String name)
{
URL res = Thread.currentThread().getContextClassLoader().getResource(name);
if (res == null)
{
res = getClass().getResource(name);
}
return res; // might be null
}
public void run() throws Exception
{
String defaultFile = "jackrabbit-standalone.jar";
final URL location = Main.class.getProtectionDomain().getCodeSource().getLocation();
if (location != null && "file".equals(location.getProtocol()))
{
final File file = new File(location.getPath());
if (file.isFile())
{
defaultFile = location.getPath();
}
}
final File file = new File(command.getOptionValue("file", defaultFile));
if (command.hasOption("help"))
{
final HelpFormatter formatter = new HelpFormatter();
formatter.printHelp("java -jar " + file.getName(), options, true);
} else if (command.hasOption("notice"))
{
copyToOutput("/META-INF/NOTICE.txt");
} else if (command.hasOption("license"))
{
copyToOutput("/META-INF/LICENSE.txt");
} else
{
message("Welcome to Apache Jackrabbit!");
message("-------------------------------");
final File repository = new File(command.getOptionValue("repo", "target/test/jackrabbit"));
message("Using repository directory " + repository);
repository.mkdirs();
final File tmp = new File(repository, "tmp");
tmp.mkdir();
final File log = new File(repository, "log");
log.mkdir();
message("Writing log messages to " + log);
prepareServerLog(log);
message("Starting the server...");
prepareWebapp(file, repository, tmp);
accessLog.setHandler(webapp);
prepareAccessLog(log);
server.setHandler(accessLog);
prepareConnector();
server.addConnector(connector);
prepareShutdown();
try
{
server.start();
String host = connector.getHost();
if (host == null)
{
host = "localhost";
}
message("Apache Jackrabbit is now running at " + "http://" + host + ":" + connector.getPort() + "/");
} catch (final Throwable t)
{
System.err.println("Unable to start the server: " + t.getMessage());
System.exit(1);
}
}
}
public void shutdown() throws Exception, InterruptedException
{
message("Shutting down the server...");
server.setGracefulShutdown(5);
server.stop();
Logger.getRootLogger().removeAppender(jackrabbitAppender);
Logger.getLogger("org.mortbay.log").removeAppender(jettyAppender);
jackrabbitAppender.close();
jettyAppender.close();
server.join();
message("-------------------------------");
message("Goodbye from Apache Jackrabbit!");
}
}