Parser kodu źródłowego Java

Wprowadzenie

Niniejszy artykuł opisuje obszary zastosowania i wydajność parsera kodu źródłowego Java w systemie.

Opis

Struktura listy wykazy zastosowania

Parser kodu źródłowego jest wymagany do rozpoznawania użycia obiektów programistycznych w klasach Java. W przeciwieństwie do istniejącego parsera kodu bajtowego, może on również rozpoznawać użycie typów obiektów programistycznych innych niż klasy Java. Wyniki są wprowadzane do globalnej listy wykazy zastosowania. Można je zobaczyć na zakładce Wykazy zastosowania w aplikacji Obiekty deweloperskie. Parser kodu źródłowego jest automatycznie wykonywany podczas zameldowania, gdy aktywowane jest zadanie programistyczne i gdy instalowane są aktualizacje oprogramowania dla odpowiednich klas Java. Wygenerowane klasy Java są ignorowane w celu skrócenia czasu działania parsera. Klasy Java, które są wymagane do rozwiązania pewnych konstrukcji, są automatycznie przeładowywane z systemu plików. Klasy Java, które są zablokowane w tym samym zadaniu programistycznym, są ładowane z katalogu roboczego zadania.

Lista Wykazy zastosowania jest całkowicie przebudowywana dla danej klasy. Najpierw usuwane są wszystkie wpisy. Następnie wszystkie znalezione obiekty programistyczne są wprowadzane do listy Wykazów zastosowania. Lista Wykazów zastosowania jest również utrzymywana przez parser kodu bajtowego.

Uwaga
Obiekty programistyczne, które są używane w klasie Java, mogą zostać usunięte dopiero po zaewidencjonowaniu dostosowanej klasy Java.
Wymagania wstępne

Konstruktory i metody, do których obiekty programistyczne (zwykle jako ciągi znaków) są przekazywane jako parametry, są rejestrowane w pliku com/cisag/sys/repository/parser/log/signatures.properties. Plik ten określa, który parametr reprezentuje ścieżkę do obiektu deweloperskiego i jest wymagany do rozwiązania (parametr jest oznaczony numerem typu obiektu deweloperskiego ). Jest to rozpoznawane i oceniane przez parser kodu źródłowego.

Ponadto klasy, które używają klas z pakietu com.cisag.pgm.gui jako klas bazowych (w szczególności com.cisag.pgm.gui.EntityField) są rozpoznawane automatycznie. Sprawdza to, czy pierwszy lub drugi parametr konstruktora jest ścieżką do obiektu programistycznego. Klasy te nie muszą być zarejestrowane w pliku source/com/cisag/sys/repository/parser/log/signatures.properties.

Jeśli obiekt deweloperskie może zostać rozpoznany, lista wykazy zastosowania jest odpowiednio tworzona.

Konstrukcje rozszerzalne

Z reguły pełna nazwa obiektu deweloperskiego (przestrzeń nazw + nazwa obiektu deweloperskiego) jest przekazywana jako ciąg znaków jako parametr konstruktora lub metody.

Przykład
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”);

Nazwa obiektu deweloperskiego może być również zdefiniowana w stałej. Można ją również zdefiniować w klasie bazowej lub interfejsie. Możliwe jest również zdefiniowanie stałej w innej klasie lub klasie wewnętrznej.

Przykład
public static final String DEV_OBJECT = „com.cisag.app.Stringtable”;

RepositoryInfo.getText(DEV_OBJECT, „constant”);

RepositoryInfo.getText(Class.DEV_OBJECT, „stała”);

RepositoryInfo.getText(Class.InnerClass.DEV_OBJECT, „stała”);

Jeśli nazwa obiektu deweloperskiego jest przekazywana jako obiekt klasy, jest to również rozpoznawane przez parser. Ta procedura jest możliwa, jeśli dla obiektu deweloperskiego istnieje klasa Java o tej samej nazwie (np. Valueset).

Przykład
RepositoryInfo.getValueSetExternalName(ValueSet.class, 1);

Jeśli w sygnaturze używany jest identyfikator Guid dla obiektu deweloperskiego, jest on również rozpoznawany i rozwiązywany.

Przykład
byte[] applicationGuid = „0260AA8F401E1E10BBAB8464961D0000”;

com.cisag.pgm.appserver.CisApplicationManager.callApplication(applicationGuid, 1, …);

Konstrukcje nierozstrzygalne

Parser kodu źródłowego nie jest interpreterem. Ciągi znaków lub guidy, które są określane w czasie wykonywania, mogą być obliczane tylko w prostych przypadkach. Poniższe przykłady ilustrują ten przypadek:

Przykład
String devObject = ObjectDirEntryLogic.getObjectNameByGuid(…);

RepositoryInfo.getText(devObject, „constant”);

byte[] appGuid = getApplicationGuid()

ApplicationManager.callApplication(appGuid, …);

Metody nie mogą być wykonywane. W związku z tym nie można określić nazwy obiektu programistycznego, a jego użycie nie jest rozpoznawane.

Przykład
public String getText(String objectName, String elementName) {

return RepositoryInfo.getText(objectName, elementName);

}

Call:

getText(DEV_OBJECT, „constant”)

Czasami w klasie definiowane są procedury pomocnicze, dzięki czemu nie zawsze trzeba pisać długie wywołanie. W tym przypadku pojawiają się dwa problemy: RepositoryInfo.getText jest monitorowane, ale wartości objectName i elementName można określić tylko w czasie wykonywania. Dlatego wywołanie RepositoryInfo.getText nie prowadzi do wpisu na liście wykazów zastosowania. Procedura getText nie jest monitorowana, ponieważ nie jest zadeklarowana w pliku signatures.properties, dlatego jej wywołanie nie prowadzi do wpisu na liście wykazów zastosowania.

Przykład
public String getText(String elementName) {

return RepositoryInfo.getText(„stringtable”, elementName);

}

Procedura pomocnicza została tutaj wprowadzona w celu określenia tylko tekstów z określonej tabeli łańcuchów. W tym przypadku użycie tabeli łańcuchów jest rozpoznawane, ale użycie elementów nie.

Wykrywanie zależności w aplikacji Panel Aktualizacja oprogramowania

Innym obszarem zastosowania parsera kodu źródłowego Java jest wykrywanie zależności między klasami Java. Funkcjonalność ta jest wymagana do automatycznej aktualizacji systemu. Celem jest określenie aktualizacji oprogramowania dla wybranej aplikacji, które są wymagane do aktualizacji (aplikacja Panel Aktualizacja oprogramowania, widok Aktualizacja systemu docelowego).

Aby to zrobić, parser kodu źródłowego jest wykonywany ponownie, gdy aktywowane jest zadanie programistyczne. Oprócz tworzenia listy wykazów zastosowania, rozpoznawane są metody klas z przestrzeni nazw com.xxxxx.app, które są używane w aktualnie analizowanej klasie Java.

Punktem wyjścia do określenia zależności jest klasa Java wprowadzona w aplikacji. Ta klasa Java jest używana do określenia wszystkich bezpośrednio używanych klas Java. Używane obiekty programistyczne są określane na podstawie tych klas Java za pośrednictwem listy wykazów zastosowania. Informacje te są wykorzystywane do obliczania aktualizacji oprogramowania, do których przypisane są znalezione obiekty programistyczne.

Przykład
Poniższy przykład przedstawia strukturę zależności:

Klasa Java J1 – metoda M1()

Klasa Java J2 – metoda M1(), metoda M2()

Klasa Java J3 – metoda M1()

Klasa Java J4 – metoda M1()

J1.M1() używa J2.M1()

J2.M1() używa J3.M1()

J2.M2() używa J4.M1()

Jeśli klasa Java J1 jest używana w aplikacji, klasy Java J2 i J3 są określane jako zależne klasy Java. Klasa Java J4 nie jest brana pod uwagę, ponieważ nie jest używana bezpośrednio przez klasę Java J1. Wymagane są również wszystkie obiekty programistyczne, które są używane w klasach Java J1, J2 i J3.

Uwaga
Jeśli metoda J2.M2() zostanie zmieniona w sposób niekompatybilny w tym kontekście, używane metody nie zostaną dostarczone. Metoda ta może nie działać poprawnie.

Ta procedura nie gwarantuje kompletności wyboru. Na przykład możliwe jest, że parser kodu źródłowego nie rozpoznał wszystkich wymaganych obiektów programistycznych (rozdział: Konstrukcje nierozstrzygalne). Możliwe jest również, że wywołania metod nie zostały w pełni rozpoznane (np. odbicia), a zatem wymagane klasy Java nie są brane pod uwagę.

Czy ten artykuł był pomocny?