Skip to content

Commit cc43524

Browse files
radeusgdfarmaazon
authored andcommitted
Fix Google API issues with Native Image (#12817)
Inner classes do not play too well with Native Image. Rewritten to only call methods on top-level classes that are explicitly `polyglot java import`ed so they are available for reflection in NI mode.
1 parent 844b5a7 commit cc43524

File tree

5 files changed

+88
-68
lines changed

5 files changed

+88
-68
lines changed

distribution/lib/Standard/Google_Api/0.0.0-dev/docs/api/Google_Sheets.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
- type Google_Api_Error
44
- Error message:Standard.Base.Any.Any cause:Standard.Base.Any.Any
55
- type Google_Sheets
6-
- Service java_service:Standard.Base.Any.Any
7-
- get_table self sheet_id:Standard.Base.Any.Any sheet_range:Standard.Base.Any.Any -> Standard.Base.Any.Any
6+
- get_sheet_names self workbook_id:Standard.Base.Data.Text.Text -> Standard.Base.Any.Any
7+
- get_table self workbook_id:Standard.Base.Data.Text.Text sheet_range:Standard.Base.Data.Text.Text -> Standard.Table.Table.Table
88
- initialize credentials:Standard.Base.Any.Any -> Standard.Base.Any.Any

distribution/lib/Standard/Google_Api/0.0.0-dev/src/Google_Sheets.enso

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
11
from Standard.Base import all
22
import Standard.Base.Data.Array_Proxy.Array_Proxy
33
import Standard.Base.Metadata.Display
4-
from Standard.Base.Metadata import make_single_choice, Widget
5-
from Standard.Base.Metadata.Widget import Single_Choice, Vector_Editor
4+
from Standard.Base.Metadata import make_single_choice
65
from Standard.Base.Enso_Cloud.Enso_Secret import as_credential_reference
76

87
from Standard.Table import Table
98

109
polyglot java import java.io.IOException
1110

12-
polyglot java import org.enso.google.GoogleSheetsHelpers
11+
polyglot java import org.enso.google.GoogleSheetsForEnso
1312
polyglot java import org.enso.google.WrappedGoogleCredentials
1413

1514
type Google_Sheets
1615
## PRIVATE
17-
Service java_service
16+
private Service java_service
1817

1918
## ICON cloud
2019
Initializes the Google Sheets instance using the given credentials file.
@@ -25,21 +24,26 @@ type Google_Sheets
2524
Google Admin Console when generating a key.
2625
initialize : File|Enso_Secret -> Google_Sheets
2726
initialize credentials =
28-
service = GoogleSheetsHelpers.createService (_wrap_credentials credentials)
27+
service = GoogleSheetsForEnso.create (_wrap_credentials credentials)
2928
Google_Sheets.Service service
3029

30+
## PRIVATE
31+
get_sheet_names self (workbook_id : Text) =
32+
_handle_exceptions <|
33+
self.java_service.getSheetNames workbook_id
34+
3135
## ICON data_input
3236
Gets a table with the given ID and sheet range.
3337

3438
Arguments:
35-
- sheet_id: the ID of the downloaded spreadsheet. It can be read from the
39+
- workbook_id: the ID of the downloaded spreadsheet. It can be read from the
3640
spreadsheet URL.
3741
- sheet_range: specifies the sheet and cell range to read, e.g.
3842
`'Sheet1!A1:B7'`.
39-
get_table : Text -> Text -> Table
40-
get_table self sheet_id sheet_range =
43+
@sheet_range _make_sheet_name_widget
44+
get_table self (workbook_id : Text) (sheet_range : Text) -> Table =
4145
values = _handle_exceptions <|
42-
self.java_service.getSheetRange sheet_id sheet_range
46+
self.java_service.getSheetRange workbook_id sheet_range
4347
# The first entry is the column name (A, B, ...) and the rest are the values.
4448
column_vectors = values.map v-> [v.first, v.drop 1]
4549
# The column lengths may not necessarily be the same, but Table.new expects the same lengths, so we normalize:
@@ -58,8 +62,14 @@ private _handle_exceptions ~action =
5862
private _wrap_credentials credential:File|Enso_Secret =
5963
case credential of
6064
secret : Enso_Secret ->
61-
WrappedGoogleCredentials.SecretCredentials.new (as_credential_reference secret)
65+
WrappedGoogleCredentials.fromCredentialReference (as_credential_reference secret)
6266
secret_file : File ->
6367
secret_file.with_input_stream [File_Access.Read] stream->
6468
stream.with_java_stream java_input_stream->
65-
WrappedGoogleCredentials.LocalFileCredentials.fromStream java_input_stream
69+
WrappedGoogleCredentials.fromStream java_input_stream
70+
71+
private _make_sheet_name_widget service:Google_Sheets cache=Nothing =
72+
workbook_id = cache.if_not_nothing <| cache "workbook_id"
73+
sheet_names = if workbook_id.is_nothing || workbook_id == "" then [] else
74+
service.get_sheet_names workbook_id
75+
make_single_choice sheet_names display=..Always
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package org.enso.google;
2+
3+
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
4+
import com.google.api.client.json.gson.GsonFactory;
5+
import com.google.api.services.sheets.v4.Sheets;
6+
import com.google.api.services.sheets.v4.SheetsScopes;
7+
import com.google.auth.http.HttpCredentialsAdapter;
8+
import java.io.IOException;
9+
import java.security.GeneralSecurityException;
10+
import java.util.List;
11+
12+
public class GoogleSheetsForEnso {
13+
14+
private final Sheets service;
15+
16+
private GoogleSheetsForEnso(Sheets service) {
17+
this.service = service;
18+
}
19+
20+
public static GoogleSheetsForEnso create(WrappedGoogleCredentials credentials)
21+
throws GeneralSecurityException, IOException {
22+
var credentialsAdapter =
23+
new HttpCredentialsAdapter(
24+
CredentialsHelper.materialize(credentials).createScoped(SheetsScopes.SPREADSHEETS));
25+
Sheets.Builder builder =
26+
new Sheets.Builder(
27+
GoogleNetHttpTransport.newTrustedTransport(),
28+
GsonFactory.getDefaultInstance(),
29+
credentialsAdapter)
30+
.setApplicationName("Enso");
31+
return new GoogleSheetsForEnso(builder.build());
32+
}
33+
34+
public List<List<Object>> getSheetRange(String sheetId, String range) throws IOException {
35+
return service
36+
.spreadsheets()
37+
.values()
38+
.get(sheetId, range)
39+
.setMajorDimension("COLUMNS")
40+
.setValueRenderOption("UNFORMATTED_VALUE")
41+
.execute()
42+
.getValues();
43+
}
44+
45+
public List<String> getSheetNames(String workbookId) throws IOException {
46+
return service
47+
.spreadsheets()
48+
.get(workbookId)
49+
.setIncludeGridData(false)
50+
.execute()
51+
.getSheets()
52+
.stream()
53+
.map(sheet -> sheet.getProperties().getTitle())
54+
.toList();
55+
}
56+
}

std-bits/google-api/src/main/java/org/enso/google/GoogleSheetsHelpers.java

Lines changed: 0 additions & 50 deletions
This file was deleted.

std-bits/google-api/src/main/java/org/enso/google/WrappedGoogleCredentials.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,14 @@ public sealed interface WrappedGoogleCredentials {
1010
record SecretCredentials(ExternalLibraryCredentialHelper.CredentialReference reference)
1111
implements WrappedGoogleCredentials {}
1212

13-
@SuppressWarnings("deprecation")
14-
record LocalFileCredentials(GoogleCredentials credential) implements WrappedGoogleCredentials {
15-
static LocalFileCredentials fromStream(InputStream stream) throws IOException {
16-
return new LocalFileCredentials(GoogleCredentials.fromStream(stream));
17-
}
13+
record LocalFileCredentials(GoogleCredentials credential) implements WrappedGoogleCredentials {}
14+
15+
static SecretCredentials fromCredentialReference(
16+
ExternalLibraryCredentialHelper.CredentialReference reference) {
17+
return new SecretCredentials(reference);
18+
}
19+
20+
static LocalFileCredentials fromStream(InputStream stream) throws IOException {
21+
return new LocalFileCredentials(GoogleCredentials.fromStream(stream));
1822
}
1923
}

0 commit comments

Comments
 (0)