/* | |
* 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!"); | |
} | |
} |