2013-03-10 17 views
0

我一直在为此奋斗了一个多月,并且已经达到了我的目标。用例如下:获取Drive SDK和DocsList并行运行

1 - 当我的客户端为他的某个客户端创建一个新文件时,他将其放入他的Google驱动器帐户的文件夹中。该文件夹与他的客户共享。由于Google没有任何机制可以自动通知某个文件夹中与其共享的文件已更改,我必须写一个文件。所以我有一个GAE/GWT应用程序,带有一个按钮Notify。该应用程序有一个扫描其客户端文件夹的按钮,如果该文件夹中有新文件,它会抓取与该文件夹共享的人员的电子邮件地址,并向他们发送一封电子邮件,告知他们有新文件。

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

Drive SDK部分很简单。直到我碰到与人分享文件夹的人才可用的墙,但没有他们的电子邮件。所以我开始尝试将旧的API DocsService与Drive SDK结合使用,以便获取电子邮件地址。我梳通示例应用程序,我发现一个工具类八九不离十我想要做什么,那就是:

/* * 版权所有(C)2010谷歌公司 * * 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() { 
    } 
} 

现在这个类处理驱动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。你能给我任何想法,为什么这不起作用?

感谢

回答

0

你应该有

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

为您的OAuth范围的一部分。

+0

在上面的newFlow()方法中,该范围已经列出。那是我尝试的第一件事情之一。 – scphantm 2013-03-12 15:07:27

+0

如何将Drive SDK范围与文档列表范围一起添加? – user1828559 2013-03-15 01:50:35

+0

看看我的课,那正是我所做的。 – scphantm 2013-03-15 13:31:29