让Drive SDK和DocsList并排运行

时间:2013-03-10 18:46:20

标签: google-drive-api

我已经与这个战斗了一个多月了,并且已经达到了我的结果。用例是这样的:

1 - 当我的客户为他的一个客户提供新文件时,他将其放在他的Google云端硬盘帐户的文件夹中。该文件夹与其客户共享。由于Google没有机制自动通知某人与他们共享的文件夹中的文件发生了变化,因此我必须编写一个。所以我有一个带有按钮的GAE / GWT应用程序Notify。该应用程序有一个扫描其客户端文件夹的按钮,如果该文件夹中有新文件,它会抓取该文件夹共享的人员的电子邮件地址,并向他们发送一封电子邮件,说明他们有新文件。

2 - 他需要定期向所有客户发送大量电子邮件。所以在他的仪表板上是第二个按钮,他格式化电子邮件并单击按钮,扫描仪转到所有客户端文件夹,并编译共享文件夹的所有人的列表。然后循环列表并发送电子邮件。

Drive SDK部分非常简单。直到我碰到了共享文件夹的人可用,而不是他们的电子邮件。因此,我开始尝试将较旧的API DocsService与Drive SDK结合使用,以便获取电子邮件地址。我通过示例应用程序进行了梳理,然后找到了一个实用程序类,它可以实现我想要的功能,在这里:

/ *  *版权所有(c)2010 Google Inc.  *  *根据Apache许可证2.0版(“许可证”)获得许可;你可能不会使用这个文件,除了  *符合许可证。您可以在以下位置获取许可证副本  *  * http://www.apache.org/licenses/LICENSE-2.0  *  *除非适用法律要求或书面同意,否则根据许可证分发的软件  *按“原样”分发,不附带任何形式的保证或条件,快递  *或暗示。有关管理权限和限制的特定语言,请参阅许可证  *许可证。  * /

package com.voice.mailer.server;

import java.io.IOException;
import java.util.HashSet;
import java.util.logging.Logger;

import javax.servlet.http.HttpServletRequest;

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.appengine.auth.oauth2.AppEngineCredentialStore;
import com.google.api.client.extensions.appengine.http.UrlFetchTransport;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.common.base.Preconditions;
import com.google.gdata.client.docs.DocsService;

/**
 * Utility class for JDO persistence, OAuth flow helpers, and others.
 * 
 * @author Yaniv Inbar
 */
class Utils {

    /** Global instance of the HTTP transport. */
    static final HttpTransport HTTP_TRANSPORT = new UrlFetchTransport();
    static Credential credential = null;
    /** Global instance of the JSON factory. */
    static final JsonFactory JSON_FACTORY = new JacksonFactory();

    private static GoogleClientSecrets clientSecrets = null;
    private static final Logger log = Logger.getLogger(Utils.class.getName());

    static GoogleClientSecrets getClientCredential() throws IOException {
        if (clientSecrets == null) {
            clientSecrets = GoogleClientSecrets.load(JSON_FACTORY,
                    Utils.class.getResourceAsStream("/client_secrets.json"));
            Preconditions
                    .checkArgument(
                            !clientSecrets.getDetails().getClientId()
                                    .startsWith("Enter ")
                                    && !clientSecrets.getDetails()
                                            .getClientSecret()
                                            .startsWith("Enter "),
                            "Download client_secrets.json file from https://code.google.com/apis/console/?api=calendar "
                                    + "into calendar-appengine-sample/src/main/resources/client_secrets.json");
        }
        return clientSecrets;
    }

    static String getRedirectUri(HttpServletRequest req) {
        GenericUrl url = new GenericUrl(req.getRequestURL().toString());
        url.setRawPath("/oauth2callback");
        return url.build();
    }

    static GoogleAuthorizationCodeFlow newFlow() throws IOException {
        HashSet<String> s = new HashSet<String>();
        s.add(DriveScopes.DRIVE_FILE);
        s.add("https://docs.google.com/feeds/");
        s.add("https://docs.googleusercontent.com/");
        s.add("https://spreadsheets.google.com/feeds/");
        s.add("http://www.google.com/accounts/AuthSubRequest");
        s.add("http://schemas.google.com/acl/2007");
        s.add("https://www.googleapis.com/auth/userinfo");

        return new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT,
                JSON_FACTORY, getClientCredential(), s)
                .setCredentialStore(new AppEngineCredentialStore())
                .setAccessType("offline").build();

        // http(s)://docs.google.com/feeds/
    }

    static Drive loadDriveClient() throws IOException {

        if (credential == null) {
            String userId = UserServiceFactory.getUserService()
                    .getCurrentUser().getUserId();
            credential = newFlow().loadCredential(userId);
        }
        return new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
                .build();
    }

    static DocsService loadDocsService(String applicationName) {

        if (credential == null) {
            String userId = UserServiceFactory.getUserService()
                    .getCurrentUser().getUserId();
            try {
                credential = newFlow().loadCredential(userId);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        DocsService service = new DocsService(applicationName);

        log.info("token: " + credential.getAccessToken());

        service.setOAuth2Credentials(credential);
        // service.setHeader("Authorization",
        // "Bearer " + credential.getAccessToken());

        return service;
    }

    /**
     * Returns an {@link IOException} (but not a subclass) in order to work
     * around restrictive GWT serialization policy.
     */
    static IOException wrappedIOException(IOException e) {
        if (e.getClass() == IOException.class) {
            return e;
        }
        return new IOException(e.getMessage());
    }

    private Utils() {
    }
}

现在这个类处理Drive SDK部分很棒,我能够调用loadDriveClient方法,并且我得到了一个准备好摇滚的类。但是当我调用loadDocsService并调用方法时,我不断收到以下错误:

 10, 2013 5:36:07 PM com.google.appengine.repackaged.org.apache.http.impl.client.DefaultRequestDirector handleResponse
WARNING: Authentication error: Unable to respond to any of these challenges: {authsub=WWW-Authenticate: AuthSub realm="http://www.google.com/accounts/AuthSubRequest"}
com.google.gdata.client.GoogleService$SessionExpiredException: OK
<HTML>
<HEAD>
<TITLE>Token invalid - AuthSub token has wrong scope</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>Token invalid - AuthSub token has wrong scope</H1>
<H2>Error 401</H2>
</BODY>
</HTML>

    at com.google.gdata.client.http.GoogleGDataRequest.handleErrorResponse(GoogleGDataRequest.java:570)
    at com.google.gdata.client.http.HttpGDataRequest.checkResponse(HttpGDataRequest.java:560)
    at com.google.gdata.client.http.HttpGDataRequest.execute(HttpGDataRequest.java:538)
    at com.google.gdata.client.http.GoogleGDataRequest.execute(GoogleGDataRequest.java:536)
    at com.google.gdata.client.Service.getFeed(Service.java:1135)
    at com.google.gdata.client.Service.getFeed(Service.java:998)
    at com.google.gdata.client.GoogleService.getFeed(GoogleService.java:652)
    at com.google.gdata.client.Service.getFeed(Service.java:1017)
    at com.voice.mailer.shared.DocumentList.getAclFeed(DocumentList.java:611)
    at com.voice.mailer.server.NewFileProcessorImpl.processNewFiles(NewFileProcessorImpl.java:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.google.appengine.tools.development.agent.runtime.Runtime.invoke(Runtime.java:115)
    at com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:561)
    at com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:208)
    at com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:248)
    at com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.doPost(AbstractRemoteServiceServlet.java:62)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
    at com.google.appengine.api.socket.dev.DevSocketFilter.doFilter(DevSocketFilter.java:74)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.tools.development.ResponseRewriterFilter.doFilter(ResponseRewriterFilter.java:123)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:34)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:61)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:125)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.tools.development.BackendServersFilter.doFilter(BackendServersFilter.java:97)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
    at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:94)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:383)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at org.mortbay.jetty.Server.handle(Server.java:326)
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
    at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938)
    at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755)
    at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
    at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
Mar 10, 2013 5:36:21 PM com.google.appengine.api.datastore.dev.LocalDatastoreService$PersistDatastore persist
INFO: Time to persist datastore: 6 ms

我已经尝试了我能想到的一切以及我能找到的每一个例子。我不知道为什么它没有正确创建DocsService。你能否告诉我为什么这不起作用?

感谢

1 个答案:

答案 0 :(得分:0)

你应该

  

https://docs.google.com/feeds/

作为OAuth范围的一部分。