UserAgent.java

  1. /*
  2.  * Copyright (C) 2015, Google Inc. and others
  3.  *
  4.  * This program and the accompanying materials are made available under the
  5.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  6.  * https://www.eclipse.org/org/documents/edl-v10.php.
  7.  *
  8.  * SPDX-License-Identifier: BSD-3-Clause
  9.  */

  10. package org.eclipse.jgit.transport;

  11. import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_AGENT;

  12. import java.util.Set;

  13. import org.eclipse.jgit.util.StringUtils;

  14. /**
  15.  * User agent to be reported by this JGit client and server on the network.
  16.  * <p>
  17.  * On HTTP transports this user agent string is always supplied by the JGit
  18.  * client in the {@code User-Agent} HTTP header.
  19.  * <p>
  20.  * On native transports this user agent string is always sent when JGit is a
  21.  * server. When JGit is a client the user agent string will be supplied to the
  22.  * remote server only if the remote server advertises its own agent identity.
  23.  *
  24.  * @since 4.0
  25.  */
  26. public class UserAgent {
  27.     private static volatile String userAgent = computeUserAgent();

  28.     private static String computeUserAgent() {
  29.         return clean("JGit/" + computeVersion()); //$NON-NLS-1$
  30.     }

  31.     private static String computeVersion() {
  32.         Package pkg = UserAgent.class.getPackage();
  33.         if (pkg != null) {
  34.             String ver = pkg.getImplementationVersion();
  35.             if (!StringUtils.isEmptyOrNull(ver)) {
  36.                 return ver;
  37.             }
  38.         }
  39.         return "unknown"; //$NON-NLS-1$
  40.     }

  41.     static String clean(String s) {
  42.         s = s.trim();
  43.         StringBuilder b = new StringBuilder(s.length());
  44.         for (int i = 0; i < s.length(); i++) {
  45.             char c = s.charAt(i);
  46.             if (c <= 32 || c >= 127) {
  47.                 if (b.length() > 0 && b.charAt(b.length() - 1) == '.')
  48.                     continue;
  49.                 c = '.';
  50.             }
  51.             b.append(c);
  52.         }
  53.         return b.length() > 0 ? b.toString() : null;
  54.     }

  55.     /**
  56.      * Get the user agent string advertised by JGit.
  57.      *
  58.      * @return a string similar to {@code "JGit/4.0"}; null if the agent has
  59.      *         been cleared and should not be shared with a peer.
  60.      */
  61.     public static String get() {
  62.         return userAgent;
  63.     }

  64.     /**
  65.      * Change the user agent string advertised by JGit.
  66.      * <p>
  67.      * The new string should start with {@code "JGit/"} (for example
  68.      * {@code "JGit/4.0"}) to advertise the implementation as JGit based.
  69.      * <p>
  70.      * Spaces and other whitespace should be avoided as these will be
  71.      * automatically converted to {@code "."}.
  72.      * <p>
  73.      * User agent strings are restricted to printable ASCII.
  74.      *
  75.      * @param agent
  76.      *            new user agent string for this running JGit library. Setting
  77.      *            to null or empty string will avoid sending any identification
  78.      *            to the peer.
  79.      */
  80.     public static void set(String agent) {
  81.         userAgent = StringUtils.isEmptyOrNull(agent) ? null : clean(agent);
  82.     }

  83.     /**
  84.      *
  85.      * @param options
  86.      * @param transportAgent
  87.      * @return The transport agent.
  88.      * @deprecated Capabilities with <key>=<value> shape are now parsed
  89.      *             alongside other capabilities in the ReceivePack flow.
  90.      */
  91.     @Deprecated
  92.     static String getAgent(Set<String> options, String transportAgent) {
  93.         if (options == null || options.isEmpty()) {
  94.             return transportAgent;
  95.         }
  96.         for (String o : options) {
  97.             if (o.startsWith(OPTION_AGENT)
  98.                     && o.length() > OPTION_AGENT.length()
  99.                     && o.charAt(OPTION_AGENT.length()) == '=') {
  100.                 return o.substring(OPTION_AGENT.length() + 1);
  101.             }
  102.         }
  103.         return transportAgent;
  104.     }

  105.     /**
  106.      *
  107.      * @param options
  108.      * @return True if the transport agent is set. False otherwise.
  109.      * @deprecated Capabilities with <key>=<value> shape are now parsed
  110.      *             alongside other capabilities in the ReceivePack flow.
  111.      */
  112.     @Deprecated
  113.     static boolean hasAgent(Set<String> options) {
  114.         return getAgent(options, null) != null;
  115.     }

  116.     private UserAgent() {
  117.     }
  118. }