我正在尝试在 GAE 中使用 Dropbox 的 java API 来覆盖 Dropbox 文件。
我正在使用 putFileOverwrite API 来覆盖文件内容,但是 api 会引发“访问被拒绝(java.lang.RuntimePermission modifyThreadGroup)”错误。我发现这是由于 GAE 中不允许多线程编程,所以我更新了 AbstractSession.java 中的代码,其中我将 IdleConnectionCloserThread 设为普通类而不是线程。
现在,当我尝试运行该函数时,我得到 java.net.Socket 异常。
any1 对如何使 Dropbox + GAE 设置正常工作有任何建议吗?
源代码:
AccessType ACCESS_TYPE = AccessType.APP_FOLDER;
AppKeyPair appKeys = new AppKeyPair(APP_KEY, APP_SECRET);
AccessTokenPair accessTokenPair = new AccessTokenPair(ACCESS_TOKEN, ACCESS_KEY);
WebAuthSession session = new WebAuthSession(appKeys, ACCESS_TYPE, accessTokenPair);
DropboxAPI<WebAuthSession> dropboxApi = new DropboxAPI<WebAuthSession>(session);
String fileContents = "Hello world";
ByteArrayInputStream inputStream = new ByteArrayInputStream(fileContents.getBytes());
try
{
dropboxApi.putFileOverwrite("/myFile.txt", inputStream, fileContents.length(), null);
}
catch(DropboxException e)
{
}
使用保管箱的 jar AS-IS 后我得到的异常:
java.security.AccessControlException: access denied (java.lang.RuntimePermission modifyThreadGroup)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:374)
at java.security.AccessController.checkPermission(AccessController.java:549)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at com.google.appengine.tools.development.DevAppServerFactory$CustomSecurityManager.checkPermission(DevAppServerFactory.java:289)
at com.google.appengine.tools.development.DevAppServerFactory$CustomSecurityManager.checkAccess(DevAppServerFactory.java:314)
at java.lang.ThreadGroup.checkAccess(ThreadGroup.java:299)
at java.lang.Thread.init(Thread.java:336)
at java.lang.Thread.<init>(Thread.java:422)
at com.dropbox.client2.session.AbstractSession$IdleConnectionCloserThread.<init>(AbstractSession.java:507)
at com.dropbox.client2.session.AbstractSession$IdleConnectionCloserThread.ensureRunning(AbstractSession.java:517)
at com.dropbox.client2.session.AbstractSession$DBClientConnManager.requestConnection(AbstractSession.java:494)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:383)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:554)
at com.dropbox.client2.RESTUtility.execute(RESTUtility.java:385)
at com.dropbox.client2.DropboxAPI$BasicUploadRequest.upload(DropboxAPI.java:1081)
at com.dropbox.client2.DropboxAPI.putFileOverwrite(DropboxAPI.java:1501)
at a.b.c.DropboxTestServlet.doGet(DropboxTestServlet.java:33)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
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.headerComplete(HttpConnection.java:923)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:547)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
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)
然后,如果我让 IdleConnectionCloserThread 不继承“线程”,我会得到以下异常:
java.net.SocketException: Permission denied: Not allowed to issue a socket connect: permission denied.
at com.google.appengine.api.socket.SocketApiHelper.translateError(SocketApiHelper.java:94)
at com.google.appengine.api.socket.SocketApiHelper.translateError(SocketApiHelper.java:105)
at com.google.appengine.api.socket.SocketApiHelper.makeSyncCall(SocketApiHelper.java:71)
at com.google.appengine.api.socket.AppEngineSocketImpl.connectSocket(AppEngineSocketImpl.java:399)
at com.google.appengine.api.socket.AppEngineSocketImpl.connectToAddress(AppEngineSocketImpl.java:346)
at com.google.appengine.api.socket.AppEngineSocketImpl.connect(AppEngineSocketImpl.java:335)
at java.net.Socket.connect(Socket.java:529)
at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:123)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:133)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:149)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:108)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:415)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:554)
at com.dropbox.client2.RESTUtility.execute(RESTUtility.java:385)
at com.dropbox.client2.DropboxAPI$BasicUploadRequest.upload(DropboxAPI.java:1081)
at com.dropbox.client2.DropboxAPI.putFileOverwrite(DropboxAPI.java:1501)
at a.b.c.DropboxTestServlet.doGet(DropboxTestServlet.java:33)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
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.headerComplete(HttpConnection.java:923)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:547)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
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)