読者です 読者をやめる 読者になる 読者になる

この日記は私的なものであり、所属会社の見解ではありません。 GitHub: takahashikzn

Firefox48以降でSelenium-RCが動作しない問題を解消する

Selenium

昨日やっとトレーナーレベル22になりました。わーい。

御存知の通り上野公園は毎週末ヤバイことになってますが、コイキングだらけのおかげでギャラドスを取れました。


さて、ウチは非プログラマもテスターとして戦力化しているので、Selenium IDEベースの環境を構築しています。

ということは当然ながら、Selenium-RCでCIを回すことになります。


先日Firefox48がリリースされたのでアップデートしてみたところ、テストが全く動かなくなりました。 調べてみたところ、アドオンの署名チェックが強制されるようになったことが原因*1のようです。 このスレッドが参考になります。

http://groups.google.com/forum/#!topic/selenium-users/kDsWkujq0Y4

結論→アドオン開発向けFirefoxビルドを使え

このスレッドの結論としては、

Technically Selenium FirefoxDriver should work with Firefox 48 if you 
disable e10s (multiprocessing) and use an unbranded build, such as 
DevEdition or a custom build.  This is because 48 also ships with 
add-on signing, and FirefoxDriver isn’t signed. 
技術的には、FirefoxDriverはFirefox48のunbrandedビルド上でe10s(マルチプロセス化)を無効化すれば動くはずだ。
Firefox48から署名チェックを強制するようになったが、FirefoxDriverは署名なしであることが問題の原因である。

とのことです。


『unbrandedビルド』とは、FAQにある通り

How will the unbranded versions of Firefox work?

They work just like Firefox, with two differences: they will have a setting to disable mandatory signature checks, and they will not have the Firefox name and logo (instead using a generic name and logo). These builds are available in the en-US locale only.
unbrandedビルドって何?

Firefox通常版と全く同じように動く。ただし...

* アドオンの署名チェックが無効化されている
* 『Firefox』という名前やロゴが消されている(かもしれない)
* 英語版のみ

だそうです。


とりあえずこいつをこのへんからダウンロードして、プロファイルで

user_pref('xpinstall.signatures.required', false);
user_pref('browser.tabs.remote.autostart', false);

としておけば、現時点の最新ベータ版である49.0b1でも元通り動くようになりました。

*1:Selenium-RCは内部的にFirefoxのアドオンAPIを利用しています

Jenkins2にアップグレードしたら問題なく動いた

Jenkins

昨晩おもむろにyum upgradeしたらLTSのバージョンもとうとうJenkins2系へ移っていた(1.651.3 → 2.7.1)ので、思い切ってアップグレードしてみました。

…とは言え、仮想マシンのスナップショットは取ってあるのでいつでも戻せますけどね。 Jenkinsサーバに万一のことがあったら全く仕事になりません。CIは超重要。

結果、特に問題なく動いた

再起動時に「オススメプラグインをインストールしますか?」というスプラッシュが出てきました。 光の速さで「No, Thanks.」をクリック。

ぱっと見たところ、細かいデザイン崩れが起きている程度です。(ちなみに僕はこちらを使っています)

かなりプラグイン入れてるつもりなんですが、全て問題なく動いています。いやあスバラシイ。

Eclipse4.6 "Neon"の新機能一覧

f:id:takahashikzn:20160621164756p:plain

毎年恒例の新バージョンリリースです。ネオン(Neon)ということで、なんだか派手になりました。 ティザーサイトによると、6/22にリリースされるとのこと。 http://www.eclipse.org/neon/


ひとつ前のリリース、4.5 "Mars"の解説はこちら。 http://takahashikzn.root42.jp/entry/2015/05/29/214749


これまではマイルストーンビルド毎の変更を追いかける形で解説していましたが、 面倒になってきたので今回からヘルプページのWhat's Newを元にします。

http://help.eclipse.org/neon/index.jsp

2016-07-19注: 記事中の画像がリンク切れになっているようです。上記URLから遷移するとなぜかJunoのヘルプページが表示されてしまうのですが、これが原因かもしれません。

2016-07-24注: 解消しました。

Eclipse本体(ワークベンチ)の新機能


SWT provides resolution-based autoscaling: SWT側で解像度を自動判定して(画像を)自動拡大

タイトル通りです。 高解像度画像が存在しない場合、画像を自動拡大するそうです。 しかも、単に拡大するのではなくベクター画像的にキレイに拡大(proportionately)してくれるとのこと。

NeonでHigh-DPI表示した例。アイコンが拡大されています。

こちらはMars(High-DPI非対応)で表示した例。


Word wrap in text editors: テキストエディタで行折り返し

行折り返しをボタン1つで切り替えられるようになりました(デフォルトでは行折り返しOFF)。 キーボードショートカットはAlt+Shift+Yです。


Commands and shortcuts to zoom in text editors: テキストエディタ上でフォントサイズ変更のコマンドとショートカットを追加

Ctrl++Ctrl+=でズームイン(フォントサイズ増加)、Ctrl--Ctrl+-でズームアウト(フォントサイズ現象)です。

この変更はその場限りの一時的なものではなく、設定画面で変更したことと同じ意味になります。つまり永続化されます。 デフォルトフォントを指定していた場合、デフォルトフォントの設定そのものが変更されます。

この機能、個人的には余計なお世話のような気がしますが…Ctrl++なんて簡単なキーバインドなので、暴発を招くだけかと。 そういうわけで、僕はキーバインドから早速解除させていただきました。 


Pinch to zoom in text editors: ピンチジェスチャーでズームイン

先程の永続的フォントサイズ変更とは別に、「一時的に」ズームしたい場合のピンチジェスチャーが使用できるようになりました。 解除するジェスチャーは「二本指で45度回転させる」だそうです。またはエディタを単に閉じて開く。

ちなみに、現在のところLinuxはサポート外だそうです。(SWTの基礎となるGTKがマルチタッチに対応してない為)


Automatic Save of dirty editors: 編集中エディタの自動セーブ

2時間分の作業がExcelのクラッシュにより失われるという悲しい事件が後を絶ちませんが、みなさんCtrl+S押してますか? 僕は手が止まるたびに押すのがクセになってます。(およそ30秒に1回)

そういう悲しい事件を少しでも減らすため、とうとうEclipseにも自動セーブが搭載されました。(デフォルトでは無効) 無操作の場合に一定時間経つと自動セーブされます。


Search in binary files: バイナリファイル検索

組み込み屋さんが使うんでしょうかね?バイナリファイル検索が搭載されました。 検索ワードに16進を打ち込むとバイナリ検索になるようです。

ただしバイナリ検索はデフォルトでOFFになっており(上画像の"Search In"の"Binary files")、以下のいずれかのファイルのみを対象とするようです。

  • テキストファイル
  • ファイルタイプ不明かつnull文字(U+0000)を含まない


Terminate and Relaunch from history: 履歴からのアプリケーション終了→再起動

履歴からEclipseからアプリケーション(TomcatJUnit、etc...)を起動する際、前回のプロセスを終了してから起動することができるようになりました。 これにより二重起動を防ぐことができます。

デフォルトではこの機能は無効になっていますが、Shiftを押しながら履歴から起動することによっても利用できるようです。

オマケ:Ctrlを押しながら起動履歴を押すとアプリケーション起動設定ダイアログを開けます。(知らなかった…ちょっと便利)


Directly start previously selected workspaces in the launcher: 最近使ったワークスーペースを直接選んで起動

Eclipse起動時にワークスペースを選択する際、最近使ったものをクリックして選べるようになりました。

パスは省略されていますが、マウスを当てるとフルパスが表示されます。 右クリックから消すこともできます。


Workspace name shown in window title by default: ワークスペース名をタイトルバーに表示

ワークスペース情報がタイトルバーに表示されるようになりました。 デフォルトではワークスペースディレクトリパスが表示されます。


Quick Access Improvement: クイックアクセスの改善

Ctrl+3のクイックアクセスで表示される候補をフィルタできるようになりました。 例えば、ビューに関係する操作だけに絞りたい場合はViews: を入力します。


Hide the window toolbars: ツールバーを隠す

クイックアクセスからツールバーの表示非表示をトグルできるようになりました。

ちなみに僕はツールバーを一切使わないので、絶対にツールバーを表示しないようにするプラグインを自作しました。 これがないと、Eclipseがクラッシュ後に再起動するとツールバーが表示される(時がある)んですよね。。


Perspective names hidden by default: パースペクティブ名は非表示に

ツールバー右上に表示されるパースペクティブ一覧ですが、名称が非表示になりました。 右クリックすれば名称が表示されます。

Neon:

Mars:


Full Screen: フルスクリーン

WindowsLinuxでもフルスクリーンがサポートされました。Webブラウザの標準キーバインドと同じくCtrl+F11で有効にできます。

OSX上ではこれまで同様にCtrl + Cmd + Fでフルスクリーンです。


Preference setting to disable the Eclipse styling (CSS base theming): CSSベースのテーマ機能をOFFにする設定

CSSベースのテーマ機能がEclipse4.2から導入されていますが、この機能をOFFにできるようになりました。 OFFにすると、Eclipseが軽くなる(かもしれない)そうです。


Selecting the text editor for unaccosiated file types: 未関連付けファイルタイプをテキストエディタで開く

未関連付けのファイルタイプを開くときのエディタ選択ルールを指定できるようになりました。


"date" template variable with custom format: ${date}変数が展開される時のフォーマットを指定可能に

コードテンプレート等を作るときに使用できるEclipseの変数のうち、${date}が展開される時のフォーマットを指定できるようになりました。


"word_selection" and "line_selection" template variable with default value: ${word_selection}と${line_selection}変数がデフォルト値を持つように

${word_selection}と${line_selection}変数にデフォルト値を指定できるようになりました。何もテキストを選択していない時に適用されます。


Import projects: プロジェクトインポートのウィザード機能

プロジェクトをEclipseワークスペースにインポートする際にウィザードを使えるようになりました。 これにより、ディレクトリまたはアーカイブからインポートするときに同一のUIで操作できます。 また、プロジェクト自動設定の精度も向上しています。

なお、プロジェクト自動設定のロジックは自作することもできるそうです。 (新たに追加された拡張ポイント org.eclipse.ui.ide.projectConfigurator で指定)


"New..." button for creating Working Sets

(特筆すべきものではないので略)


New Welcome theme 'Solstice': 新しいウェルカムテーマ「Solstice」

こんな感じになりました。


Welcome Launchbar restored: ウェルカムページのランチャーが復活

Eclipse3.xの頃にそういうものがあったらしく、それが復活しました。


Improvements in the Mac default theme: Macのデフォルトテーマ改善

OSXの他のアプリケーションと見た目が合うように調整されました。

旧:

新:


Link widget background color can be styled via CSS

リンク要素の背景がCSSでスタイル可能になりました。


Themed scroll bar enabled for editors in dark theme: ダークテーマでスクロールバーのスタイル設定が可能に

Marsまではダークテーマでダークにならない部分があって残念な感じでしたが、とうとう完全なダークテーマが達成されました。

OSネイティブのスクロールバーを廃止してSWTで自作したようです。 -Dswt.enable.themedScrollBar=falseとすればOFFにもできます。(eclipse.iniで指定)

残念ながらこの自作スクロールバー、現時点では以下の問題が残っているようです。

  • 全てのコンポーネントへ適用済みではなく、ネイティブのスクロールバーが残ることがある(例:ツリー、テーブル)
  • これまではスクロールバー非表示だった箇所でスクロールバーが表示されてしまうことがある

これらはEclipse4.7で解消する予定です。


Improved menu support on GTK3

(重要ではないので略)


Tweaking SWT's auto-scaling: SWTのHi-DPI自動スケーリングを微調整

今回のリリースで追加された自動スケーリングですが、微調整ができます。

まずGTKの場合、GTK_DPI_SCALE=1.5のようにすることで、拡大率が150%になります。(GTKの機能)

GTKおよびWindowsの場合、以下のように指定することが可能です。

  • -Dswt.autoScale=false →自動スケーリングOFF、ただしOSXでは未対応
  • -Dswt.autoScale=integer →現在の解像度に応じて100の倍数%でスケーリング(200%, 300%...)、これがデフォルト
  • -Dswt.autoScale=quarter →現在の解像度に応じて25の倍数%でスケーリング(125%, 150%...)
  • -Dswt.autoScale=exact →現在の解像度に応じて1%刻みでスケーリング
  • -Dswt.autoScale=<value>→スケーリングを指定

加えて、スケーリング方式を指定することができます。

  • -Dswt.autoScale.method=nearest最近傍補間、ギザギザした感じ、これがデフォルト
  • -Dswt.autoScale.method=smooth →スムース化、ボケた感じ、GTKのみ可


Advanced capabilities preferences are now displayed in place (no extra dialog)

(重要ではないので略)


Eclipse workspace launcher now fully functional on Wayland: EclipseランチャーがWaylandをサポート

WaylandとはX.orgの代替となるディスプレイサーバを開発することを目標としたプロジェクトです。

そのディスプレイ環境でEclipseのランチャーが起動するようになりました。


Solaris builds are now 64-bit only: Solaris向けビルドは64bitのみ

32bitソラリス上でEclipseを使う人はいないので廃止されました。


Ant 1.9.6

Eclipseの標準はAnt 1.9.6になりました。


Java9 previews: Java9プレビューに関して

そのままではJava9で起動出来ず、

-addmods java.se.ee

が必要です。

JDTの新機能

Javaエディタ


Content Assist highlights matched characters: コンテンツ・アシストでマッチ文字列がハイライトされるように

コンテンツ・アシストのポップアップで、マッチする文字列がハイライトされて判別しやすくなりました。


Substring code completion: コンテンツ・アシストが文字列の一部から補完できるように

部分文字列のマッチングで補完が効くようになりました。かなり便利。 ウザい場合は設定でOFFにもできます。


ifNotNull/ifNull templates: if(xyz == null) { ... } のようなテンプレートが追加

Optionalの登場により登場頻度が減ったお決まりのコードですが、テンプレートに追加されました。


Rename options: 識別子名変更のリファクタリングにおけるオプション指定

識別子名変更のリファクタリングで、optionsというリンクが表示されるようになりました。これを押すと詳細なオプション指定が可能なダイアログが表示されます。

実はこのダイアログ、リンクを押すまでもなくCtrl+Alt+Rをもう一度押せば表示されます。(そして、この機能自体はEclipse3.xの時代からあったはず)

インプレースモード(ダイアログを表示しないモード)は設定でOFFにすることもできます。


Javaエディタ(その他)


Clean up to remove redundant type arguments: コードクリーンアップで、冗長な型引数を除去できるように

タイトル通り。


Create new fields from method parameters: メソッド引数からフィールド宣言を生成

コード補完の一種として、メソッド引数からフィールド宣言を生成できるようになりました。

コンストラクタやセッターの引数からインスタンス変数を生成するというケースが主になるでしょう。


Search on multi-selections: 特定の要素に限定した検索

特定のクラスやメソッド等に限定して検索できるようになりました。

検索結果で表示された要素を選択して、更に検索することもできます。


Ctrl+Shift+V invokes Open from Clipboard: Ctrl+Shift+Vで「クリップボードから開く」

タイトル通り。


Adding meta-annotations while creating a new Java annotation type: アノテーションクラスを作る際にメタアノテーションを追加

アノテーションをウイザードで作成する際、お決まりの@Retention等を予め指定できるようになりました。


Grouping of referenced libraries in Project Explorer: 参照ライブラリをグルーピング

プロジェクトエクスプローラーで、参照ライブラリをツリーノード「参照ライブラリ」にぶら下げられるようになりました。


Hiding empty library containers in Project Explorer: 空のノードを非表示に

プロジェクトエクスプローラーで、空のノードを非表示にできるようになりました。


Javaコンパイラ


New problem severity level to indicate information: コンパイラの新しい警告レベル"Info"

これまではIgnore, Warning, Errorの3つの警告レベルでしたが、Infoが追加されました。

実際はこのように表示されます。


Quick fix to configure problem severity: クイックフィックスでコンパイラ警告レベルを変更可能に

頻繁に使うことはありませんが、クイックフィックスからコンパイラの警告レベル変更画面を開くことができるようになりました。


Null解析


Multiple sets of null annotations: Null解析のためのアノテーションが複数指定可能に

アノテーションベースのNull解析は、まずアノテーションを付けるところから始まります。 しかし現時点でNon-nullを表すアノテーションは統一されていません。Java標準APIだけでも

  • javax.validation.NotNull
  • javax.annotation.NonNull

と2つあります。EclipseがNull解析に力を入れ始めた頃は

  • org.eclipse.jdt.annotation.NonNull

なんてのが標準でした。

何か一つに統一されれば良いのですがそう簡単には行かないよね、というわけで。 Null解析用のアノテーションを複数指定できるようになりました。

複数指定するアノテーションには「プライマリ」と「セカンダリ」の2種類が存在します。

「セカンダリ」はコンテンツアシスト時に、本当にそのアノテーションクラスがビルドパス上に存在するか否かの検査を行わないそうです。(負荷軽減のため)

まあ、実用上はそんなに差がないと思います。


Improved null analysis with generics: ジェネリクスのNull解析の改善

ジェネリクスにおけるNull解析が改善したそうです。

改善点は次の通り。

  1. 非束縛型引数を厳し目に解析
  2. Null解析に対応していない外部ライブラリにおける非束縛型引数の扱いを改善
  3. Nullチェック用の便利クラスorg.eclipse.jdt.annotation.Checksを追加
非束縛型引数を厳し目に解析

まず一つ目ですが、非束縛型引数とは

class Foo<T> {
    T val;
}

におけるTのように、NullableとNonNullのどちらとも指定されていない型引数のことです。

この場合、非束縛型引数はNonNullであることが確定しないので警告を発するようになりました。(デフォルトはOFF)

非束縛型引数を持つクラスの作者は、Null解析の完全性を保つために以下の規約を守る必要があります。

  • TがNonNullであることを意図しているならば、インスタンス化時にNonNullな型引数を渡す必要があるし、具体的な値としてnullが来たらエラーとしなければならない
  • TがNullableであることを意図しているならば、渡された参照を使用する前にnullか否かを確認をしなければならない
Null解析に対応していない外部ライブラリにおける非束縛型引数の扱いを改善

次に二つ目ですが、例えば以下の様なクラスを考えてみます。

ListとMapのどちらもJDKのクラスで、Null解析用のアノテーションは付いていません。 従って宣言時の型引数を信じるしかありません。

List<@NonNull String> list;

// 値はNonNullということで確定でよいが、そもそもキーがあることを保証する方法がない
Map<Integer, @NonNull String> map;

@NonNull String test(int i) {
    if (i >= 0)
        // 値はNonNullなので、この式の評価結果は
        // 『NonNullなString』と『IndexOutOfBoundsException』のいずれかであることが確定
        return list.get(i);
    else
        // キーに対応する値があればNonNullなのだが、そもそもキーがあることが未保証
        // キーがなくても例外がスローされるわけではなく単にnullになる
        return map.get(i);
}

Neonでは、このようなケースで警告を発するようになりました。

この問題を解消するには、Map#get(Object)がNonNullであると指定するしか方法はありません。 そのためには、Eclipse4.5で追加された機能『Nullアノテーションの外部化』を使うことが出来ます。

詳しくは過去記事の「External annotations: Null解析用アノテーションをJarの外部から指定」を参照して下さい。


Nullチェック用の便利クラスorg.eclipse.jdt.annotation.Checksを追加

最後に三つ目ですが、Objects.requireNonNullのような便利メソッドの派生系をたくさん持っているクラスが追加されたというだけの話です。

Javadocこちら


Quick Fix to add @NonNull to local variable: クイックフィックスでローカル変数へ@NonNullアノテーションを付ける

Null解析は非常に複雑なため完璧ではありません。時にはよくわからない理由で警告を出すことがあります。

このようなケースでサクッと警告を消すために、クイックフィックスを使えるようになりました。

ただしこれで解決しないこともあり、コンパイラが次の警告を出すこともあります。


Javaコードフォーマッタ


New options in code formatter: コードフォーマッタの新オプション

コードフォーマッタにオプションが追加されました。

(1) forループ宣言部の行折り返し制御。

(2) 桁揃えのグルーピング。空白行で区切ることでグループを区別します。

(3) enumの値に付与するアノテーションを一つ毎に改行するか否か。

(4) 括弧内の改行でユーザー指定を尊重するか否か。これまでは行コメント//を末尾につけることで、行がフォーマッタにより結合されることを防いでいたのですが、そんな小細工をしなくても良くなりました。

(5) 型引数宣言の行折り返し制御。

(6) 代入演算子三項演算子の前後における行折り返し制御。


Javaデバッガ


Installing breakpoints from unrelated projects: 無関係のプロジェクトからブレークポイントをインポートしないようにする

複数のプロジェクトで、バージョンの異なる同名クラスを使うことがあります。 その場合、ブレークポイントの位置はそれぞれ異なることになります。

Neonでは、依存関係を見てバージョン毎に適切なブレークポイントを切り替えることができるようになっていますが、 この動作が邪魔な場合は設定でOFFにすることが出来ます。


JUnit


Enabled assertions for new JUnit launch configurations: JUnit起動時にデフォルトでassertは有効に

JUnit実行時にassertを有効にするか否かのオプションはありましたが、デフォルトはOFFでした。 NeonからはデフォルトONになります。

最後に

Eclipseの新機能解説を書くのはこれで6回目です。(Eclipse3.7~Eclipse4.6)

毎度毎度、「疲れるからもう今年で最後にしよう」と思うのですが... 今年のこれも、書くのに8時間は使ってますし。でも謎の義務感でやってしまいます。

「玄人はIntelliJEclipseが許されるのは小学生まで」などとディスられることが多いEclipseですが、 僕はまるでかつてのEmacsのように(過去5年ほどEmacs漬けの生活を送っていたことがある)、体に染み付いてしまったので今後も使い続けることでしょう。

では皆さま、楽しいEclipse生活を!!

TldScannerでNullPointerExceptionが出て起動しない

Tomcat

僕は普段、開発用としてTomcat-9.0.0系を使っています。

先ほどTomcat-9.0.0-M6に更新したら、このようなエラーが出て起動しなくなりました。

java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/foobar]]
    at java.util.concurrent.FutureTask.report(FutureTask.java:122)
    at java.util.concurrent.FutureTask.get(FutureTask.java:192)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:911)
    at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:890)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:152)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1403)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1393)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/foobar]]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:158)
    ... 6 more
Caused by: java.lang.NullPointerException
    at org.apache.jasper.servlet.TldScanner$TldScannerCallback.scanWebInfClasses(TldScanner.java:395)
    at org.apache.tomcat.util.scan.StandardJarScanner.scan(StandardJarScanner.java:208)
    at org.apache.jasper.servlet.TldScanner.scanJars(TldScanner.java:262)
    at org.apache.jasper.servlet.TldScanner.scan(TldScanner.java:104)
    at org.apache.jasper.servlet.JasperInitializer.onStartup(JasperInitializer.java:103)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5183)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:152)
    ... 6 more

該当箇所のソースは以下の通り。

@Override
public void scanWebInfClasses() throws IOException {
    // This is used when scanAllDirectories is enabled and one or more
    // JARs have been unpacked into WEB-INF/classes as happens with some
    // IDEs.

    Set<String> paths = context.getResourcePaths(WEB_INF + "classes/META-INF");

    for (String path : paths) { // ← 395行目
        if (path.endsWith(TLD_EXT)) {
            try {
                parseTld(path);
            } catch (SAXException e) {
                throw new IOException(e);
            }
        }
    }
}

見ての通り、pathsがnullです。

なぜだ…?と思って当該アプリケーションのMETA-INFを見てみると、空ディレクトリでした。 もしやと思い、META-INFを消すと元通りに起動するようになりました。まぁ軽いバグの一種なんですかね。

ちなみに、この現象は8.5.2でも起きるようです。(該当箇所のソースが同一なので)

Eclipse 4.6 "Neon" M7リリース

Eclipse

f:id:takahashikzn:20160511132958p:plain

そろそろ毎年恒例のイベントがやってきます。 今回のコードネームはNeonですが、惑星シリーズのネーミングは止めたようですね。

毎年のリリースペースならばマイルストーンビルドはこれで打ち止めです。次からはRC(Release Candidate)扱いになるでしょう。

(2016-05-14追記 RC1がリリースされました)

ちなみに4.7のコードネームはOxygenだそうです。 参考: Eclipse (統合開発環境) - Wikipedia

個人的に気になった追加機能

http://www.eclipse.org/eclipse/news/4.6/M7/


Improved interactive performance and reduced memory consumption (UI反応性の改善と消費メモリ低減)

This and earlier milestones contain a multitude of fixes to enhance interactive and startup performance of the Eclipse IDE, and to reduce overall memory consumption.

ちょっと前のマイルストーンビルドから様々な改善が取り入れられた結果、UI反応性と起動時のパフォーマンスが改善している。全体的な消費メモリも低減されている。


Link widget background color can be styled via CSS (リンクウィジェットの背景へCSSを適用可能に)

You can now style the background color of the SWT Link widget. This is used in the default dark theme provided by Eclipse.

SWTのリンクウィジェット背景色をCSSで設定可能にした。この機能はデフォルトのダークテーマで使用されている。


Themed scroll bar enabled for editors in dark theme (ダークテーマのためにスクロールバーへスタイルを適用可能に)

It's now possible to replace the native scroll bar of a StyledText by a styled overlay. This is enabled by default in the dark theme on Windows.

とうとうネイティブスクロールバーにスタイルを適用できるようになった。この機能はWindows上のダークテーマで使用されている。


Quick Access improvements (クイックアクセスの改善)

Quick Access (Ctrl+3) is a small text field in the toolbar. You can use it to trigger any command in the Eclipse IDE.

 

You can now restrict the search to Views, Commands, etc. by typing the category name followed by a colon. For example, to filter the list of all the views, start typing "Views: " in the search-box.

 

A few usability bugs have been fixed: The tooltip shows the keyboard shortcut, the number of search results per category is independent of the size of the proposals window, and the list with previous choices already opens when you click the field with the mouse.

Ctrl+3で起動されるクイックアクセスはツールバーにある小さなテキストボックスだが、ここで好きなコマンドを実行できるようになった。

コロン(:)に続いてカテゴリ名を入力すれば、検索される範囲をビュー(訳注:「問題」や「コンソール」などの表示領域のこと)や、コマンドに制限できる。例えば、ビューの一覧に絞って検索したければ"Views: "と入力すれば良い。

幾つかのバグも解消されている。キーボードショートカットやカテゴリごとにグループ分けされた検索結果を表示するツールチップは候補ウィンドウとは独立したサイズを持つようになった。「以前に選択したもの」リストはマウスクリックした時点でオープンされるようになる。


Full Screen (フルスクリーン)

The Full Screen feature is now also available on Windows and Linux. You can toggle the mode via shortcut (Alt+F11) or menu (Window > Appearance > Toggle Full Screen). When Full Screen is activated, you'll see a dialog which tells you how to turn it off again.

LinuxWindowsでフルスクリーン表示ができるようになった。Alt+F11でトグルされる。またはメニューからも可。(ウィンドウ → 外見 → フルスクリーン) フルスクリーンが有効にされたとき、無効にする方法を知らせるダイアログが表示されるだろう。(訳注: Chromeを全画面表示した時に表示されるアレのようなもの)


New options in code formatter

A few new options have been added in the formatter profile editor.

 

(1) In the new Parentheses tab, you can order the formatter to keep parentheses of various Java elements on separate lines, i.e. put a line break after the opening parenthesis and before the closing parenthesis. This can be done always, only when parentheses are not empty, or when their content is wrapped. There's also an > option to preserve existing positions, if you want to manually manage parentheses positions on a case-by-case basis.

コードフォーマットのオプションが増えた。

(1) 括弧位置調整のためのオプションタブが追加された。そこではJavaの構文要素ごとに、「開き括弧の前と閉じ括弧の後に改行を入れるか否かを、括弧の中身が空かどうかで個別に指定」のような細かい設定が可能だ。 また、括弧の位置を自分で調整したい場合、フォーマッターの処理対象外にすることが出来るようになった。


(2) In the Line Wrapping tab, you can set the wrapping policy for parameterized types.

型引数の行折り返し設定が追加された。


(3) Also in the Line Wrapping tab, you can decide to wrap before or after operators in assignments and conditional expressions.

演算子の前後における行折り返しポリシーが設定できるようになった。

Struts2のS2-032の要点

またOGNL絡みで脆弱性が出ました。ホントにこの機構は問題児ですね… とはいえOGNLはStruts2の根幹に関わる機能なので、OFFにすることは難しい。

「1アクション=1アクションクラス」派でない方にとっては、DMIを使えないのは死活問題になりかねません。

ちなみに僕は「1アクション=1アクションクラス」派です。


さて、POCが出回っているので、今回の攻撃が成功する原因を調べてみました。POCはこのあたりを参考に。

ひとつ目のリンクはそもそも今回の脆弱性を発見した企業のブログです。 リンク先に同等の解説があるようなのですが中国語なので僕には読解不能。

結論から言うとDefaultActionInvocation、お前だ

com.opensymphony.xwork2.DefaultActionInvocationのinvokeActionが問題です。 こちらのメソッドの抜粋は以下の通り。

protected String invokeAction(Object action, ActionConfig actionConfig) throws Exception {
    String methodName = proxy.getMethod();

    ...
    
    try {
    
        ...
        
        try {
            methodResult = ognlUtil.getValue(methodName + "()", getStack().getContext(), action);
        } catch (MethodFailedException e) {
            ...
        }
        
        ...
    } catch (NoSuchPropertyException e) {
        ...
    } catch (MethodFailedException e) {
        ...
    } finally {
        ...
    }
}

よく見てみましょう。

methodName + "()"

コレが原因です。

まず、Struts2のDMIは、method:cancelOrderのようにして、ActionクラスのcancelOrderメソッドを呼び出すような使い方を想定しています。 しかしながらパラメータの妥当性検証が不足しているために、

method:(#_memberAccess).setExcludedClasses(@java.util.Collections@EMPTY_SET),
(#_memberAccess).setExcludedPackageNamePatterns(@java.util.Collections@EMPTY_SET),
@java.lang.System@out.println('やっほー'),
new java.lang.String

というクエリパラメータが

String methodName = "(#_memberAccess).setExcludedClasses(@java.util.Collections@EMPTY_SET),(#_memberAccess).setExcludedPackageNamePatterns(@java.util.Collections@EMPTY_SET),@java.lang.System@out.println('やっほー'),new java.lang.String";

という値で格納されてしまい、

ognlUtil.getValue("@java.lang.System@out.println('やっほー'),new java.lang.String" + "()", ...)

という形へ展開されて、SecureMemberAccessのガード機構を無効化した上で(#_memberAccess.setExcludedClassesのあたり)、OGNLとして実行されてしまうわけです。 最後のjava.lang.Stringは、"()"が末尾にくっついた時に妥当なOGNL式にするための調整であり、その範疇内であれば何でも良い。 だから

method:(#_memberAccess).setExcludedClasses(@java.util.Collections@EMPTY_SET),
(#_memberAccess).setExcludedPackageNamePatterns(@java.util.Collections@EMPTY_SET),
@java.lang.System@exit

のような式も可。

対策

DMIをOFFにすることがベストです。なお、デフォルト状態ではOFFです。(※struts-2.3.15.2以降)

また、com.opensymphony.xwork2.DefaultActionProxy#prepareでDMIのメソッド名はスクリーニングされているので、

protected void prepare() {
    ...
    try {
        ...

        if (config.isAllowedMethod(method)) { // ←許可されたメソッド名であるか検査する
            invocation.init(this);
        } else {
            throw new ConfigurationException("This method: " + method + " for action " + actionName + " is not allowed!");
        }
    } finally {
    }
}

struts.xmlでDMIのメソッド名を何でもあり、すなわちregex:.*などと指定していない限り今回の脆弱性を突くことはできません。

(※手元で試した限りでは。責任は持ちませんので悪しからず)

Thanks to @Annotations, @Progress is @Unstoppable! (@Annotationが進化を促進する!)

面白いサイトを見つけたので訳してみました。

http://www.annotatiomania.com/

2000年に書いたコード

private Collection employees;

2004年に書いたコード

private Collection<Employee> employees;

2005年に書いたコード

// 糞コンパイラが文句を言うため。後で修正する
@SuppressWarnings({"unchecked", "rawtypes"})
private Collection employees;

今日書いたコード

@SuppressWarnings({"unchecked", "rawtypes"})
@Deprecated
@OneToMany(@HowManyDBADoYouNeedToChangeALightBulb)
@OneToManyMore @AnyOne @AnyBody
@YouDoNotTalkAboutOneToMany // Fightclub, LOL
@TweakThisWithThat(
    tweak = {
        @TweakID(name = "id", preferredValue = 1839),
        @TweakID(name = "test", preferredValue = 839),
        @TweakID(name = "test.old", preferredValue = 34),
    },
    inCaseOf = {
        @ConditionalXMLFiltering(run = 5),
    }
)
@ManyToMany @Many @AnnotationsTotallyRock @DeclarativeProgrammingRules @NoMoreExplicitAlgorithms
@Fetch @FetchMany @FetchWithDiscriminator(name = "no_name")
@SeveralAndThenNothing @MaybeThisDoesSomething
@JoinTable(joinColumns = {
    @JoinColumn(name = "customer_id", referencedColumnName = "id")
})
@DoesThisEvenMeanAnything @DoesAnyoneEvenReadThis
@PrefetchJoinWithDiscriminator @JustTrollingYouKnow @LOL
@IfJoiningAvoidHashJoins @ButUseHashJoinsWhenMoreThan(records = 1000)
@XmlDataTransformable @SpringPrefechAdapter
private Collection employees;

明日書くコード

var employees;

私達もオススメします!

@RadCortez, @Annotatiomaniac of the Year 2014

近頃のJavaEEの進歩のおかげで、QW@RTYキーボードを販売するビジネスを始めることができました。

エンタープライズ開発者は2個分の値段で3つ買うことができます!

@Gregor_Riegler, @Annotatiomaniac of the Year 2013

専門家として我々は自分の仕事に責任を持ち、常にベストを尽くす。そこにはミスをする余地はなく、バグの余地もない。

ごく最近、素晴らしい発明によりバグを60%近く減らすことができた。それは @CatchNullPointerException だ。

@MarkusWinand, @Annotatiomaniac of the Year 2012

大企業の顧客が、ウンザリするようなXML形式から洗練されたアノテーション形式へ移行するのを、つい最近支援したところだ。

これは顧客にとって重要な一歩だ ― アノテーションからJSONへ移行するためのね。

@simas_ch, @Annotatiomaniac of the Year 2011

顧客のために、この業界の最新の流行を身につけてもらうためのカリキュラムを用意している。

「制御構造によるレガシープログラミング」および

「モダンプログラミング ー アノテーション、応用アノテーションアノテーションプロセッサプロセッサ、高階アノテーションによるメタプログラミングエンタープライズアノテーション」だ。

アノテーションを使い続けても良いし、

jOOQでアノテーションに振り回されるのを終わりにするのも良い。

…というわけでこのサイトはjOOQの宣伝サイト?なのでした。