воскресенье, 9 мая 2010 г.

Eclipse RCP: О понятии RCP Application


В прошлый раз я обещал написать про то, как деплоить OSGi-приложение в сервлет-контейнерах, отличных от Jetty. Для решения данной задачи используется Equinox ServletBridge, однако, прежде чем разбираться с данным механизмом, необходимо вникнуть в основы построения и деплоймента Eclipse RCP-приложений. О деплойменте поговорим чуть позже, а сегодня разберемся с тем, что такое "приложение" в терминах Eclipse RCP.

Приложением называется класс, реализующий интерфейс IApplication. В каком-то смысле приложение является точкой входа в Eclipse RCP и является аналогом метода main Java или C/C++ программы. В поставку Eclipse Plugins Development Environment включено несколько примеров приложений. Вот код класса, реализующего интерфейс IApplication из примера Hello RCP:



package name.samolisov.plugins.app;



import org.eclipse.equinox.app.IApplication;

import org.eclipse.equinox.app.IApplicationContext;

import org.eclipse.swt.widgets.Display;

import org.eclipse.ui.IWorkbench;

import org.eclipse.ui.PlatformUI;



/**

 * This class controls all aspects of the application's execution

 */


public class Application implements IApplication {



    /* (non-Javadoc)

     * @see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app.IApplicationContext)

     */


    public Object start(IApplicationContext context) throws Exception {

        Display display = PlatformUI.createDisplay();

        try {

            int returnCode = PlatformUI.createAndRunWorkbench(display, new ApplicationWorkbenchAdvisor());

            if (returnCode == PlatformUI.RETURN_RESTART)

                return IApplication.EXIT_RESTART;

            else

                return IApplication.EXIT_OK;

        } finally {

            display.dispose();

        }

       

    }



    /* (non-Javadoc)

     * @see org.eclipse.equinox.app.IApplication#stop()

     */


    public void stop() {

        if (!PlatformUI.isWorkbenchRunning())

            return;

        final IWorkbench workbench = PlatformUI.getWorkbench();

        final Display display = workbench.getDisplay();

        display.syncExec(new Runnable() {

            public void run() {

                if (!display.isDisposed())

                    workbench.close();

            }

        });

    }

}

 


В методе start происходит инициализация приложения. В данном случае здесь создается workbench и регистрируется менеджер связки "воркбенч - окно", в котором, в свою очередь, регистрируется непосредственно главное окно приложения. Метод start может возвращать следующие значения типа Integer, которые являются некоторым аналогом кода завершения приложения:
- IApplication.EXIT_OK - приложение запущено корректно.
- IApplication.EXIT_RESTART - приложение требует перезапуска платформы
- IApplication.EXIT_RELAUNCH - приложение требует останова и нового запуска платформы. Обычно данный код возвращают, если требуется запуск приложения с какими-то другими аргументами командной строки.

В методе stop, соответственно, происходит освобождение ресурсов, общих для всего приложения. В данном примере - происходит закрытие воркбенча.

В случае, если разрабатывается веб-приложение, запускаемое в сервлет-контейнере Jetty, код класса может быть таким:

package name.samolisov.plugins.app;



import java.util.Dictionary;

import java.util.Hashtable;



import org.eclipse.equinox.app.IApplication;

import org.eclipse.equinox.app.IApplicationContext;

import org.eclipse.equinox.http.jetty.JettyConfigurator;



public class WebApplication implements IApplication

{

    private static final String HTTP_PORT_KEY = "http.port";



    private static final int HTTP_PORT = 8080;



    private static final String SERVER_NAME = "demojetty";



    @Override

    public Object start(IApplicationContext context) throws Exception

    {

        Dictionary<String, Object> properties = new  Hashtable<String, Object>();

        properties.put(HTTP_PORT_KEY, HTTP_PORT);

        JettyConfigurator.startServer(SERVER_NAME, properties);

        System.out.println("Server " + SERVER_NAME + " has been started");



        return EXIT_OK;

    }



    @Override

    public void stop()

    {

        try

        {

            JettyConfigurator.stopServer(SERVER_NAME);

            System.out.println("Server " + SERVER_NAME + " has been stoped");

        }

        catch (Exception e)

        {

            e.printStackTrace();

        }

    }

}

 


Класс-приложение необходимо зарегистрировать. Для этого служит точка расширения org.eclipse.core.runtime.applications. Воспользоваться ею можно следующим образом:

<extension

        id="name.samolisov.plugins.app.application"

        point="org.eclipse.core.runtime.applications">

      <application>

         <run

              class="name.samolisov.plugins.app.Application">

         </run>

      </application>

</extension>


После регистрации приложение становится доступно для запуска. Его можно выбрать в качестве значения параметра Run an application конфигурации запуска (соответственно, при нажатии кнопки Run, будет запущен не Eclipse, а наше приложение):



Если бандл с приложением поместить в каталог plugins инсталяции Eclipse, то запустить приложение можно будет из командной строки, указав его идентификатор в качестве значения параметра -application:

eclipse.exe -application name.samolisov.plugins.app.application

Теперь рассмотрим развертывание приложения отдельно от инсталяции Eclipse. Для этого необходимо создать следующую структуру каталогов (подробнее о структуре каталогов и запуске Equinox) можно прочесть здесь):

\demo
---\configuration
------config.ini
---eclipse.exe
---\plugins
------\org.eclipse.equinox.launcher.win32.win32.x86_1.0.100
---------eclipse.dll

В каталог plugins необходимо скопировать все плагины, которые требуются для бандла с приложением. В случае приложения Hello RCP, входящего в набор примеров Eclipse PDE, необходимы следующие бандлы:


com.ibm.icu
name.samolisov.plugins.app
org.eclipse.core.commands
org.eclipse.core.contenttype
org.eclipse.core.databinding.observable
org.eclipse.core.databinding.property
org.eclipse.core.databinding
org.eclipse.core.expressions
org.eclipse.core.jobs
org.eclipse.core.runtime.compatibility.auth
org.eclipse.core.runtime.compatibility.registry
org.eclipse.core.runtime
org.eclipse.equinox.app
org.eclipse.equinox.common
org.eclipse.equinox.launcher.win32.win32.x86
org.eclipse.equinox.launcher
org.eclipse.equinox.preferences
org.eclipse.equinox.registry
org.eclipse.help
org.eclipse.jface.databinding
org.eclipse.jface
org.eclipse.osgi.services
org.eclipse.osgi
org.eclipse.swt.win32.win32.x86
org.eclipse.swt
org.eclipse.ui.workbench
org.eclipse.ui


Файл configuration/config.ini должен иметь следующее содержание:

#Product Runtime Configuration File

osgi.bundles=org.eclipse.equinox.common@2:start,org.eclipse.core.jobs@start,org.eclipse.equinox.registry@start,org.eclipse.equinox.preferences@start,org.eclipse.core.contenttype@start,org.eclipse.equinox.app@start,org.eclipse.core.runtime@start,org.eclipse.core.commands@start,org.eclipse.ui.workbench@start,org.eclipse.help@start,org.eclipse.swt@start,org.eclipse.jface@start,org.eclipse.ui@start,org.eclipse.core.expressions@start,com.ibm.icu@start,org.eclipse.jface.databinding@start,org.eclipse.core.databinding.observable@start,org.eclipse.core.databinding.property@start,org.eclipse.core.databinding@start,org.eclipse.swt.win32.win32.x86@start,name.samolisov.plugins.app@start

osgi.bundles.defaultStartLevel=4

eclipse.application=name.samolisov.plugins.app.application

 


В данном файле для нас важна строчка eclipse.application=name.samolisov.plugins.app.application, задающая приложение по-умолчанию. Теперь для запуска не нужно указывать параметр командной строки -application, а можно просто запускать файл eclipse.exe.

Понятно, что неудобно каждый раз руками отслеживать зависимости бандлов и копировать плагины вручную. Так же неудобно вручную прописывать значения в файле config.ini. Хочется, чтобы все это делалось автоматически. К тому же, иногда хочется добавить к приложению какой-то брендинг - иконки запуска, ярлычок, указать лицензию и т.д. Для этого в Eclipse RCP существует такое понятие, как "Продукт". Однако, это уже тема другого разговора.

Понравилось сообщение - подпишитесь на блог или читайте меня в twitter

5 комментариев:

Анатоль комментирует...

"Понятно, что неудобно каждый раз руками отслеживать зависимости бандлов и копировать плагины вручную. Так же неудобно вручную прописывать значения в файле config.ini. Хочется, чтобы все это делалось автоматически. К тому же, иногда хочется добавить к приложению какой-то брендинг - иконки запуска, ярлычок, указать лицензию и т.д. Для этого в Eclipse RPC существует такое понятие, как "Проект"."

)) Перед сдачей курсового за час до сдачи выяснили, что плугинов насоздавали, из эклипса свою рсп запустить можем, а как сделать без эклипса? Пришлось за полчаса разобраться с этим проектомом :)

Pavel Samolisov комментирует...

Полчаса - тоже время. Напишу заметку, вдруг, кому-то пригодится.

Анатоль комментирует...

Ага, было бы полезно. Потому как тогда на адреналине сделал, а теперь заставь повторить - сомневаюсь, что смогу с ходу.

Сергей комментирует...

Здравствуйте.
где вызывается метод stop()?

у меня вообще такого метода нет, только run()
вся глупость в том, что когда закрываю главное окно своего rcp приложения, другие окна не закрываются

Pavel Samolisov комментирует...

Метод stop() будет автоматически вызван платформой при завершении приложения (например, при выгрузке соответствующего бандла).

Отправить комментарий

Любой Ваш комментарий важен для меня, однако, помните, что действует предмодерация. Давайте уважать друг друга!