= Google Storage Component
:doctitle: Google Storage
:shortname: google-storage
:artifactid: camel-google-storage
:description: Store and retrieve objects from Google Cloud Storage Service using the google-cloud-storage library.
:since: 3.9
:supportlevel: Stable
:component-header: Both producer and consumer are supported
//Manually maintained attributes
:group: Google
:camel-spring-boot-name: google-storage

*Since Camel {since}*

*{component-header}*

The Google Storage component provides access to https://cloud.google.com/storage/[Google Cloud Storage] via
the https://github.com/googleapis/java-storage[google java storage library].

Maven users will need to add the following dependency to their pom.xml
for this component:

[source,xml]
------------------------------------------------------
<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-google-storage</artifactId>
    <!-- use the same version as your Camel core version -->
    <version>x.x.x</version>
</dependency>
------------------------------------------------------

[[GoogleStorage-AuthenticationConfiguration]]

== Authentication Configuration

Google Storage component authentication is targeted for use with the GCP Service Accounts.
For more information please refer to https://cloud.google.com/storage/docs/reference/libraries#setting_up_authentication[Google Storage Auth Guide].

When you have the **service account key** you can provide authentication credentials to your application code.
Google security credentials can be set through the component endpoint:

[source,java]
--------------------------------------------------------
String endpoint = "google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json";
--------------------------------------------------------

Or by providing the path to the GCP credentials file location:

Provide authentication credentials to your application code by setting the environment variable `GOOGLE_APPLICATION_CREDENTIALS` :

--------------------------------------------------------
export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/my-key.json"
--------------------------------------------------------


== URI Format

--------------------------------------------------------
google-storage://bucketNameOrArn?[options]
--------------------------------------------------------

By default the bucket will be created if it don't already exists. +
You can append query options to the URI in the following format,
?options=value&option2=value&...

For example in order to read file `hello.txt` from bucket `myCamelBucket`, use the following snippet:

[source,java]
--------------------------------------------------------------------------------
from("google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json&objectName=hello.txt")
  .to("file:/var/downloaded");
--------------------------------------------------------------------------------


// component-configure options: START

// component-configure options: END

// component options: START
include::partial$component-configure-options.adoc[]
include::partial$component-endpoint-options.adoc[]
// component options: END

// endpoint options: START

// endpoint options: END


== Usage

=== Message headers evaluated by the Google Storage Producer

[width="100%",cols="10%,10%,80%",options="header",]
|=======================================================================
|Header |Type |Description

|`CamelGoogleCloudStorageBucketName` |`String` |The bucket Name which this object will be stored or which will be used for the current operation

|`CamelGoogleCloudStorageObjectName` |`String` |The object Name which will be used for the current operation

|`CamelGoogleCloudStorageDestinationBucketName` |`String` |The bucket Destination Name which will be used for the current operation

|`CamelGoogleCloudStorageDestinationObjectName` |`String` |The object Destination Name which will be used for the current operation

|`CamelGoogleCloudStorageContentLength` |`Long` |The content length of this object.

|`CamelGoogleCloudStorageContentType` |`String` |The content type of this object.

|`CamelGoogleCloudStorageContentDisposition` |`String` |The content disposition of this object.

|`CamelGoogleCloudStorageContentEncoding` |`String` |The content encoding of this object.

|`CamelGoogleCloudStorageContentMd5` |`String` |The md5 checksum of this object.

|`CamelGoogleCloudStorageOperation` |`String` |The operation to perform. Permitted values are copyObject, listObjects, deleteObject, deleteBucket, listBuckets, getObject, createDownloadLink

|`CamelGoogleCloudStorageDownloadLinkExpirationTime` |`Long` |The time in millisecond the download link will be valid.

|=======================================================================

=== Message headers set by the Google Storage Producer

[width="100%",cols="10%,10%,80%",options="header",]
|=======================================================================
|Header |Type |Description

|`CamelGoogleCloudStorageETag` |`String` |The ETag value for the newly uploaded object.

|=======================================================================

=== Message headers set by the Google Storage Consumer

[width="100%",cols="10%,10%,80%",options="header",]
|=======================================================================
|Header |Type |Description
|`CamelGoogleCloudStorageBucketName` |`String` |The bucket Name which this object will be stored or which will be used for the current operation
|`CamelGoogleCloudStorageObjectName` |`String` |The object Name which will be used for the current operation
| `CamelGoogleCloudStorageCacheControl` |`String` | The Cache-Control metadata can specify two different aspects of how data is served from Cloud Storage: whether the data can be cached and whether the data can be transformed
| `CamelGoogleCloudStorageComponentCount` |`String` | The component count of this object
| `CamelGoogleCloudStorageContentDisposition` |`String` |The content disposition of this object.
| `CamelGoogleCloudStorageContentEncoding` |`String` |The content encoding of this object.
| `CamelGoogleCloudStorageContentLanguage` |`String` | The Content-Language metadata indicates the language(s) that the object is intended for.
| `CamelGoogleCloudStorageContentType` |`String` |The content type of this object.
| `CamelGoogleCloudStorageCustomTime` |`String` | The Custom-Time metadata is a user-specified date and time represented in the RFC 3339 format YYYY-MM-DD'T'HH:MM:SS.SS'Z' or YYYY-MM-DD'T'HH:MM:SS'Z' when milliseconds are zero. This metadata is typically set in order to use the DaysSinceCustomTime condition in Object Lifecycle Management.
| `CamelGoogleCloudStorageCrc32cHex` |`String` | The CRC32c of the object
| `CamelGoogleCloudStorageETag` |`String` | The ETag for the Object.
| `CamelGoogleCloudStorageGeneration` |`String` | Is the generation number of the object for which you are retrieving information.
| `CamelGoogleCloudStorageBlobId` |`String` | The blob id of the object
| `CamelGoogleCloudStorageKmsKeyName` |`String` | The KMS key name
| `CamelGoogleCloudStorageContentMd5` |`String` |The md5 checksum of this object.
| `CamelGoogleCloudStorageMediaLink` |`String` | The media link
| `CamelGoogleCloudStorageMetageneration` | `String` | The metageneration of the object
| `CamelGoogleCloudStorageContentLength` |`Long` |The content length of this object.
| `CamelGoogleCloudStorageStorageClass` | `String` | The storage class of the object
| `CamelGoogleCloudStorageCreateTime` |`String` | The creation time of the object
| `CamelGoogleCloudStorageLastUpdate` |`String` | The last update of the object
|=======================================================================

=== Google Storage Producer operations

Google Storage component provides the following operation on the producer side:

- copyObject
- listObjects
- deleteObject
- deleteBucket
- listBuckets
- getObject
- createDownloadLink

If you don't specify an operation explicitly the producer will a file upload.

=== Advanced component configuration

If you need to have more control over the `storageClient` instance configuration, you can create your own instance and refer to it in your Camel google-storage component configuration:

[source,java]
--------------------------------------------------------------------------------
from("google-storage://myCamelBucket?storageClient=#client")
.to("mock:result");
--------------------------------------------------------------------------------

=== Google Storage Producer Operation examples

- File Upload: This operation will upload a file to the Google Storage based on the body content

[source,java]
--------------------------------------------------------------------------------
//upload a file
byte[] payload = "Camel rocks!".getBytes();
ByteArrayInputStream bais = new ByteArrayInputStream(payload);
from("direct:start")
.process( exchange -> {
    exchange.getIn().setHeader(GoogleCloudStorageConstants.OBJECT_NAME, "camel.txt");
    exchange.getIn().setBody(bais);    
})
.to("google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json")
.log("uploaded file object:${header.CamelGoogleCloudStorageObjectName}, body:${body}");
--------------------------------------------------------------------------------

This operation will upload the file camel.txt with the content "Camel rocks!" in the myCamelBucket bucket

- CopyObject: this operation copy an object from one bucket to a different one

[source,java]
--------------------------------------------------------------------------------
  from("direct:start").process( exchange -> {
    exchange.getIn().setHeader(GoogleCloudStorageConstants.OPERATION, GoogleCloudStorageOperations.copyObject);
    exchange.getIn().setHeader(GoogleCloudStorageConstants.OBJECT_NAME, "camel.txt" );
    exchange.getIn().setHeader(GoogleCloudStorageConstants.DESTINATION_BUCKET_NAME, "myCamelBucket_dest");
    exchange.getIn().setHeader(GoogleCloudStorageConstants.DESTINATION_OBJECT_NAME, "camel_copy.txt");
  })
  .to("google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json")
  .to("mock:result");
--------------------------------------------------------------------------------

This operation will copy the object with the name expressed in the header DESTINATION_OBJECT_NAME to the DESTINATION_BUCKET_NAME bucket, from the bucket myCamelBucket.

- DeleteObject: this operation deletes an object from a bucket

[source,java]
--------------------------------------------------------------------------------
  from("direct:start").process( exchange -> {
    exchange.getIn().setHeader(GoogleCloudStorageConstants.OPERATION, GoogleCloudStorageOperations.deleteObject);
    exchange.getIn().setHeader(GoogleCloudStorageConstants.OBJECT_NAME, "camel.txt" );
  })
  .to("google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json")
  .to("mock:result");
--------------------------------------------------------------------------------

This operation will delete the object from the bucket myCamelBucket.

- ListBuckets: this operation list the buckets for this account in this region

[source,java]
--------------------------------------------------------------------------------
from("direct:start")
.to("google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json&operation=listBuckets")
.to("mock:result");
--------------------------------------------------------------------------------

This operation will list the buckets for this account.

- DeleteBucket: this operation delete the bucket specified as URI parameter or header

[source,java]
--------------------------------------------------------------------------------
from("direct:start")
.to("google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json&operation=deleteBucket")
.to("mock:result");
--------------------------------------------------------------------------------

This operation will delete the bucket myCamelBucket.

- ListObjects: this operation list object in a specific bucket

[source,java]
--------------------------------------------------------------------------------
from("direct:start")
.to("google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json&operation=listObjects")
.to("mock:result");
--------------------------------------------------------------------------------

This operation will list the objects in the myCamelBucket bucket.

- GetObject: this operation get a single object in a specific bucket

[source,java]
--------------------------------------------------------------------------------
from("direct:start")
.process( exchange -> {
  exchange.getIn().setHeader(GoogleCloudStorageConstants.OBJECT_NAME, "camel.txt");
})
.to("google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json&operation=getObject")
.to("mock:result");
--------------------------------------------------------------------------------

This operation will return an Blob objct instance related to the OBJECT_NAME object in myCamelBucket bucket.

- CreateDownloadLink: this operation will return a download link

[source,java]
--------------------------------------------------------------------------------
from("direct:start")
.process( exchange -> {
  exchange.getIn().setHeader(GoogleCloudStorageConstants.OBJECT_NAME, "camel.txt" );
  exchange.getIn().setHeader(GoogleCloudStorageConstants.DOWNLOAD_LINK_EXPIRATION_TIME, 86400000L); //1 day
})
.to("google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json&operation=createDownloadLink")
.to("mock:result");
--------------------------------------------------------------------------------

This operation will return a download link url for the file OBJECT_NAME in the bucket myCamelBucket. It's possible to specify the expiration time for the created link through the header DOWNLOAD_LINK_EXPIRATION_TIME. If not specified, by default it is 5 minutes.

== Bucket Autocreation

With the option `autoCreateBucket` users are able to avoid the autocreation of a Bucket in case it doesn't exist. The default for this option is `true`.
If set to false any operation on a not-existent bucket won't be successful and an error will be returned.

== MoveAfterRead consumer option

In addition to deleteAfterRead it has been added another option, moveAfterRead. With this option enabled the consumed object will be moved to a target destinationBucket instead of being only deleted.
This will require specifying the destinationBucket option. As example:

[source,java]
--------------------------------------------------------------------------------
  from("google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json"
    + "&autoCreateBucket=true"
    + "&destinationBucket=myCamelProcessedBucket"
    + "&moveAfterRead=true"
    + "&deleteAfterRead=true"
    + "&includeBody=true"
  )
  .to("mock:result");
--------------------------------------------------------------------------------

In this case the objects consumed will be moved to myCamelProcessedBucket bucket and deleted from the original one (because of deleteAfterRead).


include::spring-boot:partial$starter.adoc[]
