Tôi cho rằng bạn đã biết cách tạo nhóm (nếu không, hãy kiểm tra this).
Sau một debuging và thăm dò của Reflections API tôi đã nhận ra rằng vấn đề là Reflections chỉ đơn giản là không đọc OSGi URL (bundleresource: // ...) dẫn đến một ngoại lệ:
org.reflections.ReflectionsException: could not create Vfs.Dir from url,
no matching UrlType was found [bundleresource://1009.fwk651584550/]
và điều này gợi ý:
either use fromURL(final URL url, final List<UrlType> urlTypes)
or use the static setDefaultURLTypes(final List<UrlType> urlTypes)
or addDefaultURLTypes(UrlType urlType) with your specialized UrlType.
vì vậy, tôi tin rằng thực hiện một UrlType cho OSGi (ví dụ class BundleUrlType implements UrlType {...}
) và đăng ký nó như thế này:
Vfs.addDefaultURLTypes(new BundleUrlType());
nên làm cho API phản xạ có thể sử dụng được từ bên trong một gói. Các phụ thuộc phản chiếu nên được thêm vào dự án Plugin Eclipse như được mô tả here.
Đây là cách MANIFEST.MF mẫu của tôi trông giống như sau khi thêm lọ cần thiết:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: ReflectivePlugin
Bundle-SymbolicName: ReflectivePlugin
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: reflectiveplugin.Activator
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: javax.annotation;version="1.0.0",
org.osgi.framework;version="1.3.0",
org.osgi.service.log;version="1.3",
org.osgi.util.tracker;version="1.3.1"
Bundle-ClassPath: .,
lib/dom4j-1.6.1.jar,
lib/guava-r08.jar,
lib/javassist-3.12.1.GA.jar,
lib/reflections-0.9.5.jar,
lib/slf4j-api-1.6.1.jar,
lib/xml-apis-1.0.b2.jar
Export-Package: reflectiveplugin,
reflectiveplugin.data
Lưu ý: Dùng Reflections v 0.9.5
Dưới đây là một việc thực hiện mẫu UrlType:.
package reflectiveplugin;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.Iterator;
import org.osgi.framework.Bundle;
import org.reflections.vfs.Vfs;
import org.reflections.vfs.Vfs.Dir;
import org.reflections.vfs.Vfs.File;
import org.reflections.vfs.Vfs.UrlType;
import com.google.common.collect.AbstractIterator;
public class BundleUrlType implements UrlType {
public static final String BUNDLE_PROTOCOL = "bundleresource";
private final Bundle bundle;
public BundleUrlType(Bundle bundle) {
this.bundle = bundle;
}
@Override
public boolean matches(URL url) {
return BUNDLE_PROTOCOL.equals(url.getProtocol());
}
@Override
public Dir createDir(URL url) {
return new BundleDir(bundle, url);
}
public class BundleDir implements Dir {
private String path;
private final Bundle bundle;
public BundleDir(Bundle bundle, URL url) {
this(bundle, url.getPath());
}
public BundleDir(Bundle bundle, String p) {
this.bundle = bundle;
this.path = p;
if (path.startsWith(BUNDLE_PROTOCOL + ":")) {
path = path.substring((BUNDLE_PROTOCOL + ":").length());
}
}
@Override
public String getPath() {
return path;
}
@Override
public Iterable<File> getFiles() {
return new Iterable<Vfs.File>() {
public Iterator<Vfs.File> iterator() {
return new AbstractIterator<Vfs.File>() {
final Enumeration<URL> entries = bundle.findEntries(path, "*.class", true);
protected Vfs.File computeNext() {
return entries.hasMoreElements() ? new BundleFile(BundleDir.this, entries.nextElement()) : endOfData();
}
};
}
};
}
@Override
public void close() { }
}
public class BundleFile implements File {
private final BundleDir dir;
private final String name;
private final URL url;
public BundleFile(BundleDir dir, URL url) {
this.dir = dir;
this.url = url;
String path = url.getFile();
this.name = path.substring(path.lastIndexOf("/") + 1);
}
@Override
public String getName() {
return name;
}
@Override
public String getRelativePath() {
return getFullPath().substring(dir.getPath().length());
}
@Override
public String getFullPath() {
return url.getFile();
}
@Override
public InputStream openInputStream() throws IOException {
return url.openStream();
}
}
}
Và đây là cách tôi tạo phản xạ trong lớp Activator:
private Reflections createReflections(Bundle bundle) {
Vfs.addDefaultURLTypes(new BundleUrlType(bundle));
Reflections reflections = new Reflections(new Object[] { "reflectiveplugin.data" });
return reflections;
}
Bit cuối cùng rất khó hiểu, nhưng vẫn quan trọng: nếu bạn chạy plugin bên trong Eclipse (Chạy như/OSGi Framework), bạn phải thêm thư mục đầu ra của lớp vào các mẫu đường dẫn Reflections (tức là "bin" hoặc "target/classes").Mặc dù, nó không cần thiết cho một plugin được phát hành (để xây dựng một plugin/gói làm "Export" -> "Deployable plug-in and fragments").
Cảm ơn bạn đã trả lời @Vlad. Không có ý tưởng làm thế nào để tạo ra bó như vậy nhưng tôi sẽ cố gắng (Tôi xa là một chuyên gia trong OSGi được nêu ra ...). Vì vậy, tôi cần hai bó: 1) thư viện Reflections có "DynamicImport-Package: *" tại MANIFEST Plug-in của nó; 2) một gói với plugin của tôi, nơi tôi phải điền vào danh sách "Gói đã xuất" của trình chỉnh sửa cấu hình plugin, tất cả các gói có thể truy cập được vào Gói phản xạ. Sau đó, tôi đoán tôi nên soạn hai bó này thành một nhóm khác, đúng không? Bạn có thể vui lòng xây dựng thêm một chút câu trả lời của bạn? tất cả điều này có vẻ hơi phức tạp. Cảm ơn – Sergio
@Sergio, tôi đã cập nhật câu trả lời với những phát hiện của tôi (câu trả lời trước đó không cung cấp giải pháp). Thật không may, nó đã xảy ra được ít hơn nhiều về phía trước. Hy vọng, nó sẽ giúp. – Vlad
Cảm ơn bạn rất nhiều vì đã mở rộng câu trả lời của bạn @Vlad. Tôi đã cố gắng thực hiện nó mà không thành công cho đến bây giờ. Nếu tôi hiểu chính xác từ câu trả lời mới của bạn, tôi chỉ cần gói plugin và lọ Reflexions trong classpath nhóm của nó (như tôi ban đầu đã có nó). Vì vậy, tôi bỏ qua câu trả lời trước đây về việc đưa phản xạ vào một gói riêng biệt, điều này có đúng không? Về tệp kê khai của bạn: 'Bundle-ClassPath' của bạn trông giống như của tôi, trong 'Gói xuất của tôi' tôi không có tệp '.data' như bạn và trong 'Gói nhập' tôi không thấy phụ thuộc bạn có, điều quan trọng là Reflexions có hoạt động không? – Sergio