How do I access a file inside an OSGi bundle? - osgi

I am new to OSGi and created an OSGi-bundle which I run in the Apache Felix OSGi-container.
There is a file resource contained in the bundle, which I need to pass to a method as a java.io.File. To instantiate a File-object, either an URI in the "file"-scheme or the path as string is necessary. How do I retrieve any of those in a clean way?
I tried using the
context.getBundle().getResource("/myfile") (where context is of type org.osgi.framework.BundleContext) which returns the URI bundle://6.0:0/myfile.
But this URI can't be converted to a File-instance using the File(URI uri) constructor since it has the "bundle"-scheme.
One could try to construct a path to the location knowing the working directory and exploiting the bundleId of my bundle, but I doubt this is the best practice.
Any ideas?

Since the file is inside your bundle, there is no way for you to get to it using a standard File. The URL you get from Bundle.getResource() is the correct way to get to these resources, since the OSGi APIs are intended to also work on systems without an actual file system. I would always try to stick to the OSGi API instead of using framework-specific solutions.
So, if you have control over the method, I would update it to take a URL, or maybe even an InputStream (since you probably just want to read from it). For convenience, you can always provide a helper method that does take a File.
If you don't have control over the method, you will have to write some helper method that takes the URL, streams it out to a file (for instance, File.createTempFile() will probably do the trick.

Maybe the API is confusable, but You can access a file inside an OSGI bundle like this:
URL url = context.getBundle().getResource("com/my/weager/impl/test.txt");
// The url maybe like this: bundle://2.0:2/com/my/weager/impl/test.txt
// But this url is not a real file path :(, you could't use it as a file.
// This url should be handled by the specific URLHandlersBundleStreamHandler,
// you can look up details in BundleRevisionImpl.createURL(int port, String path)
System.out.println(url.toString());
BufferedReader br =new BufferedReader(new InputStreamReader(url.openConnection().getInputStream()));
while(br.ready()){
System.out.println(br.readLine());
}
br.close();
getResource will find the resource through the whole OSGI container just like OSGI classloader theory.
getEntry will find the resource from local bundle. and the return url could be convert to file but inputStream.
Here is a question same with this: No access to Bundle Resource/File (OSGi)
Hope this helping you.

What I use is getClassLoader().getResourceAsStream():
InputStream inStream = new java.io.BufferedInputStream(this.getClass().getClassLoader().getResourceAsStream(fileName));
This way the file will be loaded from your resource dir. FileName should contain the path after "src/main/resources".
Full example here:
static public byte[] readFileAsBytes(Class c, String fileName) throws IOException {
InputStream inStream = new java.io.BufferedInputStream(c.getClassLoader().getResourceAsStream(fileName));
ByteArrayOutputStream out = new ByteArrayOutputStream();
int nbytes = 0;
byte[] buffer = new byte[100000];
try {
while ((nbytes = inStream.read(buffer)) != -1) {
out.write(buffer, 0, nbytes);
}
return out.toByteArray();
} finally {
if (inStream != null) {
inStream.close();
}
if (out != null) {
out.close();
}
}
}

Related

Java I/O help. Jar Cannot Open File: URI is Not Hierarchal

I have been searching for 3 days now nonstop looking at every post I can find. My program runs on IntelliJ, but cannot run on an executable. Your help would be appreciated :)
More importantly, where can I find a in depth user-friendly tutorial? Is there a course or book I can pay for? On Udemy, the java classes completely fail to mention I/O such as classpath and URI. TutorialsPoint briefly goes over I/O buts its not indepth. Did I miss something? Is there an easier way to do all this??
Similar posts that have not worked for me:
Java Jar file: use resource errors: URI is not hierarchical
https://stackoverflow.com/a/27149287/155167
I am trying to load an excel file. I am using Maven. Apache POI says it needs a File. So InputStream does not work. http://poi.apache.org/components/spreadsheet/quick-guide.html#FileInputStream
When I java -jar jarFile, it gives me the error:
C:\Users\1010\Documents\Personal\MonsterManager>java -jar monsterManagerVer3.jar
Exception in thread "main" java.lang.IllegalArgumentException: URI is not hierarchical
at java.base/java.io.File.<init>(File.java:421)
at LoadExcel.<init>(LoadExcel.java:62)
at monsterRunner.<init>(monsterRunner.java:13)
at monsterRunner.main(monsterRunner.java:24)
Here is the code
public LoadExcel() throws IOException, URISyntaxException, InvalidFormatException {
mNames = null;
URL ins = this.getClass().getResource("/excel_List.xlsx");
if (ins == null)
throw new FileNotFoundException("The XLSX file didn't exist on the classpath");
ins.toString().replace(" ","%20"); //<-Runs without this part
File file = new File(ins.toURI()); //this is line 62
// File f = new File(getClass().getResource("/MyResource").toExternalForm());
//String path = this.getClass().getClassLoader().getResource("/excel_List.xlsx").toExternalForm();
//File file = new File(path);
OPCPackage pkg = OPCPackage.open(file);
XSSFWorkbook wb = new XSSFWorkbook(pkg);
//FileInputStream fis=new FileInputStream(new File(excelFile));
// XSSFWorkbook wb = new XSSFWorkbook(fis);
XSSFSheet sheet = wb.getSheetAt(0);
loadExcel(sheet);
cacheNames();
// fis.close();
wb.close();
}
If it helps here is the path to the excel file:
src\main\resources\excel_List.xlsx
UPDATE:
so I took the excel file out of the resources folder
\nameOfMyProgram\excel_List.xlsx
and now I get this error.
I tried several versions of using the classLoader, Class and Thread to solve this error from Different ways of loading a file as an InputStream
but I still cannot get it to compile.
Error and my code
If you have to use File object do not put xls-file into resources directory.
Maven puts all files from resources directory into jar.
Java can not create File object based on file in jar-file.
Put your xls-file somewhere in file system and create File object based on its URL.
Since your xls-file is not a resource do not use getResource.
Its URL is its full filename (with path).
This code below works with jar executable
String path = new File("excel_List.xlsx").getAbsoluteFile().toString();
File file = new File(path);
if(!file.exists()){
JOptionPane.showMessageDialog(null,"File not found!");
System.exit(0);
}
OPCPackage pkg = OPCPackage.open(file);
XSSFWorkbook wb = new XSSFWorkbook(pkg);

Spring Boot load another file from app.properties

I am new to Spring Boot. I have this emailprop.properties in src/main/resource:
//your private key
mail.smtp.dkim.privatekey=classpath:/emailproperties/private.key.der
But I am getting the error as
classpath:\email properties\private.key.der (The filename, directory
name, or volume label syntax is incorrect)
How do I properly load this file?
Update-1
my java code is
dkimSigner = new DKIMSigner(emailProps.getProperty("mail.smtp.dkim.signingdomain"), emailProps.getProperty("mail.smtp.dkim.selector"),
emailProps.getProperty("mail.smtp.dkim.privatekey"));
its working as "D:\\WorkShop\\MyDemoProj\\EmailService\\src\\main\\resources\\private.key.der"Instead of emailProps.getProperty("mail.smtp.dkim.privatekey")
Update-2
i have tried java code is
String data = "";
ClassPathResource cpr = new ClassPathResource("private.key.der");
try {
byte[] bdata = FileCopyUtils.copyToByteArray(cpr.getInputStream());
data = new String(bdata, StandardCharsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
}
dkimSigner = new DKIMSigner(emailProps.getProperty("mail.smtp.dkim.signingdomain"), emailProps.getProperty("mail.smtp.dkim.selector"),data);
Error is : java.io.FileNotFoundException: class path resource [classpath:private.key.der] cannot be resolved to URL because it does not exist
Tried Code is :
ClassPathResource resource = new ClassPathResource(emailProps.getProperty("mail.smtp.dkim.privatekey"));
File file = resource.getFile();
String absolutePath = file.getAbsolutePath();
Still same error..
please update the answer..
If you want to load this file runtime then you need to use ResourceLoader please have a look here for the documentation - section 8.4.
Resource resource = resourceLoader.getResource("classpath:/emailproperties/private.key.der");
Now if you want to keep this exact path in properties file you can keep it there and then load it in your Autowired constructor/field like that:
#Value("${mail.smtp.dkim.privatekey}") String pathToPrivateKey
and then pass this to the resource loader.
Full example you can find here. I don't want to copy paste it.
If your file is located here:
"D:\\WorkShop\\MyDemoProj\\EmailService\\src\\main\\resources\\private.key.der"
then it should be:
mail.smtp.dkim.privatekey=classpath:private.key.der
EDIT:
I see now, you are using DKIMSigner, which expects file-path string,
Try changing your code like this:
ClassPathResource resource = new ClassPathResource(emailProps.getProperty("mail.smtp.dkim.privatekey"));
File file = resource.getFile();
String absolutePath = file.getAbsolutePath();
dkimSigner = new DKIMSigner(emailProps.getProperty("mail.smtp.dkim.signingdomain"), emailProps.getProperty("mail.smtp.dkim.selector"),absolutePath
);

resource listing

I writing wicket webapp. I want to:
list all resources - videoPreview in the folder
preview it
add link to show in main preview panel.
I read a lot and look examples about resources, but seems like can't understand smthg. I write such funny code:
RepeatingView rv = new RepeatingView("showVideo");
add(rv);
File vidPrevDir = (new File("data/catalog/"+product+"/videoPreview"));
File[] list = vidPrevDir.listFiles();
for (File file : list) {
final String previewFile = file.getName();
AjaxLink link = new AjaxLink(rv.newChildId()){
#Override
public void onClick(AjaxRequestTarget target) {
container.name="iframe";
container.attrs.clear();
container.attrs.put("class", "viewPanel");
container.attrs.put("allowfullscreen", "yes");
container.attrs.put("src", "http://www.youtube.com/embed/"+previewFile.substring(previewFile.indexOf("___"), previewFile.length()-4));
target.add(container);
}
};
rv.add(link);
link.add(new Image("videoPreview", product+"/videoPreview/"+file.getName()));
}
In application i call
getResourceSettings().addResourceFolder("data");
It's work, but i feel bad when i see that. So my question is how to make such things in wicket? Maybe there is resource listing or java.io.File->wicket.Image converter ?
I only found built-in method:
ServletContext context = WicketApplication.get().getServletContext();
Set productList = context.getResourcePaths("/catalog");
It list filenames, not resources, but it is preferable approach, then i use in question.

Maven java.io.FileNotFoundException

I'm developing a project with Maven. In a class to send e-mails, in run and dev modes, I get the following error: Caused by: java.io.FileNotFoundException: jQuery/images/logo.png (Ficheiro ou directoria inexistente) ==> translation = File or directory not found.
I've tryed lots of paths, like "./jQuery/images/logo.png", "/jQuery/images/logo.png" and others. The full relative path is: "src/main/webapp/jQuery/images/logo.png".
In "target" folder, the path is "project-1.0-SNAPSHOT/jQuery/images/logo.png".
Inside war file, is "jQuery/images/logo.png".
I don't think it's important, but I'm using NetBeans 7.1.1 as IDE.
I found that the absolute path returned in runtime is "/home/user/apache-tomcat-7.0.22/bin/jQuery/images/logo.png"!... It's not the project path!
How can I get a file in webapp folder and descendents from a Java class, in a Maven project?
The code is:
MimeBodyPart attachmentPart = null;
FileDataSource fileDataSource = null;
for (File a : attachments) {
System.out.println(a.getAbsolutePath());
attachmentPart = new MimeBodyPart();
fileDataSource = new FileDataSource(a) {
#Override
public String getContentType() {
return "application/octet-stream";
}
};
attachmentPart.setDataHandler(new DataHandler(fileDataSource));
attachmentPart.setFileName(fileDataSource.getName());
multipart.addBodyPart(attachmentPart);
}
msg.setContent(multipart);
msg.saveChanges();
Transport transport = session.getTransport("smtp");
transport.connect(host, from, "password");
transport.sendMessage(msg, msg.getAllRecipients());
The path .../apache-tomcat-7.0.22/bin/jQuery/... is really odd. bin contains scripts for Tomcat, it should not contain any code nor any resources related to your application. Even if you deploy your app in the context /bin, the resources would end up under `.../apache-tomcat-7.0.22/webapps/bin/...
This looks like a mistake made in an earlier deployment.
Now back to your question. To get the path of resource of your web app, use this code:
String absolutePath = getServletContext().getRealPath("/jQuery/images/logo.png");
(docs)

How do you save images to a Blackberry device via HttpConnection?

My script fetches xml via httpConnection and saves to persistent store. No problems there.
Then I loop through the saved data to compose a list of image url's to fetch via queue.
Each of these requests calls the httpConnection thread as so
...
public synchronized void run()
{
HttpConnection connection = (HttpConnection)Connector.open("http://www.somedomain.com/image1.jpg");
connection.setRequestMethod("GET");
String contentType = connection.getHeaderField("Content-type");
InputStream responseData = connection.openInputStream();
connection.close();
outputFinal(responseData, contentType);
}
public synchronized void outputFinal(InputStream result, String contentType) throws SAXException, ParserConfigurationException, IOException
{
if(contentType.startsWith("text/"))
{
// bunch of xml save code that works fine
}
else if(contentType.equals("image/png") || contentType.equals("image/jpeg") || contentType.equals("image/gif"))
{
// how to save images here?
}
else
{
//default
}
}
What I can't find any good documentation on is how one would take the response data and save it to an image stored on the device.
Maybe I just overlooked something very obvious. Any help is very appreciated.
Thanks
I tried following this advise and found the same thing I always find when looking up BB specific issues: nothing.
The problem is that every example or post assumes you know everything about the platform.
Here's a simple question: What line of code writes the read output stream to the blackberry device? What path? How do I retrieve it later?
I have this code, which I do not know if it does anything because I don't know where it is supposedly writing to or if that's even what it is doing at all:
** filename is determined on a loop based on the url called.
FileOutputStream fos = null;
try
{
fos = new FileOutputStream( File.FILESYSTEM_PATRIOT, filename );
byte [] buffer = new byte [262144];
int byteRead;
while ((byteRead = result.read (buffer ))!=- 1)
{
fos.write (buffer, 0, byteRead);
}
fos.flush();
fos.close();
}
catch(IOException ieo)
{
}
finally
{
if(fos != null)
{
fos.close();
}
}
The idea is that I have some 600 images pulled from a server. I need to loop the xml and save each image to the device so that when an entity is called, I can pull the associated image - entity_id.png - from the internal storage.
The documentation from RIM does not specify this, nor does it make it easy to begin figuring it out.
This issue does not seem to be addressed on this forum, or others I have searched.
Thanks
You'll need to use the Java FileOutputStream to do the writing. You'll also want to close the connection after reading the data from the InputStream (move outputFinal above your call to close). You can find all kinds of examples regarding FileOutputStream easily.
See here for more. Note that in order to use the FileOutputStream your application must be signed.

Resources