Funktion 'Push-to-Client' erweitern

Ein unabhängiger Softwareanbieter (Independent Software Vendor - ISV) kann zusätzliche Erweiterungen beitragen, mit deren Hilfe andere Typen von IDE-Konfigurationen weitergegeben werden können. Nachfolgend wird beschrieben, wie eine Push-to-Client-Erweiterung bereitgestellt werden kann.

Die Funktion 'Push-to-Client' bietet die Möglichkeit der gemeinsamen Nutzung von IDE-Konfigurationen durch Benutzer. Entwickler können ihre eigenen Konfigurationen lokal exportieren, um zu einem späteren Zeitpunkt die Möglichkeit zu haben, eine vorherige IDE-Umgebung wiederherzustellen. Im Falle eines Teams von Entwicklern kann eine einzelne IDE konfiguriert und anschließend mithilfe von Push-to-Client auf einem gemeinsamen Server gemeinsam genutzt werden. Wenn Entwickler zu dem betreffenden Server eine Verbindung herstellen, wird ihre IDE automatisch mit der zuvor exportierten Konfiguration synchronisiert. Auf diese Weise können einheitliche Einstellungen teamübergreifend gemeinsam genutzt werden.

Dieses Verfahren besteht aus einem Basisframework für die Handhabung der Benutzerschnittstelle sowie einem Großteil der Verarbeitung in Verbindung mit Erweiterungen zur Handhabung bestimmter Konfigurationstypen. Push-to-Client stellt die folgenden Erweiterungen ohne Vorbereitungs- oder Anpassungsaufwand bereit:

Beiträge für Push-to-Client erstellen

Normalerweise werden Sie sich dafür entscheiden, ein neues Plug-in-Projekt für die Erweiterung zu erstellen. In das Manifest müssen Sie mindestens die folgenden Abhängigkeiten einschließen:
com.ibm.etools.systems.pushtoclient.core
org.eclipse.core.resources
org.eclipse.core.runtime
org.eclipse.ui
Im nächsten Schritt sollte ein Erweiterungspunkt 'configurationExtension' in der Datei 'plugin.xml' des Projekts definiert werden. Beispiel:
<extension
      point="com.ibm.etools.systems.pushtoclient.core.configurationExtensions">
   <configurationExtension
         class="p2c.test.ConfigurationExtension1"
         description="Custom Elements"
         icon="icons/obj.gif"
         id="p2c.test.configurationExtension1"
         name="Test Extension">
   </configurationExtension>
</extension>
Für jede Erweiterung muss eine Klasse, eine Beschreibung, ein Symbol, eine ID und ein Name vergeben werden. Die Funktionalität des Beitrags wird in die Klasse eingebettet. Die Klasse muss 'IConfigurationExtension' implementieren. In den meisten Fällen sollte die Implementierung 'ConfigurationExtension' nach Möglichkeit erweitert werden.
Anfänglich sieht Ihr Code ähnlich wie im folgenden Beispiel aus:
package p2c.test;

import com.ibm.etools.systems.pushtoclient.core.extensions.IConfigurationElement;
import com.ibm.etools.systems.pushtoclient.core.extensions.ConfigurationElement;
import com.ibm.etools.systems.pushtoclient.core.extensions.ConfigurationExtension;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.runtime.IProgressMonitor;

public class ConfigurationExtension1 extends ConfigurationExtension {

	public ConfigurationExtension1(String id, String name, String description){
		super(id, name, description);
	}
In einer Konfigurationserweiterung wird mit IConfigurationElement und der zugehörigen Standardimplementierung ConfigurationElement als Modellobjekt gearbeitet. Diese Elemente stellen Informationseinheiten dar, die angezeigt werden, damit Benutzer die danebenliegenden Kontrollkästchen aus- oder abwählen können. Jedes Element enthält beschreibende Informationen und optional untergeordnete Elemente. Sie müssen jede der folgenden vier Methoden unter Verwendung von Konfigurationselementen definieren:
  • public void populateExportElements(IConfigurationElement parent)
  • public void exportToCache(IConfigurationElement element,IFolder cacheFolder, IProgressMonitor monitor)
  • public void populateImportElements(IConfigurationElement parent)
  • public void importToWorkspace(IConfigurationElement element, IProgressMonitor monitor)
Mithilfe der Methode populateExportElements() kann ein Benutzer festlegen, welche Elemente einer Konfiguration in einem Assistenten exportiert werden sollen. Im einfachsten Fall müssen Sie lediglich angeben, ob das übergeordnete Element standardmäßig für den Export definiert werden soll. Beispiel:
public void populateExportElements(IConfigurationElement parent){
	parent.setToExport(true);
}
In diesem Fall haben Benutzer lediglich die Wahl, alle Konfigurationsinformationen oder aber keine zu übernehmen.
Im folgenden etwas komplizierteren Beispiel werden Elemente erstellt, die diskrete Artefakte für den Export darstellen:
@Override
public void populateExportElements(
		IConfigurationElement parent) {
	// folder representing one category of items
	ConfigurationElement folderElement = new ConfigurationElement("Element X", "Custom properties X");
	parent.add(folderElement);

	// contents of first category
	ConfigurationElement stuff = new ConfigurationElement("X child element", "");
	stuff.setToExport(true);
	folderElement.add(stuff);
	folderElement.setToExport(true);

	// folder representing another category of items
	ConfigurationElement folderElement2 = new ConfigurationElement("Element Y", "Custom properties Y");
	parent.add(folderElement2);

	// contents of the second category
	ConfigurationElement thing1 = new ConfigurationElement("Y child element 1", "");
	folderElement2.add(thing1);
	thing1.setToExport(true);

	ConfigurationElement thing2 = new ConfigurationElement("Y child element 2", "");
	folderElement2.add(thing2);
	folderElement2.setToExport(true);

	parent.setToExport(true);
}

Beim Exportieren mithilfe eines Push-to-Client-Assistenten werden die Elemente wie folgt angezeigt:

Anpassen des Exportassistenten

Der Name und die Beschreibung des Stammelements für diese Erweiterung (Test Extension) stammt aus dem Erweiterungspunkt, während sich die untergeordneten Elemente durch die Implementierung von populateExportElements() ergeben.

Die Methode exportToCache() wird aufgerufen, wenn ein Benutzer den Exportassistenten fertigstellt. Die Elemente der Konfigurationserweiterung werden übergeben und es werden abhängig von den ausgewählten Elementen die entsprechenden Konfigurationsartefakte in einem bestimmten Format unter dem bereitgestellten Verzeichnis Cacheordner gespeichert. Das Format wird vom Implementierer bestimmt. Dieses Verzeichnis Cacheordner ist für jede Konfigurationserweiterung eindeutig und verwendet die Konfigurations-ID als Name.

Nachfolgend steht eine Beispielimplementierung von exportToCache():
@Override
public void exportToCache(IConfigurationElement element,
		IFolder cacheFolder, IProgressMonitor monitor) {			
	// find all the elements that are "set to export" and
	// then save to the cache folder
	if (element.hasChildren()){			
		IConfigurationElement[] folders = element.getChildren();
		for (IConfigurationElement folder: folders){
			if (folder.isSetToExport()){
				IConfigurationElement[] children = folder.getChildren();
				for (IConfigurationElement child: children){
					if (child.isSetToExport()){
						// store in model for export
						...
					}						
				}
			}
		}
		
		// create file to store exported information
		IFile file = cacheFolder.getFile(new Path("test.properties"));
		...
	}
}

Nachdem eine Konfiguration in das Cacheverzeichnis exportiert wurde, erledigt das Basisframework von Push-to-Client den restlichen Teil der Operation. Wenn Sie an eine lokale Speicherposition exportieren, werden die zwischengespeicherten Informationen an der betreffenden Position archiviert. Wenn Sie auf einen allgemeinen Server exportieren, werden die geänderten Informationen archiviert und auf den betreffenden Server übertragen.

Beim Importieren von Konfigurationen lädt das Push-to-Client-Framework zunächst das Archiv mit der exportierten Konfiguration in den Eclipse-Arbeitsbereich herunter und extrahiert anschließend den archivierten Inhalt unter dem Ordner 'RemoteSystemsTempFiles'. Wie beim Export gibt es auch beim Import einen Cacheordner für jede Konfigurationserweiterung; dabei handelt es sich um denselben Ordner, der für den Export verwendet wird. Der Importassistent muss den Benutzer zur Angabe der zu importierenden Elemente auffordern. Wie bei populateExportElements() implementiert jede Konfigurationserweiterung populateImportElements(), indem Konfigurationselemente zur Darstellung der ankommenden Informationen erstellt werden. Der einzige Parameter für diese Methode ist ein Element, das den Cacheordner für Ihre Konfigurationserweiterung zurückgibt.

Im folgenden Beispiel wird die Elementhierarchie für die Konfiguration erzeugt, indem Informationen aus der Datei 'test.properties' extrahiert werden.
@Override
public void populateImportElements(
		IConfigurationElement parent) {

	// parent file is the cached folder for this configuration
	File parentFile = parent.getFile();
	
	// test.properties is contained in the parent folder
	File testFile = new File(parentFile, "test.properties");
	
	// read and parse the file and populate import elements based on contents of testFile
	...

Der folgende Dialog wird als Antwort auf den Import angezeigt. Normalerweise wird alles, was importiert wird, standardmäßig ausgewählt.

Angepasster Importassistent

Die letzte zu implementierende Methode ist importToWorkspace(). Diese Methode wird aufgerufen, nachdem der Benutzer im Importdialog OK angeklickt hat. Die ausgewählten Elemente für die Konfiguration werden an diese Methode übergeben; die Aufgabe des Implementierers besteht darin, die Informationen aus dem Cacheordner der Konfigurationserweiterung abzurufen und sie auf den Arbeitsbereich anzuwenden.
@Override
public void importToWorkspace(IConfigurationElement element,
		IProgressMonitor monitor) {
	// find all the elements that are "set to export" (same as "set to import")
	if (element.hasChildren()){			
		IConfigurationElement[] folders = element.getChildren();
		for (IConfigurationElement folder: folders){
			if (folder.isSetToExport()){
				IConfigurationElement[] children = folder.getChildren();
				for (IConfigurationElement child: children){
					if (child.isSetToExport()){
						// transfer the corresponding information to the workspace					...
					}						
				}
			}
		}
	}
}

Feedback