java.fedora.server.journal.readerwriter.multicast.rmi.RmiJournalReceiver Maven / Gradle / Ivy
Show all versions of fcrepo-client Show documentation
/*
* -----------------------------------------------------------------------------
*
* License and Copyright: The contents of this file are subject to 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.fedora-commons.org/licenses.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* The entire file consists of original code.
* Copyright © 2008 Fedora Commons, Inc.
*
Copyright © 2002-2007 The Rector and Visitors of the University of
* Virginia and Cornell University
* All rights reserved.
*
* -----------------------------------------------------------------------------
*/
package fedora.server.journal.readerwriter.multicast.rmi;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.SimpleLayout;
import org.apache.log4j.lf5.LogLevel;
import fedora.server.journal.JournalException;
import fedora.server.journal.readerwriter.multicast.TransportOutputFile;
/**
*
* Title: RmiJournalReceiver.java
*
*
* Description: A free-standing RMI server that receives journal
* messages from an RmiTransport and writes them to files in a specified
* directory.
*
*
* Note: command-line arguments are specified in
* {@link RmiJournalReceiverArguments}.
*
*
* @author jblake
* @version $Id: RmiJournalReceiver.java,v 1.4 2007/06/21 15:59:53 jblake Exp $
*/
@SuppressWarnings("serial")
public class RmiJournalReceiver
extends UnicastRemoteObject
implements RmiJournalReceiverInterface {
private static final Logger LOG =
Logger.getLogger(RmiJournalReceiver.class);
/** The parsed arguments from the command line. */
private final RmiJournalReceiverArguments arguments;
/** The directory for journal files. */
private final File directory;
/** The journal file that is currently open, or null if no file is open. */
private TransportOutputFile journalFile;
/**
* The number of {@link #writeText(String, String) writeText} calls that
* have been made against the currently open file - used in calculating the
* itemHash.
*/
private long itemIndex;
/** A {@link FileWriter} on the current journal file. */
private Writer writer;
/** The repository hash that was supplied when the current file was opened. */
private String currentRepositoryHash;
/**
* On creation, parse the arguments and initialize Log4J for the
* application.
*/
public RmiJournalReceiver(RmiJournalReceiverArguments arguments)
throws RemoteException {
super(arguments.getServerPortNumber());
this.arguments = arguments;
directory = arguments.getDirectoryPath();
initializeLog4J(arguments.getLogLevel());
}
/**
* Set the logger to write to the console, at whatever level the user
* specified in the command line argumements.
*/
private void initializeLog4J(LogLevel logLevel) {
ConsoleAppender appender =
new ConsoleAppender(new SimpleLayout(), "System.out");
appender.setName("Console");
appender.activateOptions();
Logger root = Logger.getRootLogger();
root.addAppender(appender);
root.setLevel(Level.toLevel(logLevel.getLabel()));
}
/**
* Create an RMI registry, and bind this object to the expected name.
*/
public void exportAndBind() throws RemoteException, AlreadyBoundException,
InterruptedException {
Registry registry =
LocateRegistry
.createRegistry(arguments.getRegistryPortNumber());
registry.rebind(RMI_BINDING_NAME, this);
Thread.sleep(2000);
LOG.info("RmiJournalReceiver is ready - journal directory is '"
+ arguments.getDirectoryPath().getAbsolutePath() + "'");
}
/**
* Request to open a file. Check that:
*
* - a file is not already open,
* - we can create a {@link TransportOutputFile}, and open a
* {@link Writer} on it.
*
*/
public void openFile(String repositoryHash, String filename)
throws JournalException {
if (journalFile != null) {
throw logAndGetException("Attempting to open file '" + filename
+ "' when file '" + journalFile.getName()
+ "' has not been closed.");
}
try {
journalFile = new TransportOutputFile(directory, filename);
writer = journalFile.open();
} catch (IOException e) {
throw logAndGetException("Problem opening" + filename + "'", e);
}
currentRepositoryHash = repositoryHash;
itemIndex = 0;
LOG.debug("opened file '" + filename + "', hash is '" + repositoryHash
+ "'");
}
/**
* Request to write text to the current journal file. Check that:
*
* - a file is open,
* - the supplied indexedHash matches the one we calculate,
* - the write is successful.
*
* Increment the itemIndex after a successful write.
*/
public void writeText(String indexedHash, String text)
throws JournalException {
if (journalFile == null) {
throw logAndGetException("Attempting to write when no file "
+ "is open.");
}
String calculatedHash =
RmiJournalReceiverHelper
.figureIndexedHash(currentRepositoryHash, itemIndex);
if (!calculatedHash.equals(indexedHash)) {
LOG.debug("calculatedHash='" + calculatedHash + "', providedHash='"
+ indexedHash + "'");
throw logAndGetException("indexed hash is incorrect.");
}
try {
writer.append(text);
writer.flush();
} catch (IOException e) {
throw logAndGetException("Failed to write to '"
+ journalFile.getName() + "'", e);
}
LOG.debug("Wrote item #" + itemIndex + " to file '"
+ journalFile.getName() + "'");
itemIndex++;
}
/**
* Request to close a file. Check that:
*
* - a file is open,
* - we are able to close the file.
*
*/
public void closeFile() throws JournalException {
if (journalFile == null) {
throw logAndGetException("Attempting to close a file "
+ "when no file is open.");
}
try {
writer.close();
journalFile.close();
} catch (IOException e) {
throw logAndGetException("Problem closing the file '"
+ journalFile.getName() + "'", e);
}
LOG.debug("closing file: '" + journalFile.getName() + "'");
journalFile = null;
}
private JournalException logAndGetException(String message) {
LOG.error(message);
return new JournalException(message);
}
private JournalException logAndGetException(String message, Throwable e) {
LOG.error(message, e);
return new JournalException(message + ": " + e.toString());
}
/**
* Main routine: create the receiver from the arguments, and bind the
* receiver in the registry.
*/
public static void main(String[] args) {
try {
RmiJournalReceiverArguments arguments =
new RmiJournalReceiverArguments(args);
RmiJournalReceiver receiver = new RmiJournalReceiver(arguments);
receiver.exportAndBind();
while (true) {
Thread.sleep(60000);
}
} catch (IllegalArgumentException e) {
System.out.println("RmiJournalReciever failed: " + e.getMessage());
} catch (Exception e) {
System.out.println("RmiJournalReciever failed: ");
e.printStackTrace();
}
}
}