View Javadoc
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  
11  package org.eclipse.jgit.transport;
12  
13  import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_AGENT;
14  
15  import java.util.Set;
16  
17  import org.eclipse.jgit.util.StringUtils;
18  
19  /**
20   * User agent to be reported by this JGit client and server on the network.
21   * <p>
22   * On HTTP transports this user agent string is always supplied by the JGit
23   * client in the {@code User-Agent} HTTP header.
24   * <p>
25   * On native transports this user agent string is always sent when JGit is a
26   * server. When JGit is a client the user agent string will be supplied to the
27   * remote server only if the remote server advertises its own agent identity.
28   *
29   * @since 4.0
30   */
31  public class UserAgent {
32  	private static volatile String userAgent = computeUserAgent();
33  
34  	private static String computeUserAgent() {
35  		return clean("JGit/" + computeVersion()); //$NON-NLS-1$
36  	}
37  
38  	private static String computeVersion() {
39  		Package pkg = UserAgent.class.getPackage();
40  		if (pkg != null) {
41  			String ver = pkg.getImplementationVersion();
42  			if (!StringUtils.isEmptyOrNull(ver)) {
43  				return ver;
44  			}
45  		}
46  		return "unknown"; //$NON-NLS-1$
47  	}
48  
49  	static String clean(String s) {
50  		s = s.trim();
51  		StringBuilder b = new StringBuilder(s.length());
52  		for (int i = 0; i < s.length(); i++) {
53  			char c = s.charAt(i);
54  			if (c <= 32 || c >= 127) {
55  				if (b.length() > 0 && b.charAt(b.length() - 1) == '.')
56  					continue;
57  				c = '.';
58  			}
59  			b.append(c);
60  		}
61  		return b.length() > 0 ? b.toString() : null;
62  	}
63  
64  	/**
65  	 * Get the user agent string advertised by JGit.
66  	 *
67  	 * @return a string similar to {@code "JGit/4.0"}; null if the agent has
68  	 *         been cleared and should not be shared with a peer.
69  	 */
70  	public static String get() {
71  		return userAgent;
72  	}
73  
74  	/**
75  	 * Change the user agent string advertised by JGit.
76  	 * <p>
77  	 * The new string should start with {@code "JGit/"} (for example
78  	 * {@code "JGit/4.0"}) to advertise the implementation as JGit based.
79  	 * <p>
80  	 * Spaces and other whitespace should be avoided as these will be
81  	 * automatically converted to {@code "."}.
82  	 * <p>
83  	 * User agent strings are restricted to printable ASCII.
84  	 *
85  	 * @param agent
86  	 *            new user agent string for this running JGit library. Setting
87  	 *            to null or empty string will avoid sending any identification
88  	 *            to the peer.
89  	 */
90  	public static void set(String agent) {
91  		userAgent = StringUtils.isEmptyOrNull(agent) ? null : clean(agent);
92  	}
93  
94  	static String getAgent(Set<String> options, String transportAgent) {
95  		if (options == null || options.isEmpty()) {
96  			return transportAgent;
97  		}
98  		for (String o : options) {
99  			if (o.startsWith(OPTION_AGENT)
100 					&& o.length() > OPTION_AGENT.length()
101 					&& o.charAt(OPTION_AGENT.length()) == '=') {
102 				return o.substring(OPTION_AGENT.length() + 1);
103 			}
104 		}
105 		return transportAgent;
106 	}
107 
108 	static boolean hasAgent(Set<String> options) {
109 		return getAgent(options, null) != null;
110 	}
111 
112 	private UserAgent() {
113 	}
114 }