バンドルを作成する方法を既に理解していることを前提としています(そうでない場合は、thisをチェックしてください)。私は問題は反射は単にOSGiのURLを読み取りに失敗したということであることを認識している反射APIのいくつかのデバッグのと探検した後
(bundleresource:// ...)例外が生じ:
org.reflections.ReflectionsException: could not create Vfs.Dir from url,
no matching UrlType was found [bundleresource://1009.fwk651584550/]
と、この提案:
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.
だから私は、OSGiのためのUrlType(例えばclass BundleUrlType implements UrlType {...}
)を実装し、このようにそれを登録すると信じて:
Vfs.addDefaultURLTypes(new BundleUrlType());
は、Reflections APIをバンドルの内部から使用できるようにする必要があります。リフレクションの依存関係は、hereのようにEclipse Pluginプロジェクトに追加する必要があります。
これは私のサンプルMANIFEST.MFが必要なjarファイルを追加した後のように見えた方法です:
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
注:使用される反射V 0.9.5
ここではサンプル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();
}
}
}
これはActivatorクラスでリフレクションを作成する方法です:
private Reflections createReflections(Bundle bundle) {
Vfs.addDefaultURLTypes(new BundleUrlType(bundle));
Reflections reflections = new Reflections(new Object[] { "reflectiveplugin.data" });
return reflections;
}
最後のビットは非常に混乱しますが、重要です。プラグインをEclipse(Run As/OSGi Framework)内で実行する場合、クラス出力ディレクトリもReflectionsパスパターンに追加する必要があります。 "bin"または "target/classes")。ただし、リリースされたプラグインでは必要ありません(プラグイン/バンドルを構築するには、 "Export" - > "Deployable plug-ins and fragments"を実行してください)。
ありがとう@Vladに答えてください。そのようなバンドルを作る方法は考えられませんが、私は試してみます(OSGiの専門家ではありません...)。ですから、2つのバンドルが必要です:1)プラグインマニフェストに "DynamicImport-Package:*"を持つReflectionsライブラリ。 2)プラグインとのバンドル、プラグイン設定エディタの「エクスポートされたパッケージ」リスト、Reflexionsバンドルにアクセス可能なすべてのパッケージに記入する必要があります。それから、私はこれら2つのバンドルを別のものに組み立てるべきだと思います。あなたの答えをもう少し詳しく教えてください。このすべてはちょっと複雑なようです!ありがとう – Sergio
@Sergio、私は私の所見(前の答えは解決策を提供しなかった)で答えを更新しました。残念なことに、それはずっと簡単ではなかった。希望、それは助けになるだろう。 – Vlad
お返事ありがとうございました@Vlad。私は今まで成功せずに実装しようとしました。あなたの新しい答えから正しく理解していれば、バンドルクラスパスにプラグインバンドルとReflexions jarだけが必要です(私が元々持っていたように)。だから私は別のバンドルにReflexionsを置くことに関する以前の答えを無視しています、これは正しいのですか?あなたのマニフェストファイルについて:あなたの 'Bundle-ClassPath'は私の 'Export-Package'に似ていますが、 '.data'ファイルはありません。また、 'Import-Package'では依存関係は表示されませんあなたはReflexionsが働くことが重要ですか? – Sergio