Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Hackademy - BigQueryClientFactory
package ar.com.zupcat.lib.bean.audit;
import ar.com.zupcat.lib.bean.enums.ErrorType;
import ar.com.zupcat.lib.exception.GAEException;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.auth.oauth2.TokenResponse;
import com.google.api.client.googleapis.auth.oauth2.*;
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.jackson.JacksonFactory;
import com.google.api.services.bigquery.Bigquery;
import com.google.api.services.bigquery.BigqueryScopes;
import java.io.*;
import java.util.Collections;
import java.util.Properties;
public final class BigQueryClientFactory {
private static final String REDIRECT_URI = "urn:ietf:wg:oauth:2.0:oob";
private static final String PREVIOUSLY_AUTHORIZED_TOKENS_FILE = "google-cloud-previously-authorized-tokens.properties";
// Objects for handling HTTP transport and JSON formatting of API calls
private final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
private final JsonFactory JSON_FACTORY = new JacksonFactory();
private final GoogleClientSecrets googleClientSecrets;
private final String appName;
private final BigQueryClient bigQueryClientFactory;
/**
* @param projectNumberId Google Cloud ProjectNumber. It could be seen in, for instance, https://console.developers.google.com/project/apps~topgoalsprod
* @param appName just a reference name. For instance topgoalsprod
* @param clientSecretsJson obtained by creating a OAuth ClientId on, for instance, https://console.developers.google.com/project/apps~topgoalsprod/apiui/credential - Then you should add the downloaded json file content. See main method in this class for an example
*/
public BigQueryClientFactory(final String projectNumberId, final String appName, final String clientSecretsJson) {
try {
this.appName = appName;
googleClientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new StringReader(clientSecretsJson));
final Bigquery bigquery;
final String previouslyAuthorizedTokens = tryLoadPreviouslyAuthorizedTokens();
if (previouslyAuthorizedTokens != null) {
final GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setClientSecrets(googleClientSecrets)
.build()
.setFromTokenResponse(new TokenResponse().setRefreshToken(previouslyAuthorizedTokens));
credential.refreshToken();
bigquery = buildService(credential);
} else {
final String authorizeUrl = new GoogleAuthorizationCodeRequestUrl(
googleClientSecrets,
REDIRECT_URI,
Collections.singleton(BigqueryScopes.BIGQUERY)).setState("").build();
System.err.println("Paste this URL into a web browser to authorize BigQuery Access:\n" + authorizeUrl);
System.err.println("... and type the code you received here: ");
final BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
final String authorizationCode = in.readLine();
// Exchange the auth code for an access token and refesh token
final Credential credential = exchangeCode(authorizationCode);
// Store the refresh token for future use.
savePreviouslyAuthorizedTokens(credential.getRefreshToken());
bigquery = buildService(credential);
}
bigQueryClientFactory = new BigQueryClient(projectNumberId, bigquery);
} catch (final Exception _exception) {
throw new GAEException(ErrorType.PROGRAMMING, _exception);
}
}
public BigQueryClient getBigQueryClientFactory() {
return bigQueryClientFactory;
}
private Bigquery buildService(final Credential credential) {
return new Bigquery.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).setApplicationName(appName).build();
}
private Credential exchangeCode(final String authorizationCode) throws IOException {
final GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT,
JSON_FACTORY,
googleClientSecrets,
Collections.singleton(BigqueryScopes.BIGQUERY))
.setAccessType("offline").setApprovalPrompt("force").build();
final GoogleTokenResponse response = flow.newTokenRequest(authorizationCode).setRedirectUri(REDIRECT_URI).execute();
return flow.createAndStoreCredential(response, null);
}
private String tryLoadPreviouslyAuthorizedTokens() {
String result = null;
try {
final Properties properties = new Properties();
properties.load(new FileInputStream(PREVIOUSLY_AUTHORIZED_TOKENS_FILE));
result = (String) properties.get("freshToken");
} catch (final Exception _exception) {
// ok to ignore
}
return result;
}
private void savePreviouslyAuthorizedTokens(final String freshToken) {
try {
final Properties properties = new Properties();
properties.setProperty("freshToken", freshToken);
properties.store(new FileOutputStream(PREVIOUSLY_AUTHORIZED_TOKENS_FILE), null);
} catch (final Exception _exception) {
// ok to ignore
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment