Package org.gocha.gui

Source Code of org.gocha.gui.ApplicationGlobal

/*******************************************************************************
gocha.org-lib-java Библеотека общего назначения
(с) Камнев Георгий Павлович 2009 GPLv2

Данная программа является свободным программным обеспечением. Вы вправе
распространять ее и/или модифицировать в соответствии с условиями версии 2
либо по вашему выбору с условиями более поздней версии
Стандартной Общественной Лицензии GNU, опубликованной Free Software Foundation.

Мы распространяем данную программу в надежде на то, что она будет вам полезной,
однако НЕ ПРЕДОСТАВЛЯЕМ НА НЕЕ НИКАКИХ ГАРАНТИЙ,
в том числе ГАРАНТИИ ТОВАРНОГО СОСТОЯНИЯ ПРИ ПРОДАЖЕ
и ПРИГОДНОСТИ ДЛЯ ИСПОЛЬЗОВАНИЯ В КОНКРЕТНЫХ ЦЕЛЯХ.
Для получения более подробной информации ознакомьтесь
со Стандартной Общественной Лицензией GNU.

Вместе с данной программой вы должны были получить экземпляр
Стандартной Общественной Лицензии GNU.
Если вы его не получили, сообщите об этом в Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*******************************************************************************/

package org.gocha.gui;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.gocha.collection.map.ReadOnlyMap;
import org.gocha.common.ExitListener;
import org.gocha.common.ExitEvent;
import org.gocha.files.FileUtil;
import org.gocha.xml.XMLUtil;

/**
* Глобальный класс GUI приложения.
* <p>
* Данный класс предназначен как единственный экземпляр приложения,
* который отмечает начало и завершение работы приложения.<br/>
* К прослушиванию события выхода можно подцепить любой объект реализующий <b>ExitListener.</b>
* Начало работы приложения отмечается при помощи метода <b>start()</b>, завершение при помощи <b>fireExit()</b>
* </p><p>
* Также можно подципить объекты к <b>AutoClose</b>, которые должны быть автоматически закрыти при получении
* сообщения выхода (<i>fireExit()</i>)
* </p><p>
* Для каждого отдельного прилоежния подразумевает свой контекст,
* который связан с соответствующей пользовательской директорией.<br/>
* Контекст прдставляется как имя класса с указанием пакета. Например: <b>myorg.app.ver</b>.
* При запросе рабочего каталога приложения
* Соответственно в каталоге пользователя будут создан каталог myorg/app/ver (если его еще нет)
* </p><p>
* При вызове метода <i>start()</i> можно указать параметры:
* <table border="1">
*   <tr>
*     <td><b>Параметр</b></td>
*     <td><b>Описание</b></td>
*     <td><b>Примеры</b></td>
*   </tr>
*   <tr>
*     <td><b>-appdir <i>путь_к_каталогу</i></b></td>
*     <td>Указывает контекст приложения - путь к каталогу.</td>
*     <td>
*       Пример unix:<br/>
*       <b>-appdir "/home/user/applicationDataDir"</b><br/><br/>
*       Пример windows:<br/>
*       <b>-appdir "C:\\Documents and settings\\user\\applicationDataDir"</b>
*     </td>
*   </tr>
*   <tr>
*     <td><b>-webapp <i>on|off|true|false</i></b></td>
*     <td>
*       При значении <i>on</i> или <i>true</i> -
*       указывает на необходимоть работы в режиме java webstart.
*       В этом режиме метод <i>getLocalApplicationDirectory()</i> - Возвращает пустую ссылку
*     </td>
*     <td>
*       Пример 1:<br/>
*       <b>-webapp "on"</b>
*       <br/><br/>
*       Пример 2:<br/>
*       <b>-webapp "false"</b>
*     </td>
*   </tr>
*   <tr>
*     <td><b>-auto <i>Класс{;Класс}</i></b></td>
*     <td>Указывает на список классов которые необходимо создать после вызова start()</td>
*     <td>
* Пример: <br>
* 1. <b>-auto "org.app.pluginA"</b> - Создаст при вызове start() класс org.app.pluginA<br/>
* 2. <b>-auto "org.app.PluginA;org.app.PluginB"</b>
* - Создаст при вызове start() классы org.app.PluginA затем org.app.PluginB
*    </td>
*   </tr>
*   <tr>
*     <td>
*       <b>-argsFile <i>Имя файла</i></b>
*     </td>
*     <td>
*       Указывает файл с дополнительными параметрами, которые не поместились в коммандную строку.<br />
*       Файл должен быть в формате XML:<br/>
*<code>
*&lt;start&gt;<br/>
*&nbsp;&nbsp;&nbsp;&nbsp;&lt;arg name="имя параметра без тире" value="значение" /&gt;<br/>
*&lt;/start&gt;
*</code>
*     </td>
*     <td>
*       -argsFile "some_file.xml"
*     </td>
*   </tr>
*   <tr>
*     <td>
*       <b>-argsFileCS <i>Кодировка файла</i></b>
*     </td>
*     <td>
*       Указывает кодировку файла с дополнительными параметрами.
*       По умолчанию испольуется UTF-8
*     </td>
*     <td>
*       -argsFileCS "UTF-8"
*     </td>
*   </tr>
* </table>
* </p>
* @see org.gocha.gui.ApplicationGlobal#start(java.lang.String[])
* <b>start()</b> - Отмечает стар приложения <br/>
*
* @see org.gocha.gui.ApplicationGlobal#fireExit(java.lang.Object)
* <b>fireExit()</b> - Отмечает завершение работы приложения <br/>
*
* @see org.gocha.gui.ApplicationGlobal#getLocalApplicationDirectory()
* <b>getLocalApplicationDirectory()</b> - Возвращает каталог (контекст) приложения <br/>
*
* @see org.gocha.common.ExitListener
* <b>ExitListener</b> - Слушает выход из приложения <br/>
*
* @see org.gocha.gui.AutoClose
* <b>AutoClose</b> -
* Класс/Сиглетон слушает сообщения выхода приложения
* и закрывает при выходе указанные объекты.
* Своебразный адаптер для закрытия объектов<br/>
* @author gocha
*/
public class ApplicationGlobal
{
    /**
     * Конструктор закрыт для непосредственного вызова.
     * Вместо этого предлогается использовать статичный метод instance()
     * @see org.gocha.gui.ApplicationGlobal#instance()
     */
    protected ApplicationGlobal()
    {
        this.addExitListener(createAutoClose());
    }

    /**
     * Создает/Возвращает объект который закрывает обекты при выходе
     * @return Автоматический закрыватель
     */
    protected AutoClose createAutoClose()
    {
        return AutoClose.instance();
    }

    protected static GuiFactory factory = null;

    /**
     * Возвращает фабрику создающую объект ApplicationGlobal
     * @return Фабрика классов
     */
    public static GuiFactory getFactory()
    {
        if( factory == null )factory = new DefaultFactory();
        return factory;
    }

    /**
     * Устанавливает фабрику создающую объект ApplicationGlobal
     * @param factory Фабрика классов
     */
    public static void setFactory(GuiFactory factory)
    {
        ApplicationGlobal.factory = factory;
    }

    /**
     * Создает экземпляр ApplicationGlobal
     * @return экземпляр ApplicationGlobal
     */
    static ApplicationGlobal create(){ return new ApplicationGlobal(); }

    protected static ApplicationGlobal inst = null;

    /**
     * Возвращает экземпляр ApplicationGlobal.
     * Доавбляет слушателя AutoClose.instance() на завершение работыю
     * @return экземпляр ApplicationGlobal
     */
    public static ApplicationGlobal instance()
    {
        if( inst==null )
        {
            inst = getFactory().createGlobal();
            if( inst!=null )inst.addExitListener(AutoClose.instance());
        }
        return inst;
    }

    protected Collection exitListeners = new HashSet();

    protected Map<String,String> programArgs = new HashMap<String, String>();

    /**
     * Возвращает параметры указанные при запуске программы.
     * <p>
     * Данные параметры доступны только для чтения.
     * Параметры разделяются на ключ/значение.
     * Признаком ключа является символ тире "<b>-</b>".
     * </p><p>
     * В данной коллекции ключ указан без тире.
     * </p>
     * @return параметры указанные при запуске программы
     */
    public Map<String, String> getProgramAruments()
    {
        return programArgs;
    }

    protected Boolean webstartApp = null;

    /**
     * Указывает что программа была запущена в режиме Java web start.
     * <p>
     * На данный признак влияет параметр коммандой строки <b>-webapp "on"</b> либо <b>-webapp "true"</b>
     * </p>
     * @return Указывает что программа была запущена в режиме Java web start.
     */
    public boolean isWebStartApplication()
    {
        if( webstartApp==null )
        {
            if( getProgramAruments().containsKey(WEBSTART_APPLICATION) )
            {
                String v = getProgramAruments().get(WEBSTART_APPLICATION);
                webstartApp = v.equalsIgnoreCase("on") || v.equalsIgnoreCase("true");
            }else{
                webstartApp = false;
            }
        }
        return webstartApp;
    }

    protected List<Class> autoClasses = new ArrayList<Class>();

    /**
     * Классы которые автоматически создаются при вызове start()
     * @return Автоматически создаваемые классы
     */
    public List<Class> getAutoCreateClasses()
    {
        return autoClasses;
    }

    protected File localApplicationDirectory = null;

    /**
     * Директория данных программы.
     * <p>
     * На данное значение влияет параметр ком. строки LOCAL_APPLICATION_DIRECTORY (-appdir).
     * Если он не указан, то используется домашняя директория пользователя + контекст.
     * Если запрещен доступ к локальным данным (режим WEB), то возвращает null
     * </p>
     * @return Директория данных программы или null
     * @see #getContext()
     */
    public File getLocalApplicationDirectory()
    {
        if( isWebStartApplication() )return null;

        if( localApplicationDirectory==null )
        {
            if( getProgramAruments().containsKey(LOCAL_APPLICATION_DIRECTORY) )
            {
                File appDir = new File(getProgramAruments().get(LOCAL_APPLICATION_DIRECTORY));
                if( appDir.exists() && appDir.isDirectory() )
                {
                    localApplicationDirectory = appDir;
                }
            }else
            {
                try
                {
                    String userHomePath = org.gocha.files.FileSystemInfo.getUserHomePath();
                    if( userHomePath!=null )
                    {
                        File userHome = new File(userHomePath);
                        if( userHome.exists() && userHome.isDirectory() && context!=null )
                        {
                          String ctx = context;

                            if(ctx.startsWith(".")&&ctx.length()>1)
                          {
                            ctx = ctx.substring(1);
                          }
                         
                          String[] ctxDirNames = ctx.split("\\.");
                            if( context.startsWith(".")
                                    && ctxDirNames.length>0
                                    && !ctxDirNames[0].startsWith(".") )
                            {
                                ctxDirNames[0] = "." + ctxDirNames[0];
                            }

                          File appDir = userHome;
                          for( String ctxD : ctxDirNames )
                          {
                            appDir = new File(appDir,ctxD);
                          }
                         
//                            File appDir = new File(userHome, ".org");
//                            appDir = new File(appDir, "gocha");
//                            appDir = new File(appDir, "notes");
                           
                            if( appDir.exists() && appDir.isDirectory() )
                            {
                                localApplicationDirectory = appDir;
                            }else{
                                if( !appDir.exists() )
                                {
                                    if( appDir.mkdirs() )
                                    {
                                        localApplicationDirectory = appDir;
                                    }
                                }
                            }
                        }
                    }
                } catch (Exception ex) {
                    Logger.getLogger(ApplicationGlobal.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return localApplicationDirectory;
    }

    /**
     * Параметр ком. строки указывающий директорию данных программы
     */
    public static final String LOCAL_APPLICATION_DIRECTORY = "appdir";

    /**
     * Параметр ком. строки указывающий режим веб приложения<br/>
     * <b>-webapp "on"</b> либо <b>-webapp "true"</b>
     */
    public static final String WEBSTART_APPLICATION = "webapp";

    /**
     * Параметр ком. строки указывающий какие классы создавать.
     * <p>
     * Пример: <br>
     * 1. <b>-auto "org.app.pluginA"</b> - Создаст при вызове start() класс org.app.pluginA<br/>
     * 2. <b>-auto "org.app.PluginA;org.app.PluginB"</b>
     * - Создаст при вызове start() классы org.app.PluginA затем org.app.PluginB
     * </p>
     */
    public static final String AUTOCLASSES = "auto";
   
    protected static String context = null;

    /**
     * Возвращает контекст приложения
     * @return Контекст приложения
     * @see #setContext(java.lang.String)
     */
    public static String getContext() {
    return context;
  }

    /**
     * Устанавливает контекст приложения.<br/><br/>
     * Контекст - Определяет каталог в домашней директории пользователя где храняться настройки,
     * если не указанно явно через коммандную строку <b>-appdir</b>.<br/>
     * Например: контекст указан как: <b>.mydomain.ru.myapplication.ver1</b>
     * то соответственно каталог будет:<b>~/.mydomain/ru/myapplication/ver1</b>
     * @param context Контекст приложения
     * @see #LOCAL_APPLICATION_DIRECTORY
     */
  public static void setContext(String context) {
    ApplicationGlobal.context = context;
  }

    /**
     * Устанавливает контекст приложения
     * @param context Контекст приложения
     * @see #setContext(java.lang.String)
     */
  public static void setContext(Class<?> context) {
        if( context!=null )
        {
            ApplicationGlobal.context = "."+context.getName();
        }
  }

    /**
     * Параметр ком. строки указывающий на файл XML с дополнительными параметрами <b>start()</b><br/>
     * Этот файл объединяется с текущими параметрами командной строки.
     * @see org.gocha.gui.ApplicationGlobal#start(java.lang.String[])
     * @see org.gocha.gui.ApplicationGlobal#ARGUMENT_FILE_CS
     */
    public static final String ARGUMENT_FILE = "argsFile";

    /**
     * Указывает какую кодировку использовать для файла указаного параметром <b>argsFile</b>.
     * По уполчанию используется кодировка <b>UTF8</b>.
     * @see org.gocha.gui.ApplicationGlobal#ARGUMENT_FILE
     */
    public static final String ARGUMENT_FILE_CS = "argsFileCS";

  /**
     * Отмечает стар приложения
     * @param args Аргумент программы
     * @see org.gocha.gui.ApplicationGlobal#ARGUMENT_FILE
     * @see org.gocha.gui.ApplicationGlobal#ARGUMENT_FILE_CS
     * @see org.gocha.gui.ApplicationGlobal#AUTOCLASSES
     * @see org.gocha.gui.ApplicationGlobal#LOCAL_APPLICATION_DIRECTORY
     * @see org.gocha.gui.ApplicationGlobal#WEBSTART_APPLICATION
     */
    public void start(String[] args)
    {
        if (args == null) {
            throw new IllegalArgumentException("args == null");
        }
       
        for( int i=0; i<args.length-1; i++ )
        {
            String arg = args[i];
            String val = args[i+1];
            if( arg.startsWith("-") && arg.length()>1 )
            {
                programArgs.put(arg.substring(1), val);
            }
        }

        if( programArgs.containsKey(ARGUMENT_FILE) )
        {
            String cs = programArgs.containsKey(ARGUMENT_FILE_CS) ? programArgs.get(ARGUMENT_FILE_CS) : "UTF8";
            String xsl = FileUtil.readAllText(ApplicationGlobal.class.getResource("startupArguments.xsl"), "UTF8");
            String xml = FileUtil.readAllText(programArgs.get(ARGUMENT_FILE), cs);
            if( xsl!=null && xml!=null )
            {
                xml = XMLUtil.toStringXSLT(xsl, xml);
                if( xml!=null )
                {
                    Object o = FileUtil.readXMLBeanFromStirng(xml,null);
                    if( o!=null && o instanceof Map )
                    {
                        for( Object key : ((Map)o).keySet() )
                        {
                            Object val = ((Map)o).get(key);
                            if( key==null || val==null )continue;
                            if( key instanceof String && val instanceof String )
                            {
                                programArgs.put((String)key, (String)val);
                            }
                        }
                    }
                }
            }
        }

        programArgs = new ReadOnlyMap<String, String>(programArgs);
        createAutoClasses();
    }

    /**
     * Добавляет класс в список автоматически создаваемых
     * @param c Класс
     */
    protected void addAutoCreatedClass(Class c)
    {
        getAutoCreateClasses().add(c);
    }

    /**
     * Создает классы указанные в списке автоматически создаваемых
     */
    protected void createAutoClasses()
    {
        String auto = getProgramAruments().containsKey(AUTOCLASSES) ?
            getProgramAruments().get(AUTOCLASSES) : null;
       
        if( auto!=null )
        {
            String[] autoCreate = auto.split(";");
            for( String className : autoCreate )
            {
                try
                {
                    Class c = Class.forName(className);
                    if( c!=null )addAutoCreatedClass(c);
                } catch (ClassNotFoundException ex) {
                    Logger.getLogger(ApplicationGlobal.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }

        for( Class c : getAutoCreateClasses() )
        {
            try
            {
                if( c==null )continue;
               
                Constructor constr = c.getConstructor();
                try
                {
                    constr.newInstance();
                } catch (InstantiationException ex) {
                    Logger.getLogger(ApplicationGlobal.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IllegalAccessException ex) {
                    Logger.getLogger(ApplicationGlobal.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IllegalArgumentException ex) {
                    Logger.getLogger(ApplicationGlobal.class.getName()).log(Level.SEVERE, null, ex);
                } catch (InvocationTargetException ex) {
                    Logger.getLogger(ApplicationGlobal.class.getName()).log(Level.SEVERE, null, ex);
                }
            } catch (NoSuchMethodException ex) {
                Logger.getLogger(ApplicationGlobal.class.getName()).log(Level.SEVERE, null, ex);
            } catch (SecurityException ex) {
                Logger.getLogger(ApplicationGlobal.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    /**
     * Отмечает завершение работы приложения. Рассылает всем подпищикам о завершении работы.
     * @param source Кто послал сообщение о завершении работы
     */
    public void fireExit(Object source)
    {
        ExitEvent evnt = new ExitEvent(source);
        for( Object o : exitListeners.toArray() )
        {
            if( o!=null && o instanceof ExitListener )
                ((ExitListener)o).exitEvent(evnt);
        }
    }

    /**
     * Добавляет подписчика на событие выхода
     * @param listener Подписчик
     */
    public void addExitListener(ExitListener listener)
    {
        if( listener!=null )exitListeners.add(listener);
    }

    /**
     * Удаляет подписчика от события выхода
     * @param listener Подписчик
     */
    public void removeExitListener(ExitListener listener)
    {
        exitListeners.remove(listener);
    }
}
TOP

Related Classes of org.gocha.gui.ApplicationGlobal

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.