/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package fedora.server;
import java.io.File;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import fedora.common.Constants;
import fedora.server.errors.authorization.AuthzDeniedException;
import fedora.server.errors.authorization.AuthzOperationalException;
import fedora.server.errors.authorization.AuthzPermittedException;
import fedora.server.errors.servletExceptionExtensions.BadRequest400Exception;
import fedora.server.errors.servletExceptionExtensions.Continue100Exception;
import fedora.server.errors.servletExceptionExtensions.Forbidden403Exception;
import fedora.server.errors.servletExceptionExtensions.InternalError500Exception;
import fedora.server.errors.servletExceptionExtensions.Ok200Exception;
import fedora.server.errors.servletExceptionExtensions.Unavailable503Exception;
import fedora.server.security.Authorization;
import fedora.server.utilities.status.ServerState;
import fedora.server.utilities.status.ServerStatusFile;
/**
* Server Controller.
*
* @author Chris Wilper
*/
public class ServerController
extends HttpServlet {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(ServerController.class);
private static Server s_server;
private ServerStatusFile _status;
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String actionLabel = "server control";
String action = request.getParameter("action");
String requestInfo =
"Got controller '" + action + "' request from "
+ request.getRemoteAddr();
if (action == null) {
throw new BadRequest400Exception(request,
actionLabel,
"no action",
new String[0]);
}
if (action.equals("status")) {
actionLabel = "getting server status";
Context context =
ReadOnlyContext.getContext(Constants.HTTP_REQUEST.REST.uri,
request);
File fedoraHome = new File(Constants.FEDORA_HOME);
if (!Server.hasInstance(fedoraHome)) {
throw new Unavailable503Exception(request,
actionLabel,
"server not available",
new String[0]);
}
Server server = null;
try {
server = Server.getInstance(fedoraHome, false);
} catch (Throwable t) {
throw new InternalError500Exception(request,
actionLabel,
"error performing action0",
new String[0]);
}
if (server == null) {
throw new InternalError500Exception(request,
actionLabel,
"error performing action1",
new String[0]);
}
try {
server.status(context);
} catch (AuthzOperationalException aoe) {
throw new Forbidden403Exception(request,
actionLabel,
"authorization failed",
new String[0]);
} catch (AuthzDeniedException ade) {
throw new Forbidden403Exception(request,
actionLabel,
"authorization denied",
new String[0]);
} catch (AuthzPermittedException ape) {
throw new Continue100Exception(request,
actionLabel,
"authorization permitted",
new String[0]);
} catch (Throwable t) {
throw new InternalError500Exception(request,
actionLabel,
"error performing action2",
new String[0]);
}
throw new Ok200Exception(request,
actionLabel,
"server running",
new String[0]);
}
if (action.equals("reloadPolicies")) {
actionLabel = "reloading repository policies";
Context context =
ReadOnlyContext.getContext(Constants.HTTP_REQUEST.REST.uri,
request);
File fedoraHome = new File(Constants.FEDORA_HOME);
if (!Server.hasInstance(fedoraHome)) {
throw new Unavailable503Exception(request,
actionLabel,
"server not available",
new String[0]);
}
Server server = null;
try {
server = Server.getInstance(fedoraHome, false);
} catch (Throwable t) {
throw new InternalError500Exception(request,
actionLabel,
"error performing action0",
new String[0]);
}
if (server == null) {
throw new InternalError500Exception(request,
actionLabel,
"error performing action1",
new String[0]);
}
Authorization authModule = null;
authModule =
(Authorization) server
.getModule("fedora.server.security.Authorization");
if (authModule == null) {
throw new InternalError500Exception(request,
actionLabel,
"error performing action2",
new String[0]);
}
try {
authModule.reloadPolicies(context);
} catch (AuthzOperationalException aoe) {
throw new Forbidden403Exception(request,
actionLabel,
"authorization failed",
new String[0]);
} catch (AuthzDeniedException ade) {
throw new Forbidden403Exception(request,
actionLabel,
"authorization denied",
new String[0]);
} catch (AuthzPermittedException ape) {
throw new Continue100Exception(request,
actionLabel,
"authorization permitted",
new String[0]);
} catch (Throwable t) {
throw new InternalError500Exception(request,
actionLabel,
"error performing action2",
new String[0]);
}
throw new Ok200Exception(request,
actionLabel,
"server running",
new String[0]);
}
throw new BadRequest400Exception(request, actionLabel, "bad action: "
+ action, new String[0]);
}
@Override
public void init() throws ServletException {
// if fedora.home servlet context init param is present and non-empty,
// this will cause Constants.FEDORA_HOME reflect the value.
String contextFH = getServletContext().getInitParameter("fedora.home");
if (contextFH != null && !contextFH.equals("")) {
System.setProperty("servlet.fedora.home", contextFH);
}
File fedoraHomeDir = getFedoraHomeDir();
// get file for writing startup status
try {
_status = new ServerStatusFile(new File(fedoraHomeDir, "server"));
} catch (Throwable th) {
failStartup("Error initializing server status file", th);
}
try {
// Start the Fedora instance
_status.append(ServerState.STARTING,
"Starting Fedora Server instance");
s_server = Server.getInstance(fedoraHomeDir);
_status.append(ServerState.STARTED, null);
} catch (Throwable th) {
String msg = "Fedora startup failed";
try {
_status.appendError(ServerState.STARTUP_FAILED, th);
} catch (Exception e) {
}
failStartup(msg, th);
}
}
/**
* Validates and returns the value of FEDORA_HOME.
*
* @return the FEDORA_HOME directory.
* @throws ServletException
* if FEDORA_HOME (or fedora.home) was not set, does not denote an
* existing directory, or is not writable by the current user.
*/
private File getFedoraHomeDir() throws ServletException {
String fedoraHome = Constants.FEDORA_HOME;
if (fedoraHome == null) {
failStartup("FEDORA_HOME was not configured properly. It must be "
+ "set via the fedora.home servlet init-param (preferred), "
+ "the fedora.home system property, or the FEDORA_HOME "
+ "environment variable.", null);
}
File fedoraHomeDir = new File(fedoraHome);
if (!fedoraHomeDir.isDirectory()) {
failStartup("The FEDORA_HOME directory, " + fedoraHomeDir.getPath()
+ " does not exist", null);
}
File writeTest = new File(fedoraHomeDir, "writeTest.tmp");
String writeErrorMessage =
"The FEDORA_HOME directory, " + fedoraHomeDir.getPath()
+ " is not writable by " + "the current user, "
+ System.getProperty("user.name");
try {
writeTest.createNewFile();
if (!writeTest.exists()) {
throw new IOException("");
}
writeTest.delete();
} catch (IOException e) {
failStartup(writeErrorMessage, null);
}
return fedoraHomeDir;
}
/**
* Prints a "FEDORA STARTUP ERROR" to STDERR along with the stacktrace of
* the Throwable (if given) and finally, throws a ServletException.
*/
private void failStartup(String message, Throwable th)
throws ServletException {
System.err.println("\n**************************");
System.err.println("** FEDORA STARTUP ERROR **");
System.err.println("**************************\n");
System.err.println(message);
if (th == null) {
System.err.println();
throw new ServletException(message);
} else {
th.printStackTrace();
System.err.println();
throw new ServletException(message, th);
}
}
@Override
public void destroy() {
if (s_server != null) {
try {
_status.append(ServerState.STOPPING,
"Shutting down Fedora Server and modules");
s_server.shutdown(null);
_status.append(ServerState.STOPPED, "Shutdown Successful");
} catch (Throwable th) {
try {
_status.appendError(ServerState.STOPPED_WITH_ERR, th);
} catch (Exception e) {
}
}
s_server = null;
}
}
}