Play Framework を使用した Java サンドボックス システムに取り組んでいます。Play のおかげで、jar ファイル (悪意のあるコードを含む可能性がある) をサーバーにアップロードしようとしているユーザーに対処しなければなりません。Play コントローラは、jar ファイルを「upload」ディレクトリにアップロードし、それを Sandbox にロードします。
public static Result upload(){
// Get the form
MultipartFormData body = request().body().asMultipartFormData();
// Get all files parts
List<FilePart> fileparts = body.getFiles();
for(FilePart filepart : fileparts)
{
if (filepart != null) {
String fileName = filepart.getFilename();
File file = filepart.getFile();
String pathToJar = Play.application().path() + "/upload/" + fileName;
file.renameTo(new File(pathToJar));
// Load the Bot in a sandboxed environment
Referee.loadJarBot("file:/" + pathToJar);
}
}
// Debug message
return ok("Uploaded");
}
このコードはかなりうまく機能します。Referee クラスは Jar ファイルを開き、この Jar から BotSample クラスをインスタンス化します。BotSample は MyrmesPlayer インターフェイスを実装します。
パブリック クラス BotSample は MyrmesPlayer を実装します
Jar ファイルを開いて BotSample の新しいインスタンスを作成するコードは次のとおりです。
public static void loadJarBot(String pathToJar){
try
{
// Load the Jar file
URL url = new URL(pathToJar);
URLClassLoader cl = new URLClassLoader(new URL[] { url });
// Load the bot class
Class<?> botClass = cl.loadClass("myrmes.bot.app.BotSample");
/* Problem comes here */
final MyrmesPlayer myrmesPlayer = (MyrmesPlayer) botClass.newInstance();
/* ... */
}
catch (Exception e)
{
e.printStackTrace();
}
}
BotSample から MyrmesPlayer へのキャストは ClassCastException をスローしますが、MyrmesPlayer はクラス階層で BotSample よりも上位にあります。O_o
java.lang.ClassCastException: myrmes.bot.app.BotSample cannot be cast to myrmes.
bot.api.MyrmesPlayer
at myrmes.referee.app.Referee.loadJarBot(Referee.java:31)
at controllers.Application.upload(Application.java:40)
at Routes$$anonfun$routes$1$$anonfun$applyOrElse$3$$anonfun$apply$3.appl
y(routes_routing.scala:81)
at Routes$$anonfun$routes$1$$anonfun$applyOrElse$3$$anonfun$apply$3.appl
y(routes_routing.scala:81)
at play.core.Router$HandlerInvoker$$anon$6$$anon$2.invocation(Router.sca
la:164)
at play.core.Router$Routes$$anon$1.invocation(Router.scala:345)
at play.core.j.JavaAction$$anon$1.call(JavaAction.scala:31)
at play.core.j.JavaAction$$anon$2.apply(JavaAction.scala:74)
at play.core.j.JavaAction$$anon$2.apply(JavaAction.scala:73)
at play.libs.F$Promise$PromiseActor.onReceive(F.java:420)
at akka.actor.UntypedActor$$anonfun$receive$1.applyOrElse(UntypedActor.s
cala:159)
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:425)
at akka.actor.ActorCell.invoke(ActorCell.scala:386)
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:230)
at akka.dispatch.Mailbox.run(Mailbox.scala:212)
at akka.dispatch.ForkJoinExecutorConfigurator$MailboxExecutionTask.exec(
AbstractDispatcher.scala:502)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:262)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool
.java:975)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:14
78)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThre
ad.java:104)
さらに、この loadJarBot メソッドをスタンドアロン アプリケーション (つまり、Play のない純粋な Java) で使用すると、このコードは完全に機能します。
よろしくお願いいたします。