JNDI DummyContext

Posted by admin on June 14, 2012

Como parte de un proyecto que estoy desarrollando con java, he decidido utilizar JNDI en un módulo como una interfaz estándar para obtener "repositorios" de objetos en tiempo de ejecución. Muchos servidores de aplicaciones (Glassfish, Tomcat, Jetty, entre otros) proveen una implementación disponible para las aplicaciones que se ejecuten en éste, sin embargo para hacer pruebas resulta conveniente contar con un SPI de JNDI independiente y sencillo.

La implementación puede ser extremadamente sencilla, tomando en cuenta sólo la funcionalidad que se necesita para cada aplicación:

TestDummyContext.java

  1. package org.devpower.test.jndi;
  2.  
  3. public class TestDummyContext {
  4.  
  5. public static void main(String[] args) {
  6. System.setProperty(Context.INITIAL_CONTEXT_FACTORY,
  7. "org.devpower.test.jndi.DummyContextFactory");
  8.  
  9. Context context = new InitialContext();
  10. System.out.println(context.lookup("test"));
  11. }
  12. }

DummyContextFactory.java

  1. package org.devpower.test.jndi;
  2.  
  3. import java.util.Map;
  4. import java.util.HashMap;
  5. import java.util.Hashtable;
  6. import javax.naming.NamingException;
  7. import javax.naming.Context;
  8.  
  9. /**
  10.  * Esta factory es la encargada de proveer la implementación
  11.  * del contexto que se inicializará al crear un nuevo InitialContext
  12.  */
  13. public class DummyContextFactory implements InitialContextFactory {
  14.  
  15. /**
  16.   * Este objeto sólo guarda referencias a objetos en un
  17.   * HashMap<String, Object>, todos los métodos lanzan
  18.   * una excepción de tipo UnsupportedOperationException
  19.   * excepto bind(String name, Object object) y lookup(String name)
  20.   * que son utilizados en el ejemplo.
  21.   */
  22. private static class DummyContext implements Context {
  23.  
  24. private Map<String, Object> bindings;
  25.  
  26. public DummyContext() {
  27. this.bindings = new HashMap<String, Object>();
  28. }
  29.  
  30. @Override
  31. public void bind(String name, Object obj) throws NamingException {
  32. bindings.put(name, obj);
  33. }
  34.  
  35. @Override
  36. public Object lookup(String name) throws NamingException {
  37. return bindings.get(name);
  38. }
  39.  
  40. /**
  41.   * LOS DEMÁS MÉTODOS QUE SÓLO LANZAN UnsupportedOperationException
  42.   * se excluyen...
  43.   *
  44.   */
  45. }
  46.  
  47. private static final DummyContext context;
  48.  
  49. static {
  50. context = new DummyContext();
  51.  
  52. context.bind("test", new Object());
  53. }
  54.  
  55. public Context getInitialContext(Hashtable<?, ?> env)
  56. throws NamingException {
  57.  
  58. return context;
  59. }
  60. }
0 Comments Read full post »

Firefox JSM: DevPower.Http.ResponseInterceptor

Posted by admin on June 14, 2012

Desde hace algunos días he estado programando una extensión de firefox, la cual debe interceptar las respuestas http basándose en las urls. Una vez interceptada la respuesta, el contenido de la misma debe almacenarse localmente.

Debido a que las extensiones de firefox utilizan javascript como lenguaje de programación, me dispuse a crear una "clase" reutilizable que se encargue de realizar dicha tarea. Esta clase es DevPower.Http.ResponseInterceptor, la cual se ha programado como un módulo JSM y su uso es muy sencillo:

  1. /** ..... importa el módulo y realiza inicializaciones
  2. ...
  3. */
  4.  
  5. /**
  6.  * Cada ResponseInterceptor debe implementar el método
  7.  * ResponseInterceptor#createChannelListener(matcher),
  8.  * el cual debe devolver un nsITraceableListener, que es el que se
  9.  * encargará de realizar las acciones necesarias sobre la respuesta recibida.
  10.  * En el script se incluye una implementación de esta interfaz que se
  11.  * encarga de descargar a una carpeta seleccionada el contenido de la
  12.  * respuesta, dicha implementación es
  13.  * DevPower.Http.ResponseInterceptor.Downloader.
  14.  */
  15. var MyInterceptor = new DevPower.Http.ResponseInterceptor();
  16. MyInterceptor.createChannelListener = function(matcher) {
  17. return new DevPower.Http.ResponseInterceptor.Downloader("/home/emerino/downloads", "mp3");
  18. };
  19.  
  20. /**
  21.  * Un interceptor necesita "matchers" para saber qué respuestas interceptar.
  22.  * En el script se incluye una implementación básica de uno llamada UrlMatcher,
  23.  * el cual verifica si la url de la respuesta actual coincide con alguna de las que
  24.  * se tienen registradas en el matcher. Dichas urls deben ser expresiones
  25.  * regulares.
  26.  *
  27.  * Independientemente de la implementación utilizada de los
  28.  * nsITraceableListeners, cada uno de estos que se creen almacenarán el listener
  29.  * original en la propiedad nsITraceableListenerImplementation.originalListener.
  30.  */
  31. var matcher = new DevPower.Http.ResponseInterceptor.UrlMatcher();
  32. matcher.addUrl("^http://www.example.com$");
  33. matcher.addUrl("^http://devio.us/.*");
  34.  
  35. MyInterceptor.addMatcher("mymatcher", matcher);
  36. MyInterceptor.start();

Con el código anterior, al llamar al método DevPower.Http.ResponseInterceptor#start(), se registra un observer para la notificación "http-on-examine-response", el cual verifica si algún DevPower.Http.Matcher causa un "match" sobre las urls dadas, de ser así se registra un nsITraceableListener con el nsIHttpChannel de la respuesta, el cual se encarga de descargar el contenido de la misma al disco duro.

El código fuente del módulo se encuentra disponible para su descarga aquí.

0 Comments Read full post »

Hace algunos días tuve que registrar algunos datos que se encontraban en un archivo de texto en una hoja de excel. Para agilizar el proceso y hacerlo automático, utilicé el lenguaje de programación python y las librerías xlwt, xlrd y xlutils.

A pesar de que cumplen con su función (xlwt: escritura, xlrd: lectura), crear un script para modificar un archivo existente con base en ciertos parámetros resulta un poco desorganizado. Es por eso que he creado la clase XLSWriter, la cual permite la modificación o creación de archivos XLS de manera sencilla:

  1. from devpower.xls import XLSWriter
  2.  
  3. # crea un archivo XLS
  4. writer = XLSWriter()
  5. writer.append(["Col1", "Col2", "Col3"])
  6. writer.save("test.xls")
  7.  
  8. #modifica un archivo XLS existente
  9. writer = XLSWriter("archivo.xls")
  10.  
  11. # añade una fila al final del documento
  12. writer.append(["Col1", "Col2", "Col3"])
  13.  
  14. # busca la cadena "VALOR" en la primera columna y reemplaza el renglón
  15. # con los datos proporcionados en la lista ["Col1", "Col2", "Col3"]
  16. writer.replace(0, "VALOR", ["Col1", "Col2", "Col3"])
  17.  
  18. # escribe los datos en el renglón 5 (índice 4)
  19. writer.write(4, ["Col1", "Col2", "Col3"])
  20.  
  21. # guarda los cambios en el archivo
  22. writer.save()
  23.  
  24. # escribe los datos a un nuevo archivo
  25. writer.save("otro.xls")

Descarga el módulo.

0 Comments Read full post »