4040import java .lang .reflect .Method ;
4141import java .net .HttpURLConnection ;
4242import java .net .URL ;
43+ import java .util .Enumeration ;
4344import java .util .Locale ;
4445import java .util .Objects ;
4546import java .util .ServiceLoader ;
4647import java .util .Set ;
48+ import java .util .jar .Attributes ;
49+ import java .util .jar .JarFile ;
50+ import java .util .jar .Manifest ;
4751import java .util .regex .Matcher ;
4852import java .util .regex .Pattern ;
4953
@@ -56,6 +60,11 @@ public abstract class ServiceOptions<
5660 private static final String DEFAULT_HOST = "https://www.googleapis.com" ;
5761 private static final long serialVersionUID = 1203687993961393350L ;
5862 private static final String PROJECT_ENV_NAME = "GCLOUD_PROJECT" ;
63+ private static final String MANIFEST_ARTIFACT_ID_KEY = "artifactId" ;
64+ private static final String MANIFEST_VERSION_KEY = "Implementation-Version" ;
65+ private static final String ARTIFACT_ID = "gcloud-java-core" ;
66+ private static final String APPLICATION_BASE_NAME = "gcloud-java" ;
67+ private static final String APPLICATION_NAME = getApplicationName ();
5968
6069 private final String projectId ;
6170 private final String host ;
@@ -522,6 +531,13 @@ public Clock clock() {
522531 return clock ;
523532 }
524533
534+ /**
535+ * Returns the application's name as a string in the format {@code gcloud-java/[version]}.
536+ */
537+ public String applicationName () {
538+ return APPLICATION_NAME ;
539+ }
540+
525541 protected int baseHashCode () {
526542 return Objects .hash (projectId , host , httpTransportFactoryClassName , authCredentialsState ,
527543 retryParams , serviceFactoryClassName , serviceRpcFactoryClassName , connectTimeout ,
@@ -568,4 +584,23 @@ private static <T> T newInstance(String className) throws IOException, ClassNotF
568584 private static <T > T getFromServiceLoader (Class <? extends T > clazz , T defaultInstance ) {
569585 return Iterables .getFirst (ServiceLoader .load (clazz ), defaultInstance );
570586 }
587+
588+ private static String getApplicationName () {
589+ String version = null ;
590+ try {
591+ Enumeration <URL > resources =
592+ ServiceOptions .class .getClassLoader ().getResources (JarFile .MANIFEST_NAME );
593+ while (resources .hasMoreElements () && version == null ) {
594+ Manifest manifest = new Manifest (resources .nextElement ().openStream ());
595+ Attributes manifestAttributes = manifest .getMainAttributes ();
596+ String artifactId = manifestAttributes .getValue (MANIFEST_ARTIFACT_ID_KEY );
597+ if (artifactId != null && artifactId .equals (ARTIFACT_ID )) {
598+ version = manifestAttributes .getValue (MANIFEST_VERSION_KEY );
599+ }
600+ }
601+ } catch (IOException e ) {
602+ // ignore
603+ }
604+ return version != null ? APPLICATION_BASE_NAME + "/" + version : APPLICATION_BASE_NAME ;
605+ }
571606}
0 commit comments