/* 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.utilities;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URI;
import java.util.Properties;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import fedora.common.Constants;
import fedora.common.http.WebClient;
import fedora.server.config.ServerConfiguration;
import fedora.server.config.ServerConfigurationParser;
public class ServerUtility {
/** Logger for this class. */
private static final Logger LOG =
Logger.getLogger(ServerUtility.class.getName());
public static final String HTTP = "http";
public static final String HTTPS = "https";
public static final String FEDORA_SERVER_HOST = "fedoraServerHost";
public static final String FEDORA_SERVER_PORT = "fedoraServerPort";
public static final String FEDORA_SERVER_CONTEXT = "fedoraAppServerContext";
public static final String FEDORA_REDIRECT_PORT = "fedoraRedirectPort";
private static ServerConfiguration CONFIG;
static {
String fedoraHome = Constants.FEDORA_HOME;
if (fedoraHome == null) {
LOG.warn("FEDORA_HOME not set; unable to initialize");
} else {
File fcfgFile = new File(fedoraHome, "server/config/fedora.fcfg");
try {
CONFIG =
new ServerConfigurationParser(new FileInputStream(fcfgFile))
.parse();
} catch (IOException e) {
LOG.warn("Unable to read server configuration from "
+ fcfgFile.getPath(), e);
}
}
}
/**
* Tell whether the server is running by pinging it as a client.
*/
public static boolean pingServer(String protocol, String user, String pass) {
try {
getServerResponse(protocol, user, pass, "/describe");
return true;
} catch (Exception e) {
LOG.debug("Assuming the server isn't running because "
+ "describe request failed", e);
return false;
}
}
/**
* Get the baseURL of the Fedora server from the host and port configured.
* It will look like http://localhost:8080/fedora
*/
public static String getBaseURL(String protocol) {
String port;
if (protocol.equals("http")) {
port = CONFIG.getParameter(FEDORA_SERVER_PORT).getValue();
} else if (protocol.equals("https")) {
port = CONFIG.getParameter(FEDORA_REDIRECT_PORT).getValue();
} else {
throw new RuntimeException("Unrecogonized protocol: " + protocol);
}
return protocol + "://"
+ CONFIG.getParameter(FEDORA_SERVER_HOST).getValue() + ":"
+ port + "/" + CONFIG.getParameter(FEDORA_SERVER_CONTEXT).getValue();
}
/**
* Signals for the server to reload its policies.
*/
public static void reloadPolicies(String protocol, String user, String pass)
throws IOException {
getServerResponse(protocol,
user,
pass,
"/management/control?action=reloadPolicies");
}
/**
* Hits the given Fedora Server URL and returns the response as a String.
* Throws an IOException if the response code is not 200(OK).
*/
private static String getServerResponse(String protocol,
String user,
String pass,
String path) throws IOException {
String url = getBaseURL(protocol) + path;
LOG.info("Getting URL: " + url);
UsernamePasswordCredentials creds =
new UsernamePasswordCredentials(user, pass);
return new WebClient().getResponseAsString(url, true, creds);
}
/**
* Tell whether the given URL appears to be referring to somewhere within
* the Fedora webapp.
*/
public static boolean isURLFedoraServer(String url) {
// scheme must be http or https
URI uri = URI.create(url);
String scheme = uri.getScheme();
if (!scheme.equals("http") && !scheme.equals("https")) {
return false;
}
// host must be configured hostname or localhost
String fHost = CONFIG.getParameter(FEDORA_SERVER_HOST).getValue();
String host = uri.getHost();
if (!host.equals(fHost) && !host.equals("localhost")) {
return false;
}
// path must begin with configured webapp context
String path = uri.getPath();
String fedoraContext = CONFIG.getParameter(
FEDORA_SERVER_CONTEXT).getValue();
if (!path.startsWith("/" + fedoraContext + "/")) {
return false;
}
// port specification must match http or https port as appropriate
String httpPort = CONFIG.getParameter(FEDORA_SERVER_PORT).getValue();
String httpsPort = CONFIG.getParameter(FEDORA_REDIRECT_PORT).getValue();
if (uri.getPort() == -1) {
// unspecified, so fedoraPort must be 80 (http), or 443 (https)
if (scheme.equals("http")) {
return httpPort.equals("80");
} else {
return httpsPort.equals("443");
}
} else {
// specified, so must match appropriate http or https port
String port = "" + uri.getPort();
if (scheme.equals("http")) {
return port.equals(httpPort);
} else {
return port.equals(httpsPort);
}
}
}
/**
* Initializes logging to use Log4J and to send WARN messages to STDOUT for
* command-line use.
*/
private static void initLogging() {
// send all log4j output to STDOUT and configure levels
Properties props = new Properties();
props.setProperty("log4j.appender.STDOUT",
"org.apache.log4j.ConsoleAppender");
props.setProperty("log4j.appender.STDOUT.layout",
"org.apache.log4j.PatternLayout");
props.setProperty("log4j.appender.STDOUT.layout.ConversionPattern",
"%p: %m%n");
props.setProperty("log4j.rootLogger", "WARN, STDOUT");
PropertyConfigurator.configure(props);
// tell commons-logging to use Log4J
final String pfx = "org.apache.commons.logging.";
System.setProperty(pfx + "LogFactory", pfx + "impl.Log4jFactory");
System.setProperty(pfx + "Log", pfx + "impl.Log4JLogger");
}
/**
* Command-line entry point to reload policies. Takes 3 args: protocol user
* pass
*/
public static void main(String[] args) {
initLogging();
if (args.length == 3) {
try {
reloadPolicies(args[0], args[1], args[2]);
System.out.println("SUCCESS: Policies have been reloaded");
System.exit(0);
} catch (Throwable th) {
th.printStackTrace();
System.err
.println("ERROR: Reloading policies failed; see above");
System.exit(1);
}
} else {
System.err.println("ERROR: Three arguments required: "
+ "http|https username password");
System.exit(1);
}
}
}