1 Themenübersicht
Dieses Dokument beschreibt die Anwedungsgebiete und Leistungsfähigkeit des Java-Source-Code-Parsers in Semiramis.
2 Beschreibung
2.1 Aufbau des Verwendungsnachweises
Der Sourcecodeparser wird für die Erkennung der Verwendung von Entwicklungsobjekten in Java-Klassen benötigt. Im Gegensatz zum vorhandenen Byte-Code-Parser kann er auch die Verwendung anderer Entwicklungsobjekttypen als Java-Klassen erkennen. Die Ergebnisse werden in den globalen Verwendungsnachweis eingetragen. Sie sind im Reiter Verwendungsnachweis in der Anwendung Entwicklungsobjekte zu sehen. Der Source-Code-Parser wird automatisch beim Checkin, bei der Aktivierung einer Entwicklungsaufgabe und bei der Installation von Softwareaktualisierungen für die entsprechenden Java-Klassen ausgeführt. Um die Laufzeit des Parserlaufs zu verkürzen werden generierte Java-Klassen ignoriert. Java-Klassen, die Auflösung bestimmter Konstrukte benötigt werden, werden automatisch aus dem Dateisystem nachgeladen. Dabei werden Java-Klassen die in der gleichen Entwicklungsaufgabe gesperrt sind, aus dem Workverzeichnis der Aufgabe geladen.
Der Verwendungsnachweis wird für eine Klasse komplett neu aufgebaut. Zuerst werden alle Einträge gelöscht. Anschließend werden alle gefundenen Entwicklungsobjekte in den Verwendungsnachweis eingetragen. Zusätzlich wird weiterhin der Verwendungsnachweis über den Byte-Code-Parser gepflegt.
Hinweis:
Entwicklungsobjekte, die in einer Java-Klasse verwendet werden, können erst gelöscht werden, nach dem die angepasste Java-Klasse eingecheckt wurde.
2.1.1 Voraussetzungen
Die Konstruktoren und Methoden, denen Entwicklungsobjekte (in der Regel als Zeichenkette) als Parameter übergeben werden, sind in der Datei com/cisag/sys/repository/parser/log/signatures.properties registriert. In dieser Datei wird definiert, welcher Parameter den Pfad zu einem Entwicklungsobjekt darstellt und für die Auflösung benötigt wird (Parameter ist mit der Nummer des Entwicklungsobjekttyps gekennzeichnet). Diese wird vom Sourcecodeparser erkannt und ausgewertet.
Zusätzlich erfolgt noch eine automatische Erkennung von Klassen, die Klassen aus dem Package com.cisag.pgm.gui als Basisklassen verwenden (besonders com.cisag.pgm.gui.EntityField). Hier wird geprüft, ob es sich beim ersten oder zweiten Parameter des Konstruktors um einen Pfad zu einem Entwicklungsobjekt handelt. Diese Klassen müssen nicht in der Datei source/com/cisag/sys/repository/parser/log/signatures.properties registriert werden.
Kann das Entwicklungsobjekt aufgelöst werden, wird der Verwendungsnachweis entsprechend aufgebaut.
2.1.2 Auflösbare Konstrukte
In der Regel wird der vollständige Entwicklungsobjektname (Namensraum + Entwicklungsobjektname) als Zeichenkette (String) als Parameter eines Konstruktors oder einer Methode übergeben.
Beispiel:
RepositoryInfo.getText(“com.cisag.app.Stringtable”, “constant”);
RepositoryInfo.getText(“com.cisag.app.” + “Stringtable”, “constant”);
String dev_object = “com.cisag.app.Stringtable”;
RepositoryInfo.getText(dev_object, “constant”);
Der Entwicklungsobjektname kann aber auch in einer Konstanten definiert werden. Diese kann auch in einer Basisklasse oder einem Interface definiert werden. Die Definition der Konstante in einer anderen Klasse oder einer inneren Klasse ist ebenfalls möglich.
Beispiel:
public static final String DEV_OBJECT = „com.cisag.app.Stringtable”;
RepositoryInfo.getText(DEV_OBJECT, “constant”);
RepositoryInfo.getText(Class.DEV_OBJECT, “constant”);
RepositoryInfo.getText(Class.InnerClass.DEV_OBJECT, “constant”);
Wird der Entwicklungsobjektname als Class-Objekt übergeben, wird dies ebenfalls vom Parser erkannt. Diese Vorgehensweise ist möglich, wenn zu einem Entwicklungsobjekt eine Java-Klasse mit gleichen Namen existiert (z.B. Valueset).
Beispiel:
RepositoryInfo.getValueSetExternalName(ValueSet.class, 1);
Wird in einer Signatur eine Guid zu einem Entwicklungsobjekt verwendet, wird diese ebenfalls erkannt und aufgelöst.
Beispiel:
byte[] applicationGuid = “0260AA8F401E1E10BBAB8464961D0000”;
com.cisag.pgm.appserver.CisApplicationManager.callApplication(applicationGuid, 1, …);
2.1.3 Nicht auflösbare Konstrukte
Der Sourcecodeparser ist kein Interpreter. Zeichenketten oder Guids, die zur Laufzeit ermittelt werden, können nur in einfachen Fällen berechnet werden, siehe oben. Die folgenden Beispiele verdeutlichen die Problematik:
Beispiel:
String devObject = ObjectDirEntryLogic.getObjectNameByGuid(…);
RepositoryInfo.getText(devObject, “constant”);
byte[] appGuid = getApplicationGuid()
ApplicationManager.callApplication(appGuid, …);
Methoden können grundsätzlich nicht ausgeführt werden. Daher kann der Entwicklungsobjektname nicht ermittelt werden und die Verwendung wird nicht erkannt.
Beispiel:
public String getText(String objectName, String elementName) {
return RepositoryInfo.getText(objectName, elementName);
}
Aufruf:
getText(DEV_OBJECT, “constant”)
Teilweise werden Hilfsroutinen in einer Klasse definiert, um nicht immer den langen Aufruf schreiben zu müssen. Hier kommen zwei Probleme zusammen, RepositoryInfo.getText wird überwacht, aber die Werte von objectName und elementName können nur zur Laufzeit ermittelt werden. Daher führt der Aufruf von RepositoryInfo.getText nicht zu einem Eintrag im Verwendungsnachweis. Die Routine getText wird nicht überwacht, da sie nicht in der Datei signatures.properties deklariert ist, daher führt der Aufruf nicht zu einem Eintrag im Verwendungsnachweis.
Ein weiteres Beispiel für eine Hilfsroutine:
Beispiel:
public String getText(String elementName) {
return RepositoryInfo.getText(“stringtable”, elementName);
}
Hier wurde die Hilfsroutine eingeführt, um nur Texte aus einer bestimmten Stringtable zu ermitteln. In diesem Fall wird zwar die Verwendung der Stringtable erkannt, die Verwendungen der Elemente nicht.
2.2 Abhänigkeitserkennung im Softwareaktualisierungscockpit
Ein weiteres Anwendungsgebiet für den Java-Sourcecodeparser ist die Abhängigkeitserkennung zwischen Java-Klassen. Diese Funktionalität wird bei der automatischen Aktualisierung eines Systems benötigt. Ziel ist es, zu einer ausgewählten Anwendung die Softwareaktualisierungen zu ermitteln, die für Aktualisierung notwendig sind (Anwendung Softwareaktualisierungscockpit, Sicht Zielsystem aktualisieren).
Dazu wird bei der Aktvierung der Entwicklungsaufgabe der Sourcecodeparser erneut ausgeführt. Neben dem Aufbau des Verwendungsnachweises erfolgt die Erkennung, welche Methoden von Klassen aus dem Namensraum com.xxxxx.app in der aktuell geparsten Java-Klasse verwendet werden.
Ausgangspunkt der Abhängigkeitsermittlung ist die in der Anwendung eingetragene Java-Klasse. Mithilfe dieser Java-Klasse werden alle direkt verwendeten Java-Klassen ermittelt. Von diesen Java-Klassen werden über den Verwendungsnachweis die verwendeten Entwicklungsobjekte ermittelt. Mit diesen Informationen werden die Softwareaktualisierungen berechnet, denen die gefundenen Entwicklungsobjekte zugeordnet sind.
Das folgende Beispiel zeigt den Aufbau der Abhängigkeiten:
Java-Klasse J1 – Methode M1()
Java-Klasse J2 – Methode M1(), Methode M2()
Java-Klasse J3 – Methode M1()
Java-Klasse J4 – Methode M1()
J1.M1() verwendet J2.M1()
J2.M1() verwendet J3.M1()
J2.M2() verwendet J4.M1()
Wird die Java-Klasse J1 in einer Anwendung verwendet, werden die Java-Klassen J2 und J3 als abhängige Java-Klassen ermittelt. Die Java-Klasse J4 wird nicht berücksichtig, da diese nicht direkt von der Java-Klasse J1 verwendet wird. Außerdem werden noch alle Entwicklungsobjekte benötigt, die in den Java-Klassen J1, J2 und J3 verwendet werden.
Hinweis:
Wird in diesem Zusammenhang die Methode J2.M2() inkompatibel geändert, werden die verwendeten Methoden nicht mit ausgeliefert. Es kann passieren, dass diese Methode nicht mehr korrekt funktioniert.
Dieses Verfahren garantiert nicht die Vollständigkeit der Auswahl. So ist es möglich, dass der Sourcecodeparser nicht alle Entwicklungsobjekte erkannt wurden, die benötigt werden (siehe Abschnitt Nicht auflösbare Konstrukte). Es ist auch möglich, dass Methodenaufrufe nicht vollständig erkannt wurden (z. B. Reflections) und somit benötigte Java-Klassen nicht berücksichtigt werden.