Lotus Notes Integration to Google Team-drive - google-drive-api

I have a requirement to create a Lotus Notes java agent that needs to upload a folder/files from local directory to Google Team Drive for scheduled backup. I did some research about the Google API's (https://developers.google.com/api-client-library/java/) for java but I'm having some difficulties trying to understand all those java code as I only have a basic knowledge in java. If I understand it correctly, the api requires a maven repository and need to define all the dependencies which are not supported in Lotus Notes (not sure about this and am I reading the correct documentation).
May be someone can tell me if this is possible and point me out where to start. You might have some sample code that I can use as a reference. Any help and suggestion is very much appreciated.
Thank you.

You might take a look at the Drive Java Quickstart [1], where you will find the prerequisites and links of how to install Gradle (which is pretty similar to Maven) and the steps to build the JAVA application to make the requests to the Drive API.
Apparently, you wouldn’t have a problem to install gradle in lotus notes, either using this plugin [2] or installing eclipse [3], and then installing gradle inside eclipse.
Following the quickstart, the Java Drive documentation [4] and this google guide to upload files [5], I created and tested this code successfully:
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
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.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.File;
import com.google.api.client.http.FileContent;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.List;
public class DriveQuickstart {
//General Variables
private static final String APPLICATION_NAME = "Google Calendar API Java Quickstart";
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
private static final String TOKENS_DIRECTORY_PATH = "tokens";
/**
* Global instance of the scopes required by this quickstart.
* If modifying these scopes, delete your previously saved tokens/ folder.
*/
private static final List<String> SCOPES = Arrays.asList(DriveScopes.DRIVE);
private static final String CREDENTIALS_FILE_PATH = "/credentials.json";
/**
* Creates an authorized Credential object.
* #param HTTP_TRANSPORT The network HTTP Transport.
* #return An authorized Credential object.
* #throws IOException If the credentials.json file cannot be found.
*/
private static Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT) throws IOException {
// Load client secrets.
InputStream in = DriveQuickstart.class.getResourceAsStream(CREDENTIALS_FILE_PATH);
if (in == null) {
throw new FileNotFoundException("Resource not found: " + CREDENTIALS_FILE_PATH);
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
// Build flow and trigger user authorization request.
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
.setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH)))
.setAccessType("offline")
.build();
LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8888).build();
return new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
public static void main(String... args) throws IOException, GeneralSecurityException {
// Build the news authorized API client services.
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
Drive driveService = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT))
.setApplicationName(APPLICATION_NAME)
.build();
File fileMetadata = new File();
fileMetadata.setName("Filename");
java.io.File filePath = new java.io.File(“Complete-File-Path”);
FileContent mediaContent = new FileContent("image/jpeg", filePath);
File file = driveService.files().create(fileMetadata, mediaContent)
.setFields("id")
.execute();
System.out.println("File ID: " + file.getId());
}
}
Just for your information, there’s a tool you can use to migrate all your information from Lotus Notes to G suite [6].
[1] https://developers.google.com/drive/api/v3/quickstart/java
[2] https://www.ibm.com/support/knowledgecenter/en/SSYJJF_1.0.0/ApplicationSecurityonCloud/src_irx_gen_gradle.html
[3] https://www.ibm.com/developerworks/lotus/library/notes-eclipse/
[4] https://developers.google.com/resources/api-libraries/documentation/drive/v3/java/latest/
[5] https://developers.google.com/drive/api/v3/manage-uploads
[6] https://support.google.com/a/answer/161642?hl=en

Related

Include a file in an Android application

I used android studio to create a java app. In the project, I created the "assets" folder, and inside I put the json file that I will need to get the credentials for GmailAPI.
AssetFolder
I wish I could access the json file. I have already tried in many ways but every time it tells me that the file is missing.
This is the code:
public class GmailApi {
public Gmail initService(String userId) throws GeneralSecurityException,
IOException {
JacksonFactory jsonFactory = JacksonFactory.getDefaultInstance();
final GoogleCredentials creds = ServiceAccountCredentials.fromStream(new FileInputStream("gmailapi-android.json"))
.createScoped(GmailScopes.GMAIL_SEND);
final GoogleCredentials delegatedCreds = creds.createDelegated("xxx#xxx.com");
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(delegatedCreds);
HttpTransport transport = new NetHttpTransport.Builder().build();
// Construct the gmail object.
Gmail service = new Gmail.Builder(transport, jsonFactory, requestInitializer)
.setApplicationName("gmailapi")
.build();
return service;
}
}
Could anyone help me? What should I put in the path to be able to access the json file?
final GoogleCredentials creds = ServiceAccountCredentials.fromStream(new FileInputStream("gmailapi-android.json"))
Did you try to open the file this way?
AssetManager assetManager = getAssets();
InputStream ims = assetManager.open("gmailapi-android.json");

Apache HTTPClient DigestAuth doesn't forward "opaque" value from Challenge

I'm trying to use Digest authentication with HTTP Client against a 3rd-party web service that I don't control.
I started out with the sample code from here:
http://hc.apache.org/httpcomponents-client-4.5.x/httpclient/examples/org/apache/http/examples/client/ClientPreemptiveDigestAuthentication.java
I got it working against httpbin.org, before attempting the next step described below.
It appears that the target 3rd-party service that I'm using requires the opaque value to be copied from the WWW-Authentication header on the initial response to the Authorization header on the next request, as described here:
https://security.stackexchange.com/questions/24425/what-is-the-opaque-field-in-http-digest-access-authentication-used-for
However, I have turned on wire-logging and stepped through the code (again this is really just the sample code linked above, no need to copy/paste it here) and I see that the opaque is NOT copied.
Any ideas what prevents it from being copied?
I even tried overriding the processChallenge method:
DigestScheme digestAuth = new DigestScheme() {
#Override
public void processChallenge(
Header header) throws MalformedChallengeException {
but it appears that any value introduced into the Parameters at this point is ignored in the next request.
Finally fixed by overriding the Authorize header explicitly, instead of relying on the internals of HttpClient to do it automatically:
package [...];
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.io.IOUtils;
import org.apache.http.*;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.*;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.auth.DigestScheme;
import org.apache.http.impl.client.*;
import org.testng.Assert;
public class DigestTest {
private static final String URL
= "https://...";
private static final String PASSWORD = ...;
private static final String USER = ...;
public static void main(String[] args) throws Exception {
new DigestTest().run();
}
public void run() throws Exception {
HttpGet httpget = new HttpGet(URL);
HttpHost target
= new HttpHost(httpget.getURI().getHost(), 443, "https");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
UsernamePasswordCredentials credentials
= new UsernamePasswordCredentials(USER, PASSWORD);
credsProvider.setCredentials(
new AuthScope(target.getHostName(), target.getPort()),
credentials);
CookieStore cookieStore = new BasicCookieStore();
CloseableHttpClient httpclient
= HttpClients.custom().setDefaultCookieStore(cookieStore)
.setDefaultCredentialsProvider(credsProvider).build();
try {
DigestScheme digestAuth = new DigestScheme();
digestAuth.overrideParamter("qop", "auth");
digestAuth.overrideParamter("nc", "0");
digestAuth.overrideParamter("cnonce", DigestScheme.createCnonce());
AuthCache authCache = new BasicAuthCache();
authCache.put(target, digestAuth);
HttpClientContext localContext = HttpClientContext.create();
localContext.setAuthCache(authCache);
CloseableHttpResponse response;
response = httpclient.execute(target, httpget, localContext);
Map<String, String> wwwAuth = Arrays
.stream(response.getHeaders("WWW-Authenticate")[0]
.getElements())
.collect(Collectors.toMap(HeaderElement::getName,
HeaderElement::getValue));
// the first call ALWAYS fails with a 401
Assert.assertEquals(response.getStatusLine().getStatusCode(), 401);
digestAuth.overrideParamter("opaque", wwwAuth.get("opaque"));
digestAuth.overrideParamter("nonce", wwwAuth.get("nonce"));
digestAuth.overrideParamter("realm", wwwAuth.get("Digest realm"));
Header authenticate = digestAuth.authenticate(credentials, httpget,
localContext);
httpget.addHeader(authenticate);
response = httpclient.execute(target, httpget, localContext);
// the 2nd call is the real deal
Assert.assertEquals(response.getStatusLine().getStatusCode(), 200);
System.out.println(IOUtils
.toString(response.getEntity().getContent(), "utf-8"));
} finally {
httpclient.close();
}
}
}

Getting domain installs for my Google Docs Add-on

We have a Google-docs Add-on (built on Google Apps Script) for which we enabled the Google Apps Marketplace SDK - so that Google Apps Administrators could install our add-on at the domain level.
We have noticed a few domains have now installed our add-on - but I can't seem to find a way to get information on which domains have installed us. Is it even possible?
I have tried the Marketplace license API https://developers.google.com/apps-marketplace/v2/reference/ but it fails with a 403 error - Not authorized to access the application ID.
{
"error": {
"errors": [
{
"domain": "global",
"reason": "forbidden",
"message": "Not authorized to access the application ID"
}
],
"code": 403,
"message": "Not authorized to access the application ID"
}
}
I even tried by creating a service account and accessed the API using the service account but got the same error.
Any input would be awesome.
Here's my Java (Groovy technically) code so far (the response is the json I've pasted above):
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport
import com.google.api.client.http.GenericUrl
import com.google.api.client.http.HttpRequest
import com.google.api.client.http.HttpRequestFactory
import com.google.api.client.http.HttpTransport
import com.google.api.client.json.JsonFactory
import com.google.api.client.json.jackson2.JacksonFactory
import org.springframework.security.access.annotation.Secured
class DataController {
/**
* Be sure to specify the name of your application. If the application name is {#code null} or
* blank, the application will log a warning. Suggested format is "MyCompany-ProductName/1.0".
*/
private static final String APPLICATION_NAME = "My app name";
private static final String APPLICATION_ID = "12 digit project number";
/** E-mail address of the service account. */
private static final String SERVICE_ACCOUNT_EMAIL = "12digitproejectnumber-compute#developer.gserviceaccount.com";
/** Global instance of the HTTP transport. */
private static HttpTransport httpTransport;
/** Global instance of the JSON factory. */
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
def getLicensedInfo() {
try {
try {
httpTransport = GoogleNetHttpTransport.newTrustedTransport();
GoogleCredential credential = new GoogleCredential.Builder().setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(Collections.singleton("https://www.googleapis.com/auth/appsmarketplace.license"))
.setServiceAccountPrivateKeyFromP12File(new File("a/valid/path/to/key.p12"))
.build();
credential.refreshToken();
String token = credential.getAccessToken();
HttpRequestFactory requestFactory = httpTransport.createRequestFactory(credential);
GenericUrl url = new GenericUrl("https://www.googleapis.com/appsmarket/v2/licenseNotification/"+APPLICATION_ID);
HttpRequest request = requestFactory.buildGetRequest(url);
com.google.api.client.http.HttpResponse response = request.execute();
log.debug(response.parseAsString());
return;
} catch (IOException e) {
System.err.println(e.getMessage());
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
When making the request to the GAM License API you need to use the same Google Developers Console project that you used for your listing. In the case of an add-on, this is the console project associated with the script.

401 response when athenticating via Service Account and OAuth2 to GoogleDrive

I seem to have hit a wall trying to get a Java application to list of files stored in my GoogleDrive folder. The
I have a project setup in the Developer Console.
I have enabled for that project the Drive API
I have create Auth credentials for a Service Account - and am using the P12 key produced.
My code looks like this :
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.auth.oauth2.CredentialRefreshListener;
import com.google.api.client.auth.oauth2.TokenErrorResponse;
import com.google.api.client.auth.oauth2.TokenResponse;
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.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.FileList;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.List;
public class GoogleDriveTest {
/** Global instance of the JSON factory. */
private static final JsonFactory JSON_FACTORY = new JacksonFactory() ;
/** instance of the HTTP transport. */
private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport() ;
/** Global instance of the Google Drive - the first connect will initialize */
private static Drive drive;
/*
* instance variables
*/
private String accessToken ;
public static void main(String[] args) throws GeneralSecurityException, IOException {
String CLIENTID = "XXXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX#developer.gserviceaccount.com" ;
String CLIENTUSER = "XXXXXXXX#gmail.com" ;
String P2FILE = "random/src/main/resources/test.p12" ;
try {
GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(CLIENTID)
.setServiceAccountScopes(Collections.singleton(DriveScopes.DRIVE_FILE))
.setServiceAccountPrivateKeyFromP12File(new java.io.File(P2FILE))
.setServiceAccountUser(CLIENTUSER)
.addRefreshListener(new CredentialRefreshListener() {
#Override
public void onTokenResponse(
Credential credential,
TokenResponse tokenResponse) throws IOException {
String token = tokenResponse.getAccessToken();
System.out.println("GOOGLEDRIVE token refreshed " + tokenResponse.getTokenType() + " successfully");
}
#Override
public void onTokenErrorResponse(
Credential credential,
TokenErrorResponse tokenErrorResponse) throws IOException {
System.out.println("GOOGLEDRIVE token refresh failure : " + tokenErrorResponse);
}
})
.build();
/*
* set up the global Drive instance
*/
drive = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).setApplicationName("API Project").build();
/*
* output results
*/
Drive.Files.List fileRequest = drive.files().list() ;
FileList afiles = fileRequest.execute() ;
List<File> bFiles = afiles.getItems() ;
for(File file : bFiles) {
System.out.println(file.getTitle()) ;
}
}
catch (GeneralSecurityException | IOException e) {
e.printStackTrace();
}
}
}
But the output I see is this :
GOOGLEDRIVE token refresh failure : null
com.google.api.client.auth.oauth2.TokenResponseException: 401 Unauthorized
at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:105)
at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:287)
at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:307)
at com.google.api.client.googleapis.auth.oauth2.GoogleCredential.executeRefreshToken(GoogleCredential.java:384)
at com.google.api.client.auth.oauth2.Credential.refreshToken(Credential.java:489)
at com.google.api.client.auth.oauth2.Credential.intercept(Credential.java:217)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:859)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:419)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)
at GoogleDriveTest.main(GoogleDriveTest.java:81)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Process finished with exit code 0
Can anyone provide some pointers on Service Account access to Google Drive and what I might be doing wrong here ?
As the Service Account is created under my Google Account (XXXXXXXX#gmail.com) I assumed it would have access to the Drive once the API was enabled.
I have seen other posts about granting access to Service Accounts to a domain account via an admin console - but my account is a plain / standard google account. I'm not even sure what a domain account is !
All help would be greatly appreciated.

403 Forbidden Error While accessing Google MapsAPI

I am trying to establish connectivity with google maps api using service account. I have a project in place in google maps api, and I have the relvant clientID, .p12 key, email address. I am using google libraries to get the credentials and to call the API as below.
CODE:
package mapsengine;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.api.services.mapsengine.MapsEngine;
import com.google.api.services.mapsengine.model.Map;
import com.google.api.services.mapsengine.model.Layer;
import java.io.File;import java.io.IOException;
import java.util.Collections;
public class Main { /** Provide the ID of the map you wish to read. */
private static final String MAP_ID = "my map id i gave";
private static final String APPLICATION_NAME = "Google-MapsEngineApiSample/1.0";
private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
private static final JsonFactory JSON_FACTORY = new JacksonFactory();
private static final String SERVICE_ACCOUNT_EMAIL= "asajdsjdheemqe#developer.gserviceaccount.com";
private static Credential authorize() throws Exception {
GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT
) .setJsonFactory(JSON_FACTORY)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(Collections.singleton("https://www.googleapis.com/auth/mapsengine"))
.setServiceAccountPrivateKeyFromP12File(new File("key.p12"))
.build();
credential.refreshToken();
System.out.println(credential);
return credential;
}
public static void main(String[] args)
{ try { // Authorize this application to access the user's data.
Credential credential = authorize();
// Create an authorized Maps Engine client with the credential.
MapsEngine mapsEngine = new MapsEngine.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential) .
setApplicationName(APPLICATION_NAME).build();
System.out.println(mapsEngine);
// Make a request to get the details of a particular map.
// Map map = mapsEngine.maps().get(MAP_ID).execute();
System.out.println(map.getName());
System.out.println(map.getDescription());
}
catch (IOException e) {
System.out.println(e.getMessage());
} catch (Throwable t) {
t.printStackTrace();
}
}
}`
I am getting an error as 403 Forbidden
{
"code" : 403,
"errors" : [ {
"domain" : "mapsengine",
"location" : "id",
"locationType" : "parameter",
"message" : "Permission denied (reader access required).",
"reason" : "noReaderAccess"
} ],
"message" : "Permission denied (reader access required)."
}
But I am able to see that the service email account which I am using has edit access, also i tried by giving view access. What else I am missign here. Please help.
you need to go your map, and add your SERVICE_ACCOUNT_EMAIL address and give it can edit or view premission follow this: https://support.google.com/mapsengine/answer/4618526?hl=en