I use the following code to test the BouncyCastle crypto library:
import java.security.Security;
public class SimpleTest {
public static void main(String[] args)
{
String providerName="BC";
if (Security.getProvider(providerName)==null)
{
System.out.println(providerName + "provider not installed");
}
else
{
System.out.println(providerName + "is installed");
}
}
}
However, Eclipse shows "BCprovider not installed", and my EditPlus shows "BC is installed".
What makes this difference?
There is a library missing somewhere in your eclipse that it can not find it. You need to revise your configuration in eclipse.
The difference?
I guess different java runtimes may have different error messages.
IMHO, unless you check underlying JRE's are the same, the difference is not between Eclipse and texteditor, but between Java SE 7u7 and Java SE 6u35 (for example).
Anyway, that is not your actual problem, but effectively deploying the provider jar in your classpath and registering it.
Actually the difference is likely to be in the static security provider configuration in Java. You need to register providers somehow to be able to use them. If you cannot change the Java runtime, you can register them dynamically if they have been signed properly.
Related
I try to use the #NotNull annotation from package com.sun.istack.internal.
I am using IDE Intellij IDEA Community Edition.
when I build a program using IDE no problem. When I try to compile a file from the command line using javac, I get an error "cannot find symbol".
package ibkr;
import com.sun.istack.internal.NotNull;
public class Main {
public static void main(String[] args) {
test("Test");
}
public static void test(#NotNull String text) {
System.out.println(text);
}
}
I don't understand why i can't compile this code using javac and how Intellij IDEA make compilation and run it.
The annotation is an internal class, it's not for public use. The closest alternative is Jetbrains' stuff:
https://www.jetbrains.com/help/idea/nullable-and-notnull-annotations.html
Even if the class is in the classpath, it doesn't necessarily mean that you can safely refer to that class. The compiler can have some limitations upon accessing some classes/packages.
In most cases, as here, it's obvious whether the package is internal or not: com.sun.istack.internal. Oracle discourages developers from using classes from such packages.
Ok i know this question is a bit old, but if my info is correct, the reason for this is the fact that intellij uses full rt.jar for compilation while javac uses incomplete version, because of ct.sym
This is an annotation used to identify non-nullable values, also this will let static analyzer have their checks in place. In case you are using IntelliJ you can use its annotation but it would make it very tool-specific, same is the case for eclipse
One can also you
https://mvnrepository.com/artifact/com.sun.xml.bind/jaxb-impl
This provides the same non-null annotation but you need to add an extra dependency there.
I thought I would use the new ResourceBundleControlProvider framework in Java 8 to fix something which Oracle themselves will never fix - the default encoding used when reading resource bundles.
So I made a control:
package com.acme.resources;
import java.io.IOException;
import java.util.Locale;
import java.util.ResourceBundle;
public class AcmeResourceBundleControl extends ResourceBundle.Control
{
#Override
public ResourceBundle newBundle(String baseName, Locale locale, String format,
ClassLoader loader, boolean reload)
throws IllegalAccessException, InstantiationException, IOException
{
throw new UnsupportedOperationException("TODO");
}
}
Then I made a provider:
package com.acme.resources;
import java.util.ResourceBundle;
import java.util.spi.ResourceBundleControlProvider;
public class AcmeResourceBundleControlProvider implements ResourceBundleControlProvider
{
private static final ResourceBundle.Control CONTROL = new AcmeResourceBundleControl();
#Override
public ResourceBundle.Control getControl(String baseName)
{
if (baseName.startsWith("com.acme."))
{
return CONTROL;
}
else
{
return null;
}
}
}
Then in META-INF/services/java.util.spi.ResourceBundleControlProvider:
com.acme.resources.AcmeResourceBundleControlProvider
Then I just tried to run our application from IDEA and I find that it never loads my provider (otherwise the exception would be raised.)
I have checked the names and they all seem to match up. I have checked the compiler output directory IDEA is using and it does contain the service file. I wrote a simple test program which just tries to look up the service:
public static void main(String[] args)
{
for (ResourceBundleControlProvider provider :
ServiceLoader.load(ResourceBundleControlProvider.class))
{
System.out.println(provider.getClass());
}
}
This does print out one entry which is the name of my implementation class. So the issue is not in the service file.
If I breakpoint inside ResourceBundle, I seem to be able to access the custom provider class. Initial forays into the debugger show that ServiceLoader isn't finding any implementations, but I can't figure out why. I'm sure there is some dodgy class loader magic going on which results in not loading my class. :(
Some scary documentation on the Javadoc makes it sound like it might have to be installed as a global extension. If that really is the case, it's a bit of a shame, because it seemed like a useful way to override the default (and in my opinion broken) behaviour. But I also read the tutorial on the matter and it didn't seem to be describing anything like that (unless the good behaviour was pulled out of Java 8 at the very last minute and the docs are out of date!)
The tutorial does state that the JAR containing the ResourceBundleControlProvider must be in the JVM's system extension directory. Section 6 of the tutorial describes the requirement:
java -Djava.ext.dirs=lib -cp build RBCPTest
When you install a Java extension, you typically put the JAR file of the extension in the lib/ext directory of your JRE. However, this command specifies the directory that contains Java extensions with the system property java.ext.dirs.
The JavaDoc for ServiceLoader.loadInstalled() also states that providers on the application's class path are ignored.
Your problem is that the java.util.ResourceBundle that comes with the JVM does a ServiceLoader.loadInstalled(ResourceBundleControlProvider.class) to obtain a list of providers in the static initializer, and uses the thus obtained list ever after.
I encountered a compilation issue under Linux.
I'm compiling java programs on Linux; the target use is both Linux and Windows.
The code check if in there are platform specific classes (as shown in the code below).
So if the code is running under Linux, the specific Windows code will not be executed.
The issue arise on the use of a platform specific class Win32MediaTray
The compile error reported is
PrinterScanner.java:9: error: cannot find symbol
import sun.print.Win32MediaTray;
^
Is it possible to compile it under Linux? Or is it just impossible?
I can use some workaround (reflection?)
Needless to say that the compilation under Windows gives no errors.
Thankyou for your help.
For reference, the code behind this issue is the following:
private String getTrayName(Media media) {
String result = "id:" + media.getValue();
boolean isWin32 = media.getClass().getName().equals("sun.print.Win32MediaTray");
if (isWin32) {
Win32MediaTray w32 = (Win32MediaTray) media;
result = result + ",winId:" + w32.winID;
}
return result;
}
I believe that the class you are trying to use is sun.print.Win32MediaTray.
And the answer is that you cannot use it ... or compile a class that uses it ... on a Linux release of Java. That class is not included in the rt.jar file on a Linux release of Java.
Furthermore, you shouldn't be using it. The Java documentation makes it very clear that application code should not make use of classes in the sun.* package hierarchy.
If you have no choice but to do this, then your best bet is to use reflection to fetch the value of that w32Id field. You'll also need to deal with the case where the media object is not an instance of the Win32MediaTray class. Beware that you are relying on implementation details that Oracle says specifically that you shouldn't. There is a risk that they will change (without notice!) in some future Windows release.
The other alternatives are:
Implement your own platform adapter classes with a different one for each platform. These have to be compiled separately on each platform, and then dynamically loaded.
Implement separate codebases for each platform.
To make the compiler happy you could implement a dummy class named sun.print.Win32MediaTray and make it available both on the compile and runtime classpath. The class doesn't need to work, it only has to be API compatible (same signatures and return types, but in this case you only really need to extend Media and have a public int winID), so that you can satisfy both the compiler and the verifier.
At runtime, the version included in rt.jar should be loaded on Windows thanks to loading delegation. On Linux, the dummy version is the only one available, but you stated that the program checks for the platform and executes another branch of code, so it shouldn't cause your program to fail.
For example, with the following class on the classpath:
package sun.print;
import javax.print.attribute.standard.Media;
public class Win32MediaTray extends Media {
public int winID = 0xBADC0DE;
protected Win32MediaTray(int value) {
super(value);
}
static {
System.out.println("Won't see me on Windows");
}
}
I managed to run this program on Windows:
public class Main {
public static void main(String[] args) {
PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null);
for (PrintService svc : services ) {
DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PAGEABLE;
Object o = svc.getSupportedAttributeValues(Media.class, flavor, null);
if (o != null && o.getClass().isArray()) {
for (Media media : (Media[]) o) {
if ( media instanceof Win32MediaTray )
System.out.println( ((Win32MediaTray) media).winID );
}
}
}
}
}
The message in the static initializer is not printed on Windows, because the definition that is actually loaded is the one from rt.jar. Obviously, the code can be compiled on any platform.
How about putting the code that uses windows-specific stuff into a separate jar; then you can compile and include that jar on windows, and leave it off systems otherwise.
One standard way to do this is to have one or more interfaces used by your application code; you can have a factory provide the implementing classes or inject them with Spring or whatever. But I think rather than "how can I compile this on Linux" your question should be "I have this Windows dependency in an app targeted at multiple operating systems, how do I handle it?"
I was working with
javax.imageio.ImageIO class
The one provided by sun doesn't provide support for reading .tif files. So if I try to read a .tif file, it just returns a null. Then I downloaded this api from oracle's website and included it in the classpath. This api uses jni as was evident from a .so file in that folder. After that I didn't have to change anything in my code and it worked. How could this happen? Wouldn't the class names have clashed?
There were 3 things in the api that i had downloaded:
clibwrapper_jiio.jar
jai_imageio.jar
libclib_jiio.so
I didn't have to do any additional import. In fact, the functionality provided by the ImageIO class was enchanced
I am really curious about how this works.
Here is the class in javax.imageio package. The class has been declared as final. And it does some weird complex stuff that I can't understand. Could someone explain how to achieve this effect with a simpler example.
http://docs.oracle.com/javase/7/docs/api/javax/imageio/ImageIO.html
ImageIO has a scanForPlugins(...) method. I'd imagine that on class load time it takes a peek around the CLASSPATH and looks for anything that could extend its functionality.
The javadoc which hints to this is here.
You could do something similar by putting a static block in one of your classes
public class MyClass {
public static scanForExtensions() {
... code looking for extensions goes here ...
... for each found extension, register them in the "ExtensionRegistry"
ExtensionRegistry.register(extension);
}
static {
scanForExtensions();
}
public void doSomething(String input) {
for (Extension extension : ExtensionRegistry.getExtensions()) {
if (extension.canHandle(input)) {
extension.handle(input);
return;
}
}
throw UnhandledInputException("No extension to handle " + input);
}
}
Java's Image IO works using the Service Provider Interface (see links below for more details).
JavaSound works the same way. To add support for (e.g.) MP3 to JavaSound, it is only necessary to add the mp3plugin.jar of the JMF to the run-time class-path, then JavaSound can decode MP3 files as easily as it can a WAV (using the exact same classes - very funky).
I expect the installation of JAI did a similar thing, by adding a bunch of service providers for different image types to the lib directory of the JRE.
ImageWriterSpi
Creating Extensible Applications With the Java Platform.
By running System.loadLibrary("myAPI"), I verified that the DLL file "myAPI.dll" can be successfully loaded into my Eclipse Java project. Now I need to call methods specified inside this DLL file from my Java code. To do this, I added JNA to my Java project. Then I wrote the below-given code snippet that should be able to get instances of classes IProject and ProjectFactory (specified in the DLL file).
I still don't understand how to properly implement this with JNA. I checked different threads, e.g. this one, but the ones I checked don't provide an answer. Any help is highly appreciated. Thanks.
import com.sun.jna.Library;
import com.sun.jna.Native;
public class MyClass {
public interface myAPI extends Library {
//...
}
void LoadProj() {
myAPI api = (myAPI) Native.loadLibrary("myAPI",myAPI.class);
String fileName = "xxx.sp";
IProject project; // this is wrong but shows what I am trying to do
try {
project = ProjectFactory.LoadProject(fileName);
}
catch (Exception ex) {
MessageBox.Show(this, ex.Message, "Load failure");
}
}
}
Not sure what problem you are facing but as a practice your myAPI interface should declare all the methods verbatim with appropriate parameter mapping. I don't see any methods inside your interface.
Please checkout the this link as well as the link mentioned above by #Perception
If there are no Java classes or Java source hidden inside this DLL (which would be ... strange), then it will never work this way. You can't instantiate C# classes or use C# interfaces. MessageBox.Show( isn't Java either, it is Windows Forms code.