Jruby: How to use third party java library? - ruby-on-rails-3

I want to use java third party qr code libary https://github.com/kenglxn/QRGen library for generating qr code.
Please guide me as i don't know how to integrate java library in jruby.

The trick in this case is to find how to properly import the 3rd party libs.
Please download the needed jars using any dependency system (I use ant with ivy).
This will download 5 jars based on the qr code library you mentioned: core-2.0.jar core-3.1.0.jar javase-2.0.jar javase-3.1.0.jar jfreesvg-2.1.jar
build.xml for ant:
<project xmlns:ivy="antlib:org.apache.ivy.ant" name="" default="retrieve">
<!--setproxy proxyhost="" proxyport="" proxyuser="" proxypassword=""/-->
<target name="retrieve">
<ivy:retrieve/>
</target>
</project>
ivy.xml for ivy:
<ivy-module version="2.0" >
<info organisation="" module=""/>
<dependencies defaultconf="default">
<dependency org="net.glxn.qrgen" name="javase" rev="2.0"/>
</dependencies>
</ivy-module>
Now typing ant retrieve will download and store 5 jars in lib subfolder.
If you do not have a dependency manager, here are the 5 jars urls you need to download manually and you need to move to a subfolder called lib:
http://search.maven.org/remotecontent?filepath=net/glxn/qrgen/javase/2.0/javase-2.0.jar
http://search.maven.org/remotecontent?filepath=com/google/zxing/javase/3.1.0/javase-3.1.0.jar
http://search.maven.org/remotecontent?filepath=com/google/zxing/core/3.1.0/core-3.1.0.jar
http://search.maven.org/remotecontent?filepath=net/glxn/qrgen/core/2.0/core-2.0.jar
http://search.maven.org/remotecontent?filepath=org/jfree/jfreesvg/2.1/jfreesvg-2.1.jar
I strongly advise you to use a java dependency manager if you wish one day to upgrade the revisions of the java libraries used in this code snippet.
Next step is to use the following ruby snip.rb code in the same folder. :
require 'java'
%w[
lib/core-2.0.jar
lib/core-3.1.0.jar
lib/javase-2.0.jar
lib/javase-3.1.0.jar
lib/jfreesvg-2.1.jar
].map &method(:require)
# this is the CRITICAL line to get it to work...
include_class 'net.glxn.qrgen.javase.QRCode'
# get QR file from text using defaults
# this will write a file (example: QRCode7247556396487679822.png) in java.io.tmpdir as defined in your JVM
file = QRCode.from("Hello World").file()
p file.name
# get QR stream from text using defaults
# if we redirect the stream as a byte array, we can have a better file control
include_class 'java.io.FileOutputStream'
stream = QRCode.from("Hello World").stream()
fos = FileOutputStream.new("QRCode.png")
fos.write(stream.toByteArray())
fos.close()
# fun with VCards
include_class 'net.glxn.qrgen.core.vcard.VCard'
johnDoe = VCard.new("John Doe")
johnDoe.setEmail("john.doe#example.org")
johnDoe.setAddress("John Doe Street 1, 5678 Doestown")
johnDoe.setTitle("Mister")
johnDoe.setCompany("John Doe Inc.")
johnDoe.setPhoneNumber("1234")
johnDoe.setWebsite("www.example.org")
stream = QRCode.from(johnDoe).stream()
fos = FileOutputStream.new("VCard.png")
fos.write(stream.toByteArray())
fos.close()
# all generated PNG can be decoded online using http://zxing.org/w/decode.jspx
Please note: jruby and java.io.tmpdir do not play well together in this particular jar case, as any call to QRcode creation with #file() will store file in java.io.tmpdir, whereever it is located. You've little control on the file location.
So I modified the original code answer to use the stream instead and create files with finer control.
You can verify all files generated with this useful URL: http://zxing.org/w/decode.jspx

Related

How to whitelist a vendor-specific API in AOSP for Android 10

I'm trying to add a vendor-specific API to my AOSP code base. I was able to get this working on Android 5 through 9, but cannot figure this out on Android 10.
I read the documentation on the AOSP docs for Implementing Java SDK Library
I have the following blueprint file:
java_sdk_library {
name: "com.mycompany.sdk.myclass",
srcs: ["java/**/*.java"],
api_packages: ["com.mycompany.sdk.myclass"],
}
I generated the api subdirectory using:
build/soong/scripts/gen-java-current-api-files.sh "vendor/mycompany/sdk/myclass" && m update-api
This put all my public method signatures into the current.txt file.
I added this as a boot jar to my top level board.mk file with:
PRODUCT_BOOT_JARS += com.mycompany.sdk.myclass
Building this creates the corresponding com.mycompany.sdk.myclass.xml permissions file:
<?xml version="1.0" encoding="utf-8"?>
<permissions>
<library name="com.mycompany.sdk.myclass"
file="/system/framework/com.mycompany.sdk.myclass.jar"/>
</permissions>
Everything builds and installs fine. I verified the permissions file is in /system/etc/permissions/ and points to the correct jar filename. But I get "Accessing hidden method (blacklist, linking, denied)" exceptions when I run a test app built against my private SDK:
W/test_app: Accessing hidden method Lcom/mycompany/sdk/myclass;->myMethod(Landroid/content/Context;Z)V (blacklist, linking, denied)
I can eliminate this blacklist error by issuing the command:
adb shell settings put global hidden_api_policy 1
So I know my jar is being built and installed correctly. But is just blacklisted for 3rd parties.
I eventually added my package name to frameworks/base/config/hiddenapi-greylist-packages.txt, and suddenly my test app runs, and properly finds the private API. Unfortunately, the blacklist errors are replaced by greylist warnings on every method call. I don't want the log cluttered with these warnings, so it must be whitelisted, not greylisted.
I tried adding it to /build/make/core/tasks/check_boot_jars/package_whitelist.txt, but this made no difference.
How do I whitelist my private API instead of greylist?
There is no white list.
The white list (allow list) is the methods listed in Android SDK.
Private API are not in Android SDK.

How to generate openapi client from uri in Gradle

I'm probably trying to do something strange, since this doesn't seem like a common question (or maybe I'm asking it all wrong). I was expecting this to be straightforward.
Basically, what I am looking for is a way to do the same as the following, except by using the gradle openapi-generator plugin:
openapi-generator generate -i www.example.com/openapi-doc -g spring
What I have tried is the following (and the associated errors):
inputSpec.set("www.example.com/openapi-doc") --> Cannot convert URL {} to a file
inputSpec.set(URL("www.example.com/openapi-doc").readText()) --> specified for property 'inputSpec' does not exist
The actual code looks something like this:
tasks.register<GenerateTask>("generateClient") {
validateSpec
generatorName.set("spring")
library.set("spring-cloud")
// inputSpec.set("$openapiSpecDir/client/openapi.json") <-- *I am currently using a file, which I don't want to do*
inputSpec.set("https://www.example.com/openapi-doc")
outputDir.set(generatedClientDir)
apiPackage.set("org.example.api")
modelPackage.set("org.example.model")
skipOverwrite.set(false)
templateDir.set("$rootDir/src/main/resources/openapi/templates/client")
configOptions.put("java8", "false")
configOptions.put("serializationLibrary", "jackson")
configOptions.put("dateLibrary", "java8")
}
Assuming you're using the OpenAPI Generator Gradle Plugin, at the time of writing this answer, getting the inputSpec from a URL is not supported. However, for Maven this has been implemented (Issue #2241 closed with PR #3826), so chances are good to have it implemented with a feature request that gets the Gradle plugin on par with its Maven counterpart.
That being said, you may want to look into Gradle Download Task. Gradle Download Task is a plugin that let's you download files from a URL. The downloaded file can be used to feed it into the OpenAPI generator.

Jython does not resolve python imports from bundled Lib files/folders on Weblogic 10.3.5

I am new to Jython and Python, trying to build a prototype that makes use of Python code to be called from within Java. The code I am developing works in Jetty and in standalone mode (running java -jar from the command line), but not when deployed to weblogic.
How can I make weblogic(10.3.5) server/Jython recognize the Lib folder within jython-standalone-2.5.4-rc1.jar?
My Java code uses the JythonObjectFactory to invoke python modules as outlined in the Jython book:
http://www.jython.org/jythonbook/en/1.0/JythonAndJavaIntegration.html
The Python modules are using external libraries like csv, logging etc. that are not packaged with jython.jar, hence I am using jython-standalone jar.
The java code includes an interface that would define the class type of the first invoked py module from within java. The interface and the input and output (to python modules) type classes are in a package structure as com.abc.xpackage. and the py modules exist at the root of this package. A controller layer calls the objectfactory and in turn executes the python code thus:
JythonObjectFactory calFactory = new JythonObjectFactory(CalcType.class, "Calculate", "Calculate");
CalcType engine = (CalcType)calFactory.createObject();
output = engine.execute(input);
The entire code is bundled as a jar file which would become part of a web application deployed on weblogic. The code was compiled with maven (with jython dependencies included in the repository) and runs fine on the included Jetty runtime within eclipse.
When deployed on weblogic, however, I get a "ImportError: no module named csv" error.
To analyze what is happening, I tried printing the Jython system state path on weblogic and the standalone environment/Jetty. What I found is,
on Jetty, the system path consists of the following:
C:\.m2\repo\org\python\jython\jython-standalone-2.5.3-rc1.jar\Lib, ____classpath__, ____pyclasspath__
on Weblogic, printing the system path by default shows the following:
____classpath__, ____pyclasspath__
I tried forcing the inclusion of the missing path using the code as follows:
public JythonObjectFactory(PySystemState state, Class interfaceType, String moduleName, String className) {
String pathToAppend = new File(state.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getAbsolutePath()+"\\Lib";
state.path.insert(0, new PyString(pathToAppend));
state.path.append(new PyString(pathToAppend));
System.out.println("Jython sys path: "+state.path);
Please note, I prepended as well as appended the path in different trials. The sys path on weblogic now displays the following:
Jython sys path: ['C:\\wldomain\\wls135\\servers\\cgServer\\tmp\\app-1\\war\\WEB-INF\\lib\\jython-standalone-2.5.4-rc1.jar\\Lib', '__classpath__', '__pyclasspath__/', 'C:\\wldomain\\wls135\\servers\\cgServer\\tmp\\app-1\\war\\WEB-INF\\lib\\jython-standalone-2.5.4-rc1.jar\\Lib']
I am still getting ImportError despite this forcing of sys path. Please help why this works in a local environment, and not on weblogic, and if there is any configuration I am missing. Apologize for the rambling long post, I did not know how to explain the problem better. I will try and include any code/artifacts as needed.
Based on a comment(by Lassi) on the blog post below:
http://www.petervannes.nl/files/e1c3c56d15d25dcfd4adb5397a9ef71e-53.php
The jython issue was resolved after explicitly adding the Lib folder python.path to the weblogic startup script as a JAVA_OPTION.
In my case I added the exploded Lib folder to the domain server lib, but based on my test this works also from within the jython jar. Both the following JAVA_OPTIONS worked:
-Dpython.path=C:\wldomain\wls135\lib\Lib
-Dpython.path=C:\wldomain\wls135\lib\jython-standalone-2.5.4-rc1.jar\Lib
The programmatic way of sys.path.append worked for the local environment(jetty) but did not seem to work for weblogic.

Android Studio: How to attach javadoc

It might be very trivial question, But I couldn't find any option to attach javadoc/source with local jar dependencies (in libs folder) in android project. I can't believe I have spent a hour on such simple stuff :(
Google search result just tells about adding android documentation or adding javadoc in eclipse. That's not What I am looking for!
I found a solution just now since I can't find any other solution for a long time.
suppose:
your lib name is: libxxx.jar
javadoc name is docs.zip
under folder .idea/libraries, you can find libxxx.xml. replace JAVADOC with
<JAVADOC>
<root url="jar://C:/yourpath/doc.zip!/" />
</JAVADOC>
then ctrl+alt+y to sync the project. (Don't do "Sync Project with Gradle files", it will delete the changes)
I've found & tested a way in which we can add the javadocs without loosing them after a gradle sync.
Right click in Project panel > External libraries > lib-name
Click Library properties
Click specify documentation URL
And specify an URL. For my machine it was file:///opt/android-sdk/extras/google/google_play_services/docs/reference
The result was:
And after a project sync I could browse the javadoc of the google play services
Note:
This placed the same JAVADOC entry in the xml identified by Jason but doesn't disappear after doing a sync with gradle
It is possible:
Open Project structure
Navigate to dependency that you want
Press button from the screenshot and provide folder or file
Another way to attach sources:
Step into class from library (Hover mouse over class name and do CMD + Left click or CMD + B)
You will see decompiled version of class there menu on the top right side of editor "Attach sources.."
I had problem with answer from Matyas that I wasn't seeing my local .jar library in the External Libraries list, because it only show maven attached libs.
Solution is mentioned here: https://code.google.com/p/android/issues/detail?id=73087#c26
Right click on the "Structure" tab and check "Split Mode" (so you can open both "Project" and "Structure" tabs at same time).
Open both "Project" and "Structure" tabs at the same time.
In "Project" tab select "Android" perspective and then select your module folder (e.g. "app")
In "Structure" window you should now see list of all libraries, including your local *.jar
Continue as in answer from Matyas:
Right click on wanted library and select "Library Properties..."
If you have *.jar with javadocs locally, you can press "add" button (green "+") and search for the file on your disk (you don't have to type "file://" path manually).
Still a current issue as of my posting it seems:
https://code.google.com/p/android/issues/detail?id=73087
After some investigation, I stumbled upon this:
https://github.com/xujiaao/AARLinkSources
Works like magic!
I wasted so much time on this too...
Here's a gradle task which finds source and javadoc by location/naming convention, and registers them in the .idea files on sync. It belongs in the root gradle file's allProjects section. As-is, it expects to find [projectname]/libs/lib.jar next to lib-sources.jar and/or lib-javadoc.jar. Also, as noted in comments, if your javadocs not pathed at "/" inside the jar, you may need to change the script to add "docs/html" (for example) at the end of "jar://$doc!/".
allprojects {
task addJavaDoc {
afterEvaluate {
// Specify paths, this will be run per non-root project
def projectDir = project.getProjectDir().getCanonicalPath()
def rootDir = project.getRootDir().getCanonicalPath()
def lib = projectDir + '/libs'
// println lib // Uncomment this to troubleshoot
// Get any jar dependencies register in the lib folder
fileTree(include: ['*.jar'], exclude: ['*-source.jar', '*-javadoc.jar'], dir: lib ).each { File jar ->
def jarName = jar.getName()
def moduleName = jarName.substring(0, jarName.lastIndexOf("."))
// IntelliJ does this to file names when making the xml files
def escapedName = moduleName.replace("-", "_").replace(".", "_")
def xmlFile = "$rootDir/.idea/libraries/${escapedName}.xml"
// println xmlFile // Uncomment this to troubleshoot
if (new File(xmlFile).exists()) {
['javadoc', 'sources'].each {String docType ->
// Get sources or java doc by naming convention, (expects name-sources or name-javadoc
def doc = "$lib/$moduleName-${docType}.jar"
// println doc // Uncomment this to troubleshoot
if(new File(doc).exists()) {
def xml = new XmlParser().parse(xmlFile);
def xmlTag = docType.toUpperCase()
// Perform xml replacement by convention
xml.library[xmlTag].replaceNode {
"$xmlTag" {
root(url: "jar://$doc!/")
}
}
// Write out changes
new XmlNodePrinter(new PrintWriter(new FileWriter(xmlFile))).print(xml)
// Notify that changes worked
println "Fixed up reference to $doc"
}
}
}
}
}
}
}
Also, if you are using jcenter or mavencentral, javadocs and sources should work for downloaded jars without using that task, but you may have to add this in each non-root gradle file:
apply plugin: 'idea'
idea{
module {
downloadJavadoc = true
downloadSources = true
}
}
Personally tested successfully!
1.Project Structure(ctrl+alt+shift+s)
2.SDK Location
3.JDK Location
4.UnCheck "Use embedded JDK(recommended)"
5.Select your own jdk path(My Path:C:\Program Files\Java\jdk1.8.0_111)
6.Synchronized(ctrl+alt+y)
success
in android studio if you use compileSdkVersion 23 in buidl.gradle and you have downloaded the SDK 23 document file and source file in SDK manager , the android API and java API doc and source will all show auto, you don't need to manual set.
There is a solution, This procedure take place through terminal ,
I have tested solution in MAC OS.
1) Move to your project folder
2) ls -al (to show hidden files)
3) Move to .idea folder , Command : cd .idea
4) Move to libraries folder , Command : cd libraries/
5) Now you can see list of all xml files for your libs or jars. Edit it like , vi open androidasync_2_1_7.xml
6) In the editor screen ,
For inserting
Press i
Now you see <SOURCES /> tag we have to provide a path here like,
<SOURCES>
<root url="file://$PROJECT_DIR$/androidasync/src/main/java" />
</SOURCES>
For exiting
Press Esc
:wq //for exiting and saving
:q! //for exiting without saving
7) Restart Android studio (Sometime it needed also sync gradle).

Update To JRE7, can not load nativelib jar, but JRE6 works fine

For my JNLP file , there is some nativelib info like below:
<resources os="Windows">
<nativelib href="lib/x264-win.jar" />
</resources>
<resources os="SunOS" arch="sparc">
<nativelib href="lib/x264-SunOS-sparc.jar" />
</resources>
<resources os="SunOS" arch="x86">
<nativelib href="lib/x264-SunOS-x86.jar" />
</resources>
When I Update To JRE7, can not load nativelib jar, but JRE6 works fine.
The load nativelib code like below:
String source = "x264.jar";
ClassLoader cl = Thread.currentThread().getContextClassLoader();
URL url= cl.getResource(source);
"x264.jar" is one jar in x264-win.jar,lib/x264-SunOS-sparc.jar or lib/x264-SunOS-x86.jar.
When I used JRE6 to load x264.jar, it worked fine.
But when I updated to JRE7, it can not load x264.jar.
When use JRE6, url would be"x264.jar" info, like jar:http://test.local:8080/JNLP.jar!/x264.jar,
but use JRE7, url would be null, and I found code not load nativelib "x264.jar"
Does any one have find JRE7 can not load nativelib.jar?
Is the problem of using Thread.currentThread().getContextClassLoader() to load "x264.jar"?
Ensure that you have the correct bitwise native binary to match your JRE. If you are testing on a 64-bit JRE, you need a 64-bit native binary. If you're testing on a 32-bit JRE, you need a 32-bit native binary. You might need to include resources for each of these three:
<resources os="Windows" arch="amd64">
<resources os="Windows" arch="x86_64">
<resources os="Windows" arch="x86">
I had similar trouble ; however even in JRE 6 this didn't get this to work.
Found a bug that could be related to that :
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6758884
Apparently JRE can have trouble downloading nativelib resources.
The bug is still opened, and targeted towards version 8 of java ...
The following "dll relying" applet is working fine (besides the security problems when using 1.7.0_51 (you need to decrease the security settings to medium since it is self signed)).
So if the native lib loading mechanism of the jnlp file is broken then you can distribute your .dll files alongside a normal jar file like in the upper example.
Put the dlls/sos in your jar file like in the example: jssc.jar
Load the libraries with System.load(libFolderPath + fileSeparator + libName); like used here.
As mentioned by Joseph please note the fine grained version differentiation between win, solaris, linux, arm and i86 and amd64 bit systems. So if you e.g. don't supply a 64Bit dll and run it with 64Bit Java it won't work...
I had forgot I solved this a while ago. I found that I had to handle this in Java code with System.loadLibrary( "jarNameNoExtension" );
Hopefully that helps others.