14/01/2012
Se añade a la interfaz JDirMonitor métodos que permiten consultar y obtener, a través del path absoluto, archivos que se encuentren dentro del directorio que se está analizando.
26/05/2012

Se añade en clase "cl.getsoftware.jdirmonitor.task.RecursiveTaskMonitor" capacidad de informar estado tanto de los archivos como de los directorios.

-----------------------------------------------------------------------------------------------------------------------


Hace unos días atrás se presentó un problema en un sistema y parte de la solución que se propuso involucraba leer información escrita en tiempo real desde múltiples archivos de bytes con objetos serializados, procesarlos y delegarlos a un sistema anexo, todo esto en Java.
Lo primero que se me ocurrió fue 'googlear' para encontrar una API que hiciera el trabajo de monitorear cambios en los archivos de un directorio y por alguna oscura razón no encontré nada...

Una vez solucionado el asunto me interesó la idea de crear una API lo suficientemente genérica, configurable y fácil de usar que solucionase dicho 'problema'.Y así nació JDirMonitor!

Entonces JDirMonitor es una API, bajo licencia LGPL que permite monitoriar y 'escuchar' los cambios que presentan todos los archivos que estén dentro de un directorio definido, avisando en su defecto cuáles han sido creados, modificados y eliminados.

Además de esto JDirMonitor posee las siguientes características:
-Definición de múltiples listeners para capturar eventos que suceden sobre los archivos.
-Definición de Filtros a aplicar sobre los archivos para, por ejemplo, discriminar cuáles deben procesarse.
-Definición de Comparators de objetos File para, por ejemplo, definir el orden en el que se deben procesar los distintos archivos.

JDirMonitor ofrece 2 tipos de monitoreos:
1) NormalTaskMonitor: analiza solamente los archivos que se encuentran en el primer nivel del directorio especificado.
2) RecursiveTaskMonitor: analiza todos los archivos que se encuentren dentro del directorio a analizar, es recursivo IN ORDEN, ya que accede a los archivos de todos los subdirectorios (en cualquier nivel de profundidad).

El siguiente código de ejemplo permite monitorear un directorio X con NormalTaskMonitor, un listener y un filtro de archivo:

import java.io.File;
import java.util.concurrent.TimeUnit;

import cl.getsoftware.jdirmonitor.DirectoryMonitor;
import cl.getsoftware.jdirmonitor.MonitorBuilder;
import cl.getsoftware.jdirmonitor.exception.DirectoryMonitorException;
import cl.getsoftware.jdirmonitor.filter.RegexNameFileFilter;
import cl.getsoftware.jdirmonitor.listener.FileListener;
import cl.getsoftware.jdirmonitor.task.NormalTaskMonitor;


public class Test {
    
    public static void main(String[] args) throws DirectoryMonitorException {
        String pathDirectory = "ruta/del/directorio/a/monitorear";
        long timeTaskExecute = 2;
        
        //Clase que permite añadir filtros a archivos y directorios
        //mediante expresiones regulares
        RegexNameFileFilter regexName = 
            new RegexNameFileFilter();
        regexName.addFileNameRegex("[a-zA-Z].*?\\.txt$");
        
        MonitorBuilder builder = new MonitorBuilder(pathDirectory,
             timeTaskExecute, new NormalTaskMonitor(),
             TimeUnit.SECONDS);
        builder.addListener(fileListener);
        builder.setFileFilter( regexName );
        DirectoryMonitor monitor = builder.build();
        monitor.start();
        
        //se deja el hilo main vivo en un ciclo infinito
        //para ver lo que imprimen los listeners en consola
        while( true ){
            try {
                Thread.sleep(10000);
            }
            catch (InterruptedException e) {}
        }
    }
    
    
    public static FileListener fileListener = new FileListener() {
        @Override
        public void fileDeleted(File file) {
            System.out.println("Archivo " + file.getAbsolutePath() + " ha sido BORRADO");
        }
        
        @Override
        public void fileCreated(File file) {
            System.out.println("Archivo " + file.getAbsolutePath() + " ha sido CREADO");
        }
        
        @Override
        public void fileChanged(File file) {
            System.out.println("Archivo " + file.getAbsolutePath() + " ha sido MODIFICADO");
        }
    };
}
Así de simple, en 4 líneas tenemos corriendo un DirectoryMonitor que revisará el directorio periódicamente cada N segundos, nos informará a través del listener los cambios que ocurren en los archivos y con la clase cl.getsoftware.jdirmonitor.filter.RegexNameFileFilter se logra filtrar solo los archivos que posean un nombre que cumpla con la expresión regular definida.

Otra ventaja es que la API te permite codificar tus propias clases de monitoreo, las cuales deben heredar de la clase cl.getsoftware.jdirmonitor.AbstractTaskMonitor.

Por ejemplo, este es el código fuente de la clase cl.getsoftware.jdirmonitor.task.NormalTaskMonitor:

/*
 * JDirMonitor a listener of files
 * Copyright (C) 2010  GetSoftware Group
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * 
 * This library was written by Eugenio Contreras for GetSoftware Group
 * Contact email: contacto@getsoftare.cl
 */

package cl.getsoftware.jdirmonitor.task;

import java.io.File;

import cl.getsoftware.jdirmonitor.AbstractTaskMonitor;

/**
 * <p>Tarea de monitoreo de directorio que analiza solamente los archivos que se 
 * encuentran en el primer nivel del directorio especificado.</p>
 * 
 * @author egacl
 *
 */
public class NormalTaskMonitor extends AbstractTaskMonitor {
    
    /** (non-Javadoc)
     * @see cl.getsoftware.jdirmonitor.AbstractTaskMonitor#monitorRutine(java.io.File)
     */
    @Override
    public void monitorRutine(File directory) {
        this.normalRutine( this.getFilesOfDirectory(directory) );
    }
    
    public void normalRutine( File []files ){
        for( File file : files ){
            if( file.exists() ){
                if( file.isFile() ){
                    this.fileMonitor( file );
                }
            }
        }
    }
    
}
El método monitorRutine se ejecuta cada vez que el DirectoryMonitor inicia la rutina de monitoreo y le envía como parámetro el objeto java.io.File del directorio a analizar. Por lo tanto allí puedes escribir la manera en que deseas realizar el monitoreo.

Puedes descargar el archivo JDirMonitor.rar (proyecto Eclipse con javadoc incluida).
Api JAR JDirMonitor.jar

EJEMPLO DE COMO UTILIZAR LA API AQUI
 

ver post completo...


Hace unos años atrás, mientras estaba estudiando, el cuarto semestre de Ingeniería... creo, me dieron una tarea que consistía en hacer un Planarity.
El resultado fue el juego JPlanarity (la J es porque está desarrollado en lenguaje Java).

Posee un buen renderizado, selección múltiple (en beta) y permite guardar partidas, ya que no es muy entretenido avanzar a altos niveles y luego empezar todo de nuevo. A todo esto ... yo llegué al nivel 15, un profesor al 18
con la esperanza de que fallara pero no fue así xD jejeje.

Puedes descargar el juego presionando AQUI.




El juego consiste en desenredar la red formada por las distintas aristas y vértices, como se puede ver en la imagen.




Cualquier sugerencia, bugs o nueva idea se acepta y comentala aquí.

Saludos.-

ver post completo...

IDEs para programar en Groovy

En el post anterior de Groovy se mostró una pequeña introducción sobre este moderno y poderoso lenguaje de programación. Pero ¿Qué se necesita para poder desarrollar aplicaciones en Groovy?


*Requisito obligatorio es tener instalada la JVM.

Lo primero que se debe hacer es descargar el Groovy Develpment Kit (GDK). Luego la instalación consiste simplemente en descomprimir el GDK en la ruta que desees y crear una variable de entorno GROOVY_HOME en linux o agregar la ruta al directorio /bin de groovy en la variable de entorno PATH en windows.
Para información más detallada visita el tutorial de groovy en su sitio oficial.

Una vez realizado lo anterior, está todo listo para empezar a programar en Groovy, ya que este proporciona un interprete IDE llamado GroovyConsole, en donde podrás codificar y ejecutar en un instante (para ejecutar la consola de Groovy, basta con ejecutar el comando groovyConsole o groovyConsole.bat).


(groovyConsole en acción)

La comunidad de Groovy ha desarrollado también un plugin para eclipse llamado Groovy-Eclipse, el cual permite fácilmente desarrollar y compilar proyectos en Groovy (en el link encontrarán una sección 'How to Install' con los pasos a seguir para la instalación).

Y como si fuera poco, la comunidad Groovy en conjunto con Spring Source han desarrollado una completa plataforma sobre Eclipse, que permite crear fácilmente proyectos en Groovy, Grails, AspectJ, etc. El proyecto se llama 'Grails - STS Integration' y lo puedes descargar desde AQUI.

En las siguientes entradas se verán códigos de ejemplo con Groovy (desde los más simple a lo complejo) hasta llegar al nivel necesario para desarrollar utilizando Grails.

ver post completo...

Colecciones en Python


Anteriormente habíamos visto algunos tipos básicos de datos como los booleanos, enteros y cadenas de texto.

A continuación veremos como utilizar algunos tipos de colecciones que nos ofrece Python.

Listas


Las listas son colecciones de datos ordenadas y son el equivalente a los ArrayList o vectores de Java o C#.
En Python las listas y las colecciones en general pueden almacenar cualquier tipo de dato, como objetos, números, colecciones, etc.

Este es un ejemplo donde podremos ver cómo utilizar las listas:

if __name__ == '__main__':      #equivale a public static void main de Java
    listado = [] #inicializamos una lista
    print("Todo lo que escribas sera guardado en una lista")
    while True:
        dato = raw_input("> ");
        if( dato=="fin" ): 
            break
        #se agrega al final de la lista un nuevo elemento
        listado.append(dato)
    
    if listado.__len__()>0:
        print("Estos son los datos ingresados")
        for i in listado:
            #la coma permite imprimir el contenido en 
            # una sola fila como un System.out.print de Java
            print i , 
        
    else:
        print("No se ingreso nada en la lista")

Python posee una característica denominada slicing y que permite seleccionar u obtener una partición de la lista, por ejemplo:
lista = ["h","o","l","a"," ","m","u","n","d","o"]
print( lista[2:5] ) #1) imprime ['l', 'a', ' ']
print( lista[:4] ) #2) imprime ['h', 'o', 'l', 'a']
print( lista[5:] ) #3) imprime ['m', 'u', 'n', 'd', 'o']
print( lista[:] ) #4) imprime ['h', 'o', 'l', 'a', ' ', 'm', 'u', 'n', 'd', 'o']
print( lista[0:4:2] ) #5) imprime ['h', 'l']
print( lista[::2] ) #6) imprime ['h', 'l', ' ', 'u', 'd']
print( lista[::3] ) #7) imprime ['h', 'a', 'u', 'o']

En el caso '1' se obtiene un fragmento del arreglo desde la posición 2 hasta la 4.
En el caso '2' se imprime el arreglo desde la posición 0 hasta la 3.
En el caso '3' se imprime el arreglo desde la posición 5 hasta la última (9).
En el caso '4' se imprime todo el arreglo.
*cuando no se especifica un número a la izquierda del slicing (:) se toma por defecto la primera posición del arreglo y a la derecha se toma la última posición.
En el caso '5' imprime desde la posición 0 hasta la 3 cada 2 caracteres.
En el caso '6' imprime desde la posición 0 hasta la 9 cada 2 caracteres.
En el caso '7' imprime desde la posición 0 hasta la 9 cada 3 caracteres.


Tuplas


Las tuplas se manejan exactamente igual a las listas, y las características más relevantes que poseen son:
-A diferencia de las listas ([]), las tuplas se inicializan con ().
-Son inmutables, es decir, su contenido no puede ser modificado.
-Tienen tamaño fijo.
-Utilizan menos memoria que las listas.

lista = ["h","o","l","a"," ","m","u","n","d","o"]
unaTupla = tuple( lista )
print( unaTupla[2:5] ) #1) imprime ['l', 'a', ' ']


Diccionarios


Los diccionarios son colecciones que permiten relacionar una clave con un valor y son el equivalente a los HashMap de Java.
La principal diferencia entre los diccionarios con las tuplas y listas, es que sus valores no son accedidos a través de un índice, porque no poseen orden (ya que los diccionarios se implementan como tablas hash), sino que mediante su clave utilizando el operador [clave]. Por esta misma razón es que tampoco puede aplicarse slicing sobre estas.

Este es un ejemplo de diccionario:
numeros = {"uno":1, "dos":2, "tres":3, 4:"cuatro", 5:"cinco", 6:"seis"}
print( numeros["uno"] )   #1) imprime 1
print( numeros[5] )       #2) imprime cinco
print( numeros.keys() )   #3) imprime [4, 5, 6, 'dos', 'tres', 'uno']
print( numeros.values() ) #4) imprime ['cuatro', 'cinco', 'seis', 2, 3, 1]

-En el caso 1 se imprime el valor obtenido de la llave 'uno'.
-En el caso 2 se imprime el valor de la llave '5'.
-En el caso 3 se imprimen todas las llaves del diccionario.
-En el caso 4 se imprimen todos los valores del diccionario.

ver post completo...

Un primer vistazo a Groovy

Actualmente en todo el mundo los lenguajes dinámicos o ágiles han logrado alcanzar mucha popularidad tanto en las empresas como para los desarrolladores (aunque en Chile y en general en Latino América, a nivel empresarial aún no son muy valorados).


Groovy me ha llamado poderosamente la atención ya que es un lenguaje nacido con la misión de llevarse bien con Java, vivir en la máquina virtual y soportar los tipos de datos estándar pero añadiendo características dinámicas y sintácticas presentes en lenguajes como Python, Smalltalk o Ruby.

El código fuente de Groovy compila a bytecodes igual que Java (generando archivos .class que podemos ejecutar directamente desde la máquina virtual), lo que permite instanciar objetos Java desde Groovy y viceversa.

La sintaxis de Groovy es bastante similar a la de Java, por lo que la curva de aprendizaje es muy alta para los desarrolladores que se familiarizan con él.

La mayoría de las cosas que hacemos con Java puede hacerse en Groovy, por ejemplo:
  • Definición de packages
  • Definición de clases (pero no internas) y métodos
  • Estructuras de control, excepto el bucle for( ; ; )
  • Control de excepciones
  • Operadores, expresiones y asignaciones
  • Literales con algunas variaciones
  • Instanciación, referencia y de-referencia de objetos, llamadas a métodos
Y algunas mejoras sintácticas que incluye Groovy:
  • En Groovy todo es un objeto
  • Facilidad en el manejo de objetos, a través de nuevas expresiones y sintaxis
  • Diversas formas para declarar literales
  • Control de flujo avanzado mediante nuevas estructuras
  • Nuevos tipos de datos con operaciones y expresiones específicas
  • Brevedad, el código Groovy es mucho más breve que el de Java

Y como es habitual y para finalizar esta entrada, veamos como sería el código del típico "Hola Mundo" en Groovy:

//Hola Mundo en Groovy
def mundo = "Mundo"
println "Hola $mundo!"
//Fin

A primera vista vemos que:
  • Se pueden escribir script en los que no hay clases (en realidad la hay pero no necesitamos declararla)
  • No hay ';' al final de cada línea. En Groovy es opcional
  • La palabra reservada def permite declarar variables de tipo dinámico. También se pueden crear variables de tipo estático (ejemplo: Integer)
  • Los comentarios son igual que en Java (// o /**/)
  • print y println son equivalentes a System.out.print y System.out.println
  • El parámetro de la función println no va entre paréntesis, es opcional

ver post completo...

Hola a todos, a muchos desarrolladores se nos hace indispensable poder implementar un módulo de envío de mail en los sistemas que desarrollamos. Dependiendo del lenguaje está la complejidad o simplicidad de la codificación de éste y como muchos sabemos, Java no siempre es un precursor de lo simple.

Es por esto que quiero publicar y facilitarles a todos una clase Mail.java que permite realizar envío de correos a través de Google Apps y mediante un servidor de correos común y corriente.

El código funciona implementando la API de SUN JavaMail (así que descarguen el JAR con la API sino nunca podrán enviar correos) y proporciona 2 métodos. Uno llamado 'enviaGoogleApp' que permite enviar el correo a través de una cuenta de Google Apps y otro llamado 'envia' que envía correos a través de un servidor de correo definido.

El código de ambos métodos es idéntico, sólo cambia la forma de autenticarse en el servidor.

Los métodos de la clase Mail sólo requieren los siguientes datos:
1) Emisor del mensaje.
2) Asunto del correo.
3) Receptor(es) del correo.
4) mensaje del correo (en formato HTML o ASCII)
5) Archivos adjuntos.

Con una leve modificación y añadiendo 2 parámetros más se pueden añadir:
1) Receptores a quienes se copia el correo.
2) Receptores a quienes se les envía copia oculta.

El código es el siguiente:


package util.mail;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

public class Mail {
 
 private class SMTPAuthenticator extends Authenticator {
  private String dEmail;
  private String dPassword;
  
  public SMTPAuthenticator(String email, String password){
   dEmail = email;
   dPassword = password;
  }
  
  public PasswordAuthentication getPasswordAuthentication(){
   return new PasswordAuthentication(dEmail, dPassword);
  }
 }
 
 /**
  * Funci&oacute;n que permite enviar un correo electr&oacute;nico con archivos adjunto.
  * &lt;br&gt;El contenido del correo puede estar en formato HTML.
  * @param emisor Correo de qui&eacute;n emite el correo
  * @param asunto Asunto del e-mail
  * @param receptores Correos de los receptores del e-mail
  * @param mensaje Mensaje del e-mail
  * @param adjuntos Ruta de archivos adjuntos en el e-mail
  * @return TRUE si el mail fue enviado con &eacute;xito, FALSE en caso contrario
  */
 public boolean enviaGoogleApp(String emisor, String asunto, List&lt;String&gt; receptores, String mensaje, List&lt;String&gt; adjuntos){
  boolean envioExitoso = true;
  String emailGetCursos = "cuenta.googleapps@algo.cl";
  String password = "password.de.cuenta.googleapps";
  Properties props = new Properties();
  props.put("mail.smtp.user", emisor);
  props.put("mail.smtp.host", "smtp.gmail.com");
  props.put("mail.smtp.port", "465");
  props.put("mail.smtp.starttls.enable", "true");
  props.put("mail.smtp.auth", "true");
  props.put("mail.smtp.socketFactory.port", "465");
  props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
  props.put("mail.smtp.socketFactory.fallback", "false");
  
  try{
   
   Authenticator auth = new SMTPAuthenticator(emailGetCursos, password);
   Session session = Session.getInstance(props, auth);

   MimeMessage message = new MimeMessage(session);
   InternetAddress[] dest = new InternetAddress[receptores.size()];
   for (int i=0;i&lt;dest.length;i++){
    dest[i] = new InternetAddress( receptores.get(i) );
   }
   
   //Se define qui&eacute;n es el emisor del e-mail
      message.setFrom(new InternetAddress(emisor));
      InternetAddress[] replyTo = new InternetAddress[1];
      replyTo[0] = new InternetAddress( emisor );
      message.setReplyTo( replyTo );
   //Se definen el o los destinatarios
   message.addRecipients(Message.RecipientType.TO, dest);
   //message.addRecipients(Message.RecipientType.CC, dest);
   //message.addRecipients(Message.RecipientType.BCC, dest);

      
   //Se defina el asunto del e-mail
      message.setSubject(asunto);
 
      //Se seteo el mensaje del e-mail
      MimeBodyPart messageBodyPart = new MimeBodyPart();
      messageBodyPart.setContent(message,"text/html");
            
      Multipart multipart = new MimeMultipart();
      multipart.addBodyPart(messageBodyPart);
            
      //Se adjuntan los archivos al correo
      if( adjuntos!=null && adjuntos.size()>0 ){
         for( String rutaAdjunto : adjuntos ){
             messageBodyPart = new MimeBodyPart();
             File f = new File(rutaAdjunto);
             if( f.exists() ){
                DataSource source = new FileDataSource( rutaAdjunto );
                messageBodyPart.setDataHandler( new DataHandler(source) );
                messageBodyPart.setFileName( f.getName() );
                multipart.addBodyPart(messageBodyPart);
             }
         }
      }
      
      //Se junta el mensaje y los archivos adjuntos
      message.setContent(multipart);
      
      //Se env&iacute;a el e-mail
      Transport.send( message );
  }
  catch (Exception e) {
   envioExitoso = false;
  }
  finally{
   //Se eliminan del servidor los archivos adjuntos
   if( adjuntos!=null && adjuntos.size()&gt;0 ){
    for( String rutaAdjunto : adjuntos ){
     try{
      File arch = new File(rutaAdjunto);
         arch.delete();
     }
     catch (Exception e) {}
    }
   }
  }
  return envioExitoso;
 }
 
 /**
  * Funci&oacute;n que permite enviar un correo electr&oacute;nico con archivos adjunto.
  * &lt;br&gt;El contenido del correo puede estar en formato HTML.
  * @param emisor Correo de qui&eacute;n emite el correo
  * @param asunto Asunto del e-mail
  * @param receptores Correos de los receptores del e-mail
  * @param mensaje Mensaje del e-mail
  * @param adjuntos Ruta de archivos adjuntos en el e-mail
  * @return TRUE si el mail fue enviado con &eacute;xito, FALSE en caso contrario
  */
 public boolean envia(String emisor, String asunto, List&lt;String&gt; receptores, String mensaje, List&lt;String&gt; adjuntos){
  boolean envioExitoso = true;
  try{
      Properties props = System.getProperties();
 
      //Se define el servidor de correos
      props.put("mail.smtp.host", "ip.servidor.de.correos");
   props.put("mail.smtp.port", "puerto.servidor.de.correo (por defecto 25)");
 
      //Se obtiene sesi&oacute;n desde el servidor de correos
      Session session = Session.getInstance(props, null);
   session.setDebug(true);
   
      MimeMessage message = new MimeMessage(session);
   InternetAddress[] dest = new InternetAddress[receptores.size()];
   for (int i=0;i&lt;dest.length;i++){
    dest[i] = new InternetAddress( receptores.get(i) );
   }
   
   //Se define qui&eacute;n es el emisor del e-mail
      message.setFrom(new InternetAddress(emisor));
      InternetAddress[] replyTo = new InternetAddress[1];
      replyTo[0] = new InternetAddress( emisor );
      message.setReplyTo( replyTo );
   //Se definen el o los destinatarios
   message.addRecipients(Message.RecipientType.TO, dest);
   //message.addRecipients(Message.RecipientType.CC, dest);
   //message.addRecipients(Message.RecipientType.BCC, dest);
      
   //Se defina el asunto del e-mail
      message.setSubject(asunto);
 
      //Se seteo el mensaje del e-mail
      MimeBodyPart messageBodyPart = new MimeBodyPart();
      messageBodyPart.setContent(message,"text/html");
            
      Multipart multipart = new MimeMultipart();
      multipart.addBodyPart(messageBodyPart);
            
      //Se adjuntan los archivos al correo
      if( adjuntos!=null && adjuntos.size()>0 ){
         for( String rutaAdjunto : adjuntos ){
             messageBodyPart = new MimeBodyPart();
             File f = new File(rutaAdjunto);
             if( f.exists() ){
                DataSource source = new FileDataSource( rutaAdjunto );
                messageBodyPart.setDataHandler( new DataHandler(source) );
                messageBodyPart.setFileName( f.getName() );
                multipart.addBodyPart(messageBodyPart);
             }
         }
      }
      
      //Se junta el mensaje y los archivos adjuntos
      message.setContent(multipart);
      
      //Se env&iacute;a el e-mail
      Transport.send( message );
  }
  catch (Exception e) {
   envioExitoso = false;
  }
  finally{
   //Se eliminan del servidor los archivos adjuntos
   if( adjuntos!=null && adjuntos.size()&gt;0 ){
    for( String rutaAdjunto : adjuntos ){
     try{
      File arch = new File(rutaAdjunto);
         arch.delete();
     }
     catch (Exception e) {}
    }
   }
  }
  return envioExitoso;
 }
 
 public static void main(String[] args) {
  List&lt;String&gt; receptores = new ArrayList&lt;String&gt;();
  receptores.add("mail.de.alguien@gmail.com");
  String emisor = "test@test.cl";
  String asunto = "Correo de prueba";
  String mensaje = "Este es un correo de &lt;font color='red'&gt;&lt;b&gt;PRUEBA&lt;/b&gt;&lt;/font&gt;";
  List&lt;String&gt; archivos = new ArrayList&lt;String&gt;();
  Mail m = new Mail();
  //m.envia(emisor, asunto, receptor, mensaje, null);
  m.enviaGoogleApp( emisor, asunto, receptores, mensaje, archivos);
 }
 
}

ver post completo...

Métodos Javascript que te pueden ser útiles

Hola a todos, Ufff hace mucho que no publico una entrada contundente. La verdad he estado demasiado ocupado realizando mi tesis de la cual les hablaré en un tiempo más... cuando la termine.

Este post algo tiene que ver con mi tesis y son algunos de los métodos javascript que he tenido que construir para facilitar la obtención de datos y validaciones (a pesar de que ya existen frameworks como JQuery que ya lo hacen, siempre es mejor saber como se hacen las cosas antes que la total abstracción).



El siguiente método obtiene todos los elementos HTML de un tipo específico y cuyo ID cumpla con patrón recibido como parámetro.

function getElementsLikeID( tagName, likeID ){
var elementsLike = [];
var elementos = document.getElementsByTagName( tagName );
if( elementos!=null ){
var j=0;
for( i=0 ; i<elementos.length ; i++ ){
if( elementos[i].id!=null && elementos[i].id.indexOf(likeID)>-1 ){
elementsLike[j++] = elementos[i];
}
}
}
return elementsLike;
}


Si ejecutas getElementsLikeID('INPUT','porcentajes_'); devolverá un arreglo con todos los elementos HTML input cuyo ID contenga la palabra 'porcentajes_'.


Utilizando el método "getElementsLikeID" se pueden hacer una infinidad de funciones, por ejemplo una que permita cambiar la clase de diversos elementos de la página.

function cambiaClassPorTag( tagName, likeID, nombreClase ){
var elementos = getElementsLikeID( tagName, likeID );
if( elementos!=null ){
for( i=0 ; i<elementos.length ; i++ ){
elementos[i].className = nombreClase;
}
}


Por ultimo les dejo unos métodos que sirven para marcar varios checkbox que posean un nombre en común y otro para marcar todos los checkbox que estén dentro de una columna de una tabla (al hacer click en la columna se marcan todos los checkbox).

1) Marcar o descmarcar todos los checkbox con nombre en común.

function checkBoxLikeNameMarcar( name ){
checkBoxLikeName( name, true );
}

function checkBoxLikeNameDesmarcar( name, marcar ){
checkBoxLikeName( name, false );
}

function checkBoxLikeName( name, marcar ){
var checkBoxes = document.getElementsByTagName('INPUT');
for ( i=0 ; i<checkBoxes.length ; i++){
if(checkBoxes.type='CHECKBOX' && checkBoxes[i].name.indexOf(name)>-1){
if( marcar && !checkBox[i].checked )
checkBoxes[i].click();
else if ( !marcar && checkBoxes[i].checked )
checkBoxes[i].click();
}
}
}


2)Marcar todos los checkbox de una columna de una tabla.
*El parámetro "aLink" es un link que va en un o al principio de la columna.

function checkColumna( aLink ){
var tdPresionado = aLink .parentNode;
var trTabla = td.parentNode;
var pos = 0;
for( var i=0 ; i<trTabla.cells.length ; i++ )
if( tr.cells[i]==tdPresionado )
pos = i+1;
for( var i=2 ; i<trTabla.parentNode.rows.length ; i++ ){
trTabla.parentNode.rows[i].cells[pos].getElementsByTagName('INPUT')[0].click();
}


Bueno eso es todo por ahora, espero les sirva ;)
Saludos

PD: Feliz navidad y año nuevo ultra atrasado xD.

ver post completo...

top