Java Media Framework(JMF)を使ってJava Web Startからクライアントのカメラデバイスを通じて動画のキャプチャなどを行うとした場合、セキュリティとデバイスの問題がある。
1つの方法としてクライアント側でJMFを事前にインストールしてセキュリティの設定をJMFRegistryを用いて行う方法があるが、いつの時代もインストールは面倒なものだし、JWS使う利点が無くなってしまう。
ということで、色々調べた結果、次のような方法が見つかった。
後に書く方法でデバイスを見つけるとjmf.propertiesに書き込みに行くが、JWSでの実行時にはセキュリティマネージャが次のような例外を出す。
"Exception on commit = java.lang.SecurityException: commit: Permission denied"
jarファイルを署名し、JNLPファイルで<all-permissions/>を設定しても無関係に発生する。
仕方がないので原因を探りにソースコードを覗くと、JMFにはJMFSecurityManagerというやつがいて、Registry#commitなどの際に書き込み権限のチェックなどをやっているらしい。
結果として、JMFSecurityManagerを無効化することは無理のようだが、
System.setSecurityManger(null);
とすることでJWSではJMFSecurityMangerを生成させずにおくことが出来た。
一度でも、JMFSecurityManagerが生成されてしまったら無効化する方法はないようだ。
続いて、デバイスの探索だが、これはJMFRegistryのソースコードから該当部分を拝借した以下のコードで実現できる。
// Check if VFWAuto or SunVideoAuto is available
Class directAudio = null;
Class autoAudio = null;
Class autoVideo = null;
Class autoVideoPlus = null;
try {
directAudio = Class.forName("DirectSoundAuto");
} catch (Exception e) {
}
try {
autoAudio = Class.forName("JavaSoundAuto");
} catch (Exception e) {
}
try {
autoVideo = Class.forName("VFWAuto");
} catch (Exception e) {
}
if (autoVideo == null) {
try {
autoVideo = Class.forName("SunVideoAuto");
} catch (Exception ee) {
}
try {
autoVideoPlus = Class.forName("SunVideoPlusAuto");
} catch (Exception ee) {
}
}
if (autoVideo == null) {
try {
autoVideo = Class.forName("V4LAuto");
} catch (Exception eee) {
}
}
if (directAudio == null && autoAudio == null && autoVideo == null
&& autoVideoPlus == null)
return;
try {
if (directAudio != null) {
directAudio.newInstance();
}
if (autoAudio != null) {
autoAudio.newInstance();
}
if (autoVideo != null) {
autoVideo.newInstance();
}
if (autoVideoPlus != null) {
autoVideoPlus.newInstance();
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}