Foros del Web » Programación para mayores de 30 ;) » Java »

Evaluar si .java de un directorio forman parte d el proyecto y acceder a metodos

Estas en el tema de Evaluar si .java de un directorio forman parte d el proyecto y acceder a metodos en el foro de Java en Foros del Web. Hola! estoy haciendo una aplicacion que sea cliente de una base de datos la filtre y mas cosas... Cada categoria o subcatecoria pone en una ...
  #1 (permalink)  
Antiguo 17/11/2012, 11:32
 
Fecha de Ingreso: noviembre-2012
Ubicación: Madrid
Mensajes: 6
Antigüedad: 11 años, 5 meses
Puntos: 0
Pregunta Evaluar si .java de un directorio forman parte d el proyecto y acceder a metodos

Hola! estoy haciendo una aplicacion que sea cliente de una base de datos la filtre y mas cosas...

Cada categoria o subcatecoria pone en una posicion de un combobox una palabra (el combobox es para seleccionar que lo que voy a crear forma parte de esa clase), por esto, y alguna cosa mas, querria evitar tener que modificar el codigo cada vez que añado una clase, en este caso tendria que modificar el metodo que rellene el combobox para decirle que tambien incluya la clase nueva.

La solucion que he encontrado y estoy desarrollando poco a poco para poder hacer esto de forma facil (facil para mantener la base de datos, no para crear el codigo de esta aplicacion, que me parece que con esto la estoy complicando mucho e incluso va a ser lenta, por lo menos al cargar al principio...) es la siguiente:
-obtengo los nombres de los ficheros de un directorio (parto del package principal donde estan los componentes (todas las clases que almacenan componentes de la base de datos) y si hay mas packages subo a ellos para leerlos tambien) y filtro los '.java' quitandoles la extension.
Código:
File fichero; //=new File("Readfile.java");
        fichero=new File(directory);
        
        String[] listaArchivos=fichero.list(); //crea un array cn los nombres de los ficheros en el directorio.      

        listaArchivos=fichero.list(new Filtro(".java")); //filtra los archivos dejando solo los que tienen extension '.java'

for(int i=0; i<listaArchivos.length; i++) //elimina la extension de el nombre del archivo
        {
            //System.out.println(listaArchivos[i]);
            listaArchivos[i]=listaArchivos[i].substring(listaArchivos[i].lastIndexOf('/') + 1, listaArchivos[i].lastIndexOf('.'));
            //System.out.println(listaArchivos[i].substring(listaArchivos[i].lastIndexOf('/') + 1, listaArchivos[i].lastIndexOf('.')));
        }
-
-creo una clase equivalente a la clase que tiene el mismo nombre del archivo
Código:
ClassLoader classLoader = Componente.class.getClassLoader();
        Class aClass = null;
        try {
        aClass= classLoader.loadClass("componentespkg.cat2."+classnamber);
}
-Instancio esa clase cast-andola (xd) con la clase que quiero comparar y ejecuto el metodo que me interesa, que es, por ejemplo el String que esa clase mandara al combobox.

El programa de momento lee los archivos en un directorio, los filtra y compara con instanceof con la clase padre o con las subclases, pero todavia tengo que darle yo demasiados datos...
Funciona, pero yo no quiero tener que saber la clase de antemano para hacer cast.
Probando si en cada metodo pongo
Código:
 static{}
solo, sin modificador ni nada (que no se para que sirve), podria obtener variables escribiendo que llame a una funcion de la clase principal y le de como parametro algo, pero el problema de eso es que solo es una funcion/metodo(?), entonces si quisiera obtener informacion ordenada de esa clase tendria que enviarla toda de golpe a la clase principal y alli ordenarla... vamos, que no ganaria mucho teniendo que crear un indice de quien me envia cada cosa y que cosa es...

Otro modo de hacer algo parecido seria con reflexion (bueno, lo tro tambien se vale de ella xd), seria leer las clases de un directorio y cargarlas en tiempo de ejecucion, el problema es que no se como podria acceder a sus metodos (si es que se puede).
Es decir: yo leo un directorio y cargo una de las clases, la clase 'abc' (el archivo se llama 'abc.java' y tiene los metodos a, b y c), que ahora esta e una clase generica Class x, por ejemplo. Como puedo acceder a los metodos 'a', 'b', 'c'? Yo se que la clase, en cuanto que se cargue (en tiempo de ejecucion) sera 'abc' y tendra el metodo 'a' al que podre llamar, pero el compilador no lo sabe.

En resumen, yo tengo una carpeta con las clases que sé, porque heredan de una clase principal que lo tiene, que tienen un metodo determinado 'metodo1', lo demas no lo se, pero ese si.
¿Como voy llamando a todos los metodos 'metodo1' de las clases que desconozco cuales son?

¿Como podria hacerlo?

Perdonar por la extension, pero no sabia como explicarlo brevemente xd.
Un saludo.

Última edición por danirebollo; 17/11/2012 a las 11:38
  #2 (permalink)  
Antiguo 17/11/2012, 14:50
 
Fecha de Ingreso: diciembre-2011
Mensajes: 152
Antigüedad: 12 años, 3 meses
Puntos: 34
Respuesta: Evaluar si .java de un directorio forman parte d el proyecto y acceder a m

Puedes utilizar anotaciones:
Código Javascript:
Ver original
  1. /*
  2.  * Copyright 2012 Leviathan.
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  *
  8.  *      http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */
  16. package mx.com.leviathan.data.filter;
  17.  
  18. import java.lang.annotation.ElementType;
  19. import java.lang.annotation.Retention;
  20. import java.lang.annotation.RetentionPolicy;
  21. import java.lang.annotation.Target;
  22.  
  23. /**
  24.  *
  25.  * @author Leviathan
  26.  */
  27. @Target(ElementType.TYPE)
  28. @Retention(RetentionPolicy.RUNTIME)
  29. public @interface Filter {
  30.  
  31.     String author();
  32.  
  33.     String name();
  34.  
  35.     String version();
  36. }

Código Javascript:
Ver original
  1. /*
  2.  * Copyright 2012 Leviathan.
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  *
  8.  *      http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */
  16. package mx.com.leviathan.data.filter;
  17.  
  18. import java.lang.annotation.ElementType;
  19. import java.lang.annotation.Retention;
  20. import java.lang.annotation.RetentionPolicy;
  21. import java.lang.annotation.Target;
  22.  
  23. /**
  24.  *
  25.  * @author Leviathan
  26.  */
  27. @Target(ElementType.METHOD)
  28. @Retention(RetentionPolicy.RUNTIME)
  29. public @interface FilterFunction {
  30.  
  31.     String[] params();
  32.  
  33.     Class<?>[] paramTypes();
  34.  
  35.     Class<?> returnType();
  36. }

Aplicarlas:
Código Javascript:
Ver original
  1. @Filter(author = "Leviathan", version = "0.1", name = "Example")
  2. public class FilterExample {
  3.  
  4.     @FilterFunction(params = {"firstName", "lastName"}, paramTypes = {String.class, String.class}, returnType = String.class)
  5.     public String testString(String firstName, String lastName) {
  6.         return firstName + lastName;
  7.     }
  8. }

y por medio de reflexión trabajar con la información proporcionada en las anotaciones.
  #3 (permalink)  
Antiguo 17/11/2012, 15:10
 
Fecha de Ingreso: noviembre-2012
Ubicación: Madrid
Mensajes: 6
Antigüedad: 11 años, 5 meses
Puntos: 0
Respuesta: Evaluar si .java de un directorio forman parte d el proyecto y acceder a m

Cita:
Iniciado por LuisChavezB Ver Mensaje
Puedes utilizar anotaciones:
Código Javascript:
Ver original
  1. /*
  2.  * Copyright 2012 Leviathan.
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  *
  8.  *      http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */
  16. package mx.com.leviathan.data.filter;
  17.  
  18. import java.lang.annotation.ElementType;
  19. import java.lang.annotation.Retention;
  20. import java.lang.annotation.RetentionPolicy;
  21. import java.lang.annotation.Target;
  22.  
  23. /**
  24.  *
  25.  * @author Leviathan
  26.  */
  27. @Target(ElementType.TYPE)
  28. @Retention(RetentionPolicy.RUNTIME)
  29. public @interface Filter {
  30.  
  31.     String author();
  32.  
  33.     String name();
  34.  
  35.     String version();
  36. }

Código Javascript:
Ver original
  1. /*
  2.  * Copyright 2012 Leviathan.
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  *
  8.  *      http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */
  16. package mx.com.leviathan.data.filter;
  17.  
  18. import java.lang.annotation.ElementType;
  19. import java.lang.annotation.Retention;
  20. import java.lang.annotation.RetentionPolicy;
  21. import java.lang.annotation.Target;
  22.  
  23. /**
  24.  *
  25.  * @author Leviathan
  26.  */
  27. @Target(ElementType.METHOD)
  28. @Retention(RetentionPolicy.RUNTIME)
  29. public @interface FilterFunction {
  30.  
  31.     String[] params();
  32.  
  33.     Class<?>[] paramTypes();
  34.  
  35.     Class<?> returnType();
  36. }

Aplicarlas:
Código Javascript:
Ver original
  1. @Filter(author = "Leviathan", version = "0.1", name = "Example")
  2. public class FilterExample {
  3.  
  4.     @FilterFunction(params = {"firstName", "lastName"}, paramTypes = {String.class, String.class}, returnType = String.class)
  5.     public String testString(String firstName, String lastName) {
  6.         return firstName + lastName;
  7.     }
  8. }

y por medio de reflexión trabajar con la información proporcionada en las anotaciones.
Uhh... XD no conocia eso de las anotaciones.
Miro a ver y te cuento...

Lo que he consegido, que me funciona parcialmente, es esto:
En main:
Código:
String str = "HELLO";
    Diodo dod;
    dod=new Diodo("","",0,"","");

    try {
 
    Method method = str.getClass().getMethod("toString"); //getMethod("toString", null);
    Object retVal = method.invoke(str); //invoke(str, null);
    System.out.println(retVal);
 
    } catch ...............(a lot of catchs xd)
Este codigo, sea con 'str.getClass()...' y 'method.invoke(str)' tratando de obtener el toString de un String, o con 'dod.getClass()...' y 'method.invoke(dod)' tratando de obtener uno de los metodos de la clase Diodo, funcionan bien, pero cuando trato de obtener un metodo de 'aClass', declarado como
Código:
Class aClass = null;
, e instanciado con:
Código:
aClass= classLoader.loadClass("componentespkg.cat2.Diodo");
, que deberia ser en este caso la clase Diodo, no funciona y me devuelve la excepcion
Código:
java.lang.NoSuchMethodException: java.lang.Class.toCB2CB()
at java.lang.Class.getMethod(Class.java:1622)
at inventarionb.InventarionbTEST.main(InventarionbTEST.java:83)
Hay una cosa, no se si tiene algo que ver con el error, cuando pone java.lang.Class.toCB2CB() en la excepcion. ¿Esa ruta es correcta? No creo que el metodo de mi clase derive del metodo Class, pero no sabria que poner... en el caso de que la clase se encuentre dentro de la clase principal, donde esta el main, no hay que poner mas cosas, pero lo mismo al estar fuera hay que poner algo en la ruta... no he conseguido que me funcione poniendo la sucesion de packages (separada por '.')
  #4 (permalink)  
Antiguo 17/11/2012, 15:55
 
Fecha de Ingreso: diciembre-2011
Mensajes: 152
Antigüedad: 12 años, 3 meses
Puntos: 34
Respuesta: Evaluar si .java de un directorio forman parte d el proyecto y acceder a m

Siempre debes de utilizar la ruta completa a la clase.

Un ejemplo:
Código Javascript:
Ver original
  1. Scanner scanner = new Scanner(System.in);
  2.         Class<?> clazz = Class.forName("mx.com.leviathan.data.filter.FilterExample");
  3.         if (clazz.isAnnotationPresent(Filter.class)) {
  4.             Object newInstance = clazz.newInstance();
  5.             Filter filter = clazz.getAnnotation(Filter.class);
  6.             System.out.printf("%s, %s %s\n", filter.author(), filter.name(), filter.version());
  7.             Method[] methods = clazz.getMethods();
  8.             for (Method method : methods) {
  9.                 if (method.isAnnotationPresent(FilterFunction.class)) {
  10.                     FilterFunction filterFunction = method.getAnnotation(FilterFunction.class);
  11.                     if (filterFunction.params().length != filterFunction.paramTypes().length) {
  12.                         System.err.println("El numero de argumentos es invalido!!");
  13.                         return;
  14.                     }
  15.                     ArrayList<Object> params = new ArrayList<>();
  16.                     for (int i = 0; i < filterFunction.params().length; i++) {
  17.                         System.out.printf("Ingresa el parametro: %s >> ", filterFunction.params()[i]);
  18.                         Object param = scanner.nextLine();
  19.                         params.add(param);
  20.                     }
  21.                     Object result = method.invoke(newInstance, params.toArray());
  22.                     System.out.printf("%s: %s\n", filterFunction.returnType(), result);
  23.                 }
  24.             }
  25.         }
  #5 (permalink)  
Antiguo 18/11/2012, 08:41
 
Fecha de Ingreso: noviembre-2012
Ubicación: Madrid
Mensajes: 6
Antigüedad: 11 años, 5 meses
Puntos: 0
Respuesta: Evaluar si .java de un directorio forman parte d el proyecto y acceder a m

Cita:
Iniciado por LuisChavezB Ver Mensaje
Siempre debes de utilizar la ruta completa a la clase.

Un ejemplo:
Código Javascript:
Ver original
  1. Scanner scanner = new Scanner(System.in);
  2.         Class<?> clazz = Class.forName("mx.com.leviathan.data.filter.FilterExample");
  3.         if (clazz.isAnnotationPresent(Filter.class)) {
  4.             Object newInstance = clazz.newInstance();
  5.             Filter filter = clazz.getAnnotation(Filter.class);
  6.             System.out.printf("%s, %s %s\n", filter.author(), filter.name(), filter.version());
  7.             Method[] methods = clazz.getMethods();
  8.             for (Method method : methods) {
  9.                 if (method.isAnnotationPresent(FilterFunction.class)) {
  10.                     FilterFunction filterFunction = method.getAnnotation(FilterFunction.class);
  11.                     if (filterFunction.params().length != filterFunction.paramTypes().length) {
  12.                         System.err.println("El numero de argumentos es invalido!!");
  13.                         return;
  14.                     }
  15.                     ArrayList<Object> params = new ArrayList<>();
  16.                     for (int i = 0; i < filterFunction.params().length; i++) {
  17.                         System.out.printf("Ingresa el parametro: %s >> ", filterFunction.params()[i]);
  18.                         Object param = scanner.nextLine();
  19.                         params.add(param);
  20.                     }
  21.                     Object result = method.invoke(newInstance, params.toArray());
  22.                     System.out.printf("%s: %s\n", filterFunction.returnType(), result);
  23.                 }
  24.             }
  25.         }
Cual es la ruta de antes del package del proyecto, "com"?

Creo que lo he resuelto (de momento me funciona, no se si luego mientras desarrolle el codigo tendre algun problema).
Hay que cambiar el package por defecto en el que busca las clases el classloader:

http://www.javablogging.com/java-classloader-2-write-your-own-classloader/

Este seria el classloader que estoy utilizando:

Código:
package pruebas;

import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;

/**
 * Our custom implementation of the ClassLoader.
 * For any of classes from "javablogging" package
 * it will use its {@link CustomClassLoader#getClass()}
 * method to load it from the specific .class file. For any
 * other class it will use the super.loadClass() method
 * from ClassLoader, which will eventually pass the
 * request to the parent.
 *
 */
public class CustomClassLoader2 extends ClassLoader {

    /**
     * Parent ClassLoader passed to this constructor
     * will be used if this ClassLoader can not resolve a
     * particular class.
     *
     * @param parent Parent ClassLoader
     *              (may be from getClass().getClassLoader())
     */
    public CustomClassLoader2(ClassLoader parent) {
        super(parent);
    }
    
    
    /**
     * Loads a given class from .class file just like
     * the default ClassLoader. This method could be
     * changed to load the class over network from some
     * other server or from the database.
     *
     * @param name Full class name
     */
    private Class<?> getClass(String name)
        throws ClassNotFoundException {
        // We are getting a name that looks like
        // javablogging.package.ClassToLoad
        // and we have to convert it into the .class file name
        // like javablogging/package/ClassToLoad.class
        String file = name.replace('.', File.separatorChar)
            + ".class";
 //       System.out.println("NAME: "+file);
        byte[] b = null;
        try {
            // This loads the byte code data from the file
            b = loadClassData(file);
            // defineClass is inherited from the ClassLoader class
            // and converts the byte array into a Class
            Class<?> c = defineClass(name, b, 0, b.length);
            resolveClass(c);
            return c;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Every request for a class passes through this method.
     * If the requested class is in "javablogging" package,
     * it will load it using the
     * {@link CustomClassLoader#getClass()} method.
     * If not, it will use the super.loadClass() method
     * which in turn will pass the request to the parent.
     *
     * @param name
     *            Full class name
     */
    @Override
    public Class<?> loadClass(String name)
        throws ClassNotFoundException {
 //       System.out.println("loading class '" + name + "'");
        if (name.startsWith("inventarionb.")) {
            return getClass(name);
        }
        else if (name.startsWith("componentespkg")) {
            return getClass(name);
        }      
        return super.loadClass(name);
    }

    /**
     * Loads a given file (presumably .class) into a byte array.
     * The file should be accessible as a resource, for example
     * it could be located on the classpath.
     *
     * @param name File name to load
     * @return Byte array read from the file
     * @throws IOException Is thrown when there
     *               was some problem reading the file
     */
    private byte[] loadClassData(String name) throws IOException {
        // Opening the file
        InputStream stream = getClass().getClassLoader()
            .getResourceAsStream(name);
        int size = stream.available();
        byte buff[] = new byte[size];
        DataInputStream in = new DataInputStream(stream);
        // Reading the binary data
        in.readFully(buff);
        in.close();
        return buff;
    }
}
y este el main:
Código:
package inventarionb;

import pruebas.*;

public class IntegerPrinterTest {
    /**
     * This main method shows a use of our CustomClassLoader for
     * loading some class and running it. All the objects referenced
     * from the IntegerPrinter class will be loaded with
     * our CustomClassLoader.
     */
    public static void main(String[] args) throws Exception 
    {
        System.out.println(stringtoclassmethod("componentespkg.cat3.DiodoSchottky","toCB"));
        String[] a=(String[])stringtoclassmethod("componentespkg.cat3.DiodoSchottky","toCol");
        for(int i=0;i<a.length;i++)
        {
        System.out.print(a[i]+", ");
        }
        System.out.print("\n");
        System.out.println(stringtoclassmethod("componentespkg.cat2.Diodo","toCB"));
        a=(String[])stringtoclassmethod("componentespkg.cat2.Diodo","toCol");
        for(int i=0;i<a.length;i++)
        {
        System.out.print(a[i]+", ");
        }
    }
    public static Object stringtoclassmethod (String dir, String method) throws Exception
    {
       // dir="componentespkg.cat3.DiodoSchottky";
       // method="toCB";
       
        CustomClassLoader2 loader = new CustomClassLoader2(IntegerPrinterTest.class.getClassLoader()); //(StaticAccessorTest.class.getClassLoader());
        Class<?> clazz =
        loader.loadClass(dir); //inventarionb.IntegerPrinter //componentespkg.cat2.Diodo 
        Object instance = clazz.newInstance();
        Object aas=clazz.getMethod(method).invoke(instance);//runMe // toCB2CB
        //System.out.println(aas);
        return aas;
    }
}
Esta un poco desordenado, hay anotaciones por el codigo y codigo omitido... pero como referencia sirve. Ire adaptandolo a mi otro programa.

Etiquetas: clase, directorio, evaluar, parte, programa, proyecto, string, aplicaciones
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 02:04.