How can I use properties taken from a file in the code of an eclipse PDE fragment/plugin project? - eclipse

I have created an eclipse plugin project and a corresponding fragment project which I use for junit tests.
In the fragment I specify the plugin project as the "Host plugin". Further I specify the following on the build.properties pane:
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
my.properties
where my.properties is a file located at the root of the fragment project. I have then written a test where I try to load the my.properties file like this:
Properties properties = new Properties();
InputStream istream = this.getClass().getClassLoader()
.getResourceAsStream("my.properties");
try {
properties.load(istream);
} catch (IOException e) {
e.printStackTrace();
}
but istream is null and the test fails with a NullPointerException when calling load in the try block.
I have tried to do the same thing in the host plugin and there it works fine. Any ideas about why I can't read resouces in my PDE fragment when using Junit?

Try using Bundle#getEntry. If your plug-in has an Activator, you get a BundleContext object when your plugin is started (use Bundle-ActivationPolicy: lazy in your manifest). You can get the Bundle object from the BundleContext:
public class Activator implements BundleActivator {
private static Bundle bundle;
public static Bundle getBundle() {
return myBundle;
}
public void start(BundleContext context) throws Exception {
bundle = context.getBundle();
}
}
...
URL url = Activator.getBundle().getEntry("my.properties");
InputStream stream = url.openStream();
properties.load(stream);

One problem you MIGHT be having is that
InputStream istream = this.getClass().getClassLoader().
getResourceAsStream("my.properties");
behaves differently in two situations where "this" is located in a different package. Since you did not append "/" to the beginning, java will automatically start looking at the package root instead of the classpath root for the resource. If the code in your plug-in project and your fragment project exist in different packages, you have a problem.

Andrew Niefer has pointed the direction, but the solution is wrong. That is one that works:
1) Add super(); to the your Activator constructor.
2) Put this into the constructor of your plugin:
Properties properties = new Properties();
try {
Bundle bundle=Activator.getDefault().getBundle();
URL url = bundle.getEntry("plugin.properties");
InputStream stream;
stream = url.openStream();
properties.load(stream);
} catch (Exception e) {
e.printStackTrace();
}
And you have functioning "properties".
Explanations:
Doing (1) you will reach all that functionality:
public class Activator implements BundleActivator {
private static Bundle bundle;
public static Bundle getBundle() {
return myBundle;
}
public void start(BundleContext context) throws Exception {
bundle = context.getBundle();
}
}
It is present already in the pre-parent class Plugin. And you simply can't put it into Activator, because getBundle() is final in Plugin.
Notice Activator.getDefault() in (2). Without it bundle is unreachable, it is not static. And if you simply create a new instance of activator, bundle of it will be null.
There is one more way to take a bundle:
Bundle bundle = Platform.getBundle(Activator.PLUGIN_ID);
Only check that Activator.PLUGIN_ID is set to the correct string - as is in the ID field of the Overview page of the plugin. BTW, you should check this Activator.PLUGIN_ID after every change of the plugin ID anyway.

Related

Set FopFactoryBuilder baseURI to jar classpath

I'm upgrading an Apache FOP 1.0 project to Apache FOP 2.1. In this project, all necessary files are packaged within the jar file.
I've added the new FopFactoryBuilder to generate a FopFactory
FopFactoryBuilder builder = new FopFactoryBuilder(new File(".").toURI());
builder = builder.setConfiguration(config);
fopFactory = builder.build();
but all my resouces are loaded from the relative path on my file system, not from the jar. How can I set the baseURI to the jar's classpath?
Thanks
We also used FOP 2.1 and want to achieve, that images inside jars-classpath will be found. Our tested and used solution is the following:
Create your own ResourceResolver
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.net.URL;
import org.apache.fop.apps.io.ResourceResolverFactory;
import org.apache.xmlgraphics.io.Resource;
import org.apache.xmlgraphics.io.ResourceResolver;
public class ClasspathResolverURIAdapter implements ResourceResolver {
private final ResourceResolver wrapped;
public ClasspathResolverURIAdapter() {
this.wrapped = ResourceResolverFactory.createDefaultResourceResolver();
}
#Override
public Resource getResource(URI uri) throws IOException {
if (uri.getScheme().equals("classpath")) {
URL url = getClass().getClassLoader().getResource(uri.getSchemeSpecificPart());
return new Resource(url.openStream());
} else {
return wrapped.getResource(uri);
}
}
#Override
public OutputStream getOutputStream(URI uri) throws IOException {
return wrapped.getOutputStream(uri);
}
}
Create the FOPBuilderFactory with your Resolver
FopFactoryBuilder fopBuilder = new FopFactoryBuilder(new File(".").toURI(), new ClasspathResolverURIAdapter());
Finally address your image
<fo:external-graphic src="classpath:com/mypackage/image.jpg" />
Because you use our own Resolver it is possible to do every lookup which you want.
By specifying the URL as a classpath URL like:
<fo:external-graphic src="classpath:fop/images/myimage.jpg"/>
In this example the file is a resource in the resource-package fop.images but the actual file gets later packed to some entirely different place inside the JAR, which is - however - part of the classpath, so the lookup as above works.

Migration from Hibernate 3 to Hibernate 5: sessionFactory (MetadataImplementor) is null

public class EntityMetaData implements SessionFactoryBuilderFactory {
// private static final ThreadLocal<MetadataImplementor> meta = new ThreadLocal<>(); // previously used, but did not work, so used HashMap
private static final Map<String, MetadataImplementor> meta = new HashMap<>();
private static final String METADATAKEY = "M";
#Override
public SessionFactoryBuilder getSessionFactoryBuilder(MetadataImplementor metadata, SessionFactoryBuilderImplementor defaultBuilder) {
// meta.set(metadata);
meta.put(METADATAKEY, metadata);
return defaultBuilder;
}
public static MetadataImplementor getMeta() {
// return meta.get();
return meta.get(METADATAKEY);
}
}
The above code works in tomcat 8 of Local environment, but in tomcat 8 of production environment not working as getMeta() method returns null.
In Local Environment, getSessionFactoryBuilder method is called while server is getting started so that it is working in Local, but in Production environment getSessionFactoryBuilder method not called thus getMeta() returns null.
Any help could be appreciated.
Please help me on this.
Finally I found the answer.
It's a compiling problem. META-INF folder is not there in classes folder, so metadata is not loading (means getSessionFactoryBuilder method not getting called) during server startup. In Local environment, META-INF is there in classes folder..But in Production environment it is not available, so tried to compile META-INF and available in classes folder, then after it's working.

Where to place Rythm template files

I am having a weird problem with Rythm templates. Currently, I have these templates placed under
myPrj/src/main/java/resources/templates folder.
And all the Java source code is under myPrj/src/main/java folder.
When I try to render, sometimes Rythm is generating the XML file and sometimes I get the file name as is.
I have the home.template set to "templates" folder:
params.put("home.template", "templates");
String myTemplateString = Rythm.render("MyTemplate.xml", parameters);
Looks like Rythm is not able to locate MyTemplate.xml and resulting in emitting MyTemplate.xml as the output.
Can you please help me on how to solve this problem?? In addition, would appreciate if you can guide me on what should be the appropriate location to place these templates.
home.template is the configuration key to initialize template engine, not the parameter to render your template.
My implementation of your app looks like
public class App {
private static RythmEngine engine;
private static void echo(String msg, Object ... args) {
System.out.println(String.format(msg, args));
}
private static void init() {
echo("initializing rythmengine");
Map<String, Object> conf = new HashMap<String, Object>();
conf.put("home.template", "templates");
engine = new RythmEngine(conf);
echo("engine initialized");
}
private static void render() {
Map<String, Object> params = new HashMap<String, Object>();
params.put("foo", "FOO");
params.put("bar", "BAR");
String result = engine.render("MyTemplate.xml", params);
echo(result);
}
private static void doJob() {
echo("start doing real job now...");
render();
}
public static void main( String[] args ) {
init();
doJob();
}
}
The complete sample code could be found at https://github.com/greenlaw110/Rythm/tree/master/samples/demo_fo_SO_150529. Download the sample code and run mvn compile exec:java to see the result
It seems your problem lies within the path for the home.template. The example on their website might help.
If I'm not mistaken, you should use params.put("home.template", "resources/templates"); rather than params.put("home.template", "templates");.
Generally speaking, this kind of behaviour takes place any time Rythm can't find the template. I found it is best to check both, the path and file name. If necessary, simply use an absolute path to your template to make sure it points to the right directory. After you got the right path, you might want to change it back to be relative.

How to programmatically new a java class which implements sepecified interface in eclipse plugin development

Friends,
Now we are developing a eclipse plugin, it contains a action to generated a service interface and it's impl stub.
Now the interface is generated, I want to use eclipse JDT to create a java class which implements sepecified interface, but don't know how.
The info we have:
the interface name, the impl class name, the packagename, the java project contains them.
Thanks in advance for your kindly help.
A quick scan of how the new class wizard does it, it seems that there is no public easy to use API for this. You can have a look at org.eclipse.jdt.ui.wizards.NewTypeWizardPage.createType(IProgressMonitor) method to see how JDT itself creates new classes.
It should be possible to extend the org.eclipse.jdt.ui.wizards.NewTypeWizardPage, so you can leverage the createType() method.
Probably the minimal steps you would have to do is simply generate source content into the correctly placed IFile. ex:
public Object execute(ExecutionEvent event) throws ExecutionException {
final String PACKAGE_PATH = "z.ex/src/z/ex/go";
final String CONTENT = "package z.ex.go;\n"
+ "public class RunAway {\npublic static void main(String[] args) {\n"
+ "System.out.println(\"Run Away\");\n}\n}\n";
final IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
final IResource packageResource = root.findMember(PACKAGE_PATH);
if (packageResource instanceof IFolder) {
IFolder packageFolder = (IFolder) packageResource;
final IFile file = packageFolder.getFile("RunAway.java");
try {
if (!file.exists()) {
file.create(new ByteArrayInputStream(CONTENT.getBytes()),
true, new NullProgressMonitor());
} else {
file.setContents(
new ByteArrayInputStream(CONTENT.getBytes()),
IFile.FORCE | IFile.KEEP_HISTORY,
new NullProgressMonitor());
}
} catch (CoreException e) {
e.printStackTrace();
}
}
return null;
}
See AbstractNewClassWizard for a smaller example that is similar to NewTypeWizardPage and uses some of the JDT APIs.
You can use the new class wizard to create classes.
This will prompt the user for the class name, et cetera. You can initialize the values of the wizard page. Below I am setting the source folder only (and tell the wizard that it cannot be changed, thus the second false parameter). You might want to set the interface and possible the package as well.
OpenNewClassWizardAction wizard = new OpenNewClassWizardAction();
wizard.setOpenEditorOnFinish(false);
NewClassWizardPage page = new NewClassWizardPage();
page.setPackageFragmentRoot(sourceFolder, false);
wizard.setConfiguredWizardPage(page);
wizard.run();
return (IType) wizard.getCreatedElement();
Hope that helps!
Create the entire java file using the JDT - AST. First create the AST and then write it to a java file. It might look as hefty work, but its the best one. You will have complete control.

Why am I having trouble accessing a .properties file in a standalone instance of tomcat but not in an eclipse-embedded instance?

I wrote a simple Hello World Servlet in Eclipse containing the following in the doGet method of my HelloWorldServlet.java
PrintWriter writer = response.getWriter();
String hello = PropertyLoader.bundle.getProperty("hello");
writer.append(hello);
writer.flush();
PropertyLoader is a simple class in the same package as the Servlet that does the following:
public class PropertyLoader {
public static final Properties bundle = new Properties();
static {
InputStream stream = null;
URL url = PropertyLoader.class.getResource("/helloSettings.properties");
stream = new FileInputStream(url.getFile());
bundle.load(stream);
}
}//End of class
I placed a file called helloSettings.properties in /WebContent/WEB-IND/classes that contains the following single line of content:
hello=Hello Settings World
When I add Tomcat 6.0 to my project and run it in eclipse it successfully prints
"Hello Settings World" to the web browser.
However when I export the project as a war file and manually place it in
.../Tomcat 6.0/webapps I then get "null" as my result.
Is it a problem with the classpath/classloader configuration? permissions? any of the other configuration files? I know for a fact that the helloSettings.properties file is in the WEB-INF/classes folder.
Any help?
Well, after much browsing I found what seems a "normal" why to do what I'm trying to do:
Instead of...(how I was doing it)
public class PropertyLoader {
public static final Properties bundle = new Properties();
static {
InputStream stream = null;
URL url = PropertyLoader.class.getResource("/helloSettings.properties");
stream = new FileInputStream(url.getFile());
bundle.load(stream);
}
}//End of class
THE FIX
public class PropertyLoader {
public static final Properties bundle = new Properties();
static {
InputStream stream = null;
stream = SBOConstants.class.getResourceAsStream("/sbonline.properties");
bundle.load(stream);
}
}//End of class
I'm modifiying someone else's code so I'm not sure why they did it the other way in the first place... but I guess url.getFile() was my problem and I don't know why.