This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch 23034
in repository https://gitbox.apache.org/repos/asf/camel.git

commit d8f26f136dd574de990c5c9a671dc7e2d71da31c
Author: Andrea Cosentino <[email protected]>
AuthorDate: Fri Feb 20 10:16:53 2026 +0100

    CAMEL-23034 - Generalize Google services authentication with common module
    
    Signed-off-by: Andrea Cosentino <[email protected]>
---
 bom/camel-bom/pom.xml                              |   5 +
 catalog/camel-allcomponents/pom.xml                |   5 +
 .../pom.xml                                        |  59 +++--
 .../services/org/apache/camel/other.properties     |   7 +
 .../src/generated/resources/google-common.json     |  15 ++
 .../google/common/GoogleCommonConfiguration.java   |  94 ++++++++
 .../google/common/GoogleCredentialsHelper.java     | 264 +++++++++++++++++++++
 .../camel-google/camel-google-sheets/pom.xml       |   4 +
 .../sheets/BatchGoogleSheetsClientFactory.java     |  62 ++---
 .../google/sheets/GoogleSheetsConfiguration.java   |  10 +-
 .../camel-google/camel-google-storage/pom.xml      |   4 +
 .../storage/GoogleCloudStorageConfiguration.java   |   4 +-
 .../GoogleCloudStorageConnectionFactory.java       |  15 +-
 components/camel-google/pom.xml                    |   1 +
 coverage/pom.xml                                   |   5 +
 .../others/examples/json/google-common.json        |   1 +
 parent/pom.xml                                     |   5 +
 .../camel/maven/packaging/PrepareCatalogMojo.java  |   1 +
 18 files changed, 485 insertions(+), 76 deletions(-)

diff --git a/bom/camel-bom/pom.xml b/bom/camel-bom/pom.xml
index 65ddf1d20781..0fdae66dc14f 100644
--- a/bom/camel-bom/pom.xml
+++ b/bom/camel-bom/pom.xml
@@ -932,6 +932,11 @@
         <artifactId>camel-google-calendar</artifactId>
         <version>4.19.0-SNAPSHOT</version>
       </dependency>
+      <dependency>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>camel-google-common</artifactId>
+        <version>4.19.0-SNAPSHOT</version>
+      </dependency>
       <dependency>
         <groupId>org.apache.camel</groupId>
         <artifactId>camel-google-drive</artifactId>
diff --git a/catalog/camel-allcomponents/pom.xml 
b/catalog/camel-allcomponents/pom.xml
index bf7e786f80e0..1f7ed5f164f9 100644
--- a/catalog/camel-allcomponents/pom.xml
+++ b/catalog/camel-allcomponents/pom.xml
@@ -797,6 +797,11 @@
             <artifactId>camel-google-calendar</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-google-common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-google-drive</artifactId>
diff --git a/components/camel-google/camel-google-storage/pom.xml 
b/components/camel-google/camel-google-common/pom.xml
similarity index 51%
copy from components/camel-google/camel-google-storage/pom.xml
copy to components/camel-google/camel-google-common/pom.xml
index 35a7f57dd982..f7eab363c5c8 100644
--- a/components/camel-google/camel-google-storage/pom.xml
+++ b/components/camel-google/camel-google-common/pom.xml
@@ -27,13 +27,14 @@
         <version>4.19.0-SNAPSHOT</version>
     </parent>
 
-    <artifactId>camel-google-storage</artifactId>
+    <artifactId>camel-google-common</artifactId>
     <packaging>jar</packaging>
-    <name>Camel :: Google :: Storage</name>
-    <description>For storing and accessing data on Google Cloud 
Platform</description>
+    <name>Camel :: Google :: Common</name>
+    <description>Camel Google Common utilities for credential 
initialization</description>
 
     <properties>
-        <camel.surefire.forkTimeout>300</camel.surefire.forkTimeout>
+        <firstVersion>4.19.0</firstVersion>
+        <label>cloud,google</label>
     </properties>
 
     <dependencies>
@@ -42,33 +43,53 @@
             <artifactId>camel-support</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.apache.camel</groupId>
-            <artifactId>camel-health</artifactId>
+            <groupId>com.google.auth</groupId>
+            <artifactId>google-auth-library-oauth2-http</artifactId>
+            <version>${google-auth-library-oauth2-http-version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.google.code.findbugs</groupId>
+                    <artifactId>jsr305</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
         <dependency>
-            <groupId>com.google.cloud</groupId>
-            <artifactId>google-cloud-storage</artifactId>
-            <version>${google-cloud-storage-version}</version>
+            <groupId>com.google.api-client</groupId>
+            <artifactId>google-api-client</artifactId>
+            <version>${google-api-client-version}</version>
             <exclusions>
                 <exclusion>
                     <groupId>com.google.code.findbugs</groupId>
                     <artifactId>jsr305</artifactId>
                 </exclusion>
+                <exclusion>
+                    <groupId>com.google.oauth-client</groupId>
+                    <artifactId>google-oauth-client</artifactId>
+                </exclusion>
             </exclusions>
         </dependency>
-
-        <!-- for testing -->
         <dependency>
-            <groupId>org.apache.camel</groupId>
-            <artifactId>camel-test-junit5</artifactId>
-            <scope>test</scope>
+            <groupId>com.google.oauth-client</groupId>
+            <artifactId>google-oauth-client</artifactId>
+            <version>${google-oauth-client-version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.google.code.findbugs</groupId>
+                    <artifactId>jsr305</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
         <dependency>
-            <groupId>com.google.cloud</groupId>
-            <artifactId>google-cloud-core</artifactId>
-            <version>${google-cloud-core-version}</version>
-            <scope>test</scope>
-            <classifier>tests</classifier>
+            <groupId>com.google.http-client</groupId>
+            <artifactId>google-http-client-jackson2</artifactId>
+            <version>${google-cloud-http-client-version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.google.code.findbugs</groupId>
+                    <artifactId>jsr305</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
     </dependencies>
+
 </project>
diff --git 
a/components/camel-google/camel-google-common/src/generated/resources/META-INF/services/org/apache/camel/other.properties
 
b/components/camel-google/camel-google-common/src/generated/resources/META-INF/services/org/apache/camel/other.properties
new file mode 100644
index 000000000000..4b534cec9013
--- /dev/null
+++ 
b/components/camel-google/camel-google-common/src/generated/resources/META-INF/services/org/apache/camel/other.properties
@@ -0,0 +1,7 @@
+# Generated by camel build tools - do NOT edit this file!
+name=google-common
+groupId=org.apache.camel
+artifactId=camel-google-common
+version=4.19.0-SNAPSHOT
+projectName=Camel :: Google :: Common
+projectDescription=Camel Google Common utilities for credential initialization
diff --git 
a/components/camel-google/camel-google-common/src/generated/resources/google-common.json
 
b/components/camel-google/camel-google-common/src/generated/resources/google-common.json
new file mode 100644
index 000000000000..64da3caea719
--- /dev/null
+++ 
b/components/camel-google/camel-google-common/src/generated/resources/google-common.json
@@ -0,0 +1,15 @@
+{
+  "other": {
+    "kind": "other",
+    "name": "google-common",
+    "title": "Google Common",
+    "description": "Camel Google Common utilities for credential 
initialization",
+    "deprecated": false,
+    "firstVersion": "4.19.0",
+    "label": "cloud,google",
+    "supportLevel": "Preview",
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-google-common",
+    "version": "4.19.0-SNAPSHOT"
+  }
+}
diff --git 
a/components/camel-google/camel-google-common/src/main/java/org/apache/camel/component/google/common/GoogleCommonConfiguration.java
 
b/components/camel-google/camel-google-common/src/main/java/org/apache/camel/component/google/common/GoogleCommonConfiguration.java
new file mode 100644
index 000000000000..d36e10ac558b
--- /dev/null
+++ 
b/components/camel-google/camel-google-common/src/main/java/org/apache/camel/component/google/common/GoogleCommonConfiguration.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.camel.component.google.common;
+
+import java.util.Collection;
+
+/**
+ * Common configuration interface for all Google components.
+ * <p>
+ * Each Google component's Configuration class should implement this interface 
to enable use of the common
+ * {@link GoogleCredentialsHelper} for credential creation.
+ * </p>
+ */
+public interface GoogleCommonConfiguration {
+
+    // ==================== Service Account Credentials ====================
+
+    /**
+     * Service account key file (JSON) for authenticating with Google 
services. Can be loaded from classpath, file
+     * system, or http(s) URL. Prefixes: classpath:, file:, http:, https:
+     */
+    String getServiceAccountKey();
+
+    // ==================== OAuth 2.0 Credentials (for legacy API client) 
====================
+
+    /**
+     * OAuth 2.0 Client ID for the Google application.
+     */
+    default String getClientId() {
+        return null;
+    }
+
+    /**
+     * OAuth 2.0 Client Secret for the Google application.
+     */
+    default String getClientSecret() {
+        return null;
+    }
+
+    /**
+     * OAuth 2.0 access token. This typically expires after an hour so 
refreshToken is recommended for long term usage.
+     */
+    default String getAccessToken() {
+        return null;
+    }
+
+    /**
+     * OAuth 2.0 refresh token. Using this, the component can obtain a new 
accessToken whenever the current one expires.
+     */
+    default String getRefreshToken() {
+        return null;
+    }
+
+    // ==================== Domain-wide Delegation ====================
+
+    /**
+     * User email to impersonate for domain-wide delegation with service 
account.
+     */
+    default String getDelegate() {
+        return null;
+    }
+
+    // ==================== Scopes ====================
+
+    /**
+     * Returns the OAuth scopes as a collection. Used when creating 
credentials.
+     */
+    default Collection<String> getScopesAsList() {
+        return null;
+    }
+
+    // ==================== Authentication Toggle ====================
+
+    /**
+     * Whether to authenticate with Google services. Set to false when using 
emulators (e.g., PubSub emulator).
+     */
+    default boolean isAuthenticate() {
+        return true;
+    }
+}
diff --git 
a/components/camel-google/camel-google-common/src/main/java/org/apache/camel/component/google/common/GoogleCredentialsHelper.java
 
b/components/camel-google/camel-google-common/src/main/java/org/apache/camel/component/google/common/GoogleCredentialsHelper.java
new file mode 100644
index 000000000000..f0d06e31aff1
--- /dev/null
+++ 
b/components/camel-google/camel-google-common/src/main/java/org/apache/camel/component/google/common/GoogleCredentialsHelper.java
@@ -0,0 +1,264 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.camel.component.google.common;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collection;
+
+import com.google.api.client.auth.oauth2.Credential;
+import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
+import com.google.api.client.http.HttpTransport;
+import com.google.api.client.http.javanet.NetHttpTransport;
+import com.google.api.client.json.JsonFactory;
+import com.google.api.client.json.jackson2.JacksonFactory;
+import com.google.auth.Credentials;
+import com.google.auth.oauth2.GoogleCredentials;
+import com.google.auth.oauth2.ServiceAccountCredentials;
+import org.apache.camel.CamelContext;
+import org.apache.camel.support.ResourceHelper;
+import org.apache.camel.util.ObjectHelper;
+
+/**
+ * Utility class providing centralized credential resolution for Google 
services.
+ * <p>
+ * This class handles the common patterns for obtaining Google credentials:
+ * <ul>
+ * <li>Service Account JSON key file (for GCP native clients)</li>
+ * <li>OAuth 2.0 credentials with client ID/secret (for legacy Google API 
clients)</li>
+ * <li>Application Default Credentials (ADC) as fallback</li>
+ * </ul>
+ */
+public final class GoogleCredentialsHelper {
+
+    private static final HttpTransport DEFAULT_HTTP_TRANSPORT = new 
NetHttpTransport();
+    private static final JsonFactory DEFAULT_JSON_FACTORY = new 
JacksonFactory();
+
+    private GoogleCredentialsHelper() {
+        // Utility class - prevent instantiation
+    }
+
+    // ==================== GCP Native Clients (google-cloud-* libraries) 
====================
+
+    /**
+     * Gets credentials for GCP native clients (Storage, Firestore, BigQuery, 
etc.).
+     * <p>
+     * Resolution order:
+     * <ol>
+     * <li>Service Account key file if provided</li>
+     * <li>Application Default Credentials (ADC) as fallback</li>
+     * </ol>
+     *
+     * @param  context     the Camel context for resource resolution
+     * @param  config      the component configuration
+     * @param  scopes      OAuth scopes to apply (optional, used for service 
account)
+     * @return             Google credentials for use with GCP native clients
+     * @throws IOException if credentials cannot be loaded
+     */
+    public static Credentials getCredentials(
+            CamelContext context,
+            GoogleCommonConfiguration config,
+            Collection<String> scopes)
+            throws IOException {
+
+        if (!config.isAuthenticate()) {
+            return null;
+        }
+
+        String serviceAccountKey = config.getServiceAccountKey();
+        if (ObjectHelper.isNotEmpty(serviceAccountKey)) {
+            return loadServiceAccountCredentials(context, serviceAccountKey, 
scopes, config.getDelegate());
+        }
+
+        // Fall back to Application Default Credentials
+        GoogleCredentials credentials = 
GoogleCredentials.getApplicationDefault();
+        if (scopes != null && !scopes.isEmpty()) {
+            credentials = credentials.createScoped(scopes);
+        }
+        return credentials;
+    }
+
+    /**
+     * Gets credentials for GCP native clients using configuration's scopes.
+     *
+     * @param  context     the Camel context for resource resolution
+     * @param  config      the component configuration
+     * @return             Google credentials for use with GCP native clients
+     * @throws IOException if credentials cannot be loaded
+     */
+    public static Credentials getCredentials(
+            CamelContext context,
+            GoogleCommonConfiguration config)
+            throws IOException {
+        return getCredentials(context, config, config.getScopesAsList());
+    }
+
+    // ==================== Legacy Google API Clients (google-api-client 
library) ====================
+
+    /**
+     * Gets OAuth credential for legacy Google API clients (Sheets, Calendar, 
Drive, Mail, etc.).
+     * <p>
+     * Resolution order:
+     * <ol>
+     * <li>OAuth 2.0 credentials if clientId and clientSecret are provided</li>
+     * <li>Service Account key file if provided</li>
+     * </ol>
+     *
+     * @param  context          the Camel context for resource resolution
+     * @param  config           the component configuration
+     * @param  scopes           OAuth scopes to apply
+     * @param  httpTransport    HTTP transport to use (pass null for default)
+     * @param  jsonFactory      JSON factory to use (pass null for default)
+     * @return                  Google credential for use with legacy API 
clients
+     * @throws IOException      if credentials cannot be loaded
+     * @throws RuntimeException if neither OAuth nor service account 
credentials are configured
+     */
+    public static Credential getOAuthCredential(
+            CamelContext context,
+            GoogleCommonConfiguration config,
+            Collection<String> scopes,
+            HttpTransport httpTransport,
+            JsonFactory jsonFactory)
+            throws IOException {
+
+        HttpTransport transport = httpTransport != null ? httpTransport : 
DEFAULT_HTTP_TRANSPORT;
+        JsonFactory factory = jsonFactory != null ? jsonFactory : 
DEFAULT_JSON_FACTORY;
+
+        // Check for OAuth 2.0 credentials first
+        if (hasOAuthCredentials(config)) {
+            return createOAuthCredential(config, scopes, transport, factory);
+        }
+
+        // Check for Service Account credentials
+        String serviceAccountKey = config.getServiceAccountKey();
+        if (ObjectHelper.isNotEmpty(serviceAccountKey)) {
+            return loadServiceAccountAsLegacyCredential(
+                    context, serviceAccountKey, scopes, config.getDelegate(), 
transport, factory);
+        }
+
+        throw new IllegalArgumentException(
+                "Either OAuth credentials (clientId + clientSecret) or 
serviceAccountKey must be provided");
+    }
+
+    /**
+     * Gets OAuth credential for legacy Google API clients using default 
transport and factory.
+     *
+     * @param  context     the Camel context for resource resolution
+     * @param  config      the component configuration
+     * @param  scopes      OAuth scopes to apply
+     * @return             Google credential for use with legacy API clients
+     * @throws IOException if credentials cannot be loaded
+     */
+    public static Credential getOAuthCredential(
+            CamelContext context,
+            GoogleCommonConfiguration config,
+            Collection<String> scopes)
+            throws IOException {
+        return getOAuthCredential(context, config, scopes, null, null);
+    }
+
+    // ==================== Private Helper Methods ====================
+
+    /**
+     * Checks if OAuth 2.0 credentials are configured.
+     */
+    private static boolean hasOAuthCredentials(GoogleCommonConfiguration 
config) {
+        return ObjectHelper.isNotEmpty(config.getClientId())
+                && ObjectHelper.isNotEmpty(config.getClientSecret());
+    }
+
+    /**
+     * Creates OAuth 2.0 credential from client ID, secret, and tokens.
+     */
+    private static Credential createOAuthCredential(
+            GoogleCommonConfiguration config,
+            Collection<String> scopes,
+            HttpTransport transport,
+            JsonFactory jsonFactory) {
+
+        Credential credential = new GoogleCredential.Builder()
+                .setJsonFactory(jsonFactory)
+                .setTransport(transport)
+                .setClientSecrets(config.getClientId(), 
config.getClientSecret())
+                .setServiceAccountScopes(scopes)
+                .build();
+
+        if (ObjectHelper.isNotEmpty(config.getRefreshToken())) {
+            credential.setRefreshToken(config.getRefreshToken());
+        }
+
+        if (ObjectHelper.isNotEmpty(config.getAccessToken())) {
+            credential.setAccessToken(config.getAccessToken());
+        }
+
+        return credential;
+    }
+
+    /**
+     * Loads service account credentials from JSON key file for GCP native 
clients.
+     */
+    private static Credentials loadServiceAccountCredentials(
+            CamelContext context,
+            String serviceAccountKey,
+            Collection<String> scopes,
+            String delegate)
+            throws IOException {
+
+        try (InputStream is = 
ResourceHelper.resolveMandatoryResourceAsInputStream(context, 
serviceAccountKey)) {
+            ServiceAccountCredentials credentials = 
ServiceAccountCredentials.fromStream(is);
+
+            if (scopes != null && !scopes.isEmpty()) {
+                credentials = (ServiceAccountCredentials) 
credentials.createScoped(scopes);
+            }
+
+            if (ObjectHelper.isNotEmpty(delegate)) {
+                credentials = (ServiceAccountCredentials) 
credentials.createDelegated(delegate);
+            }
+
+            return credentials;
+        }
+    }
+
+    /**
+     * Loads service account credentials as legacy GoogleCredential for older 
API clients.
+     */
+    private static Credential loadServiceAccountAsLegacyCredential(
+            CamelContext context,
+            String serviceAccountKey,
+            Collection<String> scopes,
+            String delegate,
+            HttpTransport transport,
+            JsonFactory jsonFactory)
+            throws IOException {
+
+        try (InputStream is = 
ResourceHelper.resolveMandatoryResourceAsInputStream(context, 
serviceAccountKey)) {
+            GoogleCredential credential = GoogleCredential
+                    .fromStream(is, transport, jsonFactory);
+
+            if (scopes != null && !scopes.isEmpty()) {
+                credential = credential.createScoped(scopes);
+            }
+
+            if (ObjectHelper.isNotEmpty(delegate)) {
+                credential = credential.createDelegated(delegate);
+            }
+
+            credential.refreshToken();
+            return credential;
+        }
+    }
+}
diff --git a/components/camel-google/camel-google-sheets/pom.xml 
b/components/camel-google/camel-google-sheets/pom.xml
index 9429cd792b27..bade44021164 100644
--- a/components/camel-google/camel-google-sheets/pom.xml
+++ b/components/camel-google/camel-google-sheets/pom.xml
@@ -43,6 +43,10 @@
     </properties>
 
     <dependencies>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-google-common</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-support</artifactId>
diff --git 
a/components/camel-google/camel-google-sheets/src/main/java/org/apache/camel/component/google/sheets/BatchGoogleSheetsClientFactory.java
 
b/components/camel-google/camel-google-sheets/src/main/java/org/apache/camel/component/google/sheets/BatchGoogleSheetsClientFactory.java
index 8030ae0fb287..777f2a228202 100644
--- 
a/components/camel-google/camel-google-sheets/src/main/java/org/apache/camel/component/google/sheets/BatchGoogleSheetsClientFactory.java
+++ 
b/components/camel-google/camel-google-sheets/src/main/java/org/apache/camel/component/google/sheets/BatchGoogleSheetsClientFactory.java
@@ -16,11 +16,9 @@
  */
 package org.apache.camel.component.google.sheets;
 
-import java.io.IOException;
 import java.util.Collection;
 
 import com.google.api.client.auth.oauth2.Credential;
-import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
 import com.google.api.client.http.HttpTransport;
 import com.google.api.client.http.javanet.NetHttpTransport;
 import com.google.api.client.json.JsonFactory;
@@ -28,8 +26,7 @@ import com.google.api.client.json.jackson2.JacksonFactory;
 import com.google.api.services.sheets.v4.Sheets;
 import org.apache.camel.CamelContext;
 import org.apache.camel.RuntimeCamelException;
-import org.apache.camel.support.ResourceHelper;
-import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.component.google.common.GoogleCredentialsHelper;
 
 public class BatchGoogleSheetsClientFactory implements 
GoogleSheetsClientFactory {
 
@@ -62,7 +59,15 @@ public class BatchGoogleSheetsClientFactory implements 
GoogleSheetsClientFactory
         }
 
         try {
-            Credential credential = authorize(clientId, clientSecret, scopes, 
refreshToken, accessToken);
+            // Create a temporary configuration to use GoogleCredentialsHelper
+            GoogleSheetsConfiguration tempConfig = new 
GoogleSheetsConfiguration();
+            tempConfig.setClientId(clientId);
+            tempConfig.setClientSecret(clientSecret);
+            tempConfig.setRefreshToken(refreshToken);
+            tempConfig.setAccessToken(accessToken);
+
+            Credential credential
+                    = GoogleCredentialsHelper.getOAuthCredential(null, 
tempConfig, scopes, transport, jsonFactory);
 
             Sheets.Builder clientBuilder = new Sheets.Builder(transport, 
jsonFactory, credential)
                     .setApplicationName(applicationName);
@@ -82,28 +87,6 @@ public class BatchGoogleSheetsClientFactory implements 
GoogleSheetsClientFactory
         clientBuilder.setRootUrl(Sheets.DEFAULT_ROOT_URL);
     }
 
-    // Authorizes the installed application to access user's protected data.
-    private Credential authorize(
-            String clientId, String clientSecret, Collection<String> scopes, 
String refreshToken, String accessToken) {
-        // authorize
-        Credential credential = new GoogleCredential.Builder()
-                .setJsonFactory(jsonFactory)
-                .setTransport(transport)
-                .setClientSecrets(clientId, clientSecret)
-                .setServiceAccountScopes(scopes)
-                .build();
-
-        if (ObjectHelper.isNotEmpty(refreshToken)) {
-            credential.setRefreshToken(refreshToken);
-        }
-
-        if (ObjectHelper.isNotEmpty(accessToken)) {
-            credential.setAccessToken(accessToken);
-        }
-
-        return credential;
-    }
-
     @Override
     public Sheets makeClient(
             CamelContext camelContext, String serviceAccountKey, 
Collection<String> scopes, String applicationName,
@@ -112,27 +95,16 @@ public class BatchGoogleSheetsClientFactory implements 
GoogleSheetsClientFactory
             throw new IllegalArgumentException("serviceAccountKey is required 
to create Google Sheets client.");
         }
         try {
-            Credential credential = authorizeServiceAccount(camelContext, 
serviceAccountKey, delegate, scopes);
+            // Create a temporary configuration to use GoogleCredentialsHelper
+            GoogleSheetsConfiguration tempConfig = new 
GoogleSheetsConfiguration();
+            tempConfig.setServiceAccountKey(serviceAccountKey);
+            tempConfig.setDelegate(delegate);
+
+            Credential credential
+                    = GoogleCredentialsHelper.getOAuthCredential(camelContext, 
tempConfig, scopes, transport, jsonFactory);
             return new Sheets.Builder(transport, jsonFactory, 
credential).setApplicationName(applicationName).build();
         } catch (Exception e) {
             throw new RuntimeCamelException("Could not create Google Sheets 
client.", e);
         }
     }
-
-    private Credential authorizeServiceAccount(
-            CamelContext camelContext, String serviceAccountKey, String 
delegate, Collection<String> scopes) {
-        // authorize
-        try {
-            GoogleCredential cred = GoogleCredential
-                    
.fromStream(ResourceHelper.resolveMandatoryResourceAsInputStream(camelContext, 
serviceAccountKey),
-                            transport,
-                            jsonFactory)
-                    .createScoped(scopes != null && !scopes.isEmpty() ? scopes 
: null)
-                    .createDelegated(delegate);
-            cred.refreshToken();
-            return cred;
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
 }
diff --git 
a/components/camel-google/camel-google-sheets/src/main/java/org/apache/camel/component/google/sheets/GoogleSheetsConfiguration.java
 
b/components/camel-google/camel-google-sheets/src/main/java/org/apache/camel/component/google/sheets/GoogleSheetsConfiguration.java
index eb2db1f9be1a..99fc3de93fb3 100644
--- 
a/components/camel-google/camel-google-sheets/src/main/java/org/apache/camel/component/google/sheets/GoogleSheetsConfiguration.java
+++ 
b/components/camel-google/camel-google-sheets/src/main/java/org/apache/camel/component/google/sheets/GoogleSheetsConfiguration.java
@@ -19,6 +19,7 @@ package org.apache.camel.component.google.sheets;
 import java.util.Collection;
 import java.util.List;
 
+import org.apache.camel.component.google.common.GoogleCommonConfiguration;
 import org.apache.camel.component.google.sheets.internal.GoogleSheetsApiName;
 import org.apache.camel.spi.Configurer;
 import org.apache.camel.spi.Metadata;
@@ -32,7 +33,7 @@ import 
org.apache.camel.support.component.AbstractApiConfiguration;
  */
 @UriParams
 @Configurer(extended = true)
-public class GoogleSheetsConfiguration extends AbstractApiConfiguration {
+public class GoogleSheetsConfiguration extends AbstractApiConfiguration 
implements GoogleCommonConfiguration {
 
     @UriPath
     @Metadata(required = true)
@@ -80,6 +81,7 @@ public class GoogleSheetsConfiguration extends 
AbstractApiConfiguration {
         this.methodName = methodName;
     }
 
+    @Override
     public String getClientId() {
         return clientId;
     }
@@ -91,6 +93,7 @@ public class GoogleSheetsConfiguration extends 
AbstractApiConfiguration {
         this.clientId = clientId;
     }
 
+    @Override
     public String getClientSecret() {
         return clientSecret;
     }
@@ -102,6 +105,7 @@ public class GoogleSheetsConfiguration extends 
AbstractApiConfiguration {
         this.clientSecret = clientSecret;
     }
 
+    @Override
     public String getAccessToken() {
         return accessToken;
     }
@@ -113,6 +117,7 @@ public class GoogleSheetsConfiguration extends 
AbstractApiConfiguration {
         this.accessToken = accessToken;
     }
 
+    @Override
     public String getRefreshToken() {
         return refreshToken;
     }
@@ -140,6 +145,7 @@ public class GoogleSheetsConfiguration extends 
AbstractApiConfiguration {
         return scopes;
     }
 
+    @Override
     public Collection<String> getScopesAsList() {
         if (scopes != null) {
             return List.of(scopes.split(","));
@@ -159,6 +165,7 @@ public class GoogleSheetsConfiguration extends 
AbstractApiConfiguration {
         this.scopes = scopes;
     }
 
+    @Override
     public String getServiceAccountKey() {
         return serviceAccountKey;
     }
@@ -172,6 +179,7 @@ public class GoogleSheetsConfiguration extends 
AbstractApiConfiguration {
         this.serviceAccountKey = serviceAccountKey;
     }
 
+    @Override
     public String getDelegate() {
         return delegate;
     }
diff --git a/components/camel-google/camel-google-storage/pom.xml 
b/components/camel-google/camel-google-storage/pom.xml
index 35a7f57dd982..52be90a96b78 100644
--- a/components/camel-google/camel-google-storage/pom.xml
+++ b/components/camel-google/camel-google-storage/pom.xml
@@ -37,6 +37,10 @@
     </properties>
 
     <dependencies>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-google-common</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-support</artifactId>
diff --git 
a/components/camel-google/camel-google-storage/src/main/java/org/apache/camel/component/google/storage/GoogleCloudStorageConfiguration.java
 
b/components/camel-google/camel-google-storage/src/main/java/org/apache/camel/component/google/storage/GoogleCloudStorageConfiguration.java
index 3447e3d535b2..d367a1c260b6 100644
--- 
a/components/camel-google/camel-google-storage/src/main/java/org/apache/camel/component/google/storage/GoogleCloudStorageConfiguration.java
+++ 
b/components/camel-google/camel-google-storage/src/main/java/org/apache/camel/component/google/storage/GoogleCloudStorageConfiguration.java
@@ -19,13 +19,14 @@ package org.apache.camel.component.google.storage;
 import com.google.cloud.storage.Storage;
 import com.google.cloud.storage.StorageClass;
 import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.google.common.GoogleCommonConfiguration;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.UriParam;
 import org.apache.camel.spi.UriParams;
 import org.apache.camel.spi.UriPath;
 
 @UriParams
-public class GoogleCloudStorageConfiguration implements Cloneable {
+public class GoogleCloudStorageConfiguration implements Cloneable, 
GoogleCommonConfiguration {
 
     @UriPath(label = "common", description = "Bucket name or ARN")
     @Metadata(required = true)
@@ -94,6 +95,7 @@ public class GoogleCloudStorageConfiguration implements 
Cloneable {
         this.bucketName = bucketName;
     }
 
+    @Override
     public String getServiceAccountKey() {
         return serviceAccountKey;
     }
diff --git 
a/components/camel-google/camel-google-storage/src/main/java/org/apache/camel/component/google/storage/GoogleCloudStorageConnectionFactory.java
 
b/components/camel-google/camel-google-storage/src/main/java/org/apache/camel/component/google/storage/GoogleCloudStorageConnectionFactory.java
index b26829ad5863..255dc31c4038 100644
--- 
a/components/camel-google/camel-google-storage/src/main/java/org/apache/camel/component/google/storage/GoogleCloudStorageConnectionFactory.java
+++ 
b/components/camel-google/camel-google-storage/src/main/java/org/apache/camel/component/google/storage/GoogleCloudStorageConnectionFactory.java
@@ -16,14 +16,11 @@
  */
 package org.apache.camel.component.google.storage;
 
-import java.io.InputStream;
-
-import com.google.api.client.util.Strings;
-import com.google.auth.oauth2.ServiceAccountCredentials;
+import com.google.auth.Credentials;
 import com.google.cloud.storage.Storage;
 import com.google.cloud.storage.StorageOptions;
 import org.apache.camel.CamelContext;
-import org.apache.camel.support.ResourceHelper;
+import org.apache.camel.component.google.common.GoogleCredentialsHelper;
 
 public final class GoogleCloudStorageConnectionFactory {
 
@@ -34,12 +31,10 @@ public final class GoogleCloudStorageConnectionFactory {
     }
 
     public static Storage create(CamelContext context, 
GoogleCloudStorageConfiguration configuration) throws Exception {
-        if (!Strings.isNullOrEmpty(configuration.getServiceAccountKey())) {
-            InputStream resolveMandatoryResourceAsInputStream
-                    = 
ResourceHelper.resolveMandatoryResourceAsInputStream(context, 
configuration.getServiceAccountKey());
+        Credentials credentials = 
GoogleCredentialsHelper.getCredentials(context, configuration);
+        if (credentials != null) {
             return StorageOptions.newBuilder()
-                    .setCredentials(
-                            
ServiceAccountCredentials.fromStream(resolveMandatoryResourceAsInputStream))
+                    .setCredentials(credentials)
                     .build().getService();
         } else {
             return StorageOptions.getDefaultInstance().getService();
diff --git a/components/camel-google/pom.xml b/components/camel-google/pom.xml
index 2c8f4aed82dd..e3a06bf48f3c 100644
--- a/components/camel-google/pom.xml
+++ b/components/camel-google/pom.xml
@@ -33,6 +33,7 @@
     <description>Camel AWS parent</description>
 
     <modules>
+        <module>camel-google-common</module>
         <module>camel-google-bigquery</module>
         <module>camel-google-calendar</module>
         <module>camel-google-drive</module>
diff --git a/coverage/pom.xml b/coverage/pom.xml
index f10f3694e522..3d7774b4ce4e 100644
--- a/coverage/pom.xml
+++ b/coverage/pom.xml
@@ -952,6 +952,11 @@
             <artifactId>camel-google-bigquery</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-google-common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-google-calendar</artifactId>
diff --git a/docs/components/modules/others/examples/json/google-common.json 
b/docs/components/modules/others/examples/json/google-common.json
new file mode 120000
index 000000000000..70db88c13f20
--- /dev/null
+++ b/docs/components/modules/others/examples/json/google-common.json
@@ -0,0 +1 @@
+../../../../../../components/camel-google/camel-google-common/src/generated/resources/google-common.json
\ No newline at end of file
diff --git a/parent/pom.xml b/parent/pom.xml
index 2123c943000a..f841fa70d097 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -1479,6 +1479,11 @@
                 <artifactId>camel-google-calendar</artifactId>
                 <version>${project.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.apache.camel</groupId>
+                <artifactId>camel-google-common</artifactId>
+                <version>${project.version}</version>
+            </dependency>
             <dependency>
                 <groupId>org.apache.camel</groupId>
                 <artifactId>camel-google-drive</artifactId>
diff --git 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogMojo.java
 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogMojo.java
index d80e467c58b3..5bf533453e72 100644
--- 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogMojo.java
+++ 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogMojo.java
@@ -932,6 +932,7 @@ public class PrepareCatalogMojo extends AbstractMojo {
                 case "camel-debezium-common":
                 case "camel-fhir":
                 case "camel-google":
+                case "camel-google-common":
                 case "camel-http-base":
                 case "camel-http-common":
                 case "camel-huawei":


Reply via email to