Está en la página 1de 13

Tutorial 1: Desarrollo de un plugin

En este tutorial introductorio se crear un plugin siguiendo una de las plantillas que
ofrece Eclipse. Concretamente se extender una vista para mostrar cierta informacin de
la plataforma.

Crear el proyecto
Se crear un proyecto de plugin con nombre org.example.demo y la informacin del
plugin se introducir como aparece en la imagen.

Tras esto, se nos indicar si deseamos crear el plugin siguiendo una plantilla,
escojeremos Plugin with a view. A continuacin se nos pedirn algunos datos para
generar el cdigo que crear el asistente.
Examinar la descripcin del plugin y la auyda de la extensin.

Descargar http://www.dsic.upv.es/~pginer/download/eclipse/tutorial1/tutorial1.java y
completar el cdigo de DemoView.java.
Crear un fichero en text/info.txt en el proyecto. Este fichero deber aadirse como parte
de la exportacin en la seccin Build Configuration.
Exportar como Deployable plugins and Fragments e indicar que se genere un fichero
Ant con nombre build-demo.xml.
Copiar el plugin en la carpeta plugins de eclipse y comprobar que funciona.

Tutorial 2: Puntos de Extensin

En este tutorial se mostrar como definir puntos de extensin y cmo crear extensiones
para stos. Como ejemplo se crear un sistema extensible de funciones aritmticas. El
usuario podr aplicar distintas funciones matemticas a un valor introducido (por
simplicidad, solo se consideran funciones con un parmetro de entrada). El sistema
estar formado por:
Un plugin que proporcionar la interfaz grfica que permita al usuario introducir
los datos, visualizar los resultados y ejecutar las distintas funciones.
Varios plugins que aportan las funciones aritmticas que se desea poder aplicar.
Las funciones que se pueden aadir debern tener un parmetro de entrada y podrn
acceder a un parmetro opcional de configuracin.

Este ejemplo ha sido tomado del artculo Notes on the Eclipse Plug-in Architecture1
actualizndolo a la nueva versin de Eclipse.

Plugin base

Crear proyecto de plugin


org.example.calculator.ui

Crear Interfaz IFunction


La interfaz actua a modo de contrato, todo plugin que quiera extender al actual
exigiremos que aporte objetos que cumplan con dicha interfaz.
package org.example.calculator.ui;
public interface IFunction {
public long compute(long x) throws ArithmeticException;
}

Fragmento 1: IFunction.java

La interfaz mostrada indica que los objetos que la implementen debern poseer un
mtodo compute que reciba un entero de tipo long y devuelva otro.
Copiar FunctionsGrid al proyecto
Descargar FunctionsGrid.java de:
http://www.dsic.upv.es/~pginer/download/eclipse/tutorial2/FunctionsGrid.java
FunctionsGrid es la definicin de la interfaz grfica de la aplicacin. Hay algunos
aspectos a destacar:
El constructor de FunctionsGrid recibe como parmetro un objeto de tipo Composite
sobre el que agrega los elementos de la interfaz. El mtodo addFunction se usar para
aadir nuevos botones que permitan invocar las nuevas funciones aritmticas. Recibe
como parmetro el objeto IFunction a invocar as como datos de la funcin para
presentarlos al usuario como un nombre, etiqueta y el valor de la constante de
configuracin usado.

Crear una nueva vista


A continuacin se extender el mecanismo de vistas de eclipse para incluir una en la
que se muestre la interfaz grfica recin creada.

http://www.eclipse.org/articles/Article-Plug-in-architecture/plugin_architecture.html

En la informacin del plugin ir a la seccin Extensions.


Aadir una nueva extensin del tipo org.eclipse.ui.views El ID y el Nombre de la
extensin no son relevantes. Sobre la extensin creada mediante un click del botn
secundario del ratn aparecern los elementos que pueden crearse como extensin
(view, category y sticky view). Se crear una categora (category) y una vista nueva
(view). Estos son los datos:
Category
id: org.example.calculator.ui.category
name: Example.org Category
View
id: org.example.calculator.ui.view
name: Calculator View
class: org.example.calculator.ui.CalculatorViewPart
category: org.example.calculator.ui.category
Con esto creamos una nueva vista y una categora que la contendr. La vista indica
mediante el atributo class, la clase que implementar la extensin. Mientras que
category representa el identificador de la categora a la que pertenece la vista.
nicamente falta para completar la vista crear la clase CalculatorViewPart. El cdigo
que se muestra a continuacin extiende la clase ViewPart. El mtodo createPartControl
se define para que pueda crearse la interfaz grfica.

package org.example.calculator.ui;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;

public class CalculatorViewPart extends ViewPart {


public void createPartControl(Composite parent) {
new FunctionsGrid(parent);
}
public void dispose() {
super.dispose();
}
public void setFocus() {
}
}

Fragmento 2 CalculatorViewPart.java

Extensiones

Permtir el acceso al plugin base


En la seccin Runtime de las propiedades del plugin aadir a la lista de Exported
Packages: org.example.calculator.ui
Esto permitir que otros plugins que lo extiendan puedan acceder a sus clases.

Crear Punto de Extensin


En la seccin Extension Points del descriptor del plugin, crear un Extension Point con
los siguientes datos:
id: functions
nombre: Functions
schema: schema/functions.exsd
El identificador del punto de extensin es functions, sin embargo cuando requiera ser
extendido
se
deber
hacer
referencia
a
su
nombre
completo
(org.example.calculator.ui.functions). El schema definir los elementos que pueden
extender el punto de extensin creado.

El schema permite documentar la extensin.


En la seccin de definicin. Se indicarn los elementos que podrn aparecer en una
extensin. Se aadir un nuevo elemento function y a este los siguientes atributos:
name, class y constant. Al elemento extension se le aadir un elemento compositor de
tipo sequence y a este una referencia al elemento function. Con ste ltmo elemento
seleccionado se marcarla propiedad unbounded relativa al nmero mximo de
elementos.

Con esto hemos especificado que la extensin consistir en una secuencia de una o ms
funciones y estas funciones estarn definidas por un nombre, una clase que las
implementar y una constante que se podr indicar en tiempo de extensin
parametrizando esta.
Procesar las exensiones desde el plugin base
El plugin base necesita tener algn tipo de acceso a las extensiones ya que en funcin de
estas deber crear un nmero variable de botones, sin embargo estas solo se conocen en
7

tiempo de ejecucin. Para ello se ha creado la clase ProcessServiceMembers que


recibir la interfaz grfica, recuperar la informacin relativa a las extensiones y
ejecutar el servicio addFunction, para aadir los botones y etiquetas necesarios para
ejecutar cada funcin.
package org.example.calculator.ui;
import
import
import
import
import
import

org.eclipse.core.runtime.CoreException;
org.eclipse.core.runtime.IConfigurationElement;
org.eclipse.core.runtime.IExtension;
org.eclipse.core.runtime.IExtensionPoint;
org.eclipse.core.runtime.Platform;
org.eclipse.ui.WorkbenchException;

public class ProcessServiceMembers {


private static final String EXTENSION_POINT =
"org.example.calculator.ui.functions";
private static final String FUNCTION_NAME_ATTRIBUTE = "name";
private static final String CLASS_ATTRIBUTE = "class";
private static final String CONSTANT_ATTRIBUTE = "constant";
public static void process(FunctionsGrid grid) throws WorkbenchException {
IExtensionPoint extensionPoint =
Platform.getExtensionRegistry().getExtensionPoint(EXTENSION_POINT);
IConfigurationElement[] members = extensionPoint.getConfigurationElements();
// For each service:
for (IConfigurationElement member:members) {
IExtension extension = member.getDeclaringExtension();
String pluginLabel = extension.getLabel();
if (pluginLabel == null) {
pluginLabel = "[unnamed plugin]"; }
String functionName = member.getAttribute(FUNCTION_NAME_ATTRIBUTE);
if (functionName == null) {
functionName = "[unnamed function]";
}
String label = pluginLabel + "/" + functionName;
Integer constant = null;
String s = member.getAttribute(CONSTANT_ATTRIBUTE);
if (s != null) {
constant = new Integer(s);
}
// Add a row to support this operation to the UI grid.
IFunction function;
try {
Object callback = member.createExecutableExtension(CLASS_ATTRIBUTE);
function = (IFunction)callback;
}
catch (CoreException ex) {
System.err.println(ex.getMessage());
ex.printStackTrace();
break;
}
grid.addFunction(function, functionName, label, constant);
}
}
}

Fragmento 3 ProcessServiceMembers.java

El cdigo presentado define un conjunto de constantes para almacenar el identificador


del punto de extensin y los nombres de los atributos que aparecern en los elementos
que forman la extensin. Estos nombres (name, class y constant) fueron los que
se dieron al definir el elemento function del esquema de la extensin.
La clase CalculatorViewPart deber incluir una llamada para procesar los servicios y
permitir a la clase ProcessServiceMembers que modifique el grid. El nuevo cdigo de
CalculatorViewPart, se muestra a continuacin (los cambios respecto a la versin
anterior se muestran resaltados):
package org.example.calculator.ui;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.part.ViewPart;
public class CalculatorViewPart extends ViewPart {
public void createPartControl(Composite parent) {
// Define the UI grid for invoking functions.
FunctionsGrid grid = new FunctionsGrid(parent);
// Do extension processing for the "functions" extension-point.
try {
ProcessServiceMembers.process(grid);
}
catch (WorkbenchException e) {
e.printStackTrace();
}
}
public void dispose() {
super.dispose();
}
public void setFocus() {
}
}

Fragmento 4 CalculatorViewPart.java

Crear nuevos plugins


El plugin creado anteriormente no aporta ninguna funcionalidad. Precisamente su
funcin es definir un punto de extensin donde otros plugins puedan aadir nuevas
funciones. A continuacin se crearn dos plugins, el primero incorporar una extensin
consistente en la funcin de copia (el valor de salida ser el proporcionado como
entrada). Un segundo plugin se definir para incluir una funcin de multiplicacin que
servir para realizar dos extensiones doble y triple que servirn para multiplicar el valor
de entrada por 2 y 3 respectivamente. En vez de definir dos funciones distintas, la
funcin multiplicar se parametrizar utilizando el valor constant de las extensiones.

Plugin Simple
Crear proyecto de plugin: org.example.calculator.copia
En la seccin Dependencias aadir org.example.calculator.ui como dependencia.
Crear una clase Copia que implemente la interfaz IFunction.

package org.example.calculator.copia;
import org.example.calculator.ui.IFunction;
public class Copia implements IFunction {
@Override
public long compute(long x) throws ArithmeticException {
return x;
}
}

Crear una extensin de tipo org.example.calculator.ui.functions


org.example.calculator.copia y nombre Copia Function.
Aadir un elemento function con los siguientes datos:
Name: Copia
Class: org.example.calculator.copia.Copia
Y sin asignar valor a la constante.

con

ID:

Plugin Avanzado
Los plugins pueden aportar mltiples extensiones a otros plugins, en este ejemplo se
crear un plugin que defina dos extensiones: doble y triple. El plugin contendr una
nica funcin, multiplicar, que har uso el parmetro constant definido para las
extensiones.
Crear un proyecto de plugin con nombre org.example.calculator.multiplicar
En la seccin Dependencias aadir org.example.calculator.ui como dependencia.
La Funcin a aadir se definir en una clase. Esta deber implementar la interfaz
IFunction y IExecutableExtension.

10

La interfaz IFunction exige definir el mtodo que especificar la operacin. En este caso
el valor devuelto ser el resultado de multiplicar el parmetro de entrada por la
constante de configuracin.
La interfaz IExecutableExtension fuerza a implementar el mtodo setInitializationData,
que servir para obtener precisamente el valor de la constante introducida en la
definicin de la extensin.
package org.example.calculator.multiplicar;
import
import
import
import

org.eclipse.core.runtime.CoreException;
org.eclipse.core.runtime.IConfigurationElement;
org.eclipse.core.runtime.IExecutableExtension;
org.example.calculator.ui.IFunction;

public class Multiplicar implements IFunction, IExecutableExtension {


private int parametro;
@Override
public long compute(long x) throws ArithmeticException {
return parametro*x;
}
@Override
public void setInitializationData(IConfigurationElement config,
String propertyName, Object data) throws CoreException {
String s=config.getAttribute("constant");
parametro=Integer.parseInt(s);
}

11

Fragmento 5 Multiplicar.java

A continuacin definiremos las dos funciones.


En
la
seccin
Extensions
aadir
una
extensin
de
tipo
org.example.calculator.ui.functions con id org.example.calculator.multiplicar y nombre
Multiplicar.
Crear un elemento de tipo function con los siguientes datos:
Name: Doble
Class: org.example.calculator.multiplicar.Multiplicar
Constant: 2
Crear un nuevo elemento function con:
Name: Triple
Class: org.example.calculator.multiplicar.Multiplicar
Constant: 3
Ambos objetos comparten la misma clase.

Consideraciones importantes
La clase ProcessServiceMembers encargada de aadir para cada extensin la parte de
interfaz grfica correspondiente. En el cdigo presentado, el objeto que implementa la
funcin es recuperado. Sin embargo para evitar un derroche innecesario de recursos, la
estratgia habitual es crear un Proxy.
Los proxies son representantes locales (ms ligeros) de un objeto. De este modo el
Proxy se crear a partir de la informacin de la extensin y solo se instanciar el objeto
correspondiente cuando sea necesario utilizar el objeto. Adems por brevedad se habian
eliminado algunas comprobaciones relativas a la gestin de excepciones. ste cdigo es
especialmente importante ya que permite detectar errores en la especificacin de
extensiones y garantizar que solo se consideren las extensiones correctas. El cdigo
completo se recoge a continuacin:
package org.example.calculator.ui;
import
import
import
import
import
import

org.eclipse.core.runtime.CoreException;
org.eclipse.core.runtime.IConfigurationElement;
org.eclipse.core.runtime.IExtension;
org.eclipse.core.runtime.IExtensionPoint;
org.eclipse.core.runtime.Platform;
org.eclipse.ui.WorkbenchException;

public class ProcessServiceMembers {


private static final String EXTENSION_POINT =
"org.example.calculator.ui.functions";
private static final String FUNCTION_NAME_ATTRIBUTE = "name";
private static final String CLASS_ATTRIBUTE = "class";
private static final String CONSTANT_ATTRIBUTE = "constant";

12

public static void process(FunctionsGrid grid) throws WorkbenchException {


IExtensionPoint extensionPoint =
Platform.getExtensionRegistry().getExtensionPoint(EXTENSION_POINT);
IConfigurationElement[] members = extensionPoint.getConfigurationElements();
// For each service:
for (IConfigurationElement member:members) {
IExtension extension = member.getDeclaringExtension();
String pluginLabel = extension.getLabel();
if (pluginLabel == null) { pluginLabel = "[unnamed plugin]";}
// Get the name of the operation implemented by the service.
String functionName = member.getAttribute(FUNCTION_NAME_ATTRIBUTE);
if (functionName == null) { functionName = "[unnamed function]";}
String label = pluginLabel + "/" + functionName;
Integer constant = null;
String s = member.getAttribute(CONSTANT_ATTRIBUTE);
if (s != null) {
constant = new Integer(s);
}
// Add a row to support this operation to the UI grid.
IFunction function;
try {
Object callback = member.createExecutableExtension(CLASS_ATTRIBUTE);
function = (IFunction)callback;
}
catch (CoreException ex) {
System.err.println(ex.getMessage());
ex.printStackTrace();
break;
}
grid.addFunction(function, functionName, label, constant);
}
}
}

Fragmento 6 ProcessServiceMembers

13

También podría gustarte