»
S
I
D
E
B
A
R
«
Creando un componente basado en Software Libre – II Parte
Diciembre 20th, 2009 by John Carlos Arrieta Arrieta


Simbiotica


Creative Commons License



www.simbiotica.com.co


Contáctenos…

Esta sitio y todo su contenido  está protegida por
licencia de Creative Commons

Creando un componente basado en Software Libre – I Parte

Saludos para todos.

En esta segunda parte les mostrare como hacer un administrador  de tareas, con algunas de las funciones básicas de que posee el aplicativo original de MS Windows, listar procesos, matar procesos y ordenar procesos.

Para realizarlo vamos a utilizar el proyecto que he creado en la primera parte de este articulo, adema de algunas utilidades del sistema operativo MS-DOS, también utilizaremos la capacidad que tiene Java para inter actual con procesos secundarios y externos a la JVM, por ultimo utilizaremos y un componente de SL (Software Libre) muy interesante que nos permite enriquecer nuestras aplicaciones de escritorio con algunos controles de GUI, entre lo que se encuentran algunas extensiones mejoradas de los componentes GUI, las cuales se encuentran dentro del paquete javax.swing incluido en el JDK desde la versión 1.2.

Manos a la obra.

1.       Iniciar NetBeans

2.       Abrir un proyecto existente

image002

3.       Seleccionar nuestro proyecto anterior

image0032

4.       Pulsar el botón abrir

Vemos como NetBeans carga todos los recursos   del proyecto

image0053

Otra que en el panel de proyectos se encuentra un árbol con ítems, cada ítem tiene a su vez más ítems anidados, notar también que el primer ítem es el nombre del proyecto, a este ítem se le conoce como ítem Raíz, se caracteriza por tener una tasita de café, ver que dentro del ítem raíz se encuentran dos ítem  importantes, el primero se llama paquete de fuentes, y es donde se encuentran los archivos de código fuente de nuestro proyecto, normalmente organizados dentro de paquetes, como por ejemplo el paquete útil, que hemos creado anterior mente en este mismo proyecto, dentro del cual se pueden ver tres clases, InformacionPC.java, MedioDeAlmacenamiento.java y Principal.java, cuyo código fuente se puede editar desde el panel de Edición  dando doble clic sobre su respetivo ítem. El segundo ítem importante del panel de proyectos es el ítem bibliotecas, este ítem  contiene las librerías necesarias para ejecutar compilar y ejecutar nuestro proyecto, en este caso se puede ver el uso de la librería Sigar, la cual se explico ampliamente en la primera parte de este artículo.

Si al abrir en proyecto NetBeans no pudo encontrar las librerías necesarias, entonces lo el IDE lo notificara, para ellos coloca unos símbolos rojos de admiración en el panel de proyectos, justo en las clases afectaras y sus respectivos paquetes, estos mismos símbolos son igualmente mostrados en el Panel de Edición, justamente en las líneas de código de las clases donde se utilizan las clases que están dentro de las o la librería faltante.

image0072

Al intentar compilar o ejecutar el proyecto, NetBeans nos emite la siguiente alerta

image010

Para corregir este problema, podemos  seguir los pasos descritos en la primera parte, pro comodidad los resumo a continuación:

1.       Ubicar el lugar donde tenemos almacenadas las librerías necesarias,

2.       Copiar todas las librerías las librerías en la RAM del PC (normalmente punzando ctrl+c)

Clic aqui para ver la Imagen

3.       Volver NetBeans y seleccionar el Panel de Archivos

4.       Ubicar el árbol de ítems de de directorios de nuestro proyecto

5.       Crear un nuevo subdirectorio llamado librerías.

6.       Dentro de este directorio librerías crear otro nuevo subdirectorio con un nombre representativo de las librerías necesarias, en este caso Sigar.

Clic aqui para ver la Imagen

Clic aqui para ver la Imagen

Clic aqui para ver la Imagen

Clic aqui para ver la Imagen

7.       Pegar  dentro de este directorio las librerías (.jar, .dll,  .dylib, .lib, .cab, etc) que seleccionamos y copiamos a memoria RAM, en el paso No.2

Clic aqui para ver la Imagen

Clic aqui para ver la Imagen

8.       Seleccionar el Panel de Proyectos y seleccionar el Ítem raíz de nuestro proyecto

9.       Ir la ítem Librerías

10.   Hacer  clic derecho sobre este ítem y seleccionar la opción  Agregar archivo JAR/Carpeta

Clic aqui para ver la Imagen

11.   Navegar por el sistema de archivos hasta llegar al directorio de nuestro proyecto.

12.   Buscar y abrir el subdirectorio librerías

13.   Ubicar y abrir el subdirectorio donde guardamos las librerías necesarias, en este caso Sigar.

14.   Seleccionar y las librerías adecuadas y necesarias para compilar y ejecutar nuestro proyecto.

Clic aqui para ver la Imagen

15.   verificar que nuestro proyecto ya tenga incluidas las librerías seleccionadas

Clic aqui para ver la Imagen

A este punto ya se debieron haber solucionados los problemas de compilación y ejecución, es decir, desaparecieron los símbolos rojos de admiración del Panel de Proyectos, de lo contrario puede que no se haya incluido todas las librería y falte alguna en proyecto, o puede que se haya modificado el código fuente de alguna clase del proyecto y presente algún tipo de error, ambas cosas habrá que corregirlas para poder continuar con la compilación y ejecución del proyecto de forma satisfactoria.

Las clases de Negocio.

Una vez configurado de forma correcta nuestro, debemos agregarle las clases que realizaran las tareas de artillería pesada, es decir las clases que tendrían escrito el código fuente java necesario para realizar las tareas fundamentales del sistema, a estas clases se les concón como clase de negocio, no confundir con clases entidades ni controladores, estas clases según el diseñador (no confundir con diseño de Interfaces de usuario) del sistema, pueden ser entidades, controladores o rara vez e inadecuado,  que sean clases interfaces de usuario y  más extraño e inaceptable aun, que sean un revuelto (espagueti) de las tres, lo más correcto es colocar este código en una clase lo más independiente del sistema, con el fin de minimizar su acoplamiento,  al conjunto de estas clases se les conoce como modelo.

En nuestro caso he decidido desarrollar una clase llamada Proceso, la cual abstrae toda la funcionalidad necesaria para trabajar con los procesos que se están ejecutando sobre la plataforma, e tre sus funciones se encuentran:

  • Devolver una lista con los procesos en ejecución
  • Buscar procesos en ejecución por nombres
  • Buscar procesos en ejecución por ID
  • Matar un proceso específico
  • Devolver la cantidad de CPU utilizada por los procesos en ejecución
  • Devolver la cantidad de RAM de utilizada por los procesos en ejecución
  • Devolver una lista de los usuarios que están ejecutando procesos.
  • Entre otros.

Crear la clase Proceso

Para crear la clase Proceso dentro de nuestro proyecto  podemos seguir los mismos pasos descritos en la primera parte de este artículo, con los cuales creamos las clases InformacionPC.java, MedioDeAlmacenamiento.java y Principal.java, los cuales resumo a continuación para comodidad de ustedes:

1.       Ir al Panel de Proyectos

2.       Seleccionar el Ítem raíz de nuestro proyecto

3.       Ir al paquete utilidad, el cual está dentro del Ítem Paquetes de Fuentes

4.       Hacer clic derecho sobre este paquete

5.       Seleccionar la opción Nueva Clase Java

Clic aqui para ver la Imagen

6.       Colocarle el nombre deseado y en el paquete deseado

image012

7.       verificar que se haya creado y colocado la nueva clase en nuestro proyecto.

image0131

Estructura de la clase Proceso

A continuación les voy a detallar la estructura de la clase Proceso

image0151

Importaciones de clases necesarias

Esta parte de las importaciones le sobra explicación, puesto que son las mismas clases que hemos venido trabajados desde la primera parte de este artículo, las únicas  clases nuevas aquí son las clases Map y la clase HashMap.


La clase Map es una clase abstracta  del paquete java.util, es una estructura de datos  que representa una colección de objetos tipo Mapa (especie de un diccionario), la clase almacena objetos en forma de lista, pero cada elemento agregado a la lista es colocado en forma de par clave/valor, donde tanto clave como valor son  cualesquier objeto Java (hijos de Object), pero el objeto clave se utiliza como identificador inequívoco   para poder ubicar al objeto valor dentro del mapa, es decir, el objeto clave esta directamente relacionado con un objeto valor, los objetos clave nos e pueden repetir dentro del mapa, mas sin embargo los objetos valor son pueden estar repetidos dentro de la colección, cada objeto valor es representado y accedido mediante su respectivo objeto clave, esta clase Map tiene un método llamado put (objClave, objValor) para poder agregar un nuevo par clave/valor dentro del Mapa, un método objValor get( objClave ) para poder obtener el valor de una clave especifica dentro del mapa, tambien tiene métodos pare quitar elementos del mapa, remove(objClave) y removeAll().

La clase HashMap es una clase hija de Map, se utiliza para implementar de forma concreta la funcionalidad modelada por la clase Abstracta Map.

image0171

Las propiedades de  un objeto Proceso y las propiedades de la clase Proceso

Estas son las variables globales o propiedades que posee el algoritmo de la clase Proceso, estas variables se utilizan para almacenar el nombre de un proceso, su identificador, la el nombre sesión del usuario que lo está ejecutando, el identificador de la sesión, el uso de la memoria RAM de dicho proceso, las dos últimas variables se utilizan para almacenar información común de todos los procesos, por  este motivo se declara de forma static, ya que su posible valor no pertenece a un objeto especifico, por el contrario es información propia de todo, como por ejemplo el total de la RAM que están utilizando y la lista de todas las sesiones de usuarios que están ejecutando los proceso en la plataforma.

image0191

Función que procesa la una línea con información sobre un proceso especifico, retornando el proceso como uno objeto Java, que ofrece mayores posibilidades de manipulación dentro de nuestros programas

image0211

Método que devuelve  la colección de procesos en ejecución

image023

Método que devuelve una colección con  cero, uno o varios procesos que coincidan con el nombre indicado como parámetro.

image025

Función que  devuelve una colección con todos los procesos que se están ejecutando en la plataforma

image0271

Función que muestra por consola todos los procesos ejecutándose en la plataforma, la he creado como mecanismo de prueba de mi clase Proceso.

Ejemplo del uso de las clases InformacionPC.java  y MedioDeAlmacenamiento.java que he creado y explicado en la primera parte, ahora agregándole mi nueva clase Proceso, para ejecutar el ejemplo debemos agregarle una línea al método main de la clase Principal.java

image0291

Ejemplo de salida que Genera el componente ejecutandose en plataforma Windows

Información del sistema

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
::: Datos del Equipo :::


::: Datos del Sistema Operativo :::


Sistema Operativo:  Win32

Arquitectura:  x86

Version:  6.0

Nuemero de actualizaciones:  Service Pack 2

Fabricante:  Microsoft

Descripcion:  Microsoft Windows 2008

Año de fabrica:  2008

Uso de CPU :  little

Maquina:

Codigo de  fabrica:  Longhorn Server

Nombre de fabrica:  Windows 2008

Fecha encendido:  2009-12-19 08:05:32 PM


::: Datos de la CPU :::


Marca CPU :  Intel

Modelo CPU:  Core(TM)2 Duo CPU     T6570  @ 2.10GHz

Velocidad CPU:  2094MHz

Consumo CPU:  0.0%

Tamaño de la Cache CPU:  -1.0

Total Nucleos:  2

Total Socket CPU:  2

Total Socket por Nucleo CPU:  1

Velocidad CPU:  2094

CPU No.1 tiene un consumo de 0.0%

CPU No.2 tiene un consumo de null


::: Datos de la  memoria RAM :::


RAM total:  3032.0 Mb

RAM Ocupada:  1.93122304E9 Mb

RAM Libre:  1.248022528E9 Mb


::: Datos del Sistema de Archivos :::


-- Particion  No.1 --

Nombre Unidad: C:\

Nombre Particion: C:\

Tipo de particion: NTFS

Dispositivo: local

Propiedades: Lectura y Escritura

Espacio Total : 218.0 GB

Espacio Ocupado: 136.0GB

Espacio Libre: 82.0GB

Porcentaje de Uso: 63.0%

-- Particion  No.2 --

Nombre Unidad: D:\

Nombre Particion: D:\

Tipo de particion: NTFS

Dispositivo: local

Propiedades: Lectura y Escritura

Espacio Total : 14.0 GB

Espacio Ocupado: 4.0GB

Espacio Libre: 10.0GB

Porcentaje de Uso: 28.0%

-- Particion  No.3 --

Nombre Unidad: E:\

Nombre Particion: E:\

Tipo de particion: cdrom

Dispositivo: cdrom

Propiedades: Lectura y Escritura

Espacio Total : 0.0 GB

Espacio Ocupado: 0.0GB

Espacio Libre: 0.0GB

Porcentaje de Uso: 0.0%

-- Particion  No.4 --

Nombre Unidad: F:\

Nombre Particion: F:\

Tipo de particion: cdrom

Dispositivo: cdrom

Propiedades: Lectura y Escritura

Espacio Total : 0.0 GB

Espacio Ocupado: 0.0GB

Espacio Libre: 0.0GB

Porcentaje de Uso: 0.0%

Procesos en ejecucion

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
                Nombre               PID          Sesion         #Ses   Ram Kb
No. 1        postgres.exe        3584        Services        0        4.604

No. 2        sqlbrowser.exe        3048        Services        0        2.936

No. 3        svchost.exe        2056        Services        0        7.508

No. 4        OfficeLiveSignIn.exe        3640        Console        1        4.22

No. 5        stacsv.exe        1192        Services        0        5.592

No. 6        firefox.exe        4492        Console        1        191.324

No. 7        svchost.exe        3244        Services        0        2.12

No. 8        SLsvc.exe        1316        Services        0        6.964

No. 9        pg_ctl.exe        3004        Services        0        5.052

No. 10        cmd.exe        1864        Console        1        1.888

No. 11        postgres.exe        3868        Services        0        5.376

No. 12        unsecapp.exe        5636        Console        1        4.608

No. 13        httpd.exe        2288        Services        0        11.288

No. 14        AWC.exe        4396        Console        1        22.0

No. 15        csrss.exe        640        Console        1        13.496

No. 16        svchost.exe        2336        Services        0        4.216

No. 17        taskeng.exe        3676        Services        0        5.708

No. 18        SearchFilterHost.exe        5368        Services        0        6.792

No. 19        svchost.exe        888        Services        0        6.1

No. 20        lsm.exe        700        Services        0        3.672

No. 21        SearchProtocolHost.exe        3960        Services        0        8.496

No. 22        svchost.exe        1520        Services        0        13.196

No. 23        GoogleCrashHandler.exe        2208        Services        0        844.0

No. 24        svchost.exe        1348        Services        0        11.232

No. 25        OEM13Mon.exe        3968        Console        1        4.3

No. 26        svchost.exe        3100        Services        0        5.324

No. 27        services.exe        676        Services        0        6.172

No. 28        ISUSPM.exe        2120        Console        1        5.02

No. 29        winlogon.exe        776        Console        1        4.792

No. 30        httpd.exe        1896        Services        0        9.216

No. 31        wmpnscfg.exe        3208        Console        1        4.472

No. 32        FSCapture.exe        5704        Console        1        15.136

No. 33        SynTPHelper.exe        3348        Console        1        2.684

No. 34        postgres.exe        3884        Services        0        4.704

No. 35        wininit.exe        632        Services        0        3.396

No. 36        svchost.exe        2264        Services        0        2.612

No. 37        svchost.exe        1088        Services        0        12.86

No. 38        conime.exe        168        Console        1        3.356

No. 39        postgres.exe        3856        Services        0        5.016

No. 40        System Idle Process        0        Services        0        24.0

No. 41        EDICT.EXE        3000        Console        1        13.0

No. 42        SynTPEnh.exe        3952        Console        1        7.996

No. 43        aswUpdSv.exe        1716        Services        0        380.0

No. 44        System        4        Services        0        2.408

No. 45        ashMaiSv.exe        3644        Services        0        1.424

No. 46        csrss.exe        588        Services        0        6.212

No. 47        AEstSrv.exe        872        Services        0        1.496

No. 48        cmd.exe        4608        Console        1        2.156

No. 49        ccSvcHst.exe        2164        Services        0        8.26

No. 50        wmpnetwk.exe        4876        Services        0        20.952

No. 51        WmiPrvSE.exe        4128        Services        0        5.64

No. 52        WLIDSVCM.EXE        5144        Services        0        2.652

No. 53        postgres.exe        3848        Services        0        5.048

No. 54        taskeng.exe        3312        Console        1        4.34

No. 55        ashServ.exe        1748        Services        0        29.892

No. 56        WLTRYSVC.EXE        1692        Services        0        2.548

No. 57        postgres.exe        3168        Services        0        12.36

No. 58        svchost.exe        1128        Services        0        76.752

No. 59        ashDisp.exe        3760        Console        1        2.012

No. 60        BCMWLTRY.EXE        1704        Services        0        15.116

No. 61        o2flash.exe        2224        Services        0        2.34

No. 62        tasklist.exe        4580        Console        1        4.708

No. 63        wlcomm.exe        5564        Console        1        40.404

No. 64        TeamViewer_Service.exe        3176        Services        0        3.148

No. 65        svchost.exe        1176        Services        0        23.176

No. 66        smss.exe        516        Services        0        628.0

No. 67        dwm.exe        3652        Console        1        58.26

No. 68        msnmsgr.exe        4056        Console        1        29.296

No. 69        audiodg.exe        1264        Services        0        15.02

No. 70        WmiPrvSE.exe        5908        Services        0        5.712

No. 71        explorer.exe        3736        Console        1        57.64

No. 72        svchost.exe        2140        Services        0        2.728

No. 73        java.exe        2084        Console        1        14.788

No. 74        sttray.exe        1736        Console        1        9.712

No. 75        taskeng.exe        4388        Console        1        10.328

No. 76        svchost.exe        1300        Services        0        4.236

No. 77        svchost.exe        952        Services        0        7.06

No. 78        sqlservr.exe        2088        Services        0        31.392

No. 79        ashWebSv.exe        1060        Services        0        456.0

No. 80        WINWORD.EXE        5340        Console        1        92.576

No. 81        dllhost.exe        4528        Services        0        3.408

No. 82        notepad.exe        3332        Console        1        6.904

No. 83        netbeans.exe        5472        Console        1        232.804

No. 84        SearchIndexer.exe        3668        Services        0        45.528

No. 85        WLIDSVC.EXE        3428        Services        0        15.34

No. 86        sqlwriter.exe        3068        Services        0        5.184

No. 87        ccSvcHst.exe        3568        Console        1        5.572

No. 88        lsass.exe        692        Services        0        2.372

No. 89        svchost.exe        528        Services        0        12.42

No. 90        spoolsv.exe        424        Services        0        8.136

Probar y Licenciar el Proyecto

Para finalizar con el desarrollo de nuestra libreria, solo nos queda por realizar dos tareas muy importantes:

  • Realizar las pruebas
  • Colocarle una Licencia

Las pruebas se realizan siguiendo un conjunto de normas, las cuales se analizaran y estudiaran en este sitio web, pero esto sera en un próximo articulo dedicado exclusivamente a ellas, pero tranquilos que aquí les coloco una pequeña introducción:

Especificación: La aplicación se debe testear a según su documentación, esto incluye tareas como:

  • Que los procedimientos sean exactamente equivalentes a los algoritmos y modelos elaborados durante la fase de diseño.
  • Que el software posea sin excepción todos sus servicios (Casos de uso) que inicialmente fueron estipulados para los usuarios en la fase de Análisis

Usabilidad: se refieres a verificar que el producto cumpla con algunas calidades de calidad inherentes a la Interfaz de Usuario (UI):

  • Intuitiva
  • Amigable
  • Livianas según los requerimientos de la plataforma sobre la que se va a usar.
  • Funcional

Unitarias: Muy aplicada a grande proyectos que generan grandes productos, básicamente se sigue el siguiente proceso:

  • Dividir el sistema en subsistemas funcionales y realizar pruebas a cada uno
  • Dividir los subsistemas en componentes más pequeños, nómademente llamados módulos y realizar pruebas a cada uno.
  • Dividir cada modulo en elementos funcionales para el usuario, normalmente llamados Casos de Uso, y realizar pruebas a cada uno
  • Dividir cada Caso de Uso en los elementos que lo conforman, normalmente llamados clases y realizar pruebas a cada una

Integración: Estas pruebas verifican el grado de compatibilidad que posee el sistema con otros sistemas (antiguos o modernos) de su entorno, permite identificar y corregir posibles errores de migración e implantación, igualmente se monitora el comportamiento del sistema con respecto a los componentes externos (librería de clases, SMBD,.., adquiridos y no desarrollados en el mimo proyecto) que lo integran, normalmente desarrollados por terceros.

Regresión: Es una prueba que planifica la iteración del proceso de pruebas, es decir, esta prueba vincula todas las pruebas realizadas al sistema, volviéndolas a aplicar en caso de que llegase a realizar modificación importantes por efecto de la fase de pruebas.

La licencia debe ser seleccionada teniendo en cuenta algunos criterios, entre los que se encuentra:

  • Tener en cuenta el licenciamiento bajo el cual estan disponibles los componentes de software de terceros que utilizamos para el desarrollo y funcionamiento de nuestro proyecto, en nuestro caso, ya sabemos que he utilizado una libreria llamada Sigar, licenciada exclusivamente como GNU-GPL, si leyeron e investigaron lo suficiente, sabrán que esto implica lo cual implica que liberar nuestro componente con la misma licencia GNU-GPL, ya que esta licencia es una de las denominadas licencia Viral, sus términos se aplican a todo tipo de producto derivado del uso o modificación de un producto libre
  • Los intereses que tengamos con el desarrollo de nuestro proyecto, esto es de vital importancia, por que si nuestro interes es ofrecer el software de forma cerrada (protegiendo el código fuente), ya sea para su comercialización o uso GRATIS que no es lo mismo que LIBRE , o para uso personal, por ejemplo para nuestra propia empresa, o una empresa que haya pagado por su desarrollo, a menos que se indique en el contrato una clausula de propiedad de codigo fuente, todo el codigo producido para desarrollar el software pertenece a la empresa que pago por su desarrollo, a esto se le conoce como desarrollo a la medida, sobra decir que en este caso no se puede utilizar Software Libre

Teniendo en cuenta lo que he explicado anteriormente, concluimos que nuestro proyecto debe ser licenciado como Software Libre GNU-GPL, esta decisión nos obliga a cumplir deberes y que se nos respeten derechos, los cuales pueden leer en el contrato GNU-GPL que he colocado aquí, ademas debemos colocar como minino el todo del cogido fuente del producto en un sitio web de Internet para que sea descargado publica y libremente,

DESCARGAR EL PROYECTO v1.1

Bueno esto es todo por hoy, en la tercera parte de este articulo, les mostrare como trabajar de forma útil con este componente, pero eso sera en la otra ocasión.

275 Visitas hoy
Comparte en tu Web:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • email
  • Reddit
  • RSS
  • StumbleUpon

One Response  
Por favor deje sus Comentarios aquí:

Get Adobe Flash playerPlugin by wpburn.com wordpress themes
© John Carlos Arrieta Arrieta