001: /*
002: * Created on 07/04/2003
003: *
004: * Swing Components - visit http://sf.net/projects/gfd
005: *
006: * Copyright (C) 2004 Igor Regis da Silva Simões
007: *
008: * This program is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU General Public License
010: * as published by the Free Software Foundation; either version 2
011: * of the License, or (at your option) any later version.
012: *
013: * This program is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: * GNU General Public License for more details.
017: *
018: * You should have received a copy of the GNU General Public License
019: * along with this program; if not, write to the Free Software
020: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
021: *
022: */package br.com.gfpshare.util;
023:
024: import java.io.File;
025: import java.lang.reflect.Method;
026: import java.util.StringTokenizer;
027: import java.util.Vector;
028:
029: import javax.swing.JFrame;
030: import javax.swing.JOptionPane;
031: import javax.swing.JTable;
032:
033: /**
034: * Com essa classe é possível lançar várias aplicações em uma mesma JVM,
035: * o trabalho deste classe essencialmente é verificar a presença de um
036: * aquivo em disco (cuje o endereço é passado como parâmetro na inicialização)
037: * e caso haja este arquivo ele lê o conteúdo do mesmo e executa as instruções
038: * da primeira linha do arquivo.
039: * <p>
040: * A sistaxe do arquivo deve ser conforme o exemplo abaixo:
041: * <p>
042: * <b>nome.completo.daClasse;parametro1;parametro2</b>
043: * <p>
044: * Exs.:<p>
045: * <b>br.com.xx.aplicativo.Classe;meuParametro</b><br>
046: * <b>br.com.xx.aplicativo.Classe;meuParametro1;meuParametro2;meuParametro3</b>
047: *
048: * @author Igor Regis da Silva Simões
049: */
050: public final class AppLauncher {
051: /**
052: * Propriedade que representa o arquivo que será monitorado para o recebimento
053: * dos parâmetros de execução das aplicações.
054: */
055: private static File arquivo = null;
056:
057: /**
058: * Propriedade que representa a linha de comando lida da primeira linha do arquivo.
059: */
060: private static String linhaDeComando = null;
061:
062: /**
063: * Propriedade que representa o nome completo da classe principal da aplicação que
064: * se deseja abrir.<br>
065: * Ex.: <code>br.com.xx.aplicativo.ClassePrincipal</code>
066: */
067: private static String aplicativo = null;
068:
069: /**
070: * Propriedade que representa o array de Strings que deverá ser passado ao método
071: * main da classe principal da aplicação a ser iniciada.
072: */
073: private static String[] parametros = null;
074:
075: /**
076: * Vector contendo a lista de todas as aplicações em execução no momento, neste JVM.
077: */
078: private static final Vector<String> aplicacoesEmExecucao = new Vector<String>();
079:
080: /**
081: * Constrói um Lanucher que monitorará o arquivo especificado como parametro
082: * para executar seu conteúdo.
083: * @param endereco Endereço em disco do arquivo que deve ser monitorado.
084: */
085: public AppLauncher(String endereco) {
086: arquivo = new File(endereco);
087: }
088:
089: /**
090: * Inicia a monitoração do arquivo, aguradando a ordem de executar um aplicação
091: */
092: public final void monitorar() {
093: java.io.BufferedReader fis = null;
094:
095: while (true) {
096: try {
097: Thread.sleep(2000);
098: if (!arquivo.exists())
099: continue;
100:
101: fis = new java.io.BufferedReader(
102: new java.io.FileReader(arquivo
103: .getAbsolutePath()));
104:
105: if ((linhaDeComando = fis.readLine()) != null) {
106: prepararLancamento();
107: if (podeLancarAplicacao())
108: lancarAplicacao();
109: }
110:
111: if (fis != null) {
112: fis.close();
113: fis = null;
114: }
115:
116: deletaArquivo();
117: } catch (Exception e) {
118: e.printStackTrace();
119: }
120: }
121: }
122:
123: /**
124: * Inicia a aplicação passada como parâmetro pelo arquivo
125: * Neste método usamos java reflection para chamar o método main do aplicativo e
126: * passar seus respectivos parâmetros.
127: */
128: private static final void lancarAplicacao() {
129:
130: //Acrecentamos a plicação à lista de aplicações em execução neste JVM
131: aplicacoesEmExecucao.addElement(aplicativo);
132:
133: (new Thread() {
134: @Override
135: public void run() {
136: Class clazz = null;
137: try {
138: clazz = Class.forName(aplicativo);
139: Class[] argsTypes = { parametros.getClass() };
140: Object[] args = { parametros };
141: Method method = clazz.getMethod("main", argsTypes);
142: method.invoke(clazz, args);
143: } catch (java.lang.ClassNotFoundException cce) {
144: System.out.println("A classe " + aplicativo
145: + " não foi encontrada no classpath.");
146: } catch (Exception e) {
147: System.out.println("Não pude executar "
148: + aplicativo);
149: e.printStackTrace();
150: }
151: }
152: }).start();
153: }
154:
155: /** Entrada do programa.
156: * @param args argumentos de entrada passados pela linha de comando
157: */
158: public static void main(String[] args) {
159: //Forçamos carga de componentes Swing
160: @SuppressWarnings("unused")
161: JFrame j = new JFrame();
162: @SuppressWarnings("unused")
163: JTable t = new JTable();
164: j = null;
165: t = null;
166:
167: if (args.length != 1) {
168: System.out.println("Aviso! - * Uso incorreto * ");
169: System.out.println("Uso correto:");
170: System.out
171: .println("java Launcher <endereço do arquivo de lançamento>");
172: System.out.println();
173: System.out
174: .println("Obs.: O arquivo de lançamento é aquele que é preenchido com o");
175: System.out
176: .println("nome completo da classe da aplicação a ser executada.");
177: System.out.println("Ex.: java Launcher c:\\dir\\");
178: return;
179: }
180:
181: AppLauncher l = new AppLauncher(args[0]);
182: l.monitorar();
183: }
184:
185: /**
186: * Deleta o arquivo que foi criado para a passagem de parâmetro,
187: * para então aguardar a passagem de um novo parametro através da
188: * criação de um novo arquivo.
189: */
190: private static final void deletaArquivo() {
191: try {
192: do {
193: arquivo.delete();
194: Thread.sleep(500);
195: } while (arquivo.exists());
196:
197: } catch (Exception e) {
198: e.printStackTrace();
199: } finally {
200: aplicativo = null;
201: }
202: }
203:
204: /**
205: * Separa a linha de comendo enviada pelo arquivo, em nome da classe a ser
206: * instanciada e seus respectivos parametros.
207: */
208: private static final void prepararLancamento() {
209:
210: StringTokenizer montador = new StringTokenizer(linhaDeComando,
211: ";");
212:
213: parametros = new String[montador.countTokens() - 1];
214:
215: aplicativo = montador.nextToken(); //O primeiro token é o nome da classe a ser instanciada.
216: int i = 0;
217: while (montador.hasMoreTokens())
218: //Os demais são seus parâmetros
219: parametros[i++] = montador.nextToken();
220: }
221:
222: /**
223: * Verifica se é permitido lançar uma nova aplicação.
224: * Assumimos aqui que só será permitida a abertura de uma instância de
225: * cada aplicação.
226: *
227: * @return boolean indicado se deve-se ou não abrir a aplicação.
228: */
229: private static final boolean podeLancarAplicacao() {
230: for (int i = 0; i < aplicacoesEmExecucao.size(); i++)
231: if (aplicacoesEmExecucao.get(i).equals(aplicativo)) {
232: JOptionPane
233: .showMessageDialog(
234: null,
235: "É permitido abrir apenas um aplicativo por computador.\nJá existe um aplicativo aberto neste micro.",
236: "Aviso", JOptionPane.WARNING_MESSAGE);
237: return false;
238: }
239: return true;
240: }
241:
242: /**
243: * Método estático que deve ser chamado pelas aplicações em execução indicando
244: * seu fechamento.<br>
245: * É necessário fazer essa chamada para indicar a classe Launcher que não há mais
246: * instancias da aplicação em execução, permitindo portanto a abertura de uma
247: * novo instancia caso desejado.
248: *
249: * @param aplicativo String indicando o nome da classe principal da aplicação que
250: * está sendo fechada.
251: */
252: public static final void fecharAplicativo(String aplicativo) {
253: aplicacoesEmExecucao.removeElement(aplicativo);
254: }
255:
256: /**
257: * Métod estático que deve ser chamado quando se deseja fechar totalmente esta
258: * instnacia da JVM.<br>
259: * Realiza uma chamada <code>System.exit(i);</code>
260: *
261: * @param i É a variável que será passada ao System.exit(i);
262: */
263: public static final void fecharJVM(int i) {
264: System.exit(i);
265: }
266: }
|