2012-05-20

PDFの参考資料

PDFの一部の出力を自力でしたいと思いPDFの仕様を調べています。参考になりそうなURLをまとめてみました(追記するかも)。

2012-05-14

PHP: evalとPHPタグ

PHPのevalの項にはこういうことが書いてあるのです。

PHP 開始タグを含めてはいけません。つまり、 '<? echo "Hi!"; >' ではなく 'echo "Hi!";' を渡さなければならないということです。 適切に PHP タグを使えば、PHP モードからいったん抜けてもう一度 PHP モードに戻るということも可能です。 たとえば、このようになります。 'echo "PHP モード!"; ?>HTML モード!<? echo "ふたたび PHP モード!";'

PHPの終了タグはもともと省略できる(PHP ManualのPHPタグの項では 「ファイル全体が純粋な PHP コードである場合は、ファイルの最後の終了タグは省略するのがおすすめ」 とさえ言っている)ので、それを踏まえてみるとPHPのeval()ってコードの直前に単純にPHPの開始タグ付けてPHP再実行したような手抜き感(?)が見えなくもないのですが…なのでPHPタグで囲われた文字列をeval()で評価したい場合は eval('?>' . $code); でいけます。開始タグがついているかどうかわからない場合は eval(preg_replace('/\A\s*<\?php/', '', $code, 1)); でいいのかなと思います。どういうものが入っているかわからないところから引っ張ってきた文字列をeval()するのは避けたほうがいいですけど…

2012-05-11

Haml: Hamlでの属性のいくつかの書き方

Hamlは便利だけど属性を書くのがすこし面倒…と思っていたんですがHTML-style Attributesという書き方があるのを最近知りました。 HTMLの属性の書き方に近くて書くのがとても楽です。

他の書き方との比較のため、Hamlでの属性の書き方をいくつか並べてみました。

4番目の書き方も短いけどやっぱり1番目の書き方が一番短くてわかりやすいです。

2012-05-06

jQuery: 空白テキストノードの除去

リストをinlineで並べた時の余白 - CSS HappyLife であるような空白を除去するために一行でソース書いたりコメントで何とかすることができない状況に遭遇した(TumblrテーマでPostの繰り返しのとき改行が入ってしまう)のでjQueryで空白テキストノードを除去してみました。コードはstackoverflowのものと同じです(Node#nodeValueだとタイプ数が面倒なのでCharacterData#dataにした以外は)。

ただ実際やってみるとページ表示の際に除去前と後の動きが見えてしまうので結局ネガティブマージンで調整しました…。

2012-05-01

Fire.appのビルド

MOONGIFTで紹介されていたFire.appを試してみようとFire.appの公式サイトに行ってみたんですが、無料で使う場合は自分でビルドする必要があるそうでビルド方法が載っているページが見当たらなかったのでビルド方法を記録しておきます(Mac OS X Lion上。RVMはインストール済とします)。

試しに実行だけしてみる場合:

rvm install jruby
rvm use jruby
gem install rawr
git clone https://github.com/handlino/FireApp.git
cd FireApp
bin/startJar-osx.sh

パッケージとしてアプリケーションフォルダに入れる場合(bin/startJar-osx.shに代えて下記を実行):

bin/build-all.sh
cp -r packages/osx/Fire.app /Applications

build-all.sh中にlaunch4j: Launch of “windres” failed: the PowerPC architecture is no longer supported.と言われていてWindows用のexeは上手く生成できていないみたいです。「org.bluestemsoftware.open.maven.plugin」の「launch4j-plugin」をLion(OS X 10.7)で実行する方法 (Kanasansoft Web Lab.) が参考になりそうなので気が向いたら試してみます(よかったら試してみて下さい)。

追記(2012-05-11)

Rakefileを見落としていました…。Macでパッケージするならbin/startJar-osx.shの代わりに下記で大丈夫でした。

rake rawr:bundle:app
cp –r packages/osx/File.app /Applications

2012-04-29

The provided compiler '/usr/bin/gcc' is LLVM based, it is not yet fully supported by ruby and gems, please read `rvm requirements`.

Mac OS X Lion上でOctopressを試してみようとしたところrvm installが失敗していました。

nissuk% rvm install ruby-1.9.2-p320
Fetching yaml-0.1.4.tar.gz to /Users/nissuk/.rvm/archives
Extracting yaml-0.1.4.tar.gz to /Users/nissuk/.rvm/src
Configuring yaml in /Users/nissuk/.rvm/src/yaml-0.1.4.
Compiling yaml in /Users/nissuk/.rvm/src/yaml-0.1.4.
Installing yaml to /Users/nissuk/.rvm/usr
The provided compiler '/usr/bin/gcc' is LLVM based, it is not yet fully supported by ruby and gems, please read `rvm requirements`.

GCCがXCodeのllvm-gccだとだめだそうで…

nissuk% gcc --version
i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.9.00)
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Can’t install Ruby under Lion with RVM – GCC issues - Stack Overflow の回答を参考に--with-gcc=clangしたところ一応通りましたが clang: error: unsupported option '--with-libyaml' と言われていて全部は入っていないみたい…動くのかな?

nissuk% rvm install ruby-1.9.2-p320 --with-gcc=clang
Fetching yaml-0.1.4.tar.gz to /Users/nissuk/.rvm/archives
Extracting yaml-0.1.4.tar.gz to /Users/nissuk/.rvm/src
Configuring yaml in /Users/nissuk/.rvm/src/yaml-0.1.4.
Compiling yaml in /Users/nissuk/.rvm/src/yaml-0.1.4.
Installing yaml to /Users/nissuk/.rvm/usr
clang: error: unsupported option '--with-libyaml'
Building 'ruby-1.9.2-p320' using clang - but it's not (fully) supported, expect errors.
Installing Ruby from source to: /Users/nissuk/.rvm/rubies/ruby-1.9.2-p320, this may take a while depending on your cpu(s)...

ruby-1.9.2-p320 - #fetching 
ruby-1.9.2-p320 - #downloading ruby-1.9.2-p320, this may take a while depending on your connection...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 8770k  100 8770k    0     0   718k      0  0:00:12  0:00:12 --:--:--  508k
ruby-1.9.2-p320 - #extracting ruby-1.9.2-p320 to /Users/nissuk/.rvm/src/ruby-1.9.2-p320
ruby-1.9.2-p320 - #extracted to /Users/nissuk/.rvm/src/ruby-1.9.2-p320
ruby-1.9.2-p320 - #configuring 
ruby-1.9.2-p320 - #compiling 
ruby-1.9.2-p320 - #installing 
Retrieving rubygems-1.8.24
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  371k  100  371k    0     0   551k      0 --:--:-- --:--:-- --:--:-- 1416k
Extracting rubygems-1.8.24 ...
Removing old Rubygems files...
Installing rubygems-1.8.24 for ruby-1.9.2-p320 ...
Installation of rubygems completed successfully.
ruby-1.9.2-p320 - adjusting #shebangs for (gem irb erb ri rdoc testrb rake).
ruby-1.9.2-p320 - #importing default gemsets (/Users/nissuk/.rvm/gemsets/)
Install of ruby-1.9.2-p320 - #complete 
clang: error: unsupported option '--with-libyaml'
Ruby 'ruby-1.9.2-p320' was build using clang - but it's not (fully) supported, expect errors.

2012-04-26

C#: Excelの読み込み(DataSet)

Visual Studio 2008のC# (C# 3.0 / .NET 3.5)でExcelを読み込むのにADO.NETの型付DataSetが使えればそれを使いたかったんですけどデータソースの設定ウィザードで設定を進めていくと 「Microsoft.VisualStudio.DataDesign.SyncDesigner.SyncFacade.SyncManager を読み込めませんでした」みたいに言われて先に進めないので普通のDataSetで読み込むことにしました。

Excelの一行目を列名として認識してくれる…

SyncManagerの件はVisual Studio 2008のService Pack(SP1)適用したら直りました。

2012-04-22

Google ChromeのアドレスバーとTLD

ドメインのTLDが「.local」だと「.com」等と同様にスキーム名(「http:」「http://」)をつけずに「example.local」のようにChromeのアドレスバーに入力してアドレスとして認識してくれることに気づいたので、最近はApacheでテスト環境を整備するときVirtualHostとhostsに設定するホスト名に「.local」を使っています(前「.localhost」を使っていましたがとても面倒でした…)。

テスト・例示用に使う他のTLDだとChromeにアドレスとして認識されるか気になったので試してみましたが何故か「.local」しか認識しないみたいでした。

表: Google Chrome(18.0.1025.162)のアドレスバーにドメインのみ入力してアドレスとして認識されるか (○: 認識される、×: 認識されない)
TLD 出典 結果
.local example.local -
.localhost example.localhost RFC 2606 ×
.test example.test RFC 2606 ×
.example example.example RFC 2606 ×
.invalid example.invalid RFC 2606 ×

「example.localhost/」のようにスラッシュをつけたらアドレスとして認識してくれました。これでもいいかも

2012-04-21

さくらのレンタルサーバ、ドメインキングのMySQLに外部から接続する

さくらのレンタルサーバの場合

さくらのレンタルサーバはSSHが使えるのでSSHポートフォワード経由でMySQLにアクセスできました。 ロリポップでもチカッパプランならSSHが使えるので同様のことができる気がします…(未検証です)。

1. SSHポートフォワードの設定

Tera Term(4.72)を使う場合は下記の手順で設定できます。

  1. メニューの 設定 > SSH転送 を選択
    image
  2. SSHポート転送画面で「追加」
    image
  3. ポート転送を行う向きの選択で「ローカルのポート」、ローカルで使うポート番号(例えば3306)、リモート側ホスト(例えばmysql00.sakura.ne.jp)、ポート(3306)を入力して「OK」
    image 

sshコマンド(Windowsならmsysgit等に入っています)を使う場合は下記で設定できます。

ssh -N -f -L ローカルで使うポート:DBホスト名:3306 サーバのユーザ名@サーバのホスト名

例えばDBホスト名が「mysql00.db.sakura.ne.jp」、ユーザ名が「user」の場合は下記です。

ssh -N -f -L 3306:mysql00.db.sakura.ne.jp:3306 user@user.sakura.ne.jp
2. 接続の確認

手っ取り早くMySQLクライアントで接続できるか試します。接続後クエリを投げてみて動くことを確認して下さい。

mysql -u サーバのユーザ名 -p

(ホストはlocalhostなので-h localhostをつけてもつけなくてもよいです。ローカルで使うポートを3306以外にした場合は「-P ポート番号」をつけます)

ドメインキングの場合

意外でしたがドメインキングは何もしなくても外部からアクセスできました。 サーバに設定したドメインが「example.com」、作成したユーザ名が「user」の場合、MySQLクライアントで下記のようにアクセスできます。

mysql -h example.com -u user -p

2012-04-17

キャメルケース補完

EclipseやVisual Studioなんかだと、キャメルケースで補完できますからね。
GetApplicationConfigurationString→SACS
SaveAllChangeSetToDatabase→SACSTD
見たいな感じで。
意外と知らない人もいるみたいですが、タイピングのリズムもいいし、好きな機能です。

長い関数名、変数名、どこまで許せる? | スラッシュドット・ジャパン デベロッパー

このコメント見るまで知らなかったので…Visual Studioでやってみました(手元にあったVisual C# 2010 Expressの例。Eclipseの例は Eclipseショートカットキーまとめ - watawata日記 にありました。Eclipseのショートカットについてとても参考になります。あとこの記事を真似してBB FlashBackを使ってみました)。

長い名前といえばDOM、ということで 連載! とことん C#: 第 22 回 LINQ to XML で楽々 XML 文書処理 のDOMのサンプルコードを入力しています。


Visual Studio 2008だとできないみたい…?

2012-04-15

Apache: RewriteBaseは書き換え後のパスのベース

mod_rewriteでURLの書き換えルールを書く機会は頻繁にあるわけではないので、いざルールを書くとなるといろいろ忘れていて結構時間を取られます…。今日はmod_rewriteのRewriteBaseとその周辺についてまとめておきたいと思います。

例えば

  1. サーバのドキュメントルートが /var/www/vhosts/example.local/
  2. サーバのURLが http://example.local/
  3. http://example.local/abc/def.html に来たアクセスを http://example.local/abc/ghi.html に書き換えたい
  4. そのためドキュメントルートの.htaccess(/var/www/vhosts/example.local/.htaccess)に書き換えルールを書く

とき、RewriteBase /abcとか/abc/にしてやれば下記のように書けるかな…と考えて

RewriteEngine On
RewriteBase /abc
RewriteRule ^def\.html$ ghi.html [L]

と書いても書き換えはできません。RewriteBaseは書き換え後のパス指定(例だとghi.html)が相対パスだった時にそこに使われる(例だと/abc/ghi.html)だけで、マッチパターン(例だと^def\.html$)には全く関係しないので下記のように書く必要があります。

RewriteEngine On
RewriteBase /abc
RewriteRule ^abc/def\.html$ ghi.html [L]

ところで下記は×です。

RewriteEngine On
RewriteBase /abc
RewriteRule ^/abc/def\.html$ ghi.html [L]

ネット上を調べると上記例のようにRewriteRuleのマッチパターンをスラッシュ(/)から始めている記述がありますが、RewriteRuleに渡ってくるパスがスラッシュから始まるのはhttpd.confにRewriteRuleを書いた時だけで、.htaccessに書いた時は.htaccessが置いてあるディレクトリからの相対パス(上記例だと abc/def.html。RewriteLogで「strip per-dir prefix」と書かれている箇所)がRewriteRuleに渡ってくるため最初のスラッシュがマッチしなくなります。

RewriteBaseを使わない場合

RewriteBaseを使わない場合は下記のように書けます。

RewriteEngine On
RewriteRule ^abc/def\.html$ /abc/ghi.html [L]

書き換え後のパス(例だと/abc/ghi.html)が相対パスではなくURLの絶対パスなのでRewriteBaseを気にする必要がありません。

ところでRewriteBaseを指定しなかった場合の既定値は.htaccessを置いたディレクトリの物理パスです。そしてRewriteBaseは書き換え後の相対パスのベースです。つまり上記例に加えて下記の3つはすべて結果的に同じです。

RewriteEngine On
RewriteRule ^abc/def\.html$ abc/ghi.html [L]
RewriteEngine On
RewriteBase /var/www/vhosts/example.local/abc
RewriteRule ^abc/def\.html$ ghi.html [L]
RewriteEngine On
RewriteRule ^abc/def\.html$ /var/www/vhosts/example.local/abc/ghi.html [L]

なぜURLでも物理パスでもいいのかはRewriteLogを見るとわかりますが、書き換え後のパスが物理パスだった場合RewriteRuleでパターンマッチして内部リダイレクトさせる前に「strip document_root prefix」という形でドキュメントルートの物理パスを取り除いているためです。

ただし外部リダイレクト(RewriteRuleにRフラグをつける)にすると話は変わってきて、例えば下記のようにすると

RewriteEngine On
RewriteRule ^abc/def\.html$ /var/www/vhosts/example.local/abc/ghi.html [R,L]

ドキュメントルートの物理パスを取り除かずに外部リダイレクトするので結果としてhttp://example.local/var/www/vhosts/example.local/abc/ghi.html にアクセスしてしまいます。

まとめ

まとめとしてはタイトルの通りですが、mod_rewriteはややこしいです。RewriteBase以外でもしょっちゅうはまります。RewriteLogを見れば内部でどうやって書き換えが行われているのかが記録されるので、mod_rewriteが意図しない動作をするときはRewriteLogを見ましょう(RewriteLogについてはできれば後日まとめたいと思いますが、RewriteLogLevel - Httpd Wiki にあるようなログが確認できます)。

2012-04-12

Java: Exifから位置情報を取得する(Sanselan)

Apache CommonsのSanselanを使うと写真の位置情報(緯度と経度)が簡単に取得できます。下記の例では写真("test.jpg”)の位置情報を単純に取得して出力します。

上記と「2地点の緯度と経度からおおよその距離を計算する」を組み合わせると写真の位置情報から写真を自動的に場所ごとのフォルダに振り分けたりすることができます。

2地点の緯度と経度からおおよその距離を計算する

球面三角法(PDF) の最後の「3-2. 地上の2地点間の距離」がわかりやすかったので少し引用します。

image

図の太線で囲まれた球面三角形に余弦法則を適用すると

であり、

によって x を計算できる。この場合は0≦ x ≦ 180°なので、cos-1によって得た結果にあいまいさは無い。2地点間の距離 L は、

によって計算できる。ただし x はラジアンの値にしておくことが必要である。

プログラム(Java)で書くと下のような感じです。度はラジアンにします(* Math.PI / 180で変換していますがJavaならMath.toRadians()でもいいです。PHPならdeg2rad())。

 

カシオの計算サイトに同様の計算式で距離を計算するフォームがあって便利でした。

2012-04-10

PgcEdit: 自動ループ再生DVD

DVD Shrinkで複数VOBを1つにまとめたDVDのループ再生(リピート)が上手くいかなかったのでPgcEditを使ってループさせるようにしました。

  1. http://download.videohelp.com/r0lz/pgcedit/ からPgcEditとShrinkプラグインをダウンロードして解凍
  2. PgcEditを一旦起動してpluginsフォルダを生成してもらう
  3. Shrinkプラグイン(dvdshrink_plugin.tcl)をpluginsフォルダに放り込む
  4. PgcEditを起動し直してDVDデータのあるフォルダを開く
  5. plugins > DVDShrink > Enhance and fix authoringを選択
    image
  6. 「loop back to the beginning of the first title.」にチェックしてOKimage
  7. 保存

確認のためDVDデータをISOに変換、Daemon ToolsでマウントしてWindows Media Playerで再生してみたところ「この DVD は、ユーザーの国/地域での再生が禁止されているため、再生できません。地域にあったディスクを入力して下さい。」と言われてしまいました(リージョンのエラー?Daemon ToolsのデバイスパラメータのDVD地域は問題ないです)。PgcEditのせいかと思いましたが手元の環境ではShrinkでVOB編集して作成したISOの場合Deamon ToolsでマウントするとPgcEdit関係なく同じエラーが出ていました…。

Windows Media PlayerでIFOを再生してみるか再生プレイヤーをVLC Media Playerにして確認するか実際にDVDに書き込むかすれば確認できるみたいです。

2012-04-08

Antタスクのデバッグ (S2JDBC-Gen)

S2JDBC-Genのgen-entity等が出力するコードを変更するのに内部動作を調べていたんですがAntでそのままgen-entityタスクを実行するとEclipseでブレークポイントを付けても止まらないので Ant カスタムタスクのデバッグ方法:アーキテクト360を参考に下記のようなコードを書いて実行しています(Antのant.jarとant-launcher.jarが必要です)。

public class AntDebug {
public static void main(String[] args) {
org.apache.tools.ant.Main.main(
"-f s2jdbc-gen-build.xml gen-entity".split(" "));
}
}

これでS2JDBC-Gen(s2jdbc-gen-2.4.43.jar)内のclassファイルにブレークポイントを付けて止めることはできましたが、そのままだとソースを書き換えてテストすることができないので Seasar2 – Downloads からS2JDBC-Genのソース群をダウンロードしてsrc/main/java以下にjarと同じ構成で配置します。これでjarを弄らなくてもソースの方を変更すれば変更が反映されます(エラーになるファイルが若干ありましたが今回調べたかった箇所はエラーになるファイルが不要だったため単純に削除するだけで大丈夫でした) 。

また GenerateServiceCommand#doExecute() 等の中にブレークポイントを付けてもそれを呼び出している AbstractTask#executeCommand() がコマンドをJavaタスク内で実行しているせいかブレークポイントで止まらないので取り急ぎToStringBuilderを使って変数の内容を出力して確認しています…。

それとgen-entityした後の生成ファイル群を削除するのがすごく面倒だなぁ…と思いgen-entityする直前の状態をgit commit → gen-entity後にgit clean -dfで生成されたファイルをすべて削除、とすることで対処しています。便利ですがその後にEclipseのメニューで プロジェクト > クリーン しておかないと実行した時に「log4j:WARN No appenders could be found for logger」等と言われてエラーになるので注意です。

2012-04-05

Eclipse: テンプレートで使用するパッケージを自動でimportさせる

(Eclipse 3.7 Indigo Pleiades All In One)

普通にテンプレートを書いて挿入するとパッケージのimportがされていなくてエラーになることがありますが、テンプレート変数のimportでimportの設定ができるそうです。

${:import([type[,type]*])}
すでにインポートされていない各タイプのインポート・ステートメントを追加します。競合するイン
ポートが存在する場合、何も実行しません。何にも評価されません。

例:
${:import(java.util.List, java.util.Collection)}

commons-langのToStringBuilderとlog4jでPHPのvar_dump()のようにオブジェクトのダンプをするコードのテンプレートを作成する場合は下記のように記述すればOKでした。

${:import(org.apache.log4j.Logger, org.apache.commons.lang3.builder.ToStringBuilder, org.apache.commons.lang3.builder.ToStringStyle)}Logger.getLogger(getClass()).debug(ToStringBuilder.reflectionToString(${cursor}, ToStringStyle.MULTI_LINE_STYLE));

Eclipseテンプレート

${:import}の行末で改行するとインデントの調整がずれる(以降の行もimportのインデントレベルと同じインデントレベルになる)ので${:import}の行末では改行しないほうがいいみたいです。

2012-03-22

Java: スーパークラスのフィールドの書き換え

スーパークラスのフィールドをサブクラスでオーバーライドしようとしてもフィールドはオーバーライドではなく隠蔽という形になるので、サブクラスをスーパークラスのインスタンスとして扱うときにはオーバーライドしたつもりのフィールドの値がスーパークラスのフィールドの値になってしまいます(例のためfieldをpublicにしています)。

public class A {
	public String field = "A";
}
public class SubA extends A {
	public String field = "SubA";
}
public class Main {
	public static void main(String[] args) {
		SubA subA = new SubA();
		A a = subA;

		System.out.println(subA.field); // SubA
		System.out.println(a.field); // A ← SubAになってほしい
	}
}

スーパークラスとして扱っていてもサブクラスのフィールドの値を参照させたかったので、どうすればできるか試しました。

1. スーパークラスのメソッドを経由する → ×

スーパークラスにメソッドを定義してメソッド経由でフィールドにアクセスさせてもスーパークラスのメソッドがアクセスするのはスーパークラスのフィールドなので、そのメソッドを継承してきたサブクラスでもメソッド内ではスーパークラスのフィールドにアクセスしてしまいます。

public class A {
	public String field = "A";
	public String getField() {
		return field;
	}
}
public class SubA extends A {
	public String field = "SubA";
}
public class Main {
	public static void main(String[] args) {
		SubA subA = new SubA();
		A a = subA;

		System.out.println(subA.getField()); // A ← SubAになってほしい
		System.out.println(a.getField()); // A ← SubAになってほしい
	}
}

2. サブクラスで同名のフィールドを定義せず、コンストラクタ等でフィールドの値を書き換える → ○

これだとフィールドの隠蔽がされないのでサブクラスでは常にスーパークラスのfieldにアクセスするようになります。

public class A {
	public String field = "A";
	public String getField() {
		return field;
	}
}
public class SubA extends A {
	public SubA() {
		field = "SubA";
	}
}
public class Main {
	public static void main(String[] args) {
		SubA subA = new SubA();
		A a = subA;

		System.out.println(subA.getField()); // SubA
		System.out.println(a.getField()); // SubA
	}
}

サブクラスで同名フィールドを定義してしまうと×です。

3. コンストラクタ等で明示的にスーパークラスのフィールドの値を書き換える → ○

サブクラスで同名フィールドを定義していても、superキーワード経由でフィールドにアクセスすればスーパークラスのフィールドを書き換えられます。

public class A {
	public String field = "A";
	public String getField() {
		return field;
	}
}
public class SubA extends A {
	public String field = "SubA";
	public SubA() {
		super.field = this.field;
	}
}
public class Main {
	public static void main(String[] args) {
		SubA subA = new SubA();
		A a = subA;

		System.out.println(subA.getField()); // SubA
		System.out.println(a.getField()); // SubA
	}
}

4. オーバーライドしたメソッドを経由する → ○

サブクラスでスーパークラスと同じメソッドを定義してオーバーライドします。オーバーライドしたサブクラスのメソッドはサブクラスのフィールドにアクセスしてくれます(スーパークラスのフィールドを書き換えたわけではないですが)。ただスーパークラスとサブクラスで同じメソッドを書いているので無駄な感じがします…。

public class A {
	public String field = "A";
	public String getField() {
		return field;
	}
}
public class SubA extends A {
	public String field = "SubA";
	@Override
	public String getField() {
		return field;
	}
}
public class Main {
	public static void main(String[] args) {
		SubA subA = new SubA();
		A a = subA;

		System.out.println(subA.getField()); // SubA
		System.out.println(a.getField()); // SubA
	}
}

静的フィールドの場合

静的フィールドもサブクラスで同名フィールドを定義するとオーバーライドではなく隠蔽になります。またインスタンスメソッドと違い静的メソッドも隠蔽になるので上記4の方法は使えません。2だと問題ありません。3の場合…

public class A {
	public static String FIELD = "A";
	public static String getField() {
		return FIELD;
	}
}
public class SubA extends A {
	public static String FIELD = "SubA";
	static {
		A.FIELD = FIELD;
	}
}
public class Main {
	public static void main(String[] args) {
		System.out.println(SubA.getField()); // SubA
		System.out.println(A.getField()); // SubA
	}
}

static初期化子等の中でsuperが使えないのでクラス名を直に書かないといけません。

ただスーパークラスの静的フィールドを書き換えてしまうと影響が大きいのでやめたほうがいいです…。

2012-03-17

XAMPP(1.7.4): Apacheが起動しない

XAMPP(今使っているのはEclipse 3.7 Indigo Pleiades All in Oneに同梱されている1.7.4です)のコントロールパネルでApacheを起動しようとしても「Busy…」と言われて起動しない時があります。Apacheの標準設定ではポート80(HTTP)と443(SSL)をlistenするので、Apacheを起動させる前に他のプロセスに80や443を使われていると起動できません。

80、443を使うプロセス

遭遇したことのあるものではSkype、TeamViewerが80と443を使っていました。SkypeとTeamViewerは80と443を使わないように設定できます。

image
Skype (80, 443を使わないように設定した状態)

image
TeamViewer (80, 443を使わないように設定した状態)

80を使うプロセス

遭遇したことのあるものではGladinet Cloud Desktopが80を使っていました。設定変更は見つかりませんでした…誰か知っている人いたら教えて下さい…。

443を使うプロセス

遭遇したことのあるものではサービスのRouting and Remote Accessが443を使っていました。

image
Routing and Remote Access (無効にした状態)

何のプロセスが先にポートを使っているかわからないので、Apacheのconf/httpd.confとconf/extra/httpd-ssl.confに設定されているListen 80、Listen 443を変えたほうがイライラしなくてすむかもしれません(個人的に基本はVMware + CentOS + Apache、突発のものはXAMPPという形で作業しているので、自分はListen先を変えました)。

2012-03-14

EC-CUBE(2.11.5): パスワードのハッシュ化処理

Webシステムではユーザのパスワードはsha1等のハッシュアルゴリズムを使ってハッシュ化(暗号化)してDBに保存するのが普通です。今日はEC-CUBEの管理者のパスワードがわからなかったのでどのようにパスワードをハッシュ化しているか調べていました。

EC-CUBE(2.11系)では基本的には下記の要領でパスワードハッシュを生成しているようです。

hash_hmac(PASSWORD_HASH_ALGOS, "生パスワード:AUTH_MAGIC", salt);
PASSWORD_HASH_ALGOS data/config/config.php内のPASSWORD_HASH_ALGOSの値(“sha256”等)
生パスワード 入力するパスワード
AUTH_MAGIC data/config/config.php内のAUTH_MAGICの値
salt dtb_member(管理者)またはdtb_customer(会員)テーブルのsaltの値

ハッシュ化の処理はSC_Utils(data/class/util/SC_Utils.php)のsfGetHashString()が行なっていました。

/**
     * パスワードのハッシュ化
     *
     * @param string $str 暗号化したい文言
     * @param string $salt salt
     * @return string ハッシュ暗号化された文字列
     */
    function sfGetHashString($str, $salt) {
        $res = '';
        if ($salt == '') {
            $salt = AUTH_MAGIC;
        }
        if ( AUTH_TYPE == 'PLAIN') {
            $res = $str;
        } else {
            $res = hash_hmac(PASSWORD_HASH_ALGOS, $str . ":" . AUTH_MAGIC, $salt);
        }
        return $res;
    }

2012-03-11

Fiddler(2.3.9.3): サーバ上のファイルを一時的に置き換える

サーバ上にあるファイル(CSS、JS、画像ファイル等)を修正したりデバッグしたいとき、修正ファイルをサーバにアップロードせずにテストできると便利です(アップロード→確認 を何回も繰り返す必要がなくなるため)。

Fiddlerを使うと、下のような手順でサーバ上のファイルを置き換えることができます(例としてサンプルのJavaScriptを書き換えてみます。Fiddlerの説明については「実はFiddlerがすごすぎたので、機能まとめ紹介 :  blog.loadlimit - digital matter -」が詳しいです)。

  1. サーバにある書き換えたいファイルをローカルに保存しておく
    今回の例では http://dl.dropbox.com/u/5447955/test/20120312/js/script.js
  2. Fiddlerを起動する
  3. サーバにある書き換えたいファイルをブラウザで開く(すでに開いていれば再読み込み)
  4. Fiddler左側にログがたまっていくので、そこから該当するファイルの項目を見つけておく
    image
  5. Fiddler右側のAutoResponderタブを表示する
    image
  6. 「Enable automatic responses」「Unmatched requests passthrough」にチェックを入れる
    image
  7. 4.の項目を右側にドラッグする
    image
  8. Rule Editorの下側を「find a file…」にして1.のファイルを指定する
    image
  9. 1.のファイルを修正する
  10. 3.で開いておいたファイルを再読み込みする

再読み込みするとファイルの内容がローカルのものになっているのがわかります。

2012-03-09

Windows: telnet FTP接続 + NLSTの確認

FTPサーバでNLSTが動いているのか確認したいという話になったのでWindowsでの確認方法を簡単にまとめました(確認したクライアントはWindows 7 Home Premium + telnet、サーバはCentOS 5.6 + ProFTPD 1.3.1です)。

まずコマンドプロンプトをひとつ立ちあげて下記のように入力します(強調されている箇所。返ってくるメッセージはサーバによって変わります)。

C:\Users\user>telnet ホスト名 ポート番号(だいたい21)

220 ProFTPD 1.3.1 Server (ProFTPD) [xxx.xx.xxx.xx]
USER ユーザー名
331 Password required for xxxxx
PASS パスワード
230 User xxxxx logged in
PASV
227 Entering Passive Mode (xxx,xx,xxx,xx,a,b).
NLST

PASVの応答メッセージで数字(上記のxxx,xx,xxx,xx,a,bの箇所。xxx,xx,xxx,xxはサーバのIPアドレス。a,bはランダムな数字)が出てきたらNLSTの結果の受信用にコマンドプロンプトを立ち上げ、ホスト名と共にa * 256 + bの値をポート番号として入力して接続します(xxx,xx,xxx,xx,212,11 なら 212 * 256 + 11 = 54283)。

C:\Users\user>telnet ホスト名 ポート番号

接続すると新しく立ち上げた画面にはファイルとディレクトリの一覧が表示され、元の画面には例えば下記のように表示されます。

150 Opening BINARY mode data connection for file list
226-Transfer complete
226 Quotas off

(余談)

Windowsのftpコマンド(ftp.exe)でも確認は可能でした(コマンド送信用にftp.exe, 受信用にtelnetになるだけですが…)。ftpコマンドの場合PASVやNLSTなどはそのまま送信することはできませんが、quoteかliteralを使うと送信できました(quote PASVやquote NLST)。また ftp -d ホスト名 として起動するとlsやcdなどを実行した時の実際に送信されている生コマンドを表示してくれるので諸々の確認がしやすくなります。

2012-02-18

Processing 2.0a4: 手軽なGlow / OpenGLを使うとAppletが動かない

 

気分転換にProcessing(Proce55ing)を少し触っています。Processingといえば発光体とかパーティクルのイメージがあるので、まず発光体を作るために簡単にGlowさせられる方法を調べてサンプルを作りました。

  • 手軽なGlow (※要Javaプラグイン。マウスに追従して発光体が動きます)

image

調べた中ではGlowする方法として

  1. ピクセルを全なめして自力で加算合成
  2. blend()でADDを指定
  3. OpenGL(JOGL)で加算合成

の3パターンがあったんですが、この中ではOpenGLを使うのが重くならなくて簡単な感じがしたのでサンプルではOpenGLを使っています(blend()は重かったです…)。3. の方法は上記リンク先にあるソースとコメントを見て下さい。

発光体をもうちょっとどろっとした質感にしたいです。

それと最初はProcessing 1.5.1で作っていたんですが、OpenGLを使うとwidthやmouseXなどを2倍しないと意図したように動かないのと下記の問題の1.5.1での対処がわからなかったので2系にしてしまいました。

OpenGLを使うとAppletが動かない

OpenGLを使ったSketchで「File」 > 「Export Applet」を実行して、生成されたAppletのHTMLをブラウザで開くと「java.io.FileNotFoundException: http://jogamp.org/deployment/webstart/jogl-core.jnlp」と言われてAppletが動きませんでした。

Issue 845 - processing に書いてあった通りAppletのHTMLの<applet>のjogl-core.jnlpのURLを変更してもリンク先の最後のPostと同じように「java.io.IOException: Cannot validate certificate for nativewindow_awt.dll」と言われてしまいます。

いろいろ試してみたんですが http://jogamp.org/deployment/ 以下のファイル構造が変わっているためjogl-core.jnlp + 3つのjar(nativewindow.all.jar, jogl.all.jar, gluegen-rt.jar)のURLを変えないと動かないようでした。

/v2.0-rc2/以下のファイルはAppletのHTMLに書かれているURLと似ているのでAppletのHTMLのソースで「/webstart/」となっている箇所をすべて「/v2.0-rc2/」に一括置換するようにすると動くようになります。例えば「http://jogamp.org/deployment/webstart/nativewindow.all.jar」は「http://jogamp.org/deployment/v2.0-rc2/nativewindow.all.jar」とします。

ただ/v2.0-rc2/配下のファイルがもし消されたらまた動かなくなってしまうのでjogamp.orgのURLを使わずにjarをダウンロードしておく方がいいかもしれません。

2012-02-09

Visual Studio 2008: セットアッププロジェクトで.NET Frameworkを非ネット接続環境でもインストールできるようにする 等

Visual Studio 2008: セットアッププロジェクトで.NET Frameworkを非ネット接続環境でもインストールできるようにする

  1. セットアッププロジェクトのプロパティ画面の「必須コンポーネント」を開く
  2. 必要な.NET Frameworkのバージョンにチェック
  3. 「アプリケーションと同じ場所から必須コンポーネントをダウンロードする」を選択
  4. リビルド

Visual Studio 2008: セットアッププロジェクトのビルド後にautorun.infを出力ディレクトリにコピーする

通常のプロジェクトと違って「出力ディレクトリにコピー」のようなものがないのでPostBuildEventにコピーするコマンドを入れる

例:

copy "$(ProjectDir)autorun.inf" "$(ProjectDir)$(Configuration)\autorun.inf" 

PHP 5.4 (Windows): ビルトインウェブサーバでファイルがあるのにNot foundと表示される

パスに「予」等(ダメ文字)が入ると-tを指定した時にDocumentRootのパスがおかしくなる

例:

...\予定>.\php.exe -t foo
Document root is: ...\予予定\foo

Astah Community 6.5: 図を別ファイルにコピーできない

仕様のようです

2012-02-05

PowerShell: コマンドプロンプトを開いた時にPowerShellを有効にする 等

PowerShell: コマンドプロンプトを開いた時にPowerShellを有効にする

  1. 起動用バッチ(例えばinit.batで保存)を作ってバッチに「powershell」と書きこむ
  2. レジストリのHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor に「AutoRun」という項目を作って作った起動用バッチのパスを指定する

これでコマンドプロンプトが開かれるときはすべて自動的にPowerShellが有効になります。構文を戻したいときはコマンドプロンプト上でcmd /D (や exit)とします。

参考: コマンドプロンプト(Hishidama's DOS-command "cmd" Memo) #初期実行(WindowsXP)

(PowerShellもいつかまとめたいです)

Joomla 1.5: Chronoforms V4 RC3.11 が動かない

  • フォームの保存ができない
    • プラグインの「System - Mootools Upgrade」を有効にしないとJavaScriptでエラーになるみたいです
  • フォームを表示したときに「There is no form with this name or may be the form is unpublished, Please check the form and the url and the form management.」と出る
    • Forms Managerの右側の「Published」にチェックを入れる
  • 表示されない (Powered By ChronoForms - ChronoEngine.com しか出ない)
    • Edit in Easy ModeにあるActionsのOn Loadに「Show html」アクションを入れるまでフォームHTMLが表示されないみたいです
  • Plugin-Mambotを有効にするとページが白紙になる
    • 調査中です…

Windows: FTPサーバを普通のフォルダに似た形で使う

ネットワークプレース(Windows7)の場合」が詳しいです。ネットワークプレースはWebDAVしかできないと思い込んでいましたがFTPでもできるみたいです(ただFTP+ネットワークプレースだとファイルの直接編集はできない)。

Windows: WebDAV + ネットワークプレースでアクセスが遅いとき

Windows 7でWebDAVが遅い時はインターネットオプションのLANの設定で「設定を自動的に検出する」のチェックを外せばOK (https://twitter.com/#!/k_tsj/status/9084918867) でした。

image

image

関係ないですが記録を残すときEvernoteにメモ → たまったらWindows Live Writerにメモをコピペして整形(+ スクリーンショットがいるときはGrenshotでスクリーンショット撮って加工してクリップボードコピー → Live Writerにペースト)すると比較的楽に記録が残せます。

2012-01-29

Notepad++ 5.9.3: Python版Zen-Codingのmy_zen_settings.pyファイルの場所 など

Notepad++ 5.9.3: Python版Zen-Codingのmy_zen_settings.pyファイルの場所

  • C:\Users\(ユーザー名)\AppData\Roaming\Notepad++\plugins\Config\ZenCodingPython\zencoding\ (Windows 7の場合)
    • 特殊フォルダ名入りパスだと %appdata%\Notepad++\plugins\Config\ZenCodingPython\zencoding\

ZenCodingPythonフォルダにuser_settings.pickleがあるとそちらの設定が優先されてmy_zen_settings.pyの設定が効かないので、このファイルがある場合名前を変えるか削除して下さい。

参考: Adding snippets to Zen Coding in Notepad++ (jamestease)

コントロールパネルで設定をしてもCDの自動再生ができない

Excel: 矢印キーを押すとセル移動ではなくスクロールしてしまう

使っていたPC(Gateway ID59C-H52D)にスクロールロッキキーがなく代替キーもわからなかったのでスクリーンキーボード出して戻しました。

2012-01-25

最近の記録

最低限でも書いておくことにしました。

  • PHP: Windows + ビルトインウェブサーバでGDを動かす
    1. Windows版のPHP 5.4をダウンロード(現時点では http://windows.php.net/qa/ から) 
    2. php.iniのextension_dir=ext と extension=php_gd2.dll の頭のセミコロンを外す
    3. php -S <ホストとポート> -t <ドキュメントルートのパス> -c <php.iniのパス> で起動させる
  • C#: フォルダ内のファイルすべてを「出力ディレクトリにコピー」する
    • プロジェクトのプロパティを開く→ビルドイベントの「ビルド後に実行するコマンドライン」の入力欄に必要なフォルダを出力フォルダにxcopyするコマンドを書くといいです
  • C#: リリースビルドでvshost.exeとpdbを生成しないようにする
  • カセットテープ音源を.wavファイルに

2012-01-19

まとめたいもののまとめ

やったことの手順などを記録しないとすぐ忘れてしまって2回目以降にできなくなったりするのでいろいろ整理して記録しておきたいのですが時間が取れていません… 最近やったことでまとめたいことをまとめました。

  • phpMyAdmin: CSVエクスポートのデフォルト区切り文字をセミコロンからカンマにする
  • Java: SanselanでJPEGのExif情報を取得する
  • PowerShell: JPEGの緯度・経度情報を取得する
  • Google Maps API v3: ルートを自力で描画する
  • NILScript: Windowsフォームの動作をテストするプログラムを書く
  • CentOS: tomcat7等のインストール手順
  • Joomla 1.5: contentプラグイン, editor-xtdプラグインをつくる
  • CSS: Webkit(Chrome, Safari)のCSS不具合
    • floatした要素内だとpage-break-before等が無効になっている
    • tbodyに背景画像を適用するとth, tdそれぞれ個別に背景画像がつく
  • C: 前置・後置インクリメントの優先順位
    • ++*p++とすれば間接的にわかる。でも使いどころがある感じではない。それより*p++の方がはまりやすそう
  • XCode: XCode3の併用インストール手順
  • PDFの範囲印刷について
    • Adobe Readerメニューの編集 > スナップショット で範囲選択後に印刷すればできる
  • 集中力を削ぐサイトはhostsでブロックするよりWindows Live ファミリーセーフティでブロックすると便利
    • 設定がネット上に保存されるので複数PCで設定を使いまわせる。でもエラーメッセージが「保護者 (ほごしゃ) の方にお願いして、このページにアクセスできるようにしてもらってください」となっていて恥ずかしいです…
  • Notepad++: JScript版Zen-Codingだと特殊文字($とか)のエスケープが使えない?
  • 発注促進税制のまとめ