I want to do what's described in question 724043, namely encode the path components of a URI. The class recommended to do that is URIUtil from Commons HttpClient 3.1. Unfortunately, that class seems to have disappeared from the most recent version of HttpClient. A similarly named class from HttpClient 4.1, URIUtils, doesn't provide the same functionality. Has this class/method been moved to some other library that I'm not aware of or is it just gone? Am I best off just copying the class from the 3.1 release into my code or is there a simpler way?
The maintainers of the module have decreed that you should use the standard JDK URI class instead:
The reason URI and URIUtils got replaced with the standard Java URI was
very simple: there was no one willing to maintain those classes.
There is a number of utility methods that help work around various
issues with the java.net.URI implementation but otherwise the standard
JRE classes should be sufficient, should not they?
So, the easiest is to look at the source of encodePath from the 3.1 release and duplicate what it does in your own code (or just copy the method/class into your codebase).
Or you could go with the accepted answer on the question you referred to (but it seems you have to break the URL into parts first):
new URI(
"http",
"search.barnesandnoble.com",
"/booksearch/first book.pdf",
null).toString();
This can be achieved using org.apache.http.client.utils.URIBuilder utility in httpclient-4.X () as follows.
public static String encodePath(final String path) {
if(path.length() == 0)
return "";
else
return new URIBuilder().setPath(path).toString();
}
You can use Standard JDK functions, e.g.
public static String encodeURLPathComponent(String path) {
try {
return new URI(null, null, path, null).toASCIIString();
} catch (URISyntaxException e) {
// do some error handling
}
return "";
}
Related
Currently, this is how I check if a file is playable through the JavaFX MediaPlayer, since it's the way it is done internally.
import static com.sun.media.jfxmedia.MediaManager.canPlayContentType;
import static com.sun.media.jfxmediaimpl.MediaUtils.filenameToContentType;
public boolean isPlayable(String filename) {
return canPlayContentType(filenameToContentType(filename));
}
the problem is that the packages that contain these Methods "are not API" and not accessible on Java 9 anymore. I know that there are workarounds, but I wonder if there is an actually correct, future-proof way of doing this?
I want this method to populate a Library with all the playable content within a directory:
Files.find(folderPath, Integer.MAX_VALUE, (path, attr) ->
attr.isRegularFile() && isPlayable(path.toFile().getName()))
.forEach(path -> addSong(path));
I went through the documentation of javafx.media module for the sake of finding any such built-in API and was unable to find one.
A look at the existing Implementation of filenameToContentType(String filename), which is somewhat:-
if (extension.equals(FILE_TYPE_AIF) || extension.equals(FILE_TYPE_AIFF)) {
contentType = CONTENT_TYPE_AIFF;
} else if ... other content types
That eventually checks if the current file extension is one of the supported container type and returns the content types based on the same.
The other piece on the board crucially was canPlayContentType(String contentType) which seems to be relying eventually on the supportedContentTypes for each platform as defined in the NativeMediaManager class.
Though I haven't tested the solution as proposed below primarily due to unawareness of the overview of the task that you intend to perform eventually. Yet, the closest to your current implementation and what Basic PlayBack guidelines suggests as well, was to try
Construct a Media instance out of the filename that you were providing.
Check for a MediaException if any while performing (1).
Further, the exception type MediaException.Type MEDIA_UNSUPPORTED states that
Indicates that this media type is not supported by this platform.
Drawing from the analogy with this and your current solution, you could probably make use of the this:
private static boolean isPlayable(String filename) {
try {
Media media = new Media(filename);
} catch (MediaException e) {
if (e.getType() == MediaException.Type.MEDIA_UNSUPPORTED) {
return false;
}
}
return true;
}
PS: Though I believe this could be further optimized if you actually start making use of the Media constructed(as in the above stub) right away in your piece of code instead of just dropping it.
Today I tried including the apache.commons.codec package in my Android application and couldn't get it running. Android could not find method ord.apache.commons.codec.binary.* and output the following errors in DDMS
01-12 08:41:48.161: ERROR/dalvikvm(457): Could not find method org.apache.commons.codec.binary.Base64.encodeBase64URLSafeString, referenced from method com.dqminh.app.util.Util.sendRequest
01-12 08:41:48.161: WARN/dalvikvm(457): VFY: unable to resolve static method 10146: Lorg/apache/commons/codec/binary/Base64;.encodeBase64URLSafeString ([B)Ljava/lang/String;
01-12 08:41:48.161: WARN/dalvikvm(457): VFY: rejecting opcode 0x71 at 0x0004
Any clue on how to solve this problem ? Thanks a lot.
I had a similar problem while using android with an OAuth library I'm developing.
I also got from android that, although I had included apache.commons.codec in the classpath, a particular method (encodeBase64String) was not found.
Checking the javadocs, both methods claim to be 1.4 and greater only, so my guess is that android already includes an older version of commons.codec where these methods are indeed undefined.
My solution was to use an older method, like this:
String encodedString = new String(Base64.encodeBase64('string to encode'));
The method you want to use is different since it replaces + and / with url-safe values - and _. So you probably might use something like:
String encodedString = new String(Base64.encodeBase64('string to encode'));
String safeString = encodedString.replace('+','-').replace('/','_');
You don't have to use apache commons, on android you can use android.util.Base64 instead.
I experienced the exact same problem. So i started browsing the android source code, and as it turns out Pablo Fernandez's guess about Android having an implementation of org.apache.commons.code.binary is correct. However, its version 1.2 of the apache commons, not version 1.4 or even 1.5.
You can see for your self in the android source.
as a note this is question is a duplicate of this post
You can use the following function:
private static String encodeBase64URLSafeString(byte[] binaryData) {
return android.util.Base64.encodeToString(binaryData, Base64.URL_SAFE);
}
source + listing of other possible flags: http://developer.android.com/reference/android/util/Base64.html
My solution to the same problem was to rename the problematic class org.apache.commons.codec.binary.Base64.java into org.apache.commons.codec.binary.ApacheBase64.java. I did it using Eclipse refactor-rename.
That way, the latest and greatest apache solution is preserved and used, and there is no chance for accidental problem recurrence when my app is eventually being lifted from android 1.6 lowest denominator.
Note I had the entire apache commons source tree already set as separate Eclipse java project, next to my Android project. My Android project used many of Apache Commons classes, but failed on Base64 because of above described problems...
You could simply copy this code bit from the apache library (it is pretty isolated)
http://www.java2s.com/Open-Source/Android/Blog-Twitter/twitspeak/org/apache/commons/codec/binary/Base64.java.htm
Edit:
Updated link from the Wayback Machine as the original is gone:
http://web.archive.org/web/20130610025148/http://www.java2s.com/Open-Source/Android/Blog-Twitter/twitspeak/org/apache/commons/codec/binary/Base64.java.htm
Please note that this answer was made by Dylan Watson in the comments above:
Be aware that you need to use Base64.encode("foobar".getBytes(),
Base64.Base64.NO_WRAP); to get exactly the same result as the apache
commons library. See: stackoverflow.com/questions/17912119
This answer was the only which worked after hours of trying to communicate my android app with a java "desktop" app.
So here is some source code, maybe it will help others:
Code from the desktop applet:
private static String convertToBase64(String s) {
byte[] bytes = new byte[0];
try {
bytes = (s.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
return DatatypeConverter.printBase64Binary(bytes);
}
This snippet is used in the android app:
public static String convertToBase64(String password) {
byte[] bPwd = new byte[0];
try {
bPwd = (password.getBytes("UTF-8"));
} catch (Exception e) {
e.printStackTrace();
}
try {
password = new String(Base64.encode(bPwd, Base64.NO_WRAP), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return password;
}
You can simply import the following library under Gradle dependency
dependencies {
implementation "commons-codec:commons-codec:1.11"
}
It will work
did you include apache commons project lib,like
org.apache.commons:commons-compress
org.apache.commons:commons-email
org.apache.commons:commons-io
org.apache.commons:commons-lang3
org.apache.commons:commons-parent
org.apache.commons:commons-pool2
the commons-codec 's GAV is
commons-codec:commons-codec
but it's package name is
org.apache.commons.codec
this package name will be conflict with apache commons project libs,try to change the package name of commons-codec,then generate it as a jar or import the source code had changed the package name;
Knowing that this is an old question, but I faced this problem recently when compiling for API Level 23, and found another solution for the problem: use guava project.
// Encoding
String encodedString = BaseEncoding.base64().encode(text.getBytes(UTF_8));
System.out.println("encodedString: " + encodedString);
// Decoding
byte[] decodedString = BaseEncoding.base64().decode(encodedString);
System.out.println("decodedString: " + new String(decodedString, UTF_8));
The guava library (18.0) was the version that I've used, and the change was smooth. The code works as expected.
Solution found in here: https://memorynotfound.com/encode-decode-base64-string-using-native-java/
This works for me:
import org.apache.commons.codec.binary.Base64;
/**
* This is used to get the base64 from the bytes
*
* #param rawBytes the raw bytes
* #return the base64 encoded string
*/
public static String getBase64String(byte[] rawBytes) {
String base64Str = "";
if (rawBytes!= null) {
base64Str= new String(Base64.encodeBase64(rawBytes));
}
return base64Str;
}
public static byte[] getBase64DecodedString(String base64EncodedStr) {
byte[] base64Bytes = Base64.decodeBase64(base64EncodedStr.getBytes());
return bitmap;
}
I'm currently dealing with a particular issue with my paid application. Internally it contains a licensing check. The app is patched by hackers by modifying the app apk/jar. They are adding a new class which helps bypass the licensing check.
My goal is to somehow check for this particular patch. If I find it I know my app has been compromised.
Any tips on how to know that something has been modified on the package? Doing a hash over the app is not really an option in my case.
I thought maybe checking if this class exists would help, but what if they change the name of the class? Then, another idea is somehow check for unexpected includes added to the class.
Any of these possible? Any suggestions would help :)
Not sure about android but in standard JDK you would do something like this:
try {
Class.forName( "your.fqdn.class.name" );
} catch( ClassNotFoundException e ) {
//my class isn't there!
}
Here is what I used in Android - standard Java:
public boolean isClass(String className) {
try {
Class.forName(className);
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
Implementation example:
if (isClass("android.app.ActionBar")) {
Toast.makeText(getApplicationContext(), "YES", Toast.LENGTH_SHORT).show();
}
You can use
public static Class<?> forName (String className)
and check the ClassNotFoundException
http://developer.android.com/reference/java/lang/Class.html#forName%28java.lang.String%29
How does it get loaded if it's a random class in a random package?
That being said, see http://download.oracle.com/javase/6/docs/api/java/lang/System.html#getProperties%28%29 and java.class.path. For normal java apps, you have to walk the classpath and then search the entries (for jars) or directories (for .class files). But in a container-class-loader environment, this will fail to work (and I'm not sure how that applies to an android environment).
I am wrapping a shared library (written in C) with Java using JNA. The shared library is written internally, but that library uses functions from another external library, which again depends another external library. So the situation is something like this:
ext1 <- ext2 <- internal
I.e. the internal uses external library ext2 which again uses external library ext1. What I have tried is:
System.loadLibrary("ext1");
System.loadLibrary("ext2");
NativeLIbrary.loadLibrary("internal",xxx.class);
This approach fails with "UnresolvedException" when loading the library "ext2"; the linker complains about symbols which are indeed present in the library "ext1". So it semmes that the System.loadLibrary() function does not make the symbols from "ext1" globally available? When using the stdlib function dlopen() as:
handle = dlopen( lib_name , RTLD_GLOBAL );
All the symbols found in #lib_name will be available for symbol resolution in subsequent loads; I guess what I would like was something similar for the java variety System.loadLibrary()?
Regards - Joakim Hove
It's an old question, but I've found an acceptable solution, which should also be portable, and I thought I should post an answer. The solution is to use JNA's NativeLibrary#getInstance(), because on Linux this will pass RTLD_GLOBAL to dlopen() (and on Windows this is not needed).
Now, if you are using this library to implement a Java native method, you will also need to call System.load() (or Sysem.loadLibrary()) on the same library, after calling NativeLibrary#getInstance().
First, a link to a JNA bug: JNA-61
A comment in there says that basically one should load dependencies before the actual library to use from within JNA, not the standard Java way. I'll just copy-paste my code, it's a typical scenario:
String libPath =
"/path/to/my/lib:" + // My library file
"/usr/local/lib:" + // Libraries lept and tesseract
System.getProperty("java.library.path");
System.setProperty("jna.library.path", libPath);
NativeLibrary.getInstance("lept");
NativeLibrary.getInstance("tesseract");
OcrTesseractInterf ocrInstance = (OcrTesseractInterf)
Native.loadLibrary(OcrTesseractInterf.JNA_LIBRARY_NAME, OcrTesseractInterf.class);
I've written a small library to provide OCR capability to my Java app using Tesseract. Tesseract dependes on Leptonica, so to use my library, I need to load libraries lept and tesseract first. Loading the libraries with the standard means (System.load() and System.loadLibrary()) doesn't do the trick, neither does setting properties jna.library.path or java.library.path. Obviously, JNA likes to load libraries its own way.
This works for me in Linux, I guess if one sets the proper library path, this should work in other OSs as well.
There is yet another solution for that. You can dlopen directly inside JNI code, like this:
void loadLibrary() {
if(handle == NULL) {
handle = dlopen("libname.so", RTLD_LAZY | RTLD_GLOBAL);
if (!handle) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
}
}
...
...
loadLibrary();
This way, you will open library with RTLD_GLOBAL.
You can find detailed description here: http://www.owsiak.org/?p=3640
OK;
I have found an acceptable solution in the end, but not without significant amount of hoops. What I do is
Use the normal JNA mechanism to map the dlopen() function from the dynamic linking library (libdl.so).
Use the dlopen() function mapped in with JNA to load external libraries "ext1" and "ext2" with the option RTLD_GLOBAL set.
It actually seems to work :-)
As described at http://www.owsiak.org/?p=3640, an easy but crude solution on Linux is to use LD_PRELOAD.
If that's not acceptable, then I'd recommend the answer by Oo.oO: dlopen the library with RTLD_GLOBAL within JNI code.
Try this, add this function to your code. Call it before you load your dlls. For the parameter, use the location of your dlls.
public boolean addDllLocationToPath(String dllLocation)
{
try
{
System.setProperty("java.library.path", System.getProperty("java.library.path") + ";" + dllLocation);
Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
fieldSysPath.setAccessible(true);
fieldSysPath.set(null, null);
}
catch (Exception e)
{
System.err.println("Could not modify path");
return false;
}
return true;
}
}
In order to fix your issue you can use this package: https://github.com/victor-paltz/global-load-library. It loads the libraries directly with the RTLD_GLOBAL flag.
Here is an example:
import com.globalload.LibraryLoaderJNI;
public class HelloWorldJNI {
static {
// Loaded with RTLD_GLOBAL flag
try {
LibraryLoaderJNI.loadLibrary("/path/to/my_native_lib_A");
} catch (UnsatisfiedLinkError e) {
System.Println("Couldn't load my_native_lib_A");
System.Println(e.getMessage());
e.printStackTrace();
}
// Not loaded with RTLD_GLOBAL flag
try {
System.load("/path/to/my_native_lib_B");
} catch (UnsatisfiedLinkError e) {
System.Println("Couldn't load my_native_lib_B");
System.Println(e.getMessage());
e.printStackTrace();
}
}
public static void main(String[] args) {
new HelloWorldJNI().sayHello();
}
private native void sayHello();
}
It is using the same dlopen() trick as the previous answers, but it is packaged in a standalone code.
As it was made clear in my recent question, Swing applications need to explicitly call System.exit() when they are ran using the Sun Webstart launcher (at least as of Java SE 6).
I want to restrict this hack as much as possible and I am looking for a reliable way to detect whether the application is running under Webstart. Right now I am checking that the value of the system property "webstart.version" is not null, but I couldn't find any guarantees in the documentation that this property should be set by future versions/alternative implementations.
Are there any better ways (preferably ones that do not ceate a dependency on the the webstart API?)
When your code is launched via javaws, javaws.jar is loaded and the JNLP API classes that you don't want to depend on are available. Instead of testing for a system property that is not guaranteed to exist, you could instead see if a JNLP API class exists:
private boolean isRunningJavaWebStart() {
boolean hasJNLP = false;
try {
Class.forName("javax.jnlp.ServiceManager");
hasJNLP = true;
} catch (ClassNotFoundException ex) {
hasJNLP = false;
}
return hasJNLP;
}
This also avoids needing to include javaws.jar on your class path when compiling.
Alternatively you could switch to compiling with javaws.jar and catching NoClassDefFoundError instead:
private boolean isRunningJavaWebStart() {
try {
ServiceManager.getServiceNames();
return ds != null;
} catch (NoClassDefFoundError e) {
return false;
}
}
Using ServiceManager.lookup(String) and UnavailableServiceException is trouble because both are part of the JNLP API. The ServiceManager.getServiceNames() is not documented to throw. We are specifically calling this code to check for a NoClassDefFoundError.
Use the javax.jnlp.ServiceManager to retrieve a webstart service.
If it is availabe, you are running under Webstart.
See http://download.java.net/jdk7/docs/jre/api/javaws/jnlp/index.html
As you mentioned, checking the System property as follows is probably the cleanest way:
private boolean isRunningJavaWebStart() {
return System.getProperty("javawebstart.version", null) != null;
}
In a production system I have used the above technique for years.
You can also try to check to see if there are any properties that start with "jnlpx." but none of those are really "guaranteed" to be there either as far as I know.
An alternative could be to attempt to instantiate the DownloadService us suggested by Tom:
private boolean isRunningJavaWebStart() {
try {
DownloadService ds = (DownloadService) ServiceManager.lookup("javax.jnlp.DownloadService");
return ds != null;
} catch (UnavailableServiceException e) {
return false;
}
}
Of course that does have the downside of coupling your code to that API.
I have no real experience with Java web start other than looking at it a few years back.
How about start your application with a parameter that you define than you set when the app is started via Java web start.
If you want to pass in arguments to your app, you have to add them to the start-up file (aka JNLP descriptor) using or elements.
Then check to see if these properties are set.
Again this is a suggestion I have not coded for JWS and it may not be this easy.
You can check whether the current classloader is an instance of com.sun.jnlp.JNLPClassLoader (Java plugin 1) or sun.plugin2.applet.JNLP2ClassLoader (Java plugin 2). Despite the "applet" package, an applet using JNLP with the Java plugin 2 uses another classloader, sun.plugin2.applet.Applet2ClassLoader. It works with OpenJDK too.