private boolean acceptableType(String rtype) { TypeRef ref = analyzer.getTypeRefFromFQN(rtype); try { Clazz returnType = analyzer.findClass(ref); if (returnType.isEnum()) { return true; } // TODO check this is true for interfaces and annotations if (!returnType.isAbstract() || (returnType.isInterface() && options.contains(Options.nested))) { return true; } if (!returnType.isInterface()) { analyzer.error("Abstract classes not allowed as interface method return values: %s", rtype); } else { analyzer.error("Nested metatype only allowed with option: nested type %s", rtype); } return false; } catch (Exception e) { analyzer.error( "could not examine class for return type %s, exception message: %s", rtype, e.getMessage()); return false; } }
private void parseExtends(Clazz clazz) { TypeRef[] inherits = clazz.getInterfaces(); if (inherits != null) { if (analyzed == null) { analyzed = new HashSet<TypeRef>(); } for (TypeRef typeRef : inherits) { if (!typeRef.isJava() && analyzed.add(typeRef)) { try { Clazz inherit = analyzer.findClass(typeRef); if (inherit != null) { inherit.parseClassFileWithCollector(this); parseExtends(inherit); } else { analyzer.error( "Could not obtain super class %s of class %s", typeRef.getFQN(), clazz.getClassName().getFQN()); } } catch (Exception e) { analyzer.error( "Could not obtain super class %s of class %s; exception %s", typeRef.getFQN(), clazz.getClassName().getFQN(), e.getMessage()); } } } } }
private DesignateDef getDef() throws Exception { clazz.parseClassFileWithCollector(this); if (pid != null && designate != null) { if (pids != null && pids.length > 1) { analyzer.error( "DS Component %s specifies multiple pids %s, and a Designate which requires exactly one pid", clazz.getClassName().getFQN(), Arrays.asList(pids)); return null; } TypeRef ocdClass = designate.get("ocd"); // ocdClass = ocdClass.substring(1, ocdClass.length() - 1); OCDDef ocd = classToOCDMap.get(ocdClass); if (ocd == null) { analyzer.error( "DS Component %s specifies ocd class %s which cannot be found; known classes %s", clazz.getClassName().getFQN(), ocdClass, classToOCDMap.keySet()); return null; } String id = ocd.id; boolean factoryPid = Boolean.TRUE == designate.get("factory"); if (def == null) def = new DesignateDef(finder); def.ocdRef = id; def.pid = pid; def.factory = factoryPid; ocd.designates.add(def); return def; } return null; }
private static Map<MethodDef, List<MethodDef>> buildCatalog(Collection<Clazz> sources) throws Exception { final Map<MethodDef, List<MethodDef>> catalog = new TreeMap<MethodDef, List<MethodDef>>( new Comparator<MethodDef>() { public int compare(MethodDef a, MethodDef b) { return a.getName().compareTo(b.getName()); } }); for (final Clazz clazz : sources) { clazz.parseClassFileWithCollector( new ClassDataCollector() { @Override public boolean classStart(int access, TypeRef name) { return clazz.isPublic(); } @Override public void method(MethodDef source) { if (source.isPublic() || source.isProtected()) catalog.put(source, new ArrayList<MethodDef>()); } }); } return catalog; }
private void doOCD(ObjectClassDefinition o, Annotation annotation) { if (topLevel) { if (clazz.isInterface()) { if (ocd == null) ocd = new OCDDef(finder); ocd.id = o.id() == null ? name.getFQN() : o.id(); ocd.name = o.name() == null ? space(ocd.id) : o.name(); ocd.description = o.description() == null ? "" : o.description(); ocd.localization = o.localization() == null ? "OSGI-INF/l10n/" + name.getFQN() : o.localization(); if (annotation.get("pid") != null) { String[] pids = o.pid(); designates(pids, false); } if (annotation.get("factoryPid") != null) { String[] pids = o.factoryPid(); designates(pids, true); } if (annotation.get("icon") != null) { Icon[] icons = o.icon(); for (Icon icon : icons) { ocd.icons.add(new IconDef(icon.resource(), icon.size())); } } } else { analyzer.error( "ObjectClassDefinition applied to non-interface, non-annotation class %s", clazz); } } }
private OCDDef getDef() throws Exception { clazz.parseClassFileWithCollector(this); if (ocd != null) { topLevel = false; parseExtends(clazz); doMethods(); } return ocd; }
private void doXmlAttribute(Annotation annotation, XMLAttribute xmlAttr) { if (current == null) { if (clazz.isInterface()) { if (ocd == null) ocd = new OCDDef(finder); ocd.addExtensionAttribute(xmlAttr, annotation); } } else { current.addExtensionAttribute(xmlAttr, annotation); } }
void doComponent(java.lang.annotation.Annotation a) { Component component = (Component) a; pids = component.configurationPid(); if (pids != null) { pid = pids[0]; } if (pids == null || "$".equals(pid)) { pid = component.name(); if (pid == null) pid = clazz.getClassName().getFQN(); } }
private void parseOptionValues(Clazz c, final List<OptionDef> options) throws Exception { c.parseClassFileWithCollector( new ClassDataCollector() { @Override public void field(Clazz.FieldDef def) { if (def.isEnum()) { OptionDef o = new OptionDef(def.getName(), def.getName()); options.add(o); } } }); }
private static void crossRef( Collection<Clazz> source, final Map<MethodDef, List<MethodDef>> catalog) throws Exception { for (final Clazz clazz : source) { clazz.parseClassFileWithCollector( new ClassDataCollector() { // MethodDef source; @Override public void implementsInterfaces(TypeRef names[]) { MethodDef def = clazz.getMethodDef(0, "<implements>", "()V"); // TODO for (TypeRef interfaceName : names) { for (Map.Entry<MethodDef, List<MethodDef>> entry : catalog.entrySet()) { String catalogClass = entry.getKey().getContainingClass().getFQN(); List<MethodDef> references = entry.getValue(); if (catalogClass.equals(interfaceName.getFQN())) { references.add(def); } } } } // Method definitions @Override public void method(MethodDef source) { // this.source = source; } // TODO need to use different reference method // public void reference(MethodDef reference) { // List<MethodDef> references = catalog.get(reference); // if (references != null) { // references.add(source); // } // } }); } }
private boolean identifiableCollection(String type, boolean intface, boolean topLevel) { try { Clazz clazz = analyzer.findClass(analyzer.getTypeRefFromFQN(type)); if (clazz != null && (!topLevel || !clazz.isAbstract()) && ((intface && clazz.isInterface()) ^ clazz.hasPublicNoArgsConstructor())) { TypeRef[] intfs = clazz.getInterfaces(); if (intfs != null) { for (TypeRef intf : intfs) { if (COLLECTION.matcher(intf.getFQN()).matches() || identifiableCollection(intf.getFQN(), true, false)) { return true; } } } TypeRef ext = clazz.getSuper(); return ext != null && identifiableCollection(ext.getFQN(), false, false); } } catch (Exception e) { return false; } return false; }
static String space(String name) { return Clazz.unCamel(name); }
private void doMethods() throws Exception { for (Map.Entry<MethodDef, ADDef> entry : methods.entrySet()) { MethodDef defined = entry.getKey(); if (defined.isConstructor()) { analyzer.error( "Constructor %s for %s.%s found; only interfaces and annotations allowed for OCDs", defined.getName(), clazz.getClassName().getFQN(), defined.getName()); } if (defined.getPrototype().length > 0) { analyzer.error( "Element %s for %s.%s has parameters; only no-parameter elements in an OCD interface allowed", defined.getName(), clazz.getClassName().getFQN(), defined.getName()); continue; } ADDef ad = entry.getValue(); ocd.attributes.add(ad); ad.id = fixup(defined.getName()); ad.name = space(defined.getName()); String rtype = defined.getGenericReturnType(); if (rtype.endsWith("[]")) { ad.cardinality = Integer.MAX_VALUE; rtype = rtype.substring(0, rtype.length() - 2); } Matcher m = GENERIC.matcher(rtype); if (m.matches()) { boolean knownCollection = m.group(2) != null; boolean collection = knownCollection || identifiableCollection(m.group(3), false, true); if (collection) { if (ad.cardinality != 0) analyzer.error( "AD for %s.%s uses an array of collections in return type (%s), Metatype allows either Vector or array", clazz.getClassName().getFQN(), defined.getName(), defined.getType().getFQN()); rtype = Clazz.objectDescriptorToFQN(m.group(4)); ad.cardinality = Integer.MIN_VALUE; } } if (rtype.indexOf('<') > 0) { rtype = rtype.substring(0, rtype.indexOf('<')); } ad.type = getType(rtype); ad.required = true; TypeRef typeRef = analyzer.getTypeRefFromFQN(rtype); try { Clazz c = analyzer.findClass(typeRef); if (c != null && c.isEnum()) { parseOptionValues(c, ad.options); } } catch (Exception e) { analyzer.error( "AD for %s.%s Can not parse option values from type (%s), %s", clazz.getClassName().getFQN(), defined.getName(), defined.getType().getFQN(), e.getMessage()); } if (ad.ad != null) { doAD(ad); } if (ad.defaults == null && clazz.isAnnotation() && defined.getConstant() != null) { // defaults from annotation default Object value = defined.getConstant(); boolean isClass = false; TypeRef type = defined.getType().getClassRef(); if (!type.isPrimitive()) { if (Class.class.getName().equals(type.getFQN())) { isClass = true; } else { try { Clazz r = analyzer.findClass(type); if (r.isAnnotation()) { analyzer.warning( "Nested annotation type found in field % s, %s", defined.getName(), type.getFQN()); return; } } catch (Exception e) { analyzer.error( "Exception looking at annotation type default for element with descriptor %s, type %s", e, defined, type); } } } if (value != null) { if (value.getClass().isArray()) { // add element individually ad.defaults = new String[Array.getLength(value)]; for (int i = 0; i < Array.getLength(value); i++) { Object element = Array.get(value, i); ad.defaults[i] = valueToProperty(element, isClass); } } else { ad.defaults = new String[] {valueToProperty(value, isClass)}; } } } } }