クラスローダーに関してあなたが抱えている問題は予想されることです: Eclipse プラグイン/OSGi バンドルの依存関係が A -> B で、Clojure jar が B からブートストラップされている場合、B から A のリソースを表示できません。正常です。
Eclipse プラグインの依存関係に循環はあり得ないため、クラスローダー階層間に循環はありません。
これは、通常の Eclipse 機構を使用して A から B への拡張機能を作成する場合に直面する問題と同じです。プラグイン B はインターフェースと拡張ポイントを宣言します。次に、プラグイン A はインターフェースを実装し、拡張ポイントへの拡張を宣言できます。この最後の部分により、Eclipse フレームワークはバンドルでいくつかのトリックを実行できます。A が B への拡張を宣言していることを確認し、B で宣言されたインターフェースを実装する A からクラスをインスタンス化し (A は B に依存しているため、これは機能します)、B を提供します。 A からの実装インスタンスも B でインターフェイスを実装しているので問題ありません。
(これが明確かどうかはわかりません)。
とにかく、Clojure で書かれたプラグインに戻りましょう。
Clojure を使用すると、すぐに使用できるように、クラスローダーによって提供される個別の環境はありません。これは、すべてが 1 つの「Clojure 環境」に集約され、clojure jar を埋め込むプラグインのクラスローダー領域に存在するためです。そのため、プラグイン A の起動時に、関連する名前空間を A からロードすることが 1 つの可能性です。その後、それらは適切なタイミングでロードされ、他の Clojure コードで使用できるようになります。もう 1 つの可能性は、Extension Point/Extension 機構を使用することです。Eclipse は、「ファクトリー」を使用して拡張ポイントのインスタンスを作成する方法を提供します。反時計回りでは、この機能を活用し、適切なバンドルから適切な名前空間をロードすることを処理するジェネリック ファクトリ クラス (Java で記述されているため、AOT はありません) を使用します。
ここでは、拡張ポイントを拡張する方法について詳しく説明します。
反時計回りの例:
Eclipse フレームワークには、コンソール コンテンツのハイパーリンク検出機能を提供するための既存の拡張ポイントがあります。この拡張ポイントを反時計回りに拡張して、nrepl ハイパーリンクを追加します。
Java の世界では、IPatternMatchListenerDelegate インターフェイスを実装する自分のクラスを拡張機能で直接宣言する必要があります。
しかし、CCW では、おそらくあなたと同じ理由で、私は AOT を絶対に避けようとしているので、拡張機能で Java クラス名を指定することはできません。または、Java で記述してコンパイルする必要があったでしょう。またはgen-class
、Clojure でa を記述してAOT コンパイルします。
代わりに、CCW は plugin.xml の可能性の隠された宝石を活用します。ほとんどすべての場所で、クラス名を指定する必要がある場合、代わりにIExecutableExtensionFactoryのインスタンスを指定できます。このcreate()
メソッドは、Eclipse フレームワークによって呼び出され、そのインスタンスを作成します。希望クラス。
これにより、Clojure の世界を呼び出すためのジェネリック クラスを作成することができました。書くべきだったクラス名の代わりに、クラス名ccw.util.GenericExecutableExtensionを使用するだけです。
plugin.xmlから抽出:
<extension point="org.eclipse.ui.console.consolePatternMatchListeners">
<consolePatternMatchListener
id="ccw.editors.clojure.nREPLHyperlink"
regex="nrepl://[^':',' ']+:\d+">
<class class="ccw.util.GenericExecutableExtension">
<parameter
name="factory"
value="ccw.editors.clojure.nrepl-hyperlink/factory">
</parameter>
</class>
</consolePatternMatchListener>
属性と、要素class
を介してファクトリにパラメータを与える方法に注意してください(ファクトリは、パラメータで初期化できるようにインターフェイスIExecutableExtensionを実装する必要があります)。parameter
ccw.editors.clojure.nrepl-hyperlink
最後に、 namespaceでは、関数ファクトリはかなり単純で、make関数を呼び出すだけであることがわかります。
(defn make []
(let [state (atom nil)]
(reify org.eclipse.ui.console.IPatternMatchListenerDelegate
(connect [this console] (dosync (reset! state console)))
(disconnect [this] (reset! state nil))
(matchFound [this event] (match-found event @state)))))
(defn factory "plugin.xml hook" [ _ ] (make))
これは例として示していることに注意してください。反時計回りの関連コードは、「すぐに使用できる」独立したライブラリとしてリリースする準備ができていません。
それでも、独自のソリューションを展開できるはずです (頭の中にすべてのピースが配置されていれば、非常に簡単です)。
それが役立つことを願って、
-- ローラン