package com.vaadin.tests;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.net.JarURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import com.vaadin.server.VaadinSession;
import com.vaadin.ui.Component;
import com.vaadin.ui.ComponentContainer;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.DragAndDropWrapper;
import com.vaadin.ui.HorizontalSplitPanel;
import com.vaadin.ui.LoginForm;
import com.vaadin.ui.PopupView;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalSplitPanel;
import com.vaadin.ui.Window;
@SuppressWarnings("deprecation")
public class VaadinClasses {
public static List<Class<? extends Component>> getComponents() {
try {
return findClasses(Component.class, "com.vaadin.ui");
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public static List<Class<? extends ComponentContainer>> getComponentContainers() {
try {
return findClasses(ComponentContainer.class, "com.vaadin.ui");
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public static List<Class<? extends ComponentContainer>> getComponentContainersSupportingAddRemoveComponent() {
List<Class<? extends ComponentContainer>> classes = getComponentContainers();
classes.remove(PopupView.class);
classes.remove(CustomComponent.class);
classes.remove(DragAndDropWrapper.class);
classes.remove(CustomComponent.class);
classes.remove(LoginForm.class);
classes.remove(UI.class);
return classes;
}
public static List<Class<? extends ComponentContainer>> getComponentContainersSupportingUnlimitedNumberOfComponents() {
List<Class<? extends ComponentContainer>> classes = getComponentContainersSupportingAddRemoveComponent();
classes.remove(VerticalSplitPanel.class);
classes.remove(HorizontalSplitPanel.class);
classes.remove(Window.class);
return classes;
}
private static <T> List<Class<? extends T>> findClasses(Class<T> baseClass,
String basePackage) throws IOException {
return findClasses(baseClass, basePackage, new String[] {});
}
private static <T> List<Class<? extends T>> findClasses(Class<T> baseClass,
String basePackage, String[] ignoredPackages) throws IOException {
List<Class<? extends T>> classes = new ArrayList<>();
String basePackageDirName = "/" + basePackage.replace('.', '/');
URL location = VaadinSession.class.getResource(basePackageDirName);
if (location.getProtocol().equals("file")) {
try {
File f = new File(location.toURI());
if (!f.exists()) {
throw new IOException(
"Directory " + f.toString() + " does not exist");
}
findPackages(f, basePackage, baseClass, classes,
ignoredPackages);
} catch (URISyntaxException e) {
throw new IOException(e.getMessage());
}
} else if (location.getProtocol().equals("jar")) {
JarURLConnection juc = (JarURLConnection) location.openConnection();
findPackages(juc, basePackage, baseClass, classes);
}
Collections.sort(classes, new Comparator<Class<? extends T>>() {
@Override
public int compare(Class<? extends T> o1, Class<? extends T> o2) {
return o1.getName().compareTo(o2.getName());
}
});
return classes;
}
private static <T> void findPackages(JarURLConnection juc,
String javaPackage, Class<T> baseClass,
Collection<Class<? extends T>> result) throws IOException {
String prefix = "com/vaadin/ui";
Enumeration<JarEntry> ent = juc.getJarFile().entries();
while (ent.hasMoreElements()) {
JarEntry e = ent.nextElement();
if (e.getName().endsWith(".class")
&& e.getName().startsWith(prefix)) {
String fullyQualifiedClassName = e.getName().replace('/', '.')
.replace(".class", "");
addClassIfMatches(result, fullyQualifiedClassName, baseClass);
}
}
}
private static <T> void findPackages(File parent, String javaPackage,
Class<T> baseClass, Collection<Class<? extends T>> result,
String[] ignoredPackages) {
for (String ignoredPackage : ignoredPackages) {
if (javaPackage.equals(ignoredPackage)) {
return;
}
}
for (File file : parent.listFiles()) {
if (file.isDirectory()) {
findPackages(file, javaPackage + "." + file.getName(),
baseClass, result, ignoredPackages);
} else if (file.getName().endsWith(".class")) {
String fullyQualifiedClassName = javaPackage + "."
+ file.getName().replace(".class", "");
addClassIfMatches(result, fullyQualifiedClassName, baseClass);
}
}
}
@SuppressWarnings("unchecked")
private static <T> void addClassIfMatches(
Collection<Class<? extends T>> result,
String fullyQualifiedClassName, Class<T> baseClass) {
try {
// Try to load the class
Class<?> c = Class.forName(fullyQualifiedClassName);
if (baseClass.isAssignableFrom(c)
&& !Modifier.isAbstract(c.getModifiers())
&& !c.isAnonymousClass() && !c.isMemberClass()
&& !c.isLocalClass()) {
result.add((Class<? extends T>) c);
}
} catch (Exception e) {
// Could ignore that class cannot be loaded
e.printStackTrace();
} catch (LinkageError e) {
// Ignore. Client side classes will at least throw LinkageErrors
}
}
}