Package com.gitblit.utils

Source Code of com.gitblit.utils.FederationUtils

/*
* Copyright 2011 gitblit.com.
*
* 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.gitblit.utils;

import java.lang.reflect.Type;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

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

import com.gitblit.Constants;
import com.gitblit.Constants.FederationProposalResult;
import com.gitblit.Constants.FederationRequest;
import com.gitblit.Constants.FederationToken;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.models.FederationModel;
import com.gitblit.models.FederationProposal;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.google.gson.reflect.TypeToken;

/**
* Utility methods for federation functions.
*
* @author James Moger
*
*/
public class FederationUtils {

  private static final Type REPOSITORIES_TYPE = new TypeToken<Map<String, RepositoryModel>>() {
  }.getType();

  private static final Type SETTINGS_TYPE = new TypeToken<Map<String, String>>() {
  }.getType();

  private static final Type USERS_TYPE = new TypeToken<Collection<UserModel>>() {
  }.getType();

  private static final Type TEAMS_TYPE = new TypeToken<Collection<TeamModel>>() {
  }.getType();

  private static final Logger LOGGER = LoggerFactory.getLogger(FederationUtils.class);

  /**
   * Returns an url to this servlet for the specified parameters.
   *
   * @param sourceURL
   *            the url of the source gitblit instance
   * @param token
   *            the federation token of the source gitblit instance
   * @param req
   *            the pull type request
   */
  public static String asLink(String sourceURL, String token, FederationRequest req) {
    return asLink(sourceURL, null, token, req, null);
  }

  /**
   *
   * @param remoteURL
   *            the url of the remote gitblit instance
   * @param tokenType
   *            the type of federation token of a gitblit instance
   * @param token
   *            the federation token of a gitblit instance
   * @param req
   *            the pull type request
   * @param myURL
   *            the url of this gitblit instance
   * @return
   */
  public static String asLink(String remoteURL, FederationToken tokenType, String token,
      FederationRequest req, String myURL) {
    if (remoteURL.length() > 0 && remoteURL.charAt(remoteURL.length() - 1) == '/') {
      remoteURL = remoteURL.substring(0, remoteURL.length() - 1);
    }
    if (req == null) {
      req = FederationRequest.PULL_REPOSITORIES;
    }
    return remoteURL + Constants.FEDERATION_PATH + "?req=" + req.name().toLowerCase()
        + (token == null ? "" : ("&token=" + token))
        + (tokenType == null ? "" : ("&tokenType=" + tokenType.name().toLowerCase()))
        + (myURL == null ? "" : ("&url=" + StringUtils.encodeURL(myURL)));
  }

  /**
   * Returns the list of federated gitblit instances that this instance will
   * try to pull.
   *
   * @return list of registered gitblit instances
   */
  public static List<FederationModel> getFederationRegistrations(IStoredSettings settings) {
    List<FederationModel> federationRegistrations = new ArrayList<FederationModel>();
    List<String> keys = settings.getAllKeys(Keys.federation._ROOT);
    keys.remove(Keys.federation.name);
    keys.remove(Keys.federation.passphrase);
    keys.remove(Keys.federation.allowProposals);
    keys.remove(Keys.federation.proposalsFolder);
    keys.remove(Keys.federation.defaultFrequency);
    keys.remove(Keys.federation.sets);
    Collections.sort(keys);
    Map<String, FederationModel> federatedModels = new HashMap<String, FederationModel>();
    for (String key : keys) {
      String value = key.substring(Keys.federation._ROOT.length() + 1);
      List<String> values = StringUtils.getStringsFromValue(value, "\\.");
      String server = values.get(0);
      if (!federatedModels.containsKey(server)) {
        federatedModels.put(server, new FederationModel(server));
      }
      String setting = values.get(1);
      if (setting.equals("url")) {
        // url of the origin Gitblit instance
        federatedModels.get(server).url = settings.getString(key, "");
      } else if (setting.equals("token")) {
        // token for the origin Gitblit instance
        federatedModels.get(server).token = settings.getString(key, "");
      } else if (setting.equals("frequency")) {
        // frequency of the pull operation
        federatedModels.get(server).frequency = settings.getString(key, "");
      } else if (setting.equals("folder")) {
        // destination folder of the pull operation
        federatedModels.get(server).folder = settings.getString(key, "");
      } else if (setting.equals("bare")) {
        // whether pulled repositories should be bare
        federatedModels.get(server).bare = settings.getBoolean(key, true);
      } else if (setting.equals("mirror")) {
        // are the repositories to be true mirrors of the origin
        federatedModels.get(server).mirror = settings.getBoolean(key, true);
      } else if (setting.equals("mergeAccounts")) {
        // merge remote accounts into local accounts
        federatedModels.get(server).mergeAccounts = settings.getBoolean(key, false);
      } else if (setting.equals("sendStatus")) {
        // send a status acknowledgment to source Gitblit instance
        // at end of git pull
        federatedModels.get(server).sendStatus = settings.getBoolean(key, false);
      } else if (setting.equals("notifyOnError")) {
        // notify administrators on federation pull failures
        federatedModels.get(server).notifyOnError = settings.getBoolean(key, false);
      } else if (setting.equals("exclude")) {
        // excluded repositories
        federatedModels.get(server).exclusions = settings.getStrings(key);
      } else if (setting.equals("include")) {
        // included repositories
        federatedModels.get(server).inclusions = settings.getStrings(key);
      }
    }

    // verify that registrations have a url and a token
    for (FederationModel model : federatedModels.values()) {
      if (StringUtils.isEmpty(model.url)) {
        LOGGER.warn(MessageFormat.format(
            "Dropping federation registration {0}. Missing url.", model.name));
        continue;
      }
      if (StringUtils.isEmpty(model.token)) {
        LOGGER.warn(MessageFormat.format(
            "Dropping federation registration {0}. Missing token.", model.name));
        continue;
      }
      // set default frequency if unspecified
      if (StringUtils.isEmpty(model.frequency)) {
        model.frequency = settings.getString(Keys.federation.defaultFrequency, "60 mins");
      }
      federationRegistrations.add(model);
    }
    return federationRegistrations;
  }

  /**
   * Sends a federation poke to the Gitblit instance at remoteUrl. Pokes are
   * sent by an pulling Gitblit instance to an origin Gitblit instance as part
   * of the proposal process. This is to ensure that the pulling Gitblit
   * instance has an IP route to the origin instance.
   *
   * @param remoteUrl
   *            the remote Gitblit instance to send a federation proposal to
   * @param proposal
   *            a complete federation proposal
   * @return true if there is a route to the remoteUrl
   */
  public static boolean poke(String remoteUrl) throws Exception {
    String url = asLink(remoteUrl, null, FederationRequest.POKE);
    String json = JsonUtils.toJsonString("POKE");
    int status = JsonUtils.sendJsonString(url, json);
    return status == HttpServletResponse.SC_OK;
  }

  /**
   * Sends a federation proposal to the Gitblit instance at remoteUrl
   *
   * @param remoteUrl
   *            the remote Gitblit instance to send a federation proposal to
   * @param proposal
   *            a complete federation proposal
   * @return the federation proposal result code
   */
  public static FederationProposalResult propose(String remoteUrl, FederationProposal proposal)
      throws Exception {
    String url = asLink(remoteUrl, null, FederationRequest.PROPOSAL);
    String json = JsonUtils.toJsonString(proposal);
    int status = JsonUtils.sendJsonString(url, json);
    switch (status) {
    case HttpServletResponse.SC_FORBIDDEN:
      // remote Gitblit Federation disabled
      return FederationProposalResult.FEDERATION_DISABLED;
    case HttpServletResponse.SC_BAD_REQUEST:
      // remote Gitblit did not receive any JSON data
      return FederationProposalResult.MISSING_DATA;
    case HttpServletResponse.SC_METHOD_NOT_ALLOWED:
      // remote Gitblit not accepting proposals
      return FederationProposalResult.NO_PROPOSALS;
    case HttpServletResponse.SC_NOT_ACCEPTABLE:
      // remote Gitblit failed to poke this Gitblit instance
      return FederationProposalResult.NO_POKE;
    case HttpServletResponse.SC_OK:
      // received
      return FederationProposalResult.ACCEPTED;
    default:
      return FederationProposalResult.ERROR;
    }
  }

  /**
   * Retrieves a map of the repositories at the remote gitblit instance keyed
   * by the repository clone url.
   *
   * @param registration
   * @param checkExclusions
   *            should returned repositories remove registration exclusions
   * @return a map of cloneable repositories
   * @throws Exception
   */
  public static Map<String, RepositoryModel> getRepositories(FederationModel registration,
      boolean checkExclusions) throws Exception {
    String url = asLink(registration.url, registration.token,
        FederationRequest.PULL_REPOSITORIES);
    Map<String, RepositoryModel> models = JsonUtils.retrieveJson(url, REPOSITORIES_TYPE);
    if (checkExclusions) {
      Map<String, RepositoryModel> includedModels = new HashMap<String, RepositoryModel>();
      for (Map.Entry<String, RepositoryModel> entry : models.entrySet()) {
        if (registration.isIncluded(entry.getValue())) {
          includedModels.put(entry.getKey(), entry.getValue());
        }
      }
      return includedModels;
    }
    return models;
  }

  /**
   * Tries to pull the gitblit user accounts from the remote gitblit instance.
   *
   * @param registration
   * @return a collection of UserModel objects
   * @throws Exception
   */
  public static List<UserModel> getUsers(FederationModel registration) throws Exception {
    String url = asLink(registration.url, registration.token, FederationRequest.PULL_USERS);
    Collection<UserModel> models = JsonUtils.retrieveJson(url, USERS_TYPE);
    List<UserModel> list = new ArrayList<UserModel>(models);
    return list;
  }

  /**
   * Tries to pull the gitblit team definitions from the remote gitblit
   * instance.
   *
   * @param registration
   * @return a collection of TeamModel objects
   * @throws Exception
   */
  public static List<TeamModel> getTeams(FederationModel registration) throws Exception {
    String url = asLink(registration.url, registration.token, FederationRequest.PULL_TEAMS);
    Collection<TeamModel> models = JsonUtils.retrieveJson(url, TEAMS_TYPE);
    List<TeamModel> list = new ArrayList<TeamModel>(models);
    return list;
  }

  /**
   * Tries to pull the gitblit server settings from the remote gitblit
   * instance.
   *
   * @param registration
   * @return a map of the remote gitblit settings
   * @throws Exception
   */
  public static Map<String, String> getSettings(FederationModel registration) throws Exception {
    String url = asLink(registration.url, registration.token, FederationRequest.PULL_SETTINGS);
    Map<String, String> settings = JsonUtils.retrieveJson(url, SETTINGS_TYPE);
    return settings;
  }

  /**
   * Tries to pull the referenced scripts from the remote gitblit instance.
   *
   * @param registration
   * @return a map of the remote gitblit scripts by script name
   * @throws Exception
   */
  public static Map<String, String> getScripts(FederationModel registration) throws Exception {
    String url = asLink(registration.url, registration.token, FederationRequest.PULL_SCRIPTS);
    Map<String, String> scripts = JsonUtils.retrieveJson(url, SETTINGS_TYPE);
    return scripts;
  }

  /**
   * Send an status acknowledgment to the remote Gitblit server.
   *
   * @param identification
   *            identification of this pulling instance
   * @param registration
   *            the source Gitblit instance to receive an acknowledgment
   * @param results
   *            the results of your pull operation
   * @return true, if the remote Gitblit instance acknowledged your results
   * @throws Exception
   */
  public static boolean acknowledgeStatus(String identification, FederationModel registration)
      throws Exception {
    String url = asLink(registration.url, null, registration.token, FederationRequest.STATUS,
        identification);
    String json = JsonUtils.toJsonString(registration);
    int status = JsonUtils.sendJsonString(url, json);
    return status == HttpServletResponse.SC_OK;
  }
}
TOP

Related Classes of com.gitblit.utils.FederationUtils

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.