0

I have code that is creating an InputStream object using the getResourceAsStream method.

The file is located in the same package as the class, so I am referencing the file without slashes or dots. enter image description here

This works fine when I run in Eclipse, however, when I am calling from my web app, it is always null - it cannot find the file.

java.lang.NullPointerException
        at java.io.Reader.<init>(Reader.java:78)
        at java.io.InputStreamReader.<init>(InputStreamReader.java:72)
        at google.GoogleDrive.authorize(GoogleDrive.java:84)
        at google.GoogleDrive.getDriveService(GoogleDrive.java:106)
        at google.GoogleDrive.uploadFile(GoogleDrive.java:123)

Here is the full class:

package google;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

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.FileContent;
import com.google.api.client.http.HttpTransport;
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 play.Configuration;
import utils.AppGlobals.StringControl;

public class GoogleDrive {
    /** Application name. */
    private static final String APPLICATION_NAME = "Case Manager";

    /** Directory to store user credentials for this application. */
    private static final java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("user.home"),
            ".credentials/googledrivejava");

    /** Global instance of the {@link FileDataStoreFactory}. */
    private static FileDataStoreFactory DATA_STORE_FACTORY;

    /** Global instance of the JSON factory. */
    private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();

    /** Global instance of the HTTP transport. */
    private static HttpTransport HTTP_TRANSPORT;

    /** Credentials File Name **/
    private static String credentialsFileName = "client_secret.json";

    /**
     * Global instance of the scopes required by this quickstart.
     *
     * If modifying these scopes, delete your previously saved credentials at
     * ~/.credentials/drive-java-quickstart
     */
    // private static final List<String> SCOPES =
    // Arrays.asList(DriveScopes.DRIVE_METADATA_READONLY);
    private static final List<String> SCOPES = Arrays.asList(DriveScopes.DRIVE);

    static {
        try {
            HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
            DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR);
        } catch (Throwable t) {
            t.printStackTrace();
            System.exit(1);
        }
    }

    /**
     * Creates an authorized Credential object.
     * 
     * @return an authorized Credential object.
     * @throws IOException
     */
    public static Credential authorize() throws IOException {
        Credential credential = null;
        try {
            // Load client secrets...
            InputStream in = GoogleDrive.class.getResourceAsStream("client_secret.json");
            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(DATA_STORE_FACTORY).setAccessType("offline").build();
            credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
            System.out.println("Credentials saved to " + DATA_STORE_DIR.getAbsolutePath());
        } catch (IOException ex) {
            System.out.println(ex.toString());
            System.out.println("Could not find file " + credentialsFileName);
            ex.printStackTrace();
        }
        return credential;
    }

    /**
     * Build and return an authorized Drive client service.
     * 
     * @return an authorized Drive client service
     * @throws IOException
     */
    public static Drive getDriveService() throws IOException {
        Credential credential = authorize();
        return new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).setApplicationName(APPLICATION_NAME).build();
    }

    public static void main(String[] args) throws IOException {
        try {
            uploadFile("C:\\WebDev\\license.txt");
        } catch (Exception ex) {
            System.out.println(ex.toString());
            ex.printStackTrace();
        }
    }

    public static String uploadFile(String fullFilePath) throws IOException {
        String fileID = "";
        try {
            // Build a new authorized API client service.
            Drive service = getDriveService();

            File fileMetadata = new File();
            String fileName = StringControl.rightBack(fullFilePath, "\\");
            String fileContentType = getContentType(fileName);
            fileMetadata.setName(fileName);

            // Set the folder...
            String folderID = Configuration.root().getString("google.drive.folderid");
            fileMetadata.setParents(Collections.singletonList(folderID));

            java.io.File filePath = new java.io.File(fullFilePath);
            FileContent mediaContent = new FileContent(fileContentType, filePath);
            File file = service.files().create(fileMetadata, mediaContent).setFields("id, parents").execute();
            fileID = file.getId();
        } catch (Exception ex) {
            System.out.println(ex.toString());
            ex.printStackTrace();
        }
        return fileID;
    }

    public static String getContentType(String filePath) throws Exception {
        String type = "";
        try {
            Path path = Paths.get(filePath);
            type = Files.probeContentType(path);
            System.out.println(type);
        } catch (Exception ex) {
            System.out.println(ex.toString());
            ex.printStackTrace();
        }
        return type;
    }

}

I have tried a few different options from this post: Eclipse Java File FileInputStream vs Input Stream when loading font file

But no luck. Appreciate the help.

Dan
  • 940
  • 2
  • 14
  • 42

1 Answers1

0

Check out that when you compile your web app that resources are included on target directory. It is possible that your json -file is not copied with your compiled classes and you are getting null because of that.

Ville Venäläinen
  • 2,444
  • 1
  • 15
  • 11
  • If I put the `client_secret.json` file into another folder, such as the `app` folder which is a folder above the `google` package, how would I reference that? Or what is the best place to put this file and how would I reference in the `InputStream` object? – Dan Sep 13 '17 at 17:30
  • I think you can parse path to your file combining it to a user dir path, which can be read with `System.getProperty("user.dir")`. But at the same time, I think in your case, it is fine to use json file from the same package that your code, if you will. You only need to make sure that the file is there. How that is achieved, depends on your environment. If you are using Maven for example, you must but the json file on to resources folder of you project with same package path. – Ville Venäläinen Sep 14 '17 at 05:59