How to use tinylog in Eclipse plugin - eclipse

I am writing an Eclipse plugin and want to use tinylog in my plugin code. I tried this:
1). modified Eclipse config file (eclipse.ini) to add this line:
-Dtinylog.configuration=C:\eclipse-cpp-2018-09-win32-x86_64\eclipse\tinylog.properties
2). content of tinylog.properties:
writer = file
writer.level = debug
writer.file = C:\eclipse-cpp-2018-09-win32-x86_64\eclipse\log.txt
writer.charset = UTF-8
writer.append = true
writer.buffered = true
After launching Eclipse and run my plugin, I couldn't see log.txt
BTW, my tinylog version is of 1.3.6

You are using tinylog 1 with a configuration for tinylog 2. The correct configuration for tinylog 1.3.6 would be:
tinylog.writer = file
tinylog.writer.level = debug
tinylog.writer.filename = C:\eclipse-cpp-2018-09-win32-x86_64\eclipse\log.txt
tinylog.writer.buffered = true
tinylog.writer.append = true
In tinylog 1.3.6, the charset cannot be defined in the configuration. Instead, tinylog 1 will use the default charset for your system. The manual for tinylog 1 can be found here: https://tinylog.org/v1/configuration
Update: I just uploaded a working minimal example project on GitHub: https://github.com/pmwmedia/tinylog-eclipse-plugin-example. It contains an Eclipse plug-in that uses tinylog 1.3.6 as logging framework.

Related

Datanucleus enhancement with Bazel

I'm trying to migrate Maven project to Bazel and having troubles with Datanucleus enhancement.
After jar-file is build, Datanucleus looks inside it and does some byte-code manipulation to enhance persistable classes. The way to perform this in Bazel is by defining a rule that takes the *.jar output of java_library rule and creates a new enhanced version of the library.
The problem that I have is that for my rule I need datanucleus-core package from external libraries. When I try to access it from a genrule by $(location //third_party:datanucleus_core) it point to a jar which has no classes:
(genrule) cmd = "echo $(location //third_party:datanucleus_core)"
bazel-out/local-fastbuild/bin/third_party/liborg_datanucleus_datanucleus_core.jar
(genrule) cmd = "jar tf $(location //third_party:datanucleus_core)"
META-INF/
META-INF/MANIFEST.MF
The jar-file resolved by Bazel in genrule from $(location //third_party:datanucleus_core) contains only META-INF/MANIFEST.MF with the following content:
Manifest-Version: 1.0
Created-By: blaze
I tried to use java_binary rule that adds a correct datanucleus_core.jar into classpath, but Datanucleus enhances my libary in-place and fails to write its changes on disk (rewrite the rule's input file). Also java_binary rule is not supposed to be used for building.
So the question is what is the best way to enhance jar library in Bazel running Datanucleus utility, which is provided as a third-party dependency in Maven repository?
Bazel build label: 0.3.2-homebrew, OS: OS X El Capitan (10.11.6), java: 1.8.0_92
Update
Datanucleus dependency declaration:
# WORKSPACE
maven_jar(
name = "org_datanucleus_datanucleus_core",
artifact = "org.datanucleus:datanucleus-core:5.0.3",
)
# third_party/BUILD
java_library(
name = "org_datanucleus_datanucleus_core",
visibility = ["//visibility:public"],
exports = ["#org_datanucleus_datanucleus_core//jar"],
)
(in my question I shortened org_datanucleus_datanucleus_core to datanucleus_core)
As Neil Stockton mentioned, you cannot enhance classes in a jar. So, the basic strategy will be:
Create the jar.
Unjar the class files.
Run the enhancements.
Jar it back up.
Steps 2 & 3 have to be rolled into 4, as Bazel insists that you declare all inputs & outputs to a build rule (and you cannot know what .class files a .java file will generate, so Bazel always jars them up).
Create a datanucleus.bzl file to declare your enhancement rule in. It should look something like:
# Run datastore enhancements on the java_library named "jarname".
def enhance(jarname):
# src is the name of the jar file your java_library rule generates.
src = "lib" + jarname + ".jar"
native.genrule(
name = jarname + "-enhancement",
srcs = [
src,
"//third_party:datanucleus_core"
],
outs = [jarname + "-enhanced.jar"],
cmd = """
# Un-jar the .class files.
jar tf $(location {0})
# Run the enhance.
classes=""
for $$class in $$(find . -name *.class); do
java -cp {0}:$(location //third_party:datanucleus_core) $$class
classes="$$classes $$class"
done
# jar them back up.
jar cf $# $$classes""".format(src),
)
(I'm not too familiar with datastore so the cmd might need some modification, but it should be that general idea.)
Then, in your BUILD file, you'd do:
java_library(
name = "my-lib",
srcs = glob(["*.java"]),
deps = ["..."],
)
# import the rule you wrote.
load('//:datanucleus.bzl', 'enhance')
enhance("my-lib")
Now you can do:
bazel build //:my-lib-enhanced.jar
and use my-lib-enhanced.jar as a dependency in other java_ rules.
More info on .bzl files: https://bazel.build/versions/master/docs/skylark/concepts.html.
Edited to add more info on depending on a jar:
There are a couple of options to get a jar that contains the content of datanucleus. First, you don't need the layer of indirection: you can just say:
srcs = [
src,
"#datanucleus_core//jar"
],
This will give you the actual jar.
If, for some reason, you need the jar to be in third_party, you can modify third_party/BUILD to create a deploy jar, which is a java binary that bundles up all of its dependencies for deployment (since you're not actually going to using it as a binary, you can use whatever you want for the main class name):
java_binary(
name = "datanucleus-core",
main_class = "whatever",
runtime_deps = ["#org_datanucleus_datanucleus_core//jar"],
)
genrule(
name = "your-lib",
srcs = [":datanucleus-core_deploy.jar", ...],
)
The :datanucleus-core_deploy.jar is called an implicit target: it's only built if requested, but it can be generated from your java_binary declaration.

Eclipse plugin dev: make bundle to explode inside `plugins` folder

There is old Eclipse Image Viewer plugin https://github.com/persal/quickimage
that I want to update.
After adding maven/tycho build and building against Kepler.
It works in new Eclipse instance (project -> run as Eclipse application),
but when installing here is an issue #6
org.eclipse.swt.SWTException: i/o error (java.io.FileNotFoundException: file:\D:\Progs\Eclipses\eclipse-standard-luna-R-win32-x86_64\eclipse\plugins\nu.psnet.quickimage.plugin_1.1.0.201503030326.jar!\icons\previous.gif (The filename, directory name, or volume label syntax is incorrect.))
文件名、目录名或卷标语法不正确
Looking at the code there is line
iconsdir = FileLocator.resolve(QuickImagePlugin.getDefault().getBundle().getEntry("/")).getFile() + "icons" + File.separator;
that gets path like that.
The problem is that should work if the bungle jar becomes folder like nu.psnet.quickimage_1.0.3.2
UPDATE: As IDE using Luna 4.4.0
If you can change the source of the plugin you can change
iconsdir = FileLocator.resolve(QuickImagePlugin.getDefault().getBundle().getEntry("/")).getFile() + "icons" + File.separator;
to something like:
URL dir = FileLocator.find(QuickImagePlugin.getDefault().getBundle(),
new Path("icons"), null);
dir = FileLocator.toFileURL(dir);
String iconsdir = dir.getPath() + File.separator;
This should work even when the plugin is packaged in a jar.
This is controlled by a flag in feature.xml where the plugin is included.
<plugin id="..." unpack="true"/>

Use Eclipse Runtime Configuration to start jar file

I need to start a Java program using an Eclipse Runtime Configuration (ILaunchConfiguration). However, I want to provide the program to run as a .jar file (as part of the plugin), not as an Eclipse project.
It seems in order to start a Java program from an Eclipse Runtime Configuration I need to specify a project (and main class).
How can I use the Configuration framework to start an arbitrary .jar file?
This article helps:
http://eclipse.org/articles/Article-Java-launch/launching-java.html
I use the following code to run a .jar file which is inside my plugin's lib directory:
IPath path = new Path("lib" + File.separator + "some.jar");
Bundle bundle = Platform.getBundle(IDs.PLUGIN_ID);
URL url = FileLocator.find(bundle, path, null);
URI uri = FileLocator.resolve(url).toURI();
File file = URIUtil.toFile(uri);
IPath resolvedPath = new Path(file.toString());
IRuntimeClasspathEntry jar = JavaRuntime.newArchiveRuntimeClasspathEntry(resolvedPath);
IPath systemLibsPath = new Path(JavaRuntime.JRE_CONTAINER);
IRuntimeClasspathEntry systemLibsEntry =
JavaRuntime.newRuntimeContainerClasspathEntry(systemLibsPath, IRuntimeClasspathEntry.STANDARD_CLASSES);
List<String> classpath = new LinkedList<>();
classpath.add(aproveJar.getMemento());
classpath.add(systemLibsEntry.getMemento());
configuration.setAttribute(IJavaLaunchConfigurationConstants.ATTR_CLASSPATH, classpath);
configuration.setAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_CLASSPATH, false);

H2 driver not found when try to connect

I have gone through some other answers, but cannot get the solution to my problem.
I am using NetBeans 7.0.1 and the latest version of the H2 DB on Win7.
I successfully use the H2 console tool and I have also added the driver in NetBeans and am able to connect (i.e. see the DB, tables, issue commands, etc). However from within my Java code when running it, I get the message: "java.lang.ClassNotFoundException:org.h2.Driver".
My code is:
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:tcp://localhost/~/testDB", "sa", "");
Statement query = null;
query = conn.createStatement();
String firstString = "INSERT INTO ......";
query.executeUpdate(firstString);
I have also added the H2 jar file in the classpath (although I had to create the classpath myself and point to the jar file) - I went to environment variables -> user variables
name=classpath value=.;C:\NetBeansProjects\testdemo\src\testdemo\DB\h2-1.3.165.jar
What am I doing wrong?
Add the H2 jar file in the "Libraries" section under the source code packages.
Change parent version
spring-boot-starter-parent
1.4.3.RELEASE

How to set up classpath for the Scala interpreter in a managed environment?

I am working on an extension for the Apache Wicket web framework, which lets the user execute code in several programming languages at runtime from the browser. One of these languages is Scala, but I am having trouble when it is bundled as a WAR file and deployed to a container such as Tomcat.
When the Scala interpreter is invoked, it refuses to run the code with the following message:
Failed to initialize compiler: object scala not found.
** Note that as of 2.8 scala does not assume use of the java classpath.
** For the old behavior pass -usejavacp to scala, or if using a Settings
** object programatically, settings.usejavacp.value = true.
After setting up usejavacp on the Scala settings, it still didn't work in a managed environment. The problem seems to be that the Scala interpreter cannot find the Scala library jars on the Java class path.
Searching the web, I found a proposal, which proposes the use of two classpath resouces named 'boot.class.path' and 'app.class.path', which should include the needed classpath declarations. I tried this and it seemed to work. My problem with this solution, though, is that my extension is meant to get bundled into a WAR file and to be run in different environments, so it would be necessary for the user to modifiy these resources with respect to the environment it runs in. Also it would be a lot of work to include every single jar's path into the file.
Maybe I don't understand fully the proposal. Does anybody know of a solution for this?
I have managed to embed scala 2.9.1 within a war running in tomcat.
This is how I did it.
val code = """println("Hi");""";
val settings = new Settings
val compilerPath = java.lang.Class.forName("scala.tools.nsc.Interpreter").getProtectionDomain.getCodeSource.getLocation
val libPath = java.lang.Class.forName("scala.Some").getProtectionDomain.getCodeSource.getLocation
println("compilerPath=" + compilerPath);
println("settings.bootclasspath.value=" + settings.bootclasspath.value);
settings.bootclasspath.value = List(settings.bootclasspath.value, compilerPath, libPath) mkString java.io.File.pathSeparator
settings.usejavacp.value = true
val interpreter = new IMain(settings)
interpreter.interpret(code);
Just for the search engines. These were my exceptions before it worked.
Failed to initialize compiler: object scala not found.
** Note that as of 2.8 scala does not assume use of the java classpath.
** For the old behavior pass -usejavacp to scala, or if using a Settings
** object programatically, settings.usejavacp.value = true.
and
Exception in thread "Thread-26" java.lang.Error: typeConstructor inapplicable for <none>
at scala.tools.nsc.symtab.SymbolTable.abort(SymbolTable.scala:34)
at scala.tools.nsc.symtab.Symbols$Symbol.typeConstructor(Symbols.scala:877)
at scala.tools.nsc.symtab.Definitions$definitions$.scala$tools$nsc$symtab$Definitions$definitions$$booltype(Definitions.scala:157)
at scala.tools.nsc.symtab.Definitions$definitions$.init(Definitions.scala:814)
at scala.tools.nsc.Global$Run.<init>(Global.scala:697)
at scala.tools.nsc.interpreter.IMain.scala$tools$nsc$interpreter$IMain$$_initialize(IMain.scala:114)
at scala.tools.nsc.interpreter.IMain$$anonfun$initialize$1.apply$mcZ$sp(IMain.scala:127)
at scala.tools.nsc.interpreter.IMain$$anonfun$initialize$2.apply(IMain.scala:126)
at scala.tools.nsc.interpreter.IMain$$anonfun$initialize$2.apply(IMain.scala:126)
at scala.concurrent.ThreadRunner$$anon$2$$anonfun$run$2.apply(ThreadRunner.scala:45)
at scala.concurrent.ThreadRunner.scala$concurrent$ThreadRunner$$tryCatch(ThreadRunner.scala:31)
at scala.concurrent.ThreadRunner$$anon$2.run(ThreadRunner.scala:45)
at java.lang.Thread.run(Thread.java:662)
You could try to build and set the classpath manually:
val setting = new scala.tools.nsc.settings.MutableSettings(println(_))
settings.classpath.append("my/path")
and pass this Settings instance to the Scala compiler.
I ported to 2.10.2 and the solution provided by Peter did not work any more. I serached the web and everyone pointed to the solution Scott suggested - but it did not work for me, either. I'm using maven to copy all needed dependencies to the lib folder, which includes the scala library and compiler. Maven also sets the (relative) classpath to all those Jars in the Manifest.
I'm sure there is a more elegant way of doing this - especially accessing the right Manifest right away -, and there are probably some pitfalls, but it works for me:
//Get Jarpath
val jarfile = this.getClass.getProtectionDomain.getCodeSource.getLocation.getPath
val jarpath = jarfile.take(jarfile.lastIndexOf("/") + 1)
//Get classpath from Manifest
val resources = getClass.getClassLoader.getResources("META-INF/MANIFEST.MF");
val cpath = Buffer[String]()
//Get classpath from Manifest
while (resources.hasMoreElements()){
val manifest = new Manifest(resources.nextElement().openStream());
val attr = manifest.getMainAttributes.getValue("Class-Path")
//Convert to absolut paths
if (attr != null) {
cpath ++= attr.split(" ").map(p => {"file:" + {if(p(1) == '/') "" else jarpath} + p })
}
}
val settings = new Settings
settings.bootclasspath.value = cpath.mkString(java.io.File.pathSeparator)
settings.usejavacp.value = true