com.google.enterprise.connector.persist.StoreMigrator.java Source code

Java tutorial

Introduction

Here is the source code for com.google.enterprise.connector.persist.StoreMigrator.java

Source

// Copyright 2010 Google Inc.
//
// Licensed under 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.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.enterprise.connector.persist;

import com.google.common.collect.ImmutableMap;
import com.google.enterprise.connector.instantiator.Configuration;
import com.google.enterprise.connector.scheduler.Schedule;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Copies the objects from zero or more legacy persistent stores to
 * the production persistent store. Existing objects in the production
 * store are not overwritten.
 */
// TODO: We could optionally support overwriting existing objects in
// the target and copying objects from the legacy stores rather than
// moving them. For manual migration, we might want options to delete
// the existing production store and then migrate the legacy stores
// (so that nulls overwrite objects, for example), or to selectively
// overwrite objects, or even to prompt for each object copied.
public class StoreMigrator {
    private static final Logger LOGGER = Logger.getLogger(StoreMigrator.class.getName());

    private final PersistentStore store;
    private final List<PersistentStore> legacyStores;

    public StoreMigrator(PersistentStore store, List<PersistentStore> legacyStores) {
        this.store = store;
        this.legacyStores = (legacyStores == null) ? Collections.<PersistentStore>emptyList() : legacyStores;
    }

    /**
     * Migrates data from all legacy stores to the configured PersistentStore.
     */
    public void migrate() {
        for (PersistentStore legacyStore : legacyStores) {
            migrate(legacyStore, store, null, false);
        }
        checkMissing(store, null);
    }

    /**
     * Migrates data from the {@code sourceStore} to the {@code destStore}.
     *
     * @param sourceStore source {@link PersistentStore}
     * @param destStore destination {@link PersistentStore}
     * @param connectorNames Collection of connector names to migrate.
     * @param force if {@code true} overwrite existing data in the
     *        {@code destStore}.
     */
    public static void migrate(PersistentStore sourceStore, PersistentStore destStore,
            Collection<String> connectorNames, boolean force) {
        ImmutableMap<StoreContext, ConnectorStamps> inventory = sourceStore.getInventory();
        for (StoreContext context : inventory.keySet()) {
            if (connectorNames != null && !connectorNames.contains(context.getConnectorName())) {
                continue;
            }
            // This double assignment ensures that we check the same
            // object type that we're storing.
            Configuration config = destStore.getConnectorConfiguration(context);
            if (force || config == null) {
                config = sourceStore.getConnectorConfiguration(context);
                if (config != null) {
                    logMigration(sourceStore, destStore, context, "configuration");
                    destStore.storeConnectorConfiguration(context, config);
                }
            }
            Schedule sched = destStore.getConnectorSchedule(context);
            if (force || sched == null) {
                sched = sourceStore.getConnectorSchedule(context);
                if (sched != null) {
                    logMigration(sourceStore, destStore, context, "traversal schedule");
                    destStore.storeConnectorSchedule(context, sched);
                }
            }
            String state = destStore.getConnectorState(context);
            if (force || state == null) {
                state = sourceStore.getConnectorState(context);
                if (state != null) {
                    logMigration(sourceStore, destStore, context, "traversal state");
                    destStore.storeConnectorState(context, state);
                }
            }
        }
    }

    /**
     * Checks for missing persistently stored data in the
     * {@code persistentStore}.  If items are missing from the store,
     * log a message.
     *
     * @param persistentStore PersistentStore to check.
     * @param connectorNames Collection of connector names to check.
     */
    public static void checkMissing(PersistentStore persistentStore, Collection<String> connectorNames) {
        // Check for missing objects in the specified store.
        ImmutableMap<StoreContext, ConnectorStamps> inventory = persistentStore.getInventory();
        for (StoreContext context : inventory.keySet()) {
            if (connectorNames != null && !connectorNames.contains(context.getConnectorName())) {
                continue;
            }
            if (persistentStore.getConnectorConfiguration(context) == null) {
                logMissing(context, "configuration");
            }
            if (persistentStore.getConnectorSchedule(context) == null) {
                logMissing(context, "traversal schedule");
            }
            if (persistentStore.getConnectorState(context) == null) {
                logMissing(context, "traversal state");
            }
        }
    }

    private static void logMigration(PersistentStore sourceStore, PersistentStore destStore, StoreContext context,
            String objectType) {
        if (LOGGER.isLoggable(Level.INFO)) {
            LOGGER.info("Migrating " + objectType + " information for connector " + context.getConnectorName()
                    + " from " + sourceStore.getClass().getName() + " to " + destStore.getClass().getName());
        }
    }

    private static void logMissing(StoreContext context, String objectType) {
        if (LOGGER.isLoggable(Level.INFO)) {
            LOGGER.info("Connector " + context.getConnectorName() + " lacks saved " + objectType + ".");
        }
    }
}