blob: f3f7c61f61d3f18b4017fdd75e3391000898678e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.felix.dm.annotation.plugin.bnd;
import aQute.bnd.osgi.Clazz.FieldDef;
/**
* Class extracted from bndtools (aQute.bnd.component.AnnotationScanner), which
* allows to determine class field collection type.
* For example, given "private Collection<MyService> services;", this class allows to determine the
* "MyService" type.
*/
public class FieldTypeGetter {
public enum FieldCollectionType {
service, properties, reference, serviceobjects, tuple
}
static String determineFieldType(Logger log, FieldDef member) {
String field = member.getName();
String sig = member.getSignature();
if (sig == null)
// no generics, the descriptor will be the class name.
sig = member.getDescriptor().toString();
String[] sigs = sig.split("[<;>]");
int sigLength = sigs.length;
int index = 0;
boolean isCollection = false;
if ("Ljava/lang/Iterable".equals(sigs[index]) || "Ljava/util/Collection".equals(sigs[index]) || "Ljava/util/List".equals(sigs[index])) {
index++;
isCollection = true;
}
// Along with determining the FieldCollectionType, the following
// code positions index to read the service type.
FieldCollectionType fieldCollectionType = null;
if (sufficientGenerics(index, sigLength, sig)) {
if ("Lorg/osgi/framework/ServiceReference".equals(sigs[index])) {
if (sufficientGenerics(index++, sigLength, sig)) {
fieldCollectionType = FieldCollectionType.reference;
}
} else if ("Lorg/osgi/service/component/ComponentServiceObjects".equals(sigs[index])) {
if (sufficientGenerics(index++, sigLength, sig)) {
fieldCollectionType = FieldCollectionType.serviceobjects;
}
} else if ("Ljava/util/Map".equals(sigs[index])) {
if (sufficientGenerics(index++, sigLength, sig)) {
fieldCollectionType = FieldCollectionType.properties;
}
} else if ("Ljava/util/Map$Entry".equals(sigs[index]) && sufficientGenerics(index++ + 5, sigLength, sig)) {
if ("Ljava/util/Map".equals(sigs[index++]) && "Ljava/lang/String".equals(sigs[index++])) {
if ("Ljava/lang/Object".equals(sigs[index]) || "+Ljava/lang/Object".equals(sigs[index])) {
fieldCollectionType = FieldCollectionType.tuple;
index += 3; // ;>;
} else if ("*".equals(sigs[index])) {
fieldCollectionType = FieldCollectionType.tuple;
index += 2; // >;
} else {
index = sigLength;// no idea what service might
// be.
}
}
} else {
fieldCollectionType = FieldCollectionType.service;
}
}
if (isCollection) {
// def.fieldCollectionType = fieldCollectionType;
}
String annoService = null;
if (annoService == null && index < sigs.length) {
annoService = sigs[index].substring(1).replace('/', '.');
}
return annoService;
}
private static boolean sufficientGenerics(int index, int sigLength, String sig) {
if (index + 1 > sigLength) {
// analyzer.error(
// "In component %s, method %s, signature: %s does not have sufficient generic
// type information",
// component.effectiveName(), def.name, sig);
return false;
}
return true;
}
}