Struts + GAE java.security.AccessControlException: access denied of struts2-core-2.3.15.3.jar

google-app-engine, java, struts2

Solution

From my investigation the

java.security.AccessControlException: access denied ("java.io.FilePermission" "jar:file:\E:\eclipse\Shaun\Convergent\war\WEB-INF\lib\struts2-core-2.3.15.3.jar" "read")

exception only occurs when trying to run a Struts 2 application on Google App Engine for Windows.

I've encountered the same problem on Windows while trying to port an application to GAE, but I couldn't reproduce it under GNU/Linux nor when deployed to Google servers with appcfg.sh --oauth2 update dist/myapp

In order to solve this problem when running under Google App Engine for Windows the only working solution I found was to implement a custom plugin / extension point that implements the following interfaces com.opensymphony.xwork2.FileManager and com.opensymphony.xwork2.FileManagerFactory

The classes which implement the above interfaces inside the plugin override the implementations that Struts 2 instantiates by default, i.e. DefaultFileManager and DefaultFileManagerFactory

The custom file plugin I've created has three main components:

- The struts-plugin.xml file specifies that the FileManager and FileManagerFactory implementation from the plugin should be taken as the default

- Struts2FileManagerFactoryOnGAE, custom implemention of the FileManagerFactory interface where the only change from the DefaultFileManagerFactory implementation is the class name

- Struts2FileManagerOnGAE, custom FileManager implementation, where I've made the essential changes, that is, fileNeedsReloading() methods and internal should return false, and support() method should return true.

Also, inside the WEB-INF/web.xml of the application I've added: `<init-param> <param-name>config</param-name> <param-value>struts-default.xml,struts-plugin.xml,struts.xml</param-value> </init-param>`

Because I use Ant as a build system, I've created new targets for the custom file plugin, that compile & copy the jar of the plugin to the final artifact: https://gitlab.com/alibitek-java/Struts-GAE/blob/master/build.xml

You can see the source code for my test application at: https://gitlab.com/alibitek-java/Struts-GAE/tree/master

and if you want to give it a try you can just run:

ant dev_appserver

after setting the path to your Google App Engine SDK inside build.xml or you can see it live here http://struts-gae.appspot.com/jsp/index.jsp

What the application does is: you need to guess the random number that was generated, and after a few tries it will show you a hint, and when you guess the number it will show you in how many tries you've guessed it.

Problem

I am using struts in GAE. I am using GAE 1.8 and struts 2.3.15 jar file. In my application i am facing this exception ``` java.security.AccessControlException: access denied ("java.io.FilePermission" "jar:file:\E:\eclipse\Shaun\Convergent\war\WEB-INF\lib\struts2-core-2.3.15.3.jar" "read") at java.security.AccessControlContext.checkPermission(AccessControlContext.java:366) at java.security.AccessController.checkPermission(AccessController.java:560) at java.lang.SecurityManager.checkPermission(SecurityManager.java:549) at com.google.appengine.tools.development.DevAppServerFactory$CustomSecurityManager.checkPermission(DevAppServerFactory.java:431) at java.lang.SecurityManager.checkRead(SecurityManager.java:888) at java.util.zip.ZipFile.<init>(ZipFile.java:205) at java.util.zip.ZipFile.<init>(ZipFile.java:144) at java.util.jar.JarFile.<init>(JarFile.java:152) at java.util.jar.JarFile.<init>(JarFile.java:89) at com.opensymphony.xwork2.util.fs.JarEntryRevision.needsReloading(JarEntryRevision.java:76) at com.opensymphony.xwork2.util.fs.DefaultFileManager.fileNeedsReloading(DefaultFileManager.java:66) at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.needsReload(XmlConfigurationProvider.java:394) at org.apache.struts2.config.StrutsXmlConfigurationProvider.needsReload(StrutsXmlConfigurationProvider.java:169) at com.opensymphony.xwork2.config.ConfigurationManager.needReloadContainerProviders(ConfigurationManager.java:215) at com.opensymphony.xwork2.config.ConfigurationManager.conditionalReload(ConfigurationManager.java:179) at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:73) at org.apache.struts2.dispatcher.Dispatcher.getContainer(Dispatcher.java:968) at org.apache.struts2.dispatcher.ng.PrepareOperations.createActionContext(PrepareOperations.java:77) at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:86) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.convergent.auth.AuthorizationFilter.doFilter(AuthorizationFilter.java:32) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.convergent.auth.AuthenticationFilter.doFilter(AuthenticationFilter.java:48) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 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:63) 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.DevAppServerModulesFilter.doDirectRequest(DevAppServerModulesFilter.java:368) at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectModuleRequest(DevAppServerModulesFilter.java:351) at com.google.appengine.tools.development.DevAppServerModulesFilter.doFilter(DevAppServerModulesFilter.java:116) 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:97) at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:485) 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) ``` I did lot of search some says remove this property value from sturts.xml file ``` <constant name="struts.devMode" value="true" /> ``` Some says change the value from true to false. I did it but it didn't work. Please give a solution. I also change the jar file and use 2.1.8 version but in this i got the exception at startup of server which is ``` java.lang.NoSuchMethodError: com.opensymphony.xwork2.config.ConfigurationManager.addConfigurationProvider(Lcom/opensymphony/xwork2/config/ConfigurationProvider;)V at org.apache.struts2.dispatcher.Dispatcher.init_DefaultProperties(Dispatcher.java:310) at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:411) at org.apache.struts2.dispatcher.ng.InitOperations.initDispatcher(InitOperations.java:69) at org.apache.struts2.dispatcher.ng.listener.StrutsListener.contextInitialized(StrutsListener.java:45) at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:548) at org.mortbay.jetty.servlet.Context.startContext(Context.java:136) at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250) at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517) at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467) at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50) at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130) at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50) at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130) at org.mortbay.jetty.Server.doStart(Server.java:224) at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50) at com.google.appengine.tools.development.JettyContainerService.startContainer(JettyContainerService.java:249) at com.google.appengine.tools.development.AbstractContainerService.startup(AbstractContainerService.java:306) at com.google.appengine.tools.development.AutomaticInstanceHolder.startUp(AutomaticInstanceHolder.java:26) at com.google.appengine.tools.development.AbstractModule.startup(AbstractModule.java:79) at com.google.appengine.tools.development.Modules.startup(Modules.java:88) at com.google.appengine.tools.development.DevAppServerImpl.doStart(DevAppServerImpl.java:254) at com.google.appengine.tools.development.DevAppServerImpl.access$000(DevAppServerImpl.java:47) at com.google.appengine.tools.development.DevAppServerImpl$1.run(DevAppServerImpl.java:212) at com.google.appengine.tools.development.DevAppServerImpl$1.run(DevAppServerImpl.java:210) at java.security.AccessController.doPrivileged(Native Method) at com.google.appengine.tools.development.DevAppServerImpl.start(DevAppServerImpl.java:210) at com.google.appengine.tools.development.DevAppServerMain$StartAction.apply(DevAppServerMain.java:277) at com.google.appengine.tools.util.Parser$ParseResult.applyArgs(Parser.java:48) at com.google.appengine.tools.development.DevAppServerMain.run(DevAppServerMain.java:219) at com.google.appengine.tools.development.DevAppServerMain.main(DevAppServerMain.java:210) ``` I am also using following jar files with struts jar file ``` ognl-3.0.6.jar sitemesh-2.4.2.jar struts2-sitemesh-plugin-2.2.3.1.jar xwork-core-2.3.15.3.jar ``` please guide me.

Original source