1

できれば起動タスクを使用して、Eclipse 内から実行中の Apache Felix OSGi コンテナーに展開されたバンドル (jar ではなくフォルダー内を意味する) を (再) デプロイする方法を探しています。

私はこの質問を見つけました。これには近い答えがありますが、Gogo シェルにコマンドを入力することに依存しているため、長期的な開発の使用には不便です。これには Eclipse の起動タスク メカニズムを使用したいと考えていますが、同様に高速で便利な代替手段があれば、それも受け入れます。

Eclipse の起動タスクから Gogo シェル コマンドを起動できれば、それが解決策になると思いますが、その方法について頭を悩ませることもできません。そのためにはリモート シェル バンドルが必要だと思いますか?

Remote Shell バンドルに接続して自動化された方法で Gogo コマンドを実行できる telnet クライアントを Java で作成することを考え始めています。私は自分のニーズに合わせて変更できる例をすでにいくつか 見てきました...しかし、私はそれから「車輪の再発明」のような感覚を得ています。きっともっと良い方法がありますか?

私が何をしているかを理解するのに役立ついくつかの背景:

here で説明されているプロジェクトのセットアップと同様に、基本的に Apache Felix jar とデプロイしたいサード パーティのバンドル (Gogo シェルなど) を含む Eclipse 'OSGiContainer' プロジェクトをセットアップしました。次に、バンドルを含む 2 番目の「MyBundle」プロジェクトを作成しました。OSGiContainer プロジェクトを起動して OSGi コンテナーを開始し、開発中にずっと実行し続けたい OSGiContainer に MyBundle プロジェクトを起動して、バンドルで開発し、変更をテストしたいと考えています。

プロジェクトのレイアウト:

  • OSGiコンテナ
    • ビン (フェリックス ジャーを含む)
    • バンドル (サードパーティのバンドル)
    • conf (Felix の config.properties ファイル)
  • マイバンドル
    • ソース
    • 目標
      • クラス

次に、Gogo シェルで次のコマンドを呼び出すことにより、バンドルを OSGi コンテナーにデプロイできます。

install reference:file:../MyBundle/target/classes
start <bundleId>

再デプロイするには、次のコマンドを呼び出します。

stop <bundleId>
uninstall <bundleId>
install reference:file:../MyBundle/target/classes
start <bundleId>

シェルで毎回 4 つのコマンドを呼び出さなければならないのは、それほど楽しいことではないことは想像に難くありません。ですから、入力するコマンドを少なくする方法を教えていただければ、すでに大きな改善になるでしょう。

アップデート

少しハックして、以下のクラスを思いつきました。これは、いくつかの小さな変更を加えた telnet の例の適応であり、バンドルをアンインストールしてから再インストールして開始するために必要なコマンドを含む主要な方法です。バンドルへのパスは、プログラムへの引数として指定する必要があり、次のようになります。

reference:file:../MyBundle/target/classes

私はこの解決策がまったく好きではないので、この質問への回答を大歓迎します。ただし、これが機能することを確認しました:

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.SocketException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;

import org.apache.commons.net.telnet.TelnetClient;

public class GogoDeployer {
    static class Responder extends Thread {
        private StringBuilder builder = new StringBuilder();
        private final GogoDeployer checker;
        private CountDownLatch latch;
        private String waitFor = null;
        private boolean isKeepRunning = true;

        Responder(GogoDeployer checker) {
            this.checker = checker;
        }

        boolean foundWaitFor(String waitFor) {
            return builder.toString().contains(waitFor);
        }

        public synchronized String getAndClearBuffer() {
            String result = builder.toString();
            builder = new StringBuilder();
            return result;
        }

        @Override
        public void run() {
            while (isKeepRunning) {
                String s;

                try {
                    s = checker.messageQueue.take();
                } catch (InterruptedException e) {
                    break;
                }

                synchronized (Responder.class) {
                    builder.append(s);
                }

                if (waitFor != null && latch != null && foundWaitFor(waitFor)) {
                    latch.countDown();
                }
            }
            System.out.println("Responder stopped.");
        }

        public String waitFor(String waitFor) {
            synchronized (Responder.class) {
                if (foundWaitFor(waitFor)) {
                    return getAndClearBuffer();
                }
            }

            this.waitFor = waitFor;
            latch = new CountDownLatch(1);
            try {
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
                return null;
            }

            String result = null;
            synchronized (Responder.class) {
                result = builder.toString();
                builder = new StringBuilder();
            }

            return result;
        }
    }

    static class TelnetReader extends Thread {
        private boolean isKeepRunning = true;
        private final GogoDeployer checker;
        private final TelnetClient tc;

        TelnetReader(GogoDeployer checker, TelnetClient tc) {
            this.checker = checker;
            this.tc = tc;
        }

        @Override
        public void run() {
            InputStream instr = tc.getInputStream();

            try {
                byte[] buff = new byte[1024];
                int ret_read = 0;

                do {
                    if (instr.available() > 0) {
                        ret_read = instr.read(buff);
                    }
                    if (ret_read > 0) {
                        checker.sendForResponse(new String(buff, 0, ret_read));
                        ret_read = 0;
                    }
                } while (isKeepRunning && (ret_read >= 0));
            } catch (Exception e) {
                System.err.println("Exception while reading socket:" + e.getMessage());
            }

            try {
                tc.disconnect();
                checker.stop();
                System.out.println("Disconnected.");
            } catch (Exception e) {
                System.err.println("Exception while closing telnet:" + e.getMessage());
            }
        }
    }

    private static final String prompt = "g!";
    private static GogoDeployer client;


    private String host;
    private BlockingQueue<String> messageQueue = new LinkedBlockingQueue<String>();
    private int port;
    private TelnetReader reader;
    private Responder responder;
    private TelnetClient tc;

    public GogoDeployer(String host, int port) {
        this.host = host;
        this.port = port;
    }

    public void stop() {
        responder.isKeepRunning = false;
        reader.isKeepRunning = false;

        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
        }
        responder.interrupt();
        reader.interrupt();
    }

    public void send(String command) {
        PrintStream ps = new PrintStream(tc.getOutputStream());
        ps.println(command);
        ps.flush();
    }

    public void sendForResponse(String s) {
        messageQueue.add(s);
    }

    public void connect() throws SocketException, IOException {
        tc = new TelnetClient();
        tc.connect(host, port);
        reader = new TelnetReader(this, tc);
        reader.start();
        responder = new Responder(this);
        responder.start();
    }

    public String waitFor(String s) {
        return responder.waitFor(s);
    }

    private static String exec(String cmd) {
        String result = "";
        System.out.println(cmd);
        client.send(cmd);
        result = client.waitFor(prompt);
        return result;
    }

    public static void main(String[] args) {
        try {
            String project = args[0];
            client = new GogoDeployer("localhost", 6666);
            client.connect();
            System.out.println(client.waitFor(prompt));
            System.out.println(exec("uninstall " + project));
            String result = exec("install " + project);
            System.out.println(result);
            int start = result.indexOf(":");
            int stop = result.indexOf(prompt);
            String bundleId = result.substring(start + 1, stop).trim();
            System.out.println(exec("start " + bundleId));
            client.stop();
        } catch (SocketException e) {
            System.err.println("Unable to conect to Gogo remote shell: " + e.getMessage());
        } catch (IOException e) {
            System.err.println("Unable to conect to Gogo remote shell: " + e.getMessage());
        }
    }
}
4

1 に答える 1

1

同じ要件 (できるだけ早くターゲット/クラスからバンドルを展開する) を満たしたとき、最初に考えたのは、いくつかのシェル機能を使用してコンテナーを拡張することでした。しかし、私の 2 番目の考えは、常に最上位のウィンドウを開く単純なバンドルを作成することでした。これにより、Eclipse (またはトータル コマンダーなど) からそのウィンドウに任意のプロジェクトをドラッグ アンド ドロップできます。このコードは、ドロップされたフォルダーに target/classes フォルダーがあるかどうかをチェックし、ある場合はデプロイされます。

ソースコードはhttps://github.com/everit-org/osgi-richconsoleで入手できます

依存関係は maven-central から入手できます。

依存関係は次のとおりです。

<dependency>
    <groupId>org.everit.osgi.dev</groupId>
    <artifactId>org.everit.osgi.dev.richconsole</artifactId>
    <version>1.2.0</version>
</dependency>

開発中にバンドルを使用し、ライブサーバーをセットアップするときにバンドルを削除できます。ただし、コンテナーがヘッドレス モードで実行されている場合はポップアップ ウィンドウが表示されないため、これは必須ではありません。

将来的に(展開だけでなく)より多くの機能を追加したいので、これをリッチコンソールと呼びました:)

于 2013-04-07T23:25:24.120 に答える