Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
xapi.dev.gwtc.impl.GwtcContext Maven / Gradle / Ivy
Go to download
Everything needed to run a comprehensive dev environment.
Just type X_ and pick a service from autocomplete;
new dev modules will be added as they are built.
The only dev service not included in the uber jar is xapi-dev-maven,
as it includes all runtime dependencies of maven, adding ~4 seconds to build time,
and 6 megabytes to the final output jar size (without xapi-dev-maven, it's ~1MB).
package xapi.dev.gwtc.impl;
import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import javax.inject.Provider;
import xapi.annotation.compile.Dependency;
import xapi.annotation.compile.Resource;
import xapi.annotation.ui.UiTemplateBuilder;
import xapi.bytecode.ClassFile;
import xapi.collect.api.InitMap;
import xapi.collect.impl.InitMapDefault;
import xapi.dev.gwtc.api.GwtcService;
import xapi.dev.scanner.X_Scanner;
import xapi.dev.scanner.impl.ClasspathResourceMap;
import xapi.dev.source.XmlBuffer;
import xapi.gwtc.api.Gwtc;
import xapi.gwtc.api.Gwtc.AncestorMode;
import xapi.gwtc.api.GwtcProperties;
import xapi.inject.impl.SingletonProvider;
import xapi.log.X_Log;
import xapi.util.X_Debug;
import xapi.util.X_String;
import xapi.util.api.ConvertsValue;
import xapi.util.api.ReceivesValue;
import com.google.gwt.reflect.shared.GwtReflect;
import com.google.gwt.reflect.shared.GwtReflectJre;
@SuppressWarnings({"unchecked", "rawtypes", "unused"})
public class GwtcContext {
private static final ConvertsValue LIST_PROVIDER = new ConvertsValue() {
@Override
public Object convert(Object from) {
return new ArrayList();
}
};
private static final ConvertsValue PACKAGE_NAME =
new ConvertsValue() {
@Override
public String convert(Package from) {
return from.getName();
}
};
private static final ConvertsValue ENTITY_NAME =
new ConvertsValue() {
@Override
public String convert(Object from) {
if (from instanceof Class) {
return ((Class) from).getName();
} else if (from instanceof Method) {
return ((Method) from).toGenericString();
} else if (from instanceof Package) {
return ((Package) from).getName();
} else {
X_Log.warn(getClass(), "Unsupported toString object type",
from == null ? "null" : from.getClass(), from);
return String.valueOf(from);
}
}
};
public class GwtcConverter implements ConvertsValue {
@Override
public GwtcUnit convert(Object from) {
if (from instanceof Class) {
return newGwtcData((Class) from);
} else if (from instanceof Method) {
return newGwtcData((Method) from);
} else if (from instanceof Package) {
return newGwtcData((Package) from);
} else {
X_Log.warn(getClass(), "Unsupported toString object type", from == null ? "null" : from
.getClass(), from);
}
return null;
}
protected GwtcUnit newGwtcData(Class from) {
return new GwtcUnit(from);
}
protected GwtcUnit newGwtcData(Package from) {
return new GwtcUnit(from);
}
protected GwtcUnit newGwtcData(Method from) {
return new GwtcUnit(from);
}
}
protected static class GwtcUnit {
private final GwtcUnitType type;
public GwtcUnit(Class from) {
gwtc = from.getAnnotation(Gwtc.class);
source = from;
type = GwtcUnitType.Class;
}
public GwtcUnit(Method from) {
gwtc = from.getAnnotation(Gwtc.class);
source = from;
type = GwtcUnitType.Method;
}
public GwtcUnit(Package from) {
gwtc = from.getAnnotation(Gwtc.class);
source = from;
type = GwtcUnitType.Package;
}
protected final Gwtc gwtc;
protected GwtcXmlBuilder xml;
protected UiTemplateBuilder html;
protected final List packages = new ArrayList();
protected final List> classes = new ArrayList>();
public final Object source;
private GwtcUnit parent;
private Set children = new LinkedHashSet();
public String generateGwtXml(Gwtc gwtc, String pkg, String name) {
xml = GwtcXmlBuilder.generateGwtXml(gwtc, pkg, name);
return xml.getInheritName();
}
public boolean isFindAllParents() {
for (AncestorMode mode : gwtc.inheritanceMode()) {
if (mode == AncestorMode.INHERIT_ALL_PARENTS) {
return true;
}
}
return false;
}
@SuppressWarnings("incomplete-switch")
public boolean isFindParent() {
for (AncestorMode mode : gwtc.inheritanceMode()) {
switch (mode){
case INHERIT_ALL_PARENTS:
case INHERIT_ONE_PARENT:
return true;
}
}
return false;
}
public boolean isFindChild() {
for (AncestorMode mode : gwtc.inheritanceMode()) {
if (mode == AncestorMode.INHERIT_CHILDREN) {
return true;
}
}
return false;
}
public boolean isFindEnclosingClasses() {
for (AncestorMode mode : gwtc.inheritanceMode()) {
if (mode == AncestorMode.INHERIT_ENCLOSING_CLASSES) {
return true;
}
}
return false;
}
public boolean isFindSuperClasses() {
for (AncestorMode mode : gwtc.inheritanceMode()) {
if (mode == AncestorMode.INHERIT_SUPER_CLASSES) {
return true;
}
}
return false;
}
public void setParent(GwtcUnit parentNode) {
parent = parentNode;
parent.children.add(this);
}
/**
* Finds the next parent element annotated with @Gwtc.
*
* This method should NOT be used to recurse parent hierarchy;
* instead use {@link #getParents()}
*
* @return the next parent with @Gwtc, if there is one.
*/
public Object getParent() {
if (!isFindParent()) {
return null;
}
final boolean findAll = isFindAllParents();
Object o = source;
Class c;
switch(type) {
case Method:
if (!isFindEnclosingClasses()) {
return null;
}
o = c = ((Method)o).getDeclaringClass();
if (c.isAnnotationPresent(Gwtc.class)) {
return c;
} else if (!findAll) {
return null;
}
// fallthrough
case Class:
c = (Class)o;
if (isFindEnclosingClasses()) {
Class search = c;
while (!isObjectOrNull(search.getDeclaringClass())) {
search = search.getDeclaringClass();
if (search.isAnnotationPresent(Gwtc.class)) {
return search;
}
if (!findAll) {
break;
}
}
}
if (isFindSuperClasses()) {
Class search = c;
while (!isObjectOrNull(search.getSuperclass())) {
search = search.getSuperclass();
if (search.isAnnotationPresent(Gwtc.class)) {
return search;
}
if (!findAll) {
break;
}
}
}
o = c.getPackage();
// fallthrough
case Package:
Package p = (Package) o;
String pkg = p.getName();
if ("".equals(pkg)) {
return null;
}
do {
pkg = X_String.chopOrReturnEmpty(pkg, ".");
p = GwtReflect.getPackage(pkg);
if (p != null) {
if (p.isAnnotationPresent(Gwtc.class)) {
return p;
}
if (!findAll) {
return null;
}
}
} while (pkg.length() > 0);
}
return null;
}
public void addChild(GwtcUnit data) {
children.add(data);
assert data.parent == null || data.parent == this :
"GwtcUnit "+data+" already has a parent; "+ data.parent+
"; cannot set "+this+" as new parent.";
data.parent = this;
}
@Override
public String toString() {
return "GwtcUnit "+source+" "+type;
}
public Iterable getChildren() {
return children;
}
public GwtcUnitType getType() {
return type;
}
}
// =====================================================
// ==Store the structure of related classpath entities==
// =====================================================
private final InitMap, List> methods =
new InitMapDefault, List>(InitMapDefault.CLASS_NAME, LIST_PROVIDER);
private final InitMap, List>> innerClasses =
new InitMapDefault, List>>(InitMapDefault.CLASS_NAME, LIST_PROVIDER);
private final InitMap, List>> superClasses =
new InitMapDefault, List>>(InitMapDefault.CLASS_NAME, LIST_PROVIDER);
private final InitMap>> classes =
new InitMapDefault>>(PACKAGE_NAME, LIST_PROVIDER);
private final InitMap> packages =
new InitMapDefault>(PACKAGE_NAME, LIST_PROVIDER);
private final InitMap nodes = new InitMapDefault(ENTITY_NAME, new GwtcConverter());
// =====================================================
// ==Store sets of all entities for run-once semantics==
// =====================================================
private final Set finishedMethods = new HashSet();
private final Set> finishedClasses = new HashSet>();
private final Set finishedPackages = new HashSet();
// =====================================================
// =====================================================
// =====================================================
private final GwtcXmlBuilder module;
private final Set dependencies = new LinkedHashSet();
private final Set gwtXmlDeps = new LinkedHashSet();
private final Set launchProperties = new LinkedHashSet();
private final Set needChildren = new HashSet();
// =====================================================
// ===Scan the classpath while looking added entities===
// =====================================================
private final Provider classpath;
private final GwtcService gwtcService;
public GwtcContext(GwtcService gwtcService, ClassLoader resourceLoader) {
this.gwtcService = gwtcService;
// Start scanning the classpath, but don't block until we need to.
final Callable scanner = X_Scanner.scanClassloaderAsync(resourceLoader);
classpath = new SingletonProvider() {
@Override
protected ClasspathResourceMap initialValue() {
try {
return scanner.call();
} catch (Exception e) {
throw X_Debug.rethrow(e);
}
}
};
String genName = "Gwtc" + Math.abs(hashCode() - System.nanoTime());
module = new GwtcXmlBuilder("", genName, false);
module.addConfigurationProperty("xsiframe.failIfScriptTag", "FALSE");
module.setPublic("public");
}
public static boolean isObjectOrNull(Class cls) {
return cls == Object.class || cls == null;
}
public boolean addClass(Class cls) {
if (finishedClasses.add(cls)) {
scanClass(cls);
return true;
} else {
X_Log.warn(getClass(), "Skipping class we've already seen", cls);
}
return false;
}
public boolean addMethod(Method method) {
if (finishedMethods.add(method)) {
scanMethod(method);
return true;
} else {
X_Log.warn(getClass(), "Skipping method we've already seen", method);
return false;
}
}
public boolean addPackage(Package pkg) {
if (finishedPackages.add(pkg)) {
scanPackage(pkg);
return true;
} else {
X_Log.trace(getClass(), "Skipping package we've already seen", pkg);
return false;
}
}
private void scanClass(Class clazz) {
GwtcUnit data = nodes.get(clazz);
if (data == null) {
Object ancestor = findAncestor(clazz);
return;
} if (data.gwtc == null) {
return;
}
gwtcService.addClass(clazz);
Object parent;
if (data.isFindParent()) {
parent = findAncestor(data.source);
if (parent != null) {
GwtcUnit parentNode = nodes.get(parent);
data.setParent(parentNode);
if (data.isFindAllParents()) {
while (parent != null) {
Object ancestor = findAncestor(parent);
if (ancestor == null) {
break;
} else {
GwtcUnit ancestorNode = nodes.get(ancestor);
parentNode.setParent(ancestorNode);
parent = ancestor;
parentNode = ancestorNode;
}
}
}
}
}
Gwtc gwtc = clazz.getAnnotation(Gwtc.class);
Class c;
parent = c = clazz;
if (gwtc == null) {
while (c != Object.class) {
gwtc = c.getAnnotation(Gwtc.class);
if (gwtc != null) {
parent = c;
maybeAddAncestors(gwtc, c);
break;
}
c = c.getSuperclass();
}
Package pkg;
parent = pkg = clazz.getPackage();
if (gwtc == null) {
gwtc = pkg.getAnnotation(Gwtc.class);
String parentName = pkg.getName();
search : while (gwtc == null) {
int ind = parentName.lastIndexOf('.');
if (ind == -1) {
break;
}
parentName = parentName.substring(0, ind);
pkg = GwtReflect.getPackage(parentName);
while (pkg == null) {
ind = parentName.lastIndexOf('.');
if (ind == -1) {
X_Log.warn("No package found for ", clazz.getPackage(), "; aborting @Gwtc search");
break search;
}
parentName = parentName.substring(0, ind);
pkg = GwtReflect.getPackage(parentName);
}
gwtc = pkg.getAnnotation(Gwtc.class);
}
if (gwtc != null) {
parent = pkg;
maybeAddAncestors(gwtc, pkg);
}
} else {
maybeAddAncestors(gwtc, pkg);
}
} else {
maybeAddAncestors(gwtc, c);
inherit(data);
}
if (parent != null) {
X_Log.trace(getClass(), "Next annotated parent of ",c,"is",parent);
}
}
protected void inherit(GwtcUnit data) {
if (data.isFindAllParents()) {
} else if (data.isFindParent()) {
Object o = data.getParent();
}
}
private void scanMethod(Method method) {
}
private void scanPackage(Package pkg) {
GwtcUnit data = nodes.get(pkg);
if (data == null) {
Object ancestor = findAncestor(pkg);
if (ancestor != null) {
addPackage((Package)ancestor);
}
return;
} else if (data.gwtc == null) {
return;
}
Gwtc gwtc = pkg.getAnnotation(Gwtc.class);
addGwtcPackage(gwtc, pkg, false);
X_Log.trace(getClass(), "Parent of ",pkg,"is",data.getParent());
ClassLoader cl = Thread.currentThread().getContextClassLoader();
for (ClassFile file : classpath.get().findClassesInPackage(pkg.getName())) {
X_Log.trace(getClass(), "Checking class file ", file.getName());
try {
if (file.getEnclosedName().equals("package-info")) {
X_Log.info(getClass(), "Loading package", file);
Package p = GwtReflectJre.getPackage(file.getPackage(), cl);
if (!finishedPackages.contains(p)) {
gwtcService.addPackage(p, false);
}
} else {
Class clazz = cl.loadClass(file.getName());
X_Log.trace(getClass(), "Loaded class", clazz);
if (!finishedClasses.contains(clazz)) {
X_Log.info(getClass(), "Adding class", clazz);
gwtcService.addClass(clazz);
}
}
} catch (Exception e) {
X_Log.warn(getClass(), "Error encountered trying to load class ", file.getName(), e);
}
}
}
public void saveTo(File file, String renameTo) {
boolean absoluteFile = renameTo.endsWith(".gwt.xml");
if (absoluteFile) {
renameTo = renameTo.substring(0, renameTo.length() - 8);
}
boolean rename = !renameTo.replace('/', '.').equals(module.getInheritName());
final String inheritName;
if (rename) {
final String pkg, name;
int ind = renameTo.lastIndexOf('.');
boolean moveToPackage = ind > -1;
if (moveToPackage) {
pkg = renameTo.substring(0, ind).replace('.', '/');
name = renameTo.substring(ind + 1);
} else {
pkg = "";
name = renameTo;
}
if (pkg.length() == 0) {
inheritName = name;
} else {
if (file.isDirectory()) {
File f = new File(file, pkg);
f.mkdirs();
f.deleteOnExit();
file = f;
}
inheritName = pkg + (pkg.length() == 0 ? "" : ".") + name;
}
} else {
inheritName = renameTo;
}
}
public void saveTo(File file) {
saveTo(file, module.getInheritName());
}
public void inheritGwtXml(String inherit) {
module.inherit(inherit);
}
public String getGenName() {
return module.getInheritName();
}
public void setEntryPoint(String qualifiedName) {
module.setEntryPoint(qualifiedName);
}
public void addGwtXmlSource(String genPrefix) {
module.addSource(genPrefix);
}
public void addGwtXmlInherit(String value) {
module.addInherit(value);
}
public XmlBuffer getGwtXml() {
return module.getBuffer();
}
public void setRenameTo(String renameTo) {
module.setRenameTo(renameTo);
}
public void addEnclosingClasses(Class c) {
c = c.getDeclaringClass();
while (c != null) {
Gwtc gwtc = c.getAnnotation(Gwtc.class);
if (gwtc != null && addClass(c)) {
addGwtcClass(gwtc, c);
}
c = c.getDeclaringClass();
}
}
public void addSuperclasses(Class c) {
c = c.getSuperclass();
while (c != null) {
Gwtc gwtc = c.getAnnotation(Gwtc.class);
if (gwtc != null && addClass(c)) {
addGwtcClass(gwtc, c);
}
c = c.getSuperclass();
}
}
protected void addGwtcSettings(Gwtc gwtc) {
for (Dependency dep : gwtc.dependencies()) {
addDependency(dep);
}
for (GwtcProperties prop : gwtc.propertiesLaunch()) {
addLaunchProperty(prop);
}
}
public boolean addLaunchProperty(GwtcProperties prop) {
return launchProperties.add(prop);
}
public boolean addDependency(Dependency dep) {
return dependencies.add(dep);
}
public Iterable getLaunchProperties() {
return launchProperties;
}
public Iterable getDependencies() {
return dependencies;
}
protected void addGwtcClass(Gwtc gwtc, Class clazz) {
// Generate a new gwt.xml file and inherit it.
GwtcUnit node = nodes.get(clazz);
String inheritName = node.generateGwtXml(gwtc, clazz.getPackage().getName(), clazz.getSimpleName());
inheritGwtXml(inheritName);
addGwtcSettings(gwtc);
}
protected void addGwtcPackage(Gwtc gwtc, Package pkg, boolean recursive) {
String name = pkg.getName();
int i = name.lastIndexOf('.');
name = Character.toUpperCase(name.charAt(i + 1)) + name.substring(i + 2) + "_Package";
GwtcUnit node = nodes.get(pkg);
String inherit = node.generateGwtXml(gwtc, pkg.getName(), name);
inheritGwtXml(inherit);
addGwtcSettings(gwtc);
maybeAddAncestors(gwtc, pkg);
if (recursive) {
needChildren.add(pkg);
}
}
protected void addAllPackages(Package pkg) {
Gwtc gwtc = pkg.getAnnotation(Gwtc.class);
if (gwtc != null && addPackage(pkg)) {
addGwtcPackage(gwtc, pkg, false);
}
String parentName = pkg.getName();
int ind = parentName.lastIndexOf('.');
while (ind > -1) {
parentName = parentName.substring(0, ind);
ind = parentName.lastIndexOf('.');
pkg = GwtReflect.getPackage(parentName);
X_Log.debug(getClass(), "Checking parent package", "'"+parentName+"'", pkg != null);
if (pkg != null) {
gwtc = pkg.getAnnotation(Gwtc.class);
if (gwtc != null && addPackage(pkg)) {
addGwtcPackage(gwtc, pkg, false);
}
}
}
pkg = GwtReflect.getPackage("");
if (pkg != null) {
gwtc = pkg.getAnnotation(Gwtc.class);
if (gwtc != null && addPackage(pkg)) {
addGwtcPackage(gwtc, pkg, false);
}
}
}
protected void maybeAddAncestors(Gwtc gwtc, Package pkg) {
for (AncestorMode mode : gwtc.inheritanceMode()) {
switch (mode) {
case INHERIT_ONE_PARENT:
if (addPackage(pkg)) {
addGwtcPackage(gwtc, pkg, false);
}
break;
case INHERIT_ALL_PARENTS:
addAllPackages(pkg);
break;
case INHERIT_CHILDREN:
needChildren.add(pkg);
default:
X_Log.trace("Unsupported ancestor mode", mode, "for package", pkg, "from", "\n" + gwtc);
}
}
}
protected void maybeAddAncestors(Gwtc gwtc, Class c) {
addGwtcClass(gwtc, c);
for (AncestorMode mode : gwtc.inheritanceMode()) {
switch (mode) {
case INHERIT_ONE_PARENT:
Package pkg = c.getPackage();
gwtc = pkg.getAnnotation(Gwtc.class);
if (gwtc != null && addPackage(pkg)) {
addGwtcPackage(gwtc, pkg, false);
}
break;
case INHERIT_ALL_PARENTS:
addAllPackages(c.getPackage());
break;
case INHERIT_ENCLOSING_CLASSES:
addEnclosingClasses(c);
break;
case INHERIT_SUPER_CLASSES:
addSuperclasses(c);
break;
default:
X_Log.warn("Unsupported mode type", mode, "for class", c);
}
}
}
private Object findAncestor(Object o) {
if (o instanceof Method) {
Method m = (Method)o;
if (m.getDeclaringClass().isAnnotationPresent(Gwtc.class)) {
return m.getDeclaringClass();
}
o = m.getDeclaringClass();
}
if (o instanceof Class) {
return findAncestor((Class)o);
} else if (o instanceof Package) {
return findAncestor((Package)o);
} else {
X_Log.error(getClass(), "Unsupported object type found while searching for ancestors", o, o.getClass());
throw new IllegalArgumentException("Object "+o+" is not a method, class or package.");
}
}
private Object findAncestor(Class clazz) {
// First check enclosing classes
Class c = clazz.getDeclaringClass();
while (c != null) {
if (c.isAnnotationPresent(Gwtc.class)) {
return c;
}
c = c.getDeclaringClass();
}
Package p = clazz.getPackage();
if (p.getAnnotation(Gwtc.class) != null) {
return p;
}
Object o = findAncestor(p);
if (o == null) {
c = clazz.getSuperclass();
while (c != null) {
if (c.isAnnotationPresent(Gwtc.class)) {
return c;
}
c = c.getSuperclass();
}
}
return o;
}
private Object findAncestor(Package p) {
String name = p.getName();
int ind = name.lastIndexOf('.');
while (ind > -1) {
name = name.substring(0, ind);
p = GwtReflect.getPackage(name);
if (p != null && p.isAnnotationPresent(Gwtc.class)) {
return p;
}
ind = name.lastIndexOf('.');
}
p = GwtReflect.getPackage("");
return p == null || !p.isAnnotationPresent(Gwtc.class) ? null : p;
}
public void generateAll(final File dir, String moduleName, XmlBuffer head, XmlBuffer body) {
X_Log.info(getClass(), "Generating all resources into ",dir);
final HashSet topLevel = new HashSet();
nodes.forKeys(new ReceivesValue() {
@Override
public void set(String value) {
GwtcUnit node = nodes.getValue(value);
if (node.xml != null) {
X_Log.info(getClass(), "Generating gwt.xml for ",node.source,"to",dir);
node.xml.save(dir);
}
if (node.parent == null) {
topLevel.add(node);
}
}
});
// When generating ui templates, we simply descend from all top-level @Gwtc
for (GwtcUnit root : topLevel) {
if (root.gwtc != null) {
UiTemplateGenerator gen = new UiTemplateGenerator(root);
gen.generate(head, body);
}
}
}
public void addPackages(Package pkg, GwtcServiceImpl gwtc, boolean recursive) {
Iterable iter;
if (recursive) {
iter = classpath.get().findClassesBelowPackage(pkg.getName());
} else {
iter = classpath.get().findClassesInPackage(pkg.getName());
}
for (ClassFile file : iter) {
X_Log.info(getClass(), "Scanning file ",file);
if ("package-info".equals(file.getEnclosedName())) {
Package p = GwtReflect.getPackage(file.getPackage());
if (!finishedPackages.contains(p)) {
gwtcService.addPackage(p, false);
}
} else {
try {
Class cls = Thread.currentThread().getContextClassLoader().loadClass(file.getName());
if (!finishedClasses.contains(cls)) {
gwtc.addClass(cls);
}
} catch (ClassNotFoundException e) {
X_Log.warn(getClass(),"Unable to load class ",file);
}
}
}
}
}