Plugin gets stuck

While working on a new plugin I tried to reuse components, that already exist.
While testing the plugin froze. You could see it in the debug view by stepping to the reused component. There where no exceptions that tell you anything. Suddenly I had the idea that in the eclipse environment that I started to test the plugin might have something in the error log. Bingo: NoClassDefFoundException. But how could the plugin compile if the resource is not available? The answer is quite simple: I added the needed resource file to the buildpath instead to the plugin dependencies. Therefore at compile time the resource could be found but the plugin knew nothing of the needed resource. When building a plugin never add something needed to the buildpath, add it to the dependencies. Doing this the plugin worked as desired

Getting started with PHP Class Generator Plugin

The Eclipse plugin PHP Class Generator is now about a month up on Eclipse Plugin Central. It was now brought to my attention (thanks Tyler) that documentation is not exactly missing but at least hard to find and you have to know where and how to look. This article should help to shed light into the dark.
„Getting started with PHP Class Generator Plugin“ weiterlesen

Durchsuchen des Classpath

Das JDK bringt von Haus aus bereits ein mächtiges Framework mit sich, mit dem sich zur Runtime Informationen über die Applikation gewinnen lassen, wie auch schon in einem früheren Beitrag beschrieben. Dies funktioniert solange einwandfrei als ich weiss auf welche Klasse ich die Reflection los lasse.
Mit Annotation lässt sich eine Vielzahl von Dingen bewerkstelligen, so kann man auch auf den Gedanken verfallen, dass man Bestimmte Aufgaben definiert (beispielsweise in einer Enumeration). Die Ausführung dieser Aufgaben übernehmen Methoden mit einer nicht näher bekannten Signatur. Was aber bekannt ist, ist dass die Methode mit einer Annotation gekennzeichnet ist, die besagt, dass diese Methode jene Aufgabe erfüllt.
Wie gelange ich nun an die Klasse in der die Methode definiert ist? Nur mit dem JDK ist dies nicht möglich. Dazu müssen aus dem Classpath alle Klassen ausgelesen werden. Dann kann jede einzelne Klasse nach der Methode untersucht werden, die die spezifizierte Annotation besitzt.
Wem dies alles etwas zu abstrakt war hier das Beispiel:

public class ClassFinder {
        /**
         * Defined classpath
         */
	private static final String CLASSPATH = System.getProperty("java.class.path");
	/**
	 * List with the jar files on the classpath
	 */
	private static String[] jarFiles;
	/**
	 * List with the directories on the classpath (containing .class files)
	 */
	private static String[] binDirs;
	/**
	 * All Classpath elements
	 */
	private static File[] classPathDirs = null;
	/**
	 * Default constructur initializes the directories indicated by the
	 * CLASSPATH, if they are not yet initialized.
	 */
	public ClassFinder() {
		if (classPathDirs == null) {
			initClassPathDir();
		}
	}
	/**
	 * Initialize the directories based on the classpath
	 */
	private void initClassPathDir() {
		StringTokenizer st = new StringTokenizer(CLASSPATH, File.pathSeparator);
		int count = st.countTokens();
		classPathDirs = new File[count];
		Vector jar = new Vector();
		Vector bin = new Vector();
		for (int i = 0; i < count; i++) {
			classPathDirs[i] = new File(st.nextToken());
			if (classPathDirs[i].isDirectory()) {
				bin.add(classPathDirs[i].getAbsolutePath());
			} else {
				jar.add(classPathDirs[i].getAbsolutePath());
			}
		}
		jarFiles = new String[jar.size()];
		binDirs = new String[bin.size()];
		jar.copyInto(jarFiles);
		bin.copyInto(binDirs);
	}

	/**
	 * Retrive all classes of the indicated package. The package is searched in
	 * all classpath directories that are directories
	 * 
	 * @param packageName
	 *            name of the package as 'ch.sahits.civ'
	 * @return Array of found classes
	 * @throws ClassNotFoundException
	 */
	public Class[] getAll(String packageName) throws ClassNotFoundException {
		String packageDir = convertPackege(packageName);
		Vector classes = new Vector();
		for (int i = 0; i < binDirs.length; i++) {
			packageDir = binDirs[i] + File.separator + packageDir;
			File dir = new File(packageDir);
			classes.addAll(extractClasses(packageName, dir));
		}
		Class[] result = new Class[classes.size()];
		classes.copyInto(result);
		return result;
	}
	/**
	 * Extract all the classes from a directory
	 * @param packageName name of the package as 'ch.sahits.civ'
	 * @param dir Package as directory
	 * @return Vector with all found directories
	 * @throws ClassNotFoundException
	 */
	private Vector extractClasses(String packageName, File dir) throws ClassNotFoundException {
		Vector classes = new Vector();
		File[] files = dir.listFiles(new FilenameFilter() {
			public boolean accept(File dir, String filename) {
				return filename.endsWith(".class");
			}
		});
		if (files!=null) {	// directories without .class files may exist
			for (int j = 0; j < files.length; j++) {
				String className = packageName + "." + files[j].getName();
				className = className.substring(0, className
						.lastIndexOf(".class"));
				classes.add(Class.forName(className));
			}
		}
		return classes;
	}
	/**
	 * Convert the package name into a relative directory path
	 * @param packageName name of the package as 'ch.sahits.civ'
	 * @return relativ directory to the package
	 */
	private String convertPackege(String packageName) {
		String sep = File.separator;
		return packageName.replace(".", sep);
	}
	/**
	 * Retrive all classes of the indicated package and all subpackages. The package is searched in
	 * all classpath directories that are directories
	 * 
	 * @param packageName
	 *            name of the package as 'ch.sahits.civ'
	 * @return Array of found classes
	 * @throws ClassNotFoundException
	 */
	public Class[] getAllRecursive(String packageName) throws ClassNotFoundException {
		String packageDir = convertPackege(packageName);
		Vector classes = new Vector();
		for (int i = 0; i < binDirs.length; i++) {
			packageDir = binDirs[i] + File.separator + packageDir;
			File dir = new File(packageDir);
			classes.addAll(extractClasses(packageName, dir));
			if (dir.isDirectory()) {
				File[] sub = dir.listFiles();
				for (int j = 0; j < sub.length; j++) {
					if (sub[j].isDirectory()) {
						Class[] rec = getAllRecursive(packageName + "."
								+ sub[j].getName());
						Vector temp = new Vector(rec.length);
						for (int k = 0; k < rec.length; k++) {
							temp.add(rec[k]);
						}
						classes.addAll(temp);
					}
				}
			}
		}
		Class[] result = new Class[classes.size()];
		classes.copyInto(result);
		return result;
	}
}

Vielleicht sollte an dieser Stelle noch bemerkt werden, dass ein solches Vorgehen wohl überlegt sein soll, denn nur mit diesen Informationen ist es nicht nicht möglich, die Methode auszuführen, den dazu wird noch ein Objekt benötigt, auf welchem die Methode ausgeführt werden kann und wenn man dieses hat, kann man sich den Umweg über den Classpath sparen.

Mehrfachvererbung in Java

Im allgemeinen ist wahrscheinlich so, dass das Unterbinden von Mehrfachvererbung eher ein Segen als ein Fluch ist. Doch wie immer gibt es auch hier Fälle, wo dies unumgänglich ist. Dabei müchte ich nicht auf die Gründe eingehen. Es sei lediglich der Hinweis erlaubt: Es ist in jedem Fall weniger aufwändig, ohne Mehrfachvererbung aus zukommen. Somit ist der Aspekt ob Mehrfachvererbung tatsächlich notwendig ist zu überprüfen. Wie der Umstand von Single Inheritance umgangen werden kann soll hier am Beispiel der Programmiersprache Java erläutert werden.

  1. Beide Klassen, die Abzuleiten sind liegen im eigenen Namensraum, d.h. beide Klassen gehören zum selben Projekt wie die zu erstellende Ableitung. Hier wählt man eine Klasse aus von der man ableitet. Von der anderen Klasse erstellt man ein Interface, das man implementiert. Dieses vorgehen legt nahe, dass man für das Interface die Klasse mit weniger Implementationsaufwand verwendet. Wenn möglich sollte hier auch die erwartete API Stabilität einfliessen. D.h. eine Klasse deren API, oder zu einem geringeren Grad die Implementation, noch ändern kann sollte wo möglich nicht als Interface verwendet werden, da hier aufgrund der Anpassung der Klasse, das Interface und dann die „abgeleitete“ Klasse angepasst werden muss.
  2. Ähnlicher Fall wie oben, nur dass hier die eine Klasse ausserhalb des Projekts liegt. Liegt diese Klasse jedoch noch innerhalb des eigenen Einflussbereichs, z.B. anderes Projekt des Teams, so kann selbes vorgehen wie oben angewandt werden; andernfalls ist die externe Klasse prädestiniert für ein Interface zumal hier davon ausgegangen werden kann, dass die API stabil ist.
  3. Beide Klassen liegen Ausserhalb des Einflussbereichs. Eine der beiden Klassen implementiert ein Interface, das die essentiellen Methoden enthält. In diesem Fall kann dieses Interface implementiert werden und die andere Klasse implementiert werden.
  4. Trifft keiner der obigen Punkte zu so muss eine komplexere Lösung gefunden werden. Komplexer ist sie weil sie mehr Aufwand bedeutet, aber auch weil sie einer echten Mehrfachvererbung am nächsten kommt: Man wählt den Ansatz, dass man eine der beiden Klassen ableitet und von der anderen eine Reimplementation vornimmt. Handelt es sich hierbei um eine Klasse von Sun, so kann sie dem src.zip entnommen werden. Zum Beispiel:
    public class ObservableThread extends Thread {
        private boolean changed = false;
        private Vector obs;
        public ObservableThread() {
    	obs = new Vector();
        }
        public synchronized void addObserver(Observer o) {
            if (o == null)
                throw new NullPointerException();
    	if (!obs.contains(o)) {
    	    obs.addElement(o);
    	}
        }
        public synchronized void deleteObserver(Observer o) {
            obs.removeElement(o);
        }
        public void notifyObservers() {
    	notifyObservers(null);
        }
       public void notifyObservers(Object arg) {
            Object[] arrLocal;
    
    	synchronized (this) {
    	    if (!changed)
                    return;
                arrLocal = obs.toArray();
                clearChanged();
            }
    
            for (int i = arrLocal.length-1; i>=0; i--)
                ((Observer)arrLocal[i]).update(new HiddenObservable(this), arg);
        }
        public synchronized void deleteObservers() {
    	obs.removeAllElements();
        }
        protected synchronized void setChanged() {
    	changed = true;
        }
        protected synchronized void clearChanged() {
    	changed = false;
        }
        public synchronized boolean hasChanged() {
    	return changed;
        }
        public synchronized int countObservers() {
    	return obs.size();
        }
    

    Hierbei handelt es sich jedoch noch nicht um eine echte Mehrfachvererbung. In vielen Fällen sollte dies jedoch schon genügen. Wo nicht kann der Mehrfachvererbung mehr Authentizität verliehen werden indem von der ursprünglichen Klasse die reimplementiert wird ein Interface gebildet wird und dieses implementiert wird. Nun hat die Klasse beide Typen (Thread und Observable). Eine andere oder weitere Möglichkeit – insbesondere wenn this semantisch mit der ursprünglichen Klasse verwendet wird – besteht darin eine versteckte Inner Class zu bilden, die die reimplementierte Klasse ableitet und alle Methoden, die von dieser Klasse geerbt werden, überschreibt. Die Implementation der Methoden reicht die Ausführung an die selbe Methode in der äusseren Klasse weiter:

        private class HiddenObservable extends Observable{
        	        private ObservableThread ot;
         	        public HiddenObservable(ObservableThread obersevable){
        		       ot = obersevable;
        	        }
    		public synchronized void addObserver(Observer o) {
    			ot.addObserver(o);
    		}
    		protected synchronized void clearChanged() {
    			ot.clearChanged();
    		}
    		public synchronized int countObservers() {
    			return ot.countObservers();
    		}
    		public synchronized void deleteObserver(Observer o) {
    			ot.deleteObserver(o);
    		}
    		public synchronized void deleteObservers() {
    			ot.deleteObservers();
    		}
    		public synchronized boolean hasChanged() {
    			return ot.hasChanged();
    		}
    		public void notifyObservers() {
    			ot.notifyObservers();
    		}
    		public void notifyObservers(Object arg) {
    			ot.notifyObservers(arg);
    		}
    		protected synchronized void setChanged() {
    			ot.setChanged();
    		}
        }
    

    Zu beachten: Dies ist nötig, da im ersten Code-Teil (bereits angepasst) ein Aufruf mit this gemacht wird und this nun mal vom Typ Observable und nicht vom Typ Thread oder ObservableThread ist.
    Einziger Nachteil dieser Lösung: instanceof Observable wird immer false zurückgeben. Solange diese Abfrage jedoch im eigenen Code ist, spielt dies keine weitere Rolle.

Reflecting on Java

Oft kommt man in die Verlegenheit, dass man eine Methode aufrufen möchte, deren Signatur oder Klasse man nicht kennt oder die private ist. Grund dafür ist meistens, dass zum Zeitpunkt der Implementierung die relevante Klasse nicht bekannt ist oder die Aufgabe abhängig von verschiedenen Faktoren durch unterschiedliche Klassen erledigt werden muss. Solche und ähnliche Probleme lassen sich mit dem Package java.lang.reflect lösen. Doch hier nun zuerst ein Listing der Klasse, über die wir reflektieren wollen. Often you wish to call a method and you don’t know the exact signature or class or the method might altogether be private, so you’re stuck. Such may occure when the implementing class isn’t known on implementation time or the task may be done by different classes with respect on many factors. Such and similar problems can be solved with the package java.lang.reflect. But first let’s look at te listing of the class on which we will be reflecting:
1:  public class ReflectionTest {
2:     public int someNumber = 42;
3:     private String hiddenWords = "Hello world";
4: 
5:     public ReflectionTest(int number, String s){ ... }
6:     public ReflectionTest(int number){ ... }
7: 
8:    public int getAnyNumber(){ ... }
9:    public int getAnyNumber(int someInput){ ... }
10:   private void doSomethingSecret() throws Exception { ... }
11:   public static Class getThisClassName() { ... }
12: }

Inspecting the class

Als Erstes brauchen wir ein Klassen Objekt (Class). Ein solches kann man auf verschiedene Weisen erhalten:

  • Wenn man ein Objekt der Klasse hat, liefert die Methode getClass() das gewünsche Objekt.
  • Wenn die Klasse bekannt ist, kann das Class-Objekt durch anhängen von .class erstellt werden ReflectionTest.class. Wenn die Klasse importiert wurde oder full.package.path.ReflectionTest.class
  • Wenn man den Namen der Klasse kennt, da er z.B. als Argument übergeben wird, kann mit Class.forName ("full.package. path.ReflectionTest")auf ein Class Objekt zugegriffenwerden. Wenn die Klasse nicht gefunden werden kann, wird eine ClassNotFoundException geworfen. Häufig ist die Ursache ein falscher Pfad. Die Klasse muss im Classpath des Programms enthalten sein.
First we need a class object (Class). There are several ways to achieve that:

  • If you have already an object of the class you can get the class object by calling getClass()
  • If the class is known an class object can be obtained by appending .class: ReflectionTest.class if the class is in the imports or full.package. path.ReflectionTest.class otherwise.
  • If the name of the class is known, e.g. supplemented by argument, you can get the class object with Class.forName ("full.package. path.ReflectionTest") When the class cannot be found a ClassNotFoundException is thrown. The cause is often a wrong path. The class has to be in the classpath of the program.
Eine Klasse, wie unser Beispiel, kann Felder oder Variablen besitzen. Es gibt 4 Methoden um Informationen über die Felder zu erhalten. getField und getFields liefern nur öffentliche Felder, die nicht Arrays sind. getDeclaredField und getDeclaredFields liefert die definierten Felder, also insbesondere die nicht öffentlichen. A class as in our example can contain fields or variables. There are 4 methods to retrive information on these fields. getField and getFields can provide all public fields that are not arrays. getDeclaredField and getDeclaredFields provide all difined fields in particular non public fields.


Field f1 = c.getField("someNumber");
// Instance of the field 'someNumber'
Field[] f2 = c.getFields();
// Array of instances of field. It contains one element:
// 'someNumber'
Field f3 = c.getDeclaredField("hiddenWords");
// Instance of the field 'hiddenWords'
Field[] f4 = c.getDeclaredFields();
// Array of instances of field. It contains two elements
// 'someNumber' and 'hiddenWords'

Zum Ermitteln der Construktoren und Methoden gibt es analoge Methoden. Bei den Methoden

  • getDeclaredConstructor
  • getConstructor
  • getDeclaredMethod
  • getMethod

wird neben dem Namen des Konstruktors/Methode ein Array von Class Objekten übergeben. Diese geben die Typen der Argumente wieder. Wichtig ist zu beachten, dass int.class und Integer.class nicht denselben Typ repräsentieren.

To retrive Construktors and Methods there are similar methods. In the methods

  • getDeclaredConstructor
  • getConstructor
  • getDeclaredMethod
  • getMethod

the second argument is an array of Class objects indicating the types of the arguments. Its imortant to realise that int.class and Integer.class are not of the same type.

Method Call

Hat man die Methode die man aufrufen möchte gefunden, so kann man diese über invoke aufrufen. Wenn die Methode nicht static, ist muss erst ein Objekt aufgetrieben werden, auf dem die Methode aufgerufen wird. Ist für die Klasse ein Default Konstruktor (Konstruktor ohne Argumente) definiert, so kann ein Objekt über c.newInstance() erstellt werden, wobei c das Class Objekt ist.
Hat die Methode einen Return Type, so wird dieser zurückgegeben. Handelt es sich um einen primitiven Typ, wird ein entsprechender Wrapper zurückgegeben (Boxing).
Für Konstruktoren ist es etwas einfacher, da diese immer static sind. Somit kann über newInstance ein neues Objekt erzeugt werden.
Sowohl newInstance als auch invoke haben als letztes Argument ein Objekt-Array in dem die Parameter für den Konstruktor/Methodenaufruf enthalten sind.
Is the method which should be called found, it can be executed with a call of invoke. If the method is static you need an object on which the method can be executed. If a default constructor (constructor with no arguments) is defined on the class, an object can be obtained by c.newInstance() where c is the Class Object.
When the method has a return type it is returned. If the return type is a primitive type it is wrapped accordingly (boxing)
Constructors are somewhat easier to handle because they are always static. Therefore a new object can be obtaind by invoking newInstance
In both methods (newInstance and invoke) the last argument is an object array that contains the arguments for the call.
Class[] types = {int.class};
Constructor con = c.getConstructor(types);
Object[] args = {42};
Object o = con.newInstance(args);
ReflectionTest o2 = (ReflectionTest) c.newInstance();
// Causes InstantiationException because no default
// constructor is defined
Method m = c.getMethod("getAnyNumber", types);
o = m.invoke(o, args);
// o is of type Integer
Class[] types2 = {};
Object[] args2 = {};
Method m2 = c.getMethod("getThisClassName", types2);
// 'getThisClassName' is a static method
m2.invoke(null, args2);

Private access

Richtig nützlich werden solche Mechanismen, wenn nicht öffentliche Methoden aufgerufen werden müssen. Dies ist oft der Fall, wenn ein Unit Test geschrieben wird: Ohne diese Methoden können nur öffentliche Methoden getestet werden. Um protected Methoden zu testen, muss die Testklasse eine Ableitung sein. Package-Private Methoden können nur getestet werden, wenn die Testklasse im selben Package ist. Private Klassen können nur getestet werden, wenn die Testklasse eine Innere Klasse ist.
Es gibt genügend Gründe, Methoden in einem objektorientierten Design nicht nach aussen sichtbar zu machen. Auf der anderen Seite sind solche Methoden meistens Bausteine von anderen Methoden. Tests sollten bei der kleinsten Einheit beginnen, um sicher zu stellen, dass die Grundlagen korrekt sind auf denen die Funktionalität aufbaut.
Objekte des Typs Field, Method oder Constructor sind alle von AccessibleObject abgeleitet. In dieser Klasse ist die Methode setAccessible definiert, mit der die Sichtbarkeit zur Laufzeit auf public gesetzt wird.

Realy usful are these mechanism when you have to call non public methods. That is often the case when you write a unit test on a private method: without these mechanisms only public methods can be testet. Protected methods can be testet if the test class extends the tested class which isn’t good design. Package private methods can be tested if the test class is in the same package. Private methods can only be tested if the test class is an inner class.
In an object oriented design there are ample reasons not to make certain methods visible. Such private methodes are used by other more complex methods. Tests should start with the smallest building block to ensure a correct basis on which more functionality is built.
Objects of type Field, Method or Constructor all extend AccessibleObject. There the method setAccessible is defined. It can be used to set the visibility of methods at runtime to public.
Method[] m3 = c.getMethods();
for (int i = 0; i < m3.length; i++) {
    if (m3[i].getName().equals("getThisClassName")){
        o = con.newInstance(args);
	m3[i].setAccessible(true);
	m3[i].invoke(o, args2);
    }
}
Der Source-Code der Klasse über die reflektiert wird und der Beisiel-Code ist verfügbar. The source code of the reflected class and the reflecting class are available.