Package org.fcrepo.server.utilities.rebuild

Source Code of org.fcrepo.server.utilities.rebuild.Rebuild

/* 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 org.fcrepo.server.utilities.rebuild;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.slf4j.bridge.SLF4JBridgeHandler;

import org.fcrepo.common.Constants;

import org.fcrepo.server.Module;
import org.fcrepo.server.Server;
import org.fcrepo.server.config.Configuration;
import org.fcrepo.server.config.Parameter;
import org.fcrepo.server.config.ServerConfiguration;
import org.fcrepo.server.config.ServerConfigurationParser;
import org.fcrepo.server.errors.InitializationException;
import org.fcrepo.server.storage.lowlevel.IListable;
import org.fcrepo.server.storage.lowlevel.ILowlevelStorage;
import org.fcrepo.server.storage.translation.DODeserializer;
import org.fcrepo.server.storage.translation.DOTranslationUtility;
import org.fcrepo.server.storage.translation.FOXML1_1DODeserializer;
import org.fcrepo.server.storage.types.BasicDigitalObject;
import org.fcrepo.server.storage.types.DigitalObject;
import org.fcrepo.server.utilities.ServerUtility;

import org.fcrepo.utilities.LogConfig;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Entry-point for rebuilding various aspects of the repository.
*
* @author Chris Wilper
*/
public class Rebuild implements Constants, Runnable {

    private static Server server;

    private static Logger logger = LoggerFactory.getLogger(Rebuild.class
            .getName());

    private static final String llstoreInterface = ILowlevelStorage.class
            .getName();

    private static final String listableInterface = IListable.class.getName();

    private final Rebuilder m_rebuilder;

    private final Map<String, String> m_options;

    public Rebuild(Rebuilder rebuilder, Map<String, String> options,
            Server server)
            throws Exception {
        // set these here so DOTranslationUtility doesn't try to get a Server
        // instance
        System.setProperty("fedoraServerHost", server
                .getParameter("fedoraServerHost"));
        System.setProperty("fedoraServerPort", server
                .getParameter("fedoraServerPort"));
        System.setProperty("fedoraAppServerContext", server
                .getParameter("fedoraAppServerContext"));
        boolean serverIsRunning = ServerUtility.pingServer("http", null, null);
        if (serverIsRunning && rebuilder.shouldStopServer()) {
            throw new Exception("The Fedora server appears to be running."
                    + "  It must be stopped before the rebuilder can run.");
        }
        m_options = options;
        m_rebuilder = rebuilder;
        if (options != null) {
            try {
                // ensure rebuilds are possible before trying anything,
                // as rebuilder.start() may be destructive!
                Module mod = server.getBean(llstoreInterface, Module.class);
                Class<?> clazz = mod.getClass();
                boolean isListable = false;
                for (Class<?> iface : clazz.getInterfaces()) {
                    if (iface.getName().equals(listableInterface)) {
                        isListable = true;
                    }
                }
                if (!isListable) {
                    throw new Exception("ERROR: Rebuilds are not supported" +
                            " by " + clazz.getName() +
                            " because it does not implement the" +
                            " org.fcrepo.server.storage.lowlevel.IListable" +
                            " interface.");
                }

            } finally {
            }
        } else {
            logger.warn("Null options for " + getClass().getName());
        }
    }

    public void run() {
        try {
            if (m_options != null && m_rebuilder != null) {
                System.err.println();
                System.err.println("Rebuilding...");
                try {
                    // looks good, so init the rebuilder
                    m_rebuilder.start(m_options);

                    // add each object in llstore
                    ILowlevelStorage llstore =
                            (ILowlevelStorage) getServer().getModule(
                                    llstoreInterface);
                    if (llstore == null) {
                        logger.error("No module/bean definition for " +
                                llstoreInterface);
                    } else {
                        logger.info("Loaded bean/module " + llstoreInterface +
                                " with impl " + llstore.getClass().getName());
                    }
                    Iterator<String> pids = ((IListable) llstore).listObjects();
                    int total = 0;
                    int errors = 0;
                    DODeserializer deser = new FOXML1_1DODeserializer();

                    while (pids.hasNext()) {
                        total++;
                        String pid = pids.next();
                        System.out.println("Adding object #" + total + ": " +
                                pid);
                        if (!addObject(m_rebuilder, llstore, deser, pid)) {
                            errors++;
                        }
                    }
                    if (errors == 0) {
                        System.out.println("SUCCESS: " + total +
                                " objects rebuilt.");
                    } else {
                        System.out.println("WARNING: " + errors + " of " +
                                total +
                                " objects failed to rebuild due to errors.");
                    }
                } finally {
                    m_rebuilder.finish();
                    if (server != null) {
                        server.shutdown(null);
                        server = null;
                    }
                    System.err.print("Finished.");
                    System.err.println();
                }
                return;
            } else {
                System.out.println("Exiting without rebuilding.");
                if (server != null) {
                    server.shutdown(null);
                    server = null;
                }
            }
        } catch (Exception e) {
            System.err.println("Rebuild failed:");
            System.err.println(e.toString());
            e.printStackTrace(System.err);
        } finally {
           
        }
    }

    private boolean addObject(Rebuilder rebuilder, ILowlevelStorage llstore,
            DODeserializer deser, String pid) {
        InputStream in = null;
        try {
            in = llstore.retrieveObject(pid);
            DigitalObject obj = new BasicDigitalObject();
            deser.deserialize(in, obj, "UTF-8",
                    DOTranslationUtility.SERIALIZE_STORAGE_INTERNAL);
            rebuilder.addObject(obj);
            return true;
        } catch (Exception e) {
            System.out.println("WARNING: Skipped " + pid +
                    " due to exception: ");
            e.printStackTrace();
            return false;
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                }
            }
        }
    }

    /**
     * Gets the instance of the server appropriate for rebuilding. If no such
     * instance has been initialized yet, initialize one.
     *
     * @return the server instance.
     * @throws InitializationException
     *         if initialization fails.
     */
    public static Server getServer() throws InitializationException {
        if (server == null) {
            server =
                    RebuildServer.getRebuildInstance(new File(
                            Constants.FEDORA_HOME));
        }
        return server;
    }

    private static Map<String, String> getOptions(Map<String, String> descs)
            throws IOException {
        Map<String, String> options = new HashMap<String, String>();
        if (descs != null) {
            Iterator<String> iter = descs.keySet().iterator();
            while (iter.hasNext()) {
                String name = iter.next();
                String desc = descs.get(name);
                options.put(name, getOptionValue(name, desc));
            }
        }
        int c = 1;

        if (System.getProperty("rebuilder") == null) {
            if (options.size() > 0) {
                c =
                        getChoice("Start rebuilding with the above options?",
                                new String[] {"Yes",
                                        "No, let me re-enter the options.",
                                        "No, exit."});

                if (c == 0) {
                    return options;
                }
                if (c == 1) {
                    System.err.println();
                    return getOptions(descs);
                }
            } else {
                c =
                        getChoice("No options to set. Start rebuilding?",
                                new String[] {"Yes", "No, exit."});
                if (c == 0) {
                    return options;
                }
            }
        } else {
            return options;
        }
        return null;
    }

    private static String getOptionValue(String name, String desc)
            throws IOException {
        System.err.println("[" + name + "]");
        System.err.println(desc);
        System.err.println();
        System.err.print("Enter a value --> ");
        String val =
                new BufferedReader(new InputStreamReader(System.in)).readLine();
        System.err.println();
        return val;
    }

    private static Rebuilder getRebuilder() throws Exception {
        Server server = getServer();
        String[] rebuilders = server.getBeanNamesForType(Rebuilder.class);
        String[] labels = new String[rebuilders.length + 1];
        int i = 0;
        for (i = 0; i < rebuilders.length; i++) {
            Rebuilder r = server.getBean(rebuilders[i], Rebuilder.class);

            labels[i] = r.getAction();
        }
        labels[i] = "Exit";
        int choiceNum = i;
        if (System.getProperty("rebuilder") == null) {
            choiceNum = getChoice("What do you want to do?", labels);
        } else {
            System.out.println("Getting rebuilder... " +
                    System.getProperty("rebuilder"));
            for (int j = 0; j < rebuilders.length; j++) {
                if (rebuilders[j].equals(System.getProperty("rebuilder"))) {
                    choiceNum = j;
                }
            }
        }
        if (choiceNum == i) {
            return null;
        } else {
            return server.getBean(rebuilders[choiceNum], Rebuilder.class);
        }
    }

    private static int getChoice(String title, String[] labels)
            throws IOException {
        boolean validChoice = false;
        int choiceIndex = -1;
        System.err.println(title);
        System.err.println();
        for (int i = 1; i <= labels.length; i++) {
            System.err.println("  " + i + ") " + labels[i - 1]);
        }
        System.err.println();
        while (!validChoice) {
            System.err.print("Enter (1-" + labels.length + ") --> ");
            BufferedReader in =
                    new BufferedReader(new InputStreamReader(System.in));
            String line = in.readLine();
            try {
                int choiceNum = Integer.parseInt(line);
                if (choiceNum > 0 && choiceNum <= labels.length) {
                    choiceIndex = choiceNum - 1;
                    validChoice = true;
                }
            } catch (NumberFormatException nfe) {
            }
        }
        return choiceIndex;
    }

    private static ServerConfiguration getServerConfig(File serverDir,
            String profile) throws IOException {
        ServerConfigurationParser parser =
                new ServerConfigurationParser(new FileInputStream(new File(
                        serverDir, "config/fedora.fcfg")));
        ServerConfiguration serverConfig = parser.parse();
        // set all the values according to the profile, if specified
        if (profile != null) {
            int c = setValuesForProfile(serverConfig, profile);

            c +=
                    setValuesForProfile(serverConfig.getModuleConfigurations(),
                            profile);
            c +=
                    setValuesForProfile(serverConfig
                            .getDatastoreConfigurations(), profile);
            if (c == 0) {
                throw new IOException("Unrecognized server-profile: " + profile);
            }
        }
        return serverConfig;
    }

    private static int
            setValuesForProfile(Configuration config, String profile) {
        int c = 0;
        Iterator<Parameter> iter =
                config.getParameters(Parameter.class).iterator();
        while (iter.hasNext()) {
            Parameter param = iter.next();
            String profileValue = param.getProfileValues().get(profile);
            if (profileValue != null) {
                param.setValue(profileValue);
                c++;
            }
        }
        return c;
    }

    private static int setValuesForProfile(
            List<? extends Configuration> configs, String profile) {
        Iterator<? extends Configuration> iter = configs.iterator();
        int c = 0;
        while (iter.hasNext()) {
            c += setValuesForProfile(iter.next(), profile);
        }
        return c;
    }

    private static Map<String, String> getUserInput(Rebuilder rebuilder,
            File serverDir, ServerConfiguration serverConfig) throws Exception {
        if (rebuilder != null) {
            System.err.println();
            System.err.println(rebuilder.getAction());
            System.err.println();
            //refactor these, as they should be injected
            rebuilder.setServerConfiguration(serverConfig);
            rebuilder.setServerDir(serverDir);
            rebuilder.init();
            Map<String, String> options = getOptions(rebuilder.getOptions());
            return options;
        } else {
            return new HashMap<String, String>();
        }
    }

    public static void fail(String message, boolean showUsage, boolean exit) {
        System.err.println("Error: " + message);
        System.err.println();
        if (showUsage) {
            System.err.println("Usage: fedora-rebuild [server-profile]");
            System.err.println();
        }
        if (exit) {
            System.exit(1);
        }
    }

    public static void main(String[] args) {
        String profile = null;
        if (args.length == 1) {
            profile = args[0];
        }
        if (args.length > 1) {
            for (int i = 0; i < args.length - 1; i+=2) {
                if ("-p".equals(args[i])) profile = args[i+1];
                if ("-r".equals(args[i])) System.setProperty("rebuilder", args[i+1]);
            }
            if (profile == null && System.getProperty("rebuilder") == null) {
                fail("Too many arguments", true, true);
            }
        }
        try {
            File fedoraHomeDir = new File(Constants.FEDORA_HOME);

            // Configure logging from file
            System.setProperty("fedora.home", Constants.FEDORA_HOME);
            System.setProperty("logfile.extension", "-rebuild.log");
            LogConfig.initFromFile(new File(fedoraHomeDir,
                    "server/config/logback.xml"));

            // Replace java.util.logging's default handlers with one that
            // redirects everything to SLF4J
            java.util.logging.Logger rootLogger =
                    java.util.logging.LogManager.getLogManager().getLogger("");
            java.util.logging.Handler[] handlers = rootLogger.getHandlers();
            for (int i = 0; i < handlers.length; i++) {
                rootLogger.removeHandler(handlers[i]);
            }
            SLF4JBridgeHandler.install();

            File serverDir = new File(fedoraHomeDir, "server");
            ServerConfiguration serverConfig =
                    getServerConfig(serverDir, profile);
            System.err.println();
            System.err.println("                       Fedora Rebuild Utility");
            System.err
                    .println("                     ..........................");
            System.err.println();
            System.err
                    .println("WARNING: Live rebuilds are not currently supported.");
            System.err
                    .println("         Make sure your server is stopped before continuing.");
            System.err.println();
            System.err.println("Server directory is " + serverDir.toString());
            if (profile != null) {
                System.err.print("Server profile is " + profile);
            }
            System.err.println();
            System.err
                    .println("---------------------------------------------------------------------");
            System.err.println();
            Rebuilder rebuilder = getRebuilder();
            Map<String, String> options =
                    getUserInput(rebuilder, serverDir, serverConfig);
            new Rebuild(rebuilder, options, getServer()).run();
            return;
        } catch (Throwable th) {
            String msg = th.getMessage();
            if (msg == null) {
                msg = th.getClass().getName();
            }
            fail(msg, false, false);
            th.printStackTrace();
            try {
                getServer().shutdown(null);
            } catch (Throwable t) {
                System.err.println("Server shutdown error: " + t.toString());
            }
        }
    }

}
TOP

Related Classes of org.fcrepo.server.utilities.rebuild.Rebuild

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.