Sistema Modular

11 respostas
J

Boa tarde pessoal, sou novo no forum e estou voltando agora a programar em java.

Bom inicialmente estou desenvolvendo um sistema que utiliza de modulos(plugin) assim como acontece no Eclipse, NetBeans e afins, o que eu estou precisando fazer seria o seguinte, eu tenho um JFrame instanciado em uma classe que inicializa o programa, eu gostaria de acessar a mesma sem ter que passar o objeto JFrame pra outra classe para que possa incluir botoes na toolbar e assim por diante, e tambem por exemplo quando é feito o load do plugin que o mesmo possa incluir seus botoes e outras coisas na interface sem que eu tenha que passar o JFrame pra ele fazer isso.

Obrigado.

11 Respostas

sergiotaborda

joaoks:
Boa tarde pessoal, sou novo no forum e estou voltando agora a programar em java.

Bom inicialmente estou desenvolvendo um sistema que utiliza de modulos(plugin) assim como acontece no Eclipse, NetBeans e afins, o que eu estou precisando fazer seria o seguinte, eu tenho um JFrame instanciado em uma classe que inicializa o programa, eu gostaria de acessar a mesma sem ter que passar o objeto JFrame pra outra classe para que possa incluir botoes na toolbar e assim por diante, e tambem por exemplo quando é feito o load do plugin que o mesmo possa incluir seus botoes e outras coisas na interface sem que eu tenha que passar o JFrame pra ele fazer isso.

Obrigado.

Uma ideia é vc criar um objeto de modelo. nesse objeto vc registra tudo o que quer no frame. Va passa esse objeto entre os plugins para que eles possam dar o seu pitaco. Por fim, um mecanismo cria o frame com base nesse modelo.

J

Na verdade aideia seria não passar nenhum tipo de objeto para o plugin, e sim ele buscar o objeto, eu andei lendo sobre reflection mas nao sei se ele ajudaria alguma coisa nesse caso.

Felagund

Ajuda sim, sem reflection pode ser meio complicado.

Vc poderia criar uma interface, Plugin, que passa o Frame Principal como parametro e pode molda-lo de acordo com o gosto.

J

Então o que estou querendo e fugir de ter que passar qualquer tipo de objeto para o plugin.

E quanto ao reflection, eu li reli e li mais uma vez e ainda não entendi direito como utilizar, tem varios exemplos muito basicos, os quais não vi a nescessidade de se usar reflection, na verdade fiquei bem confuso, sera que alguem teria um bom tutorial mesmo, com um exemplo de aplicação real, e quais as vantagens de usalo.

M

Acho que uma possível solução é usar annotations e reflection.

J

Você teria algum exemplo de como aplicar isso ?

M

Um exemplo comum é o JUnit que permite uso de anotações para realizar testes de caso. De qualquer forma, aqui vai um exemplo prático:

Classe utilitária usada para vasculhar os classpath por classes que contenham a anotação:

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class ClassFinder {

	private static List<Class<?>> classes;

	private static List<Class<?>> scan() {
		// initializes the List
		classes = new ArrayList<Class<?>>();
		// and gets all URLs
		URLClassLoader urlLoader = (URLClassLoader) ClassLoader
				.getSystemClassLoader();
		URL[] urls = urlLoader.getURLs();
		// iterate
		for (URL url : urls) {
			File location = null;
			try {
				location = new File(url.toURI());
			} catch (URISyntaxException e) {
				e.printStackTrace();
				return null;
			}
			// and for each directory, find the classes
			if (location.isDirectory()) {
				getClassesInDirectory(null, location);
			} else {
				getClassesInJar(location);
			}
		}
		return classes;
	}

	private static void getClassesInDirectory(String parent, File location) {
		File[] files = location.listFiles();
		StringBuilder builder = null;

		for (File file : files) {
			builder = new StringBuilder(100);
			builder.append(parent).append("/").append(file.getName());
			String name = (parent == null ? file.getName() : builder.toString());

			if (file.isDirectory()) {
				getClassesInDirectory(name, file);
			} else if (file.getName().endsWith(".class")) {
				addClass(name);
			}
		}
	}

	private static void getClassesInJar(File location) {
		try {
			JarFile jar = new JarFile(location);
			Enumeration<JarEntry> entries = jar.entries();
			while (entries.hasMoreElements()) {
				JarEntry entry = entries.nextElement();
				String name = entry.getName();
				if (!entry.isDirectory() && name.endsWith(".class")) {
					addClass(name);
				}
			}
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
	}

	private static void addClass(String name) {
		String className = name.replaceAll("\\" + File.separator, ".")
				.substring(0, name.lastIndexOf(".class"));
		try {
			classes.add(Class.forName(className));
		} catch (ClassNotFoundException e) {
			// do nothing (must not occur)
		}
	}

	public static List<Class<?>> getAnnotatedClasses(
			Class<? extends Annotation> filter) {
		List<Class<?>> filtered = new ArrayList<Class<?>>();
		for (Class<?> c : scan()) {
			if (c.isAnnotationPresent(filter)) {
				filtered.add(c);
			}
		}
		return filtered;
	}

}

A anotação propriamente dita:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Criamos uma anotação que recebe o nome do método que executaremos.
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Plugin {

	String method();

}

Duas classes que contenham essa anotação:

/**
 * Essa classe servirá de exemplo e executará o método {@link #abc()}
 */
@Plugin(method = "abc")
public class MeuPlugin1 {

	// classe de exemplo #1

	public MeuPlugin1() {
		System.out.println("Construtor de MeuPlugin1");
	}

	public void abc() {
		System.out.println("O método executado foi abc()");
	}

}
/**
 * Essa classe servirá de exemplo e executará o método {@link #test()}
 */
@Plugin(method = "test")
public class MeuPlugin2 {

	// classe de exemplo #2

	public MeuPlugin2() {
		System.out.println("Construtor de MeuPlugin2");
	}

	public void test() {
		System.out.println("O método executado foi test()");
	}

}

E a classe principal:

public class ListarPlugins {

	public static void main(String[] args) throws Exception {
		// para cada classe que contenha essa anotação
		for (Class<?> c : ClassFinder.getAnnotatedClasses(Plugin.class)) {
			// criamos uma instância dessa classe
			Object instance = c.newInstance();
			// pegamos o nome do método a partir da anotação
			String method = c.getAnnotation(Plugin.class).method();
			// e invocamos o método
			c.getMethod(method).invoke(instance);
		}
	}

}
paulofafism

Boa tarde pessoal, sou novo no forum e estou voltando agora a programar em java.

Bom inicialmente estou desenvolvendo um sistema que utiliza de modulos(plugin) assim como acontece no Eclipse, NetBeans e afins, o que eu estou precisando fazer seria o seguinte, eu tenho um JFrame instanciado em uma classe que inicializa o programa, eu gostaria de acessar a mesma sem ter que passar o objeto JFrame pra outra classe para que possa incluir botoes na toolbar e assim por diante, e tambem por exemplo quando é feito o load do plugin que o mesmo possa incluir seus botoes e outras coisas na interface sem que eu tenha que passar o JFrame pra ele fazer isso.

Sua idéia e de poder customizar o sistema sem ter que alterar a estrutura original dele? Se for isso você pode utilizar linguagens de script com o Groovy, você pode fazer as implementações adicionais nele, e você so libera para o Groovy os objetos interressados. Eu estou fazendo isso eu meu sistema, e estou obtendo sucesso com ele.

J

marcobiscaro2112, o que você me enviou eu ja faço, o que eu realmente preciso que acho que nao ficou bem claro é, o meu plugin sem receber nenhum objeto acesse o objeto JFrame da aplicação.

M

Ahhh… agora entendi. Bom, sua janela precisa chegar lá (até o plugin) de algum modo. Se você não quer passar nenhum argumento o plugin precisa buscar a janela em algum lugar. Talvez se você tivesse uma classe responsável por manter a instância da janela (por exemplo uma classe Kernel que instancie a janela no construtor) e criasse métodos de acesso.

J

sim seria isso, estou buscando uma especie de canal para um acessar o outro, como se fosse um “repositorio” de objetos, onde eu teria la os plugins instanciados, a janela principal, e assim por diante…
e esqueci de falar se isso ajuda, mas por exemplo o plugin sabera o nome da JFrame, seria um padrao entende.

Criado 16 de março de 2010
Ultima resposta 16 de mar. de 2010
Respostas 11
Participantes 5