I have an RCP application (referred to as RCP-APP). I have created a new plug-in (referred to as plug-in A) that wraps a media player api (.jar file) and a folder of C libraries (dlls) that the media player api accesses via JNA. I then created another plugin (referred to as plug-in B) that contains a media player application that depends on Plug-in A.
When plug-in B is activated I get the following error messages informing me that Plug-in B cannot find the media player .dlls it is looking for:
!ENTRY org.eclipse.jface 4 2 2009-06-22 10:05:22.475
!MESSAGE Problems occurred when invoking code from plug-in: "org.eclipse.jface".
!STACK 0
java.lang.UnsatisfiedLinkError: Unable to load library 'libvlc': The specified module could not be found.
at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:114)
at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:157)
at com.sun.jna.Library$Handler.(Library.java:123)
at com.sun.jna.Native.loadLibrary(Native.java:260)
at com.sun.jna.Native.loadLibrary(Native.java:246)
at org.videolan.jvlc.internal.LibVlc.(LibVlc.java:41)
at org.videolan.jvlc.JVLC.(JVLC.java:45)
at com.bah.gs.arts.jekyll.plugins.videolog.VideoLogDisplay.displayStream(VideoLogDisplay.java:32)
at com.bah.gs.arts.jekyll.core.extensionpoints.DisplayStreamFactory.getDisplayStreams(DisplayStreamFactory.java:57)
at com.bah.gs.arts.jekyll.core.views.medialist.MediaListView$1.doubleClick(MediaListView.java:91)
at org.eclipse.jface.viewers.StructuredViewer$1.run(StructuredViewer.java:799)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:37)
at org.eclipse.core.runtime.Platform.run(Platform.java:880)
at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:48)
at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:175)
at org.eclipse.jface.viewers.StructuredViewer.fireDoubleClick(StructuredViewer.java:797)
at org.eclipse.jface.viewers.AbstractTreeViewer.handleDoubleSelect(AbstractTreeViewer.java:1419)
at org.eclipse.jface.viewers.StructuredViewer$4.widgetDefaultSelected(StructuredViewer.java:1173)
at org.eclipse.jface.util.OpenStrategy.fireDefaultSelectionEvent(OpenStrategy.java:237)
at org.eclipse.jface.util.OpenStrategy.access$0(OpenStrategy.java:234)
at org.eclipse.jface.util.OpenStrategy$1.handleEvent(OpenStrategy.java:295)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1003)
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3823)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3422)
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2384)
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2348)
at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2200)
at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:495)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:288)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:490)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
at com.bah.gs.arts.jekyll.core.Application.start(Application.java:20)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:193)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:386)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:549)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:504)
at org.eclipse.equinox.launcher.Main.run(Main.java:1236)
at org.eclipse.equinox.launcher.Main.main(Main.java:1212)
How do I inform Plug-in B (or the RCP-APP) that the .dlls are in a specific folder in Plug-in A?
It appears that the api expects to find the .dlls via it's environment PATH variable.
How can I essentially communicate "plug-in A/Folder-Name"?
Thanks for your assistance.
To get access to the .DLL files in plugin-a/folder you need access to the Bundle instance of plug-in A. One way is to implement an Activator for plug-in A which extends at least the class Plugin ("PluginA").
The call PluginA.getDefault().getBundle().getEntry("folder/some.dll") will return an URL to the .DLL file.
IMHO it is better to put all code that directly accesses the .DLL files into plug-in A. This way you don't need to expose the internal file structure of your plug-in to its users.
You will probably want to look at plugin fragments; this provides a mechanism to keep the public facing Java API apart from the (platform specific) dll/so files.
The packaging of SWT would be a good place to start looking at this sort of problem.
You could build a "binaries" plugin, put the dll in a subfolder bin/ of it, then make sure in the manifest
* you add an activator + singleton property.
* you check bin/ in the "Build", "Runtime Build" section
In the feature that includes your binaries plug-in, make sure to check "Unpack the plugin archive after installation"
In the activator of your binaries plugin, add something like this :
public enum Tool {reach, ctl, ltl};
private static URI toolUri [] = new URI [3];
public static URI getProgramURI(Tool tool) throws IOException {
if (toolUri[tool.ordinal()] == null) {
String relativePath = "bin/its-"+ tool.toString() ;
URL toolff = getDefault().getBundle().getResource(relativePath);
if (toolff == null) {
log.severe("unable to find an executable [" + tool + "] in path " + relativePath);
Enumeration<URL> e = getDefault().getBundle().findEntries("bin/", "*", true);
log.fine("Lising URL available in bin/");
while (e.hasMoreElements()) {
log.finer(e.nextElement().toString());
}
throw new IOException("unable to find the tool binary");
}
URL tmpURL = FileLocator.toFileURL(toolff);
// use of the multi-argument constructor for URI in order to escape appropriately illegal characters
URI uri;
try {
uri = new URI(tmpURL.getProtocol(), tmpURL.getPath(), null);
} catch (URISyntaxException e) {
throw new IOException("Could not create a URI to access the binary tool :", e);
}
toolUri[tool.ordinal()] = uri;
log.fine("Location of the binary : " + toolUri);
File crocExec = new File(uri);
if (!crocExec.setExecutable(true)) {
log.severe("unable to make the command-line tool executable [" + toolUri + "]");
throw new IOException("unable to make the command-line tool executable");
}
}
return toolUri[tool.ordinal()];
}
I copy pasted from some code of mine, so sorry it doesn't perfectly match your DLL example, I was getting executable paths from a restricted list (see enum Tool). The last step (setting the +x flag on the file) is probably useless in your case. On the other hand you get some exception handling code and a cache for free :) And its tested pretty thoroughly.
It does the job you are trying to do, pass the url to the binary to the downstream plugin.
Related
In domain mode , I am able to use properties file as a module but the problem is if there is any modification in the file then i'l need to do it for all slaves in the domain.
I want to centralize the file so that at one point I can change and it will be reflected on all slaves.
I know in domain.xml we can configure global level system properties but I have around 25 properties files.
So is there a way to centralized the files??
myjar.jar
-->package
--> class
-->properties
-->xml files
myjar.jar is an archived jar file
To fetch the xml files
URL url = Thread.currentThread().getContextClassLoader().getResource("./properties");
File queryFolder = new File(url.getFile());
for (File fileName : queryFolder.listFiles()) // null pointer exception
{
if (fileName.getName().toUpperCase().endsWith("XML"))
{
saxParser.parse(fileName, this);
}
}
This is not working.
Tried this
How do I list the files inside a JAR file?
And facing the same problem given in below link
JBoss wildfly 8.x Provider "vfs" not installed when using java nio Paths
URL w_url = mmyClass.class.getProtectionDomain().getCodeSource().getLocation();
JarEntry w_ze = null;
LOGGER.info("Jar******************" + w_url.toString());
if (w_url.toString().endsWith(".jar"))
{
try (JarInputStream jar = new JarInputStream(w_url.openStream()))
{
while ((w_ze = jar.getNextJarEntry()) != null)
{
LOGGER.info("Name *******" + w_ze.getName());
}
}
catch(Exception e)
{
}
}
Added properties folder inside a war file and fetched the exploded folder path using below code in the servlet of the war file.
config.getServletContext().getRealPath("/");
This gives the vfs path of the folder.
and configured the same in
System.setProperty("REALPATH", config.getServletContext().getRealPath("/"));
and used the same in the jar file.
I've created a JKS file with public and private RSA keys. When I load this file using external path (like c:/file.jks), the program executes like a charm. However, if I try load this same file from classpath, I got this exception:
java.io.IOException: Invalid keystore format
This is the code used to load the jks:
KeyStore keyStore = KeyStore.getInstance("JKS");
InputStream stream=this.getClass().getResourceAsStream("/lutum.jks") ;
keyStore.load(stream,passe);
the only difference is that I use FileInputStream with full path when loading externally.
What I'm doing wrong?
In general your solution should work, provisionally.
What are those provisions? Make sure that your resource folder is in your classpath. If you aren't sure, add it to the -cp flag passed to java when executing your program, or if you are using Eclipse or some other IDE, make sure it is listed as a member of the classpath for that project.
Next, check out this stackoverflow that relates to your question. While the way you are using the class's getResourceAsStream() method is valid (including the / at the start of the filename causes the class resource loader to defer to the ClassLoader's method) it is perhaps less confusing to use the ClassLoader directly. Another good example is found here.
So, first, check that your resources folder is explicitly part of the classpath. Second, prefer the following construction for finding the resource:
InputStream stream= this.class.getClassLoader().getResourceAsStream("lutum.jks");
Note the missing / from the filename. This is because the ClassLoader will automatically start searching at "project root", and the slash will likely just cause issues (if you deploy to JBoss or Tomcat, for instance, that will probably get interpreted by the classloader as an absolute file system path instead of a relative path).
I hope this helps. If not, comment me with more details on your project and I'll alter my answer accordingly.
I suspect that the two keystores are in fact not the same, and that the keystore on the classpath are somehow corrupt.
Try comparing the two keystores. Just read the files into a byte array with something like this:
public static byte[] streamToByteArray(InputStream is) throws IOException {
ByteArrayOutputStream tmp = new ByteArrayOutputStream();
int b = is.read();
while (b > -1) {
tmp.write(b);
b = is.read();
}
tmp.flush();
return tmp.toByteArray();
}
And then compare them like this:
InputStream cpStream = this.getClass().getResourceAsStream("/lutum.jks");
InputStream fileStream = new FileInputStream("c:/file.jks");
byte[] cpBytes = streamToByteArray(cpStream);
byte[] fileBytes = streamToByteArray(fileStream);
if (Arrays.equals(cpBytes, fileBytes)) {
System.out.println("They are the same.");
} else {
System.out.println("They are NOT the same.");
// print the file content ...
}
How to create new file in a user directory on NetBeans Platform application? I used:
System.getProperty("netbeans.user", "user.home") + "/myfile");
But the NB IDE 7.1.1 told me that it is depreceated and I should use InstalledFile Locator instead. Ok, I tried this:
File file = InstalledFileLocator.getDefault().locate("myfile", null, false);
It works fine, if the file already exists. I cannot see any way, how to create new with the InstalledFileLocator. But the javadoc say, this method allows to get folder. So I tried this:
File file = InstalledFileLocator.getDefault().locate("myfile", null, false);
if (file == null) {
file = new File(InstalledFileLocator.getDefault().locate("", null, false), "myfile");
}
Again without success, the method locate now fails that it can't find anything (the "/" is forbidden and does not work too).
So my question is, how to corectly load in my NetBeans Platform application an existing file in the user directory (it is for writing also, so it should not be in the program directory) and if it does not exist, create it?
You could use Places.getUserDirectory().
File file = InstalledFileLocator.getDefault().locate("myfile", null, false);
if (file == null)
{
file = new File(Places.getUserDirectory() + File. separator + "myfile");
}
From the netbeans platform docs InstalledFileLocator should not be used to find resources on the system filesystem. To find data in the system filesystem, use the Filesystems API. Ex:
FileObject fo = FileUtil.getConfigFile(myfile);
if (fo == null) {
fo = FileUtil.getConfigRoot().createData(myFile,ext);
}
Probably the easiest thing you can do is to include a simple empty file (say "here.txt") in your module that will be installed in the user directory automatically. You can see an example of this here (see the section "Lessons learned: bundling files with your NetBeans modules").
Basically you include the file in the "release/modules/ext/here.txt" directory of your module.
When the module is installed the platform will install the 'here.txt' file included in your module in the user directory automatically for you, so you don't have to worry about this.
Once your module is installed an running you want to locate the file like this:
File hereTXT = InstalledFileLocator.getDefault()
.locate("modules/ext/here.txt",
"a.b.c",
false);
(Where "a.b.c" is your module identifier.)
And then from that 'hereTXT' file you can get the directory with 'hereTXT.getParent()', and you're all set.
I am using Icefaces for webapplication development. I wish to read a file from the resources folder and use it in the sessionbean.
Actually I wish to setup Jasper Reports. I have already setup the libraries in the classpath. The problem I get is while fetching the file from /WEB-INF/resources/ folder. Everytime I run the code from SessionBean, I get the exception:
net.sf.jasperreports.engine.JRException: java.io.FileNotFoundException: /resources/reports/myreport.jrxml (No such file or directory)
The Code I use is:
public void generateReport() {
try {
JasperCompileManager.compileReportToFile(
"/resources/reports/myreport.jrxml",
"/resources/reports/myreport.jasper");
} catch (Exception e) {
e.printStackTrace();
}
}
The above code is in the SessionBean.
Plz help
You are passing relative
URLs to method JasperCompileManager.compileReportToFile.
This method expects filenames as parameters, not URLs.
The solution suggested in other internet forums is:
JasperCompileManager.compileReportToFile(
getServletContext().getRealPath(xmlFile),
getServletContext().getRealPath(compiledFile));
I can't start my GWT application in hosted mode (Debug as -> web application) using Eclipse. It throws me the exception mentioned in the title. Eclipse debug shows me the following code:
/*
* GOOGLE: Since we're bundling our own version of SWT, we need to be
* able to tell SWT where its dynamic libraries live. Otherwise we'd
* have to force our users to always specify a -Djava.library.path
* on the command line.
*/
String swtLibraryPath = System.getProperty ("swt.library.path");
try {
String newName = name + "-" + platform + "-" + version; //$NON-NLS-1$ //$NON-NLS-2$
if (swtLibraryPath != null)
System.load(swtLibraryPath + System.mapLibraryName(newName));
else
System.loadLibrary (newName);
return;
} catch (UnsatisfiedLinkError e1) {
try {
String newName = name + "-" + platform; //$NON-NLS-1$
if (swtLibraryPath != null)
System.load(swtLibraryPath + System.mapLibraryName(newName));
else
System.loadLibrary (newName);
return;
} catch (UnsatisfiedLinkError e2) {
throw e1;
}
}
The exception being thrown is e1. I have not made any changes to the application, just created it and fired the debug.
What am I missing? I'm using Ubuntu 9.04 64 bits (don't know if this matters)
EDIT: stack trace
Exception in thread "main" java.lang.UnsatisfiedLinkError: /home/rafael/.eclipse/640022211/plugins/com.google.gwt.eclipse.sdkbundle.linux_1.7.0.v200907291526/gwt-linux-1.7.0/libswt-pi-gtk-3235.so: /home/rafael/.eclipse/640022211/plugins/com.google.gwt.eclipse.sdkbundle.linux_1.7.0.v200907291526/gwt-linux-1.7.0/libswt-pi-gtk-3235.so: wrong ELF class: ELFCLASS32 (Possible cause: architecture word width mismatch)
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1767)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1663)
at java.lang.Runtime.load0(Runtime.java:787)
at java.lang.System.load(System.java:1022)
at org.eclipse.swt.internal.Library.loadLibrary(Library.java:132)
at org.eclipse.swt.internal.gtk.OS.(OS.java:22)
at org.eclipse.swt.internal.Converter.wcsToMbcs(Converter.java:63)
at org.eclipse.swt.internal.Converter.wcsToMbcs(Converter.java:54)
at org.eclipse.swt.widgets.Display.(Display.java:126)
at com.google.gwt.dev.SwtHostedModeBase.(SwtHostedModeBase.java:82)
Could not find the main class: com.google.gwt.dev.HostedMode. Program will exit.
Solved the issue. After reading the stack trace more carefully (thanks Warren!), I ended up googling for different terms, and determined the cause to be the word width issue indeed.
The solution was to install a 32-bit JVM and tell Eclipse to use it instead of the 64-bit one. This is done by installing the new JVM, going to Window > Preferences > Java > Installed JREs in Eclipse and adding your new JVM (remember to point to the jre dir). Then I set it as the default one, and managed to run the example.
Including the stacktrace, at least a few lines of it, can really help with these ones as it generally means your system is missing a system library of some form. I think the variable 'newname' actually will list the missing library if you're going through with a debugger.
I also run Ubuntu 9.04, though not 64 bit and when I hit an UnsatisfiedLink error, it was due to the wrong version of libstdc++. This fixed it for me:
sudo apt-get install libstdc++5