/* 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 java.io.InputStream;
import org.apache.log4j.Logger;
import org.w3c.dom.Element;
import fedora.common.Constants;
import fedora.common.Models;
import fedora.common.PID;
import fedora.common.rdf.RDFName;
import fedora.server.errors.ModuleInitializationException;
import fedora.server.errors.ServerInitializationException;
import fedora.server.storage.DOManager;
import fedora.server.storage.DOWriter;
import fedora.server.utilities.status.ServerState;
import fedora.server.utilities.status.ServerStatusFile;
/**
* Fedora Server.
*
* @author Chris Wilper
*/
public class BasicServer
extends Server {
/** Logger for this class. */
private static Logger LOG = Logger.getLogger(BasicServer.class.getName());
public BasicServer(Element rootElement, File fedoraHomeDir)
throws ServerInitializationException, ModuleInitializationException {
super(rootElement, fedoraHomeDir);
}
@Override
public void initServer() throws ServerInitializationException {
String fedoraServerHost = null;
String fedoraServerPort = null;
// fedoraServerHost (required)
fedoraServerHost = getParameter("fedoraServerHost");
if (fedoraServerHost == null) {
throw new ServerInitializationException("Parameter fedoraServerHost "
+ "not given, but it's required.");
}
// fedoraServerPort (required)
fedoraServerPort = getParameter("fedoraServerPort");
if (fedoraServerPort == null) {
throw new ServerInitializationException("Parameter fedoraServerPort "
+ "not given, but it's required.");
}
LOG.info("Fedora Version: " + Server.VERSION);
LOG.info("Fedora Build Date: " + Server.BUILD_DATE);
LOG.info("Fedora Build Number: " + Server.BUILD_NUMBER);
ServerStatusFile status = getStatusFile();
try {
status.append(ServerState.STARTING,
"Fedora Version: " + Server.VERSION);
status.append(ServerState.STARTING,
"Fedora Build Date: " + Server.BUILD_DATE);
status.append(ServerState.STARTING,
"Fedora Build Number: " + Server.BUILD_NUMBER);
status.append(ServerState.STARTING, "Server Host Name: "
+ fedoraServerHost);
status.append(ServerState.STARTING, "Server Port: "
+ fedoraServerPort);
} catch (Exception e) {
e.printStackTrace();
throw new ServerInitializationException("Unable to write to status file: "
+ e.getMessage());
}
}
/**
* Gets the names of the roles that are required to be fulfilled by modules
* specified in this server's configuration file.
*
* @return String[] The roles.
*/
@Override
public String[] getRequiredModuleRoles() {
return new String[] {DOManager.class.getName()};
}
@Override
public void postInitServer() throws ServerInitializationException {
// check for system objects and pre-ingest them if necessary
DOManager doManager = (DOManager) getModule(DOManager.class.getName());
try {
boolean firstRun = checkFirstRun();
preIngestIfNeeded(firstRun, doManager, Models.CONTENT_MODEL_3_0);
preIngestIfNeeded(firstRun, doManager, Models.FEDORA_OBJECT_3_0);
preIngestIfNeeded(firstRun, doManager, Models.SERVICE_DEFINITION_3_0);
preIngestIfNeeded(firstRun, doManager, Models.SERVICE_DEPLOYMENT_3_0);
} catch (Exception e) {
throw new ServerInitializationException("Failed to ingest "
+ "system object(s)", e);
}
}
private boolean checkFirstRun() throws IOException {
File hasStarted = new File(FEDORA_HOME, "server/fedora-internal-use/has-started.txt");
if (hasStarted.exists()) {
return false;
} else {
hasStarted.createNewFile();
return true;
}
}
/**
* Ingests the given system object if it doesn't exist, OR if it
* exists, but this instance of Fedora has never been started.
* This ensures that, upon upgrade, the old system object
* is replaced with the new one.
*/
private void preIngestIfNeeded(boolean firstRun,
DOManager doManager,
RDFName objectName) throws Exception {
PID pid = new PID(objectName.uri.substring("info:fedora/".length()));
boolean exists = doManager.objectExists(pid.toString());
if (exists && firstRun) {
LOG.info("Purging old system object: " + pid.toString());
Context context = ReadOnlyContext.getContext(null,
null,
null,
false);
DOWriter w = doManager.getWriter(USE_DEFINITIVE_STORE,
context,
pid.toString());
w.remove();
try {
w.commit("Purged by Fedora at startup (to be re-ingested)");
exists = false;
} finally {
doManager.releaseWriter(w);
}
}
if (!exists) {
LOG.info("Ingesting new system object: " + pid.toString());
InputStream xml = getStream("fedora/server/resources/"
+ pid.toFilename() + ".xml");
Context context = ReadOnlyContext.getContext(null,
null,
null,
false);
DOWriter w = doManager.getIngestWriter(USE_DEFINITIVE_STORE,
context,
xml,
Constants.FOXML1_1.uri,
"UTF-8",
false);
try {
w.commit("Pre-ingested by Fedora at startup");
} finally {
doManager.releaseWriter(w);
}
}
}
private InputStream getStream(String path) throws IOException {
InputStream stream = getClass().getClassLoader().getResourceAsStream(
path);
if (stream == null) {
throw new IOException("Classloader cannot find resource: " + path);
} else {
return stream;
}
}
}