Archive for 7月, 2010
実はこの間、ある会社の経営者とHTML5についてお話をしました。
そこで、HTML5についてずいぶん違った認識をもっているのだなーと。
HTML5をFlashと比べる方が多いので、どうやら、アニメーション機能をもっていると思っている方が多いようです。
残念ながらHTML5は、アニメーション機能は持っていません。
HTML5 + JS でアニメーションを作れるという事です。
また、基本的にはFlashでできない表現が、HTML5でできるようになったかと言えば、そうでもありません。
と、このように伝えると、なんだかHTML5に対する大きな期待がなくなってしまったようです。
じゃ、なぜこれほどHTML5が騒がれているのでしょうか?
というよりも、騒ぐ必要があるから騒いでいるという側面があるのではないでしょうか?
まず、Flashですが、Flashは長い間、ずーとクローズドでやってきました。
すると、昨今のオープンの波の為もあり、HTML + JavaScriptである部分、代替する人がちらほらと出始めました。
なーんだ、限定した使い方ならFlashじゃなくても、HTML + JSでいけるじゃん。
それに、チープな動きからだんたんとオープンのまま、進展してきたこともあり、オープンの波は大きくなります。
現在はおおよそはいけるんじゃないの?ってところまではきたと思います。
まあ、これはアニメーション型サイトから、コミュニケーション型サイトへ移ってきたことも、影響が大きいでしょう。
昔みたいに派手でこっていたアニメーションが嫌われることになったし、芸術的なサイトよりも、
機能的なサイトの方が価値が出始めてきました。
ただし、後一歩のところで、いろいろな意味でFlashに追いつかないのです。
それは細かい動きの部分もありますし、IEだとひたすら遅いとか・・・・
ここで、HTML5になればどうなるでしょうか?
まず、ブラウザが新しくなります。
当たり前ですが、これがブラウザを作っている方達からのHTML5を進める利点です。
これで細かい表現の違いによる影響が今よりは改善されるはずです。
ここで、IEの牙城を崩せればと思うはずです。
さらにブラウザを新しくするにはOSが新しくなります。(なりやすい)
大多数の方はブラウザだけをインストールなんてしません。
初めから入っているブラウザを使います。
そしてOSが新しくなれば、ハードが新しくなります。(同様になりやすい)
こちらも、OSだけの再インストールもしません。
最近ではOSのインストールもしたことがない、技術者だった当たり前にいるくらいですから・・・
つまり、速度は速くなります。
これで、速度面も解決していきます。
これだけでしょうか?
実は大きなのはコミュニティではないでしょうか?
なんか、LinuxとSolarisにちょっとにている気がします。
Linuxが不完全でチープで小さいうちにオープンに広まったからこそ、
その内部を知っている人が多く出てきました。
一方、Solarisは今でもLinuxよりもOSとしては完成されているのかもしれませんが、
今更オープンにしても、なかなか中身を見るには大きすぎるのです。
つまり、変化に勢いを感じることができないのです。
要するに、人の世代交換が、物の世代交換になったという事で、
物自体の価値というのはそれほど大きくはないのではないでしょうか?
ということで、HTML5が部分的にはFlashに変わっていくことはやむを得ない気がします。
しかし、一方で不安があります。
それは、プログラムがわからないデザイナがHTML5向けに使えるエディタが世の中に出てくるのか?
Adobeが自らのFlashをいらないと言わせるほどの、Dreamweaverを作るのか・・・とか。
あとは今まで、プログラムのソースを完全に自動で出力するツールが世の中で普及した事実を私は知りません。
それは、機能を作るのがプログラムであったから普及することが過去なかっただけなのか、それとも実用に耐えうるものができないからなのかは、
私には今のところはわかりません。
それと、もう一つ。
今でも、Ajaxのサイトは増えています。今はHTMLアプリはここが危険だ。とさんざん苦労して来た人たちがまだまだ作っています。
しかし、今から作るエンジニアをたくさん増えているのでしょうが、
それと同時に「危険だな-」という作りを平気でしてきます。
つまり、ちょっと詳しくなれば、「あー、これは簡単に攻撃ができるな」というサイトもたくさん出てくることでしょう。
かつて、CGIは難しいという時代に、PHPという言語は簡単なために急速に広まっていきましたが、一方で危険な言語の烙印も押されてしまいました。
そのおかげで、PHPという言語はバージョンが上がる毎にどんどん難しくなっています。
それはPHPという言語が危険というより、それを使う人のスキルが危険ということで、
それでも安全なようにと便利な機能がだんだんとなくなっていったのです。
(よい言い方をすれば、エンタープライズ向けになったという事です。)
そうすると、HTML5 + JSのサイトは危険な可能性があり、もっとセキュリティを考慮した物じゃないとだめだ-と声を上げる人も出てくるでしょう。
そしたら、FlashのPlayerにセキュリティホールがあろうと、Flashのほうがまだましだとなるかもしれません。
(Flash PlayerのセキュリティホールはAdobeさんが直しますが、自社で作ったJSのセキュリティホールは誰も直してくれませんから・・・)
ただし、どちらにしても言えることが、「必要以上に難しくなった」という気がします。
見た目のデザインと動きのデザインと、処理ロジックの3つの能力が必要になってきてしまったのですから・・・
前回、記したgmail port:587 での送信をas3cryptoを使用し試みた。
このために、airxmailもstarttlsコマンドに対応をした。
結果は・・・・・
SMTP over SSLと変わらず。
もしかして、ポートが異なれば違う動きをするかも?と淡い期待をしてみたが、やはり結果は同じだった。
メールサイズが大きくなると、エラーになってしまう。
(小さい物だと問題無いのも同様。)
まあ、結果的に同じ結果になったが、ほかのサーバでうまく動くケースもあるかもしれないので、
ただ、せっかくなので一応、後でgoogle codeのほうにコミットしておくことにはします。
airxmailもいろいろと使ってもらえるようになり、いろいろな人から意見やら、バグ報告やらいただいた。
アメリカやイギリスからも報告をいただき、本当にありがたいことです。
そして、問題もある程度見えてきました。
ただ、説明が不足している部分もあるようなので、時間があるときにデバッグの方法なんかも今後記述したいとは思います。
さて、現在の課題だが、以下の2点だろう。
1) SSL/TLSへの対応。
2) 大きな添付ファイルなどをつけた時に遅いこと。
問題1は、as3cryptoやAIR2のSecureSocketに責任を丸投げしてしまっているところがあったので、
あまり、作るときに真剣に考えなかったが、やはり何らかの対応は必要のようだ。
特に、SMTP over SSL では今のままの形になるが、STARTTLS( いわゆる Port : 587を使う)には何らかの対応が必要だろう。
(といっても、SSL/TLSライブラリを作ることからは始めないので、やはり今のas3cryptoなりの外部ライブラリで対応できなければ厳しい。)
現在、どうしてもgmailのSMTP over SSLで、as3cryptoを使うと通信の途中でエラーが起きてしまうのだ。
しかも、添付ファイルをつけた時に発生する。
また、AIR2でSecureSocketを使うと、今度はなぜかたまに接続に失敗する。接続に成功すれば、こちらは今のところ、1Mクラスの添付ファイルでもおくれるようです。
ただ、どうして接続が失敗するのかはわからないのです。接続自体が失敗しているので、この先に何もできないという状態です。
ということで、今の段階では、できるだけ接続手段を用意するという意味でも、STARTTLSに対応することが必要だろう。
問題2は、Base64のところが遅いのだと思われる。
このあたりも真剣に調査したわけではないのだが、前回、添付ファイルをつけた時にCRLFではなく、
LFにしてしまっていたあたりを調査した際にもはっきりと遅いな-とは思ったものだ。
ただ、こちらもflex標準のクラスを使っていることから、まあとりあえずは仕方がないなとしてしまった。
しかし、やはりエンコード/デコードは外部に出そうと思う。
まあ、そうすればエンコード・デコード部分だけで調査ができるし、ここを最適化するのもしやすくなるだろう。
しかし、これらの問題が解決しない場合も考えられる。
そこで、JAVA-AIRのブリッジという解決策も用意したいと考えている。
まあ、要するに、airxmailを使って送信しているようでも、実はJavaMailのAPIをたたいているだけという事だ。
そのためにも、airxmailのMimeMessageの構造を見直すことと、エンコード・デコードあたりは外部にださないいけないなという感じです。
airxmailで文字化けしますが・・・・という方いましたので、ちょっと詳しく説明することにしました。
そちらの方はご自分で解決していただけたようですが、確かにわかりにくい気もしますので・・・・
(ご報告していただいた方、ありがとうございました。)
airxmailでは、文字コードは何も設定しないと、JIS(ISO-2022-JP)に設定されます。
ただし、
if(Capabilities.language == "ja"){
return "ISO-2022-JP";
}
else{
return "UTF-8";
}
となっており、日本の環境でない(と判断された場合)には、UTF-8になる。
さらに、ただしがあり、文字コードにはairxmailでは2つある。
1つは、ヘッダの文字コードであり、(こちらは日本環境ではなければデフォルトはない。つまり、ASCII)
2つは、本文の文字コードである。
では、この設定を変更するにはどうすればいいかと言えば、
AirxMailConfig.setDefaultBodyCharset("UTF-8");
AirxMailConfig.setDefaultHeaderCharset("UTF-8");
とすることで、何も文字コードを設定していない場合には、UTF-8が使われることになる。
では、個別に文字コードを変えたい場合にはどうすればいいかと言えば、
サブジェクトの場合には
var mimeMsg:MimeMessage = new MimeMessage();
mimeMsg.setSubject("これでUTF-8になるよ","UTF-8");
本文の場合には・・・とこれがちょっとややこしい。
というか、あまりきちんと整理されていないし、こちらで細かくテストをしきれているわけではないので、
問題があるかもしれませんが・・・ので・・それでもやりたい方への一応説明。
(おかしい場所があったら、教えてくださればできるだけ対応します。)
まずは、普通のテキストメールの場合(マルチパートでない場合)には
ContentTypeのcharsetを見ます。
従って、
var mimeMsg:MimeMessage = new MimeMessage(ContentType.parseValue("text/plain; charset=Shift_JIS"));
のようにします。
ただし、これだけでは単なる文字コードがShift_JISになるだけなので、うまくいかないケースもあります。
(このあたりが電子メールの面倒なところです。できるだけ見えるようにするために多少のバグがあっても問題ないケースがあったりするのです。)
ただしくは、
var mimeMsg:MimeMessage = new MimeMessage(ContentType.parseValue("text/plain; charset=Shift_JIS"));
mimeMsg.transferEncoding = "8bit";
にしなければならないのです。
ちなみに、UTF-8にしたときには、自動的にこちらを”8bit”にしてしまいます。
(だったら、SJISとかもすればいいじゃないか・・・かな・・・)
もう一つは、テキストパートの場合です。
こちらは、MimeMessage(ただしくはその親クラスのMimeMultiPart)にcreateTextPart()というメソッドがあります。
こちらの実装が、以下のようになっています。
public function createTextPart(charset:String = null,transferEnc:String = "7bit"):MimeTextPart{
var part:MimeTextPart = new MimeTextPart();
if(charset){
part.contentType.setParameter("charset",charset);
}
part.transferEncoding = transferEnc;
this.addChildPart(part);
return part;
}
つまり、引数に文字コードを渡してもいいですし、返ってきたオブジェクトのcontentTypeのcharsetにセットしてもいいわけです。
こちらも同様に、設定した文字コードに対応するtransferEncodingを設定する必要があります。
ちなみに、文字化けするが意味がわからない。いったいどこでおかしくなってるんだ。
という方は、リビジョン53で、DirSenderというクラスを追加しました。
こちら、メールを送る代わりに、ローカルのディレクトリにファイルで書き出します。
//var sender:IMailSender = new SMTPSender(); var sender:IMailSender = new DirSender();
と、クラス名だけ変えてもらえば、それで動くようになります。
File.userDirectory.resolvePath(“airxmail”);
のディレクトリに書き出します。
JAVAで透過するウィンドウや、独自シェイプのウィンドウを作成する方法のメモ。
ただし、すべての環境でできるわけではないので注意。
(すべての環境でこれを実現するには、Robotを使って画面をキャプチャしてから、その上に自分で作成していくなどの方法が必要になる。)
基本的に、詳しい説明は以下のサイトにあるのでそちらで
http://java.sun.com/developer/technicalArticles/GUI/translucent_shaped_windows/
さて、この方法をEclipse上で開発を行っていると、
「アクセス制限: 型 AWTUtilities は必須ライブラリー C:\Program Files\Java\jre6\lib\rt.jar で制限されているためアクセスできません」
とエラーになってしまい使えません。
でも、これを以下のようにして強制的に使ってしまいます。
import org.apache.commons.lang.reflect.MethodUtils;
:
Class clz = Class.forName("com.sun.awt.AWTUtilities");
if(clz != null){
try{
Object[] args1 = {frame,bg};
Class[] types1 = {Window.class,Shape.class};
MethodUtils.invokeExactStaticMethod(clz, "setWindowShape",args1,types1);
Object[] args2 = {frame,0.8f};
Class[] types2 = {Window.class,float.class};
MethodUtils.invokeExactStaticMethod(clz, "setWindowOpacity", args2,types2);
}
catch(Exception ex){}
こんな感じにReflectionを使ってしまいます。
ただし、Reflectもすべて自前で行ってもそれほど面倒でもないのですが、
ここでは、ほかの理由もあってすでにApache commonsのlangライブラリを使っていたので、そちらを使いました。
OSGiのすべてのサービスをきちんと落とす方法がわからない。
そもそも、停止する側もサービスの一部なのに、停止できるのかなやんだ。
きちんと止められるならば、必ず、もっと上位のクラスからstopできるはずと調べてしまった。
BundleContextからすべてのBundleを取得して、それぞれをstop()していくと、エラーが発生する。
そもそも、依存関係がわからないにの、順番におとしていいのかもよくわからない。
でも、いろいろ試していたら、
context.getBundle(0).stop()
で、私の思い通りには止まっているようだ。
ただ、これでJAVAのプロセスが止まるわけではないので、次に
System.exit(0);
としてやる。
これで本当に問題無いのかはわからないが、今のところ、特に問題になる感じもない。
まあ、いきなりSystem.exit(0)をやっても、それほど問題無いのだが・・・・
多少AIRにも限界を感じてきたところで、JavaとFlashのブリッジを考えながらサーバを作ってきた。
せっかくだから、AIRとJavaではなく、やはり(ブラウザ上の)Flashも対象にしたいとおもっていたので、
XMLSocketで通信をしていて、だいぶ形になってきた。
また、Java側は結局OSGiを使うことでだいぶ柔軟な感じにできるようになってきた。
たとえば、今、ローカルのFileSystemにアクセスするモジュールを作りながら確認をしているが、
OSGiならばそのモジュールを動的に追加することも、削除することも可能だ。
だから、極端な話Coreな部分だけ初めにローカルにインストールしてあれば、
後は、更新、追加は動的にそれなりに簡単にできる。
要するにブラウザからモジュールの追加、更新ができるわけだ。
(まあ、それがいいかわからないが・・・・)
それなりに強力な事ができてしまうと、それを抑制するほうも考えなければいけない。
というわけで、それをコントロールする機能もOSGiのモジュールとして作ろうと思う。
どんな感じがセキュリティ上いいのかなと思っていたが、
まずは、接続を試みてきたら、POPUPで接続の許可を求めてくる感じでいいだろう。
1クライアントにつき、基本的には1接続だからそんなに面倒ではないはずだ。
AIRの配布が署名なんかも含めて面倒な感じもするので、ブラウザベースでGUIはWEBで配信し、
処理の実装はJavaでローカルで動くってのも、また、おもしろいRIAの形ではないだろうか?
と個人的にはおもっているのだが、どうであろうか?
データがローカルからしかアクセスできないような制限のある業務においても、
RIAを適用できるようになるとおもう。
あとは、よーくWEBのグループウェアを使っている人から出てくるクレーム(文句)で、
ブラウザの外にメールがきたことを通知できないとか・・・
技術的には当たり前と言えば当たり前なのだが、これが業務をやっている人には結構なストレスらしい。
(まあ、今やメールも電話と同様に、きたらすぐに対応しなければいけなくなってきていますからね・・・・)
以前、規定のJavaのオブジェクトをAMFを用いてas3上のクラスにマッピングする方法を記述しましたが、
今回は、任意のJavaクラス(自分で作成したJavaクラス)についてです。
1.Javaのクラス定義の際にjava.io.Externalizableインターフェイスを実装する
以下は必要となるメソッドのみを抜粋しています。
@Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
isDirectory = in.readBoolean();
isFile = in.readBoolean();
isAbsolute = in.readBoolean();
isHidden = in.readBoolean();
absolutePath = (String)in.readObject();
canonicalPath = (String)in.readObject();
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeBoolean(isDirectory);
out.writeBoolean(isFile);
out.writeBoolean(isAbsolute);
out.writeBoolean(isHidden);
out.writeObject(absolutePath);
out.writeObject(canonicalPath);
}
という感じに、readExternal()とwriteExternalを実装する必要があります。
2.AS3上でflash.utils.IExternalizableインターフェイスを実装したクラスを作成する
AS3上でもJavaと同様な感じにします。
public function writeExternal(output:IDataOutput):void{
output.writeBoolean(isDirectory);
output.writeBoolean(isFile);
output.writeBoolean(isAbsolute);
output.writeBoolean(isHidden);
output.writeFloat(lastModifed);
output.writeFloat(length);
output.writeObject(absolutePath);
output.writeObject(canonicalPath);
}
public function readExternal(input:IDataInput):void{
isDirectory = input.readBoolean();
isFile = input.readBoolean();
isAbsolute = input.readBoolean();
isHidden = input.readBoolean();
lastModifed = input.readDouble();
length = input.readDouble();
absolutePath = input.readObject();
canonicalPath = input.readObject();
}
3.AS3上のクラスに対して、RemoteClassの指定をする。
[RemoteClass ( alias="com.coltware.serene.service.file.JFile") ]
public class JFile implements IExternalizable{
// 省略
}
という感じになります。



