Lotus Domino 8.5.2 Java Agent , write Metadata to extracted attachments? - java

I'm using Lotus Domino server 8.5.2. Using Java scheduled agents, I can extract the attachments of several Lotus Domino Documents in to the file system (win 32). The Idea is that after extraction I need add some metadata to the files and upload the files to another system.
Does someone knows, or can give me a few tips (preferably using Java) of how I can write some metadata to the extracted files? I need add some keywords, change the author, and so on. I understand Lotus Domino 8.5.2 supports Java 6
thank you!
Alex.

According to this answer, Java 7 has a native ability to manipulate Windows metadata but Java 6 does not.
It does say that you can use Java Native Access (JNA) to make calls to native DLLs, which means you should be able to use dsofile.dll to manipulate the metadata. Example from here of using JNA to access the "puts" function from msvcrt.dll (couldn't find any examples specific to dsofile.dll):
Interface
package CInterface;
import com.sun.jna.Library;
public interface CInterface extends Library
{
public int puts(String str);
}
Sample class
// JNA Demo. Scriptol.com
package CInterface;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
public class hello
{
public static void main(String[] args)
{
String mytext = "Hello World!";
if (args.length != 1)
{
System.err.println("You can enter your own text between quotes...");
System.err.println("Syntax: java -jar /jna/dist/demo.jar \"myowntext\"");
}
else
mytext = args[0];
// Library is c for unix and msvcrt for windows
String libName = "c";
if (System.getProperty("os.name").contains("Windows"))
{
libName = "msvcrt";
}
// Loading dynamically the library
CInterface demo = (CInterface) Native.loadLibrary(libName, CInterface.class);
demo.puts(mytext);
}
}

Related

Access parameters from custom URI scheme in Java application on OS X

I've successfully added a custom URI scheme in info.plist on OS X so my Java 1.7 based application (written in Netbeans) is launched whenever the user enters "myApp:SomeParameter" in their browser:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>My App</string>
<key>CFBundleURLSchemes</key>
<array>
<string>myApp</string>
</array>
</dict>
</array>
I have also successfully added the corresponding registry entry for the application if installed on a Windows machine. The problem is that on the Windows platform I can easily pass on parameters (in the above case I want "SomeParameter" from the entered uri "myApp:SomeParameter"). It is simply passed on to the application main method as regular parameters, but this is not the case on OS X. I have done some research and tried this solution but it requires some Cocoa libraries and causes issues when compiled and run on Windows.
EDIT: I have tried to track down a version of AppleJavaExtensions that contains the com.apple.eawt.Application.setOpenURIHandler() but I've only found version 1.4 where it's missing. Any idea why?
Is there another way to pass parameters from a custom URI scheme to a cross platform Java application running on Mac / OS X?
EDIT 2: Please see accepted answer below, but as a side note: we successfully experimented with a possible workaround using AppleScript as a middle-tier. The script in this article can be simplified to receive the full URL with parameters, and then invoke your Java based application with the query string as normal command line parameters.
It looks like you're on the right track. Your Info.plist looks correct. You don't need to create any custom native Cocoa code, just use setOpenURIHandler(). For example:
public class AppleMenus implements com.apple.eawt.OpenURIHandler {
private MyApp myApp;
public AppleMenus(MyApp myApp) {
this.myApp = myApp;
final com.apple.eawt.Application app = com.apple.eawt.Application.getApplication();
app.setOpenURIHandler(this);
}
#Override
public void openURI(final com.apple.eawt.AppEvent.OpenURIEvent oue) {
myApp.openCustomURL(oue.getURI());
}
}
The only reason you would need AppleJavaExtensions is if you are trying to compile this code on a non-Apple environment, such as Windows. Windows won't know what OpenURIHandler is, so you will get a compile error there. AppleJavaExtensions just provides that necessary API without implementation, just for the purposes of being able to compile in these other environments.
Here, is the official latest (and probably last) version: https://developer.apple.com/legacy/library/samplecode/AppleJavaExtensions/Introduction/Intro.html
Note that your URI handler will be called in the currently running instance of you app or will first create a new instance of your app then get called. The OpenURIEvent will contain the entire URI message you send.
The following (for Java 9) will work cross platform (Windows and macOS has been tested):
import java.awt.*;
import java.awt.desktop.OpenURIEvent;
import java.awt.desktop.OpenURIHandler;
import java.net.URI;
import java.net.URISyntaxException;
public class UriLaunchedApp {
public static void main(String[] args) throws URISyntaxException {
try {
Desktop.getDesktop().setOpenURIHandler(new OpenURIHandler() {
#Override
public void openURI(OpenURIEvent e) {
System.out.println("We are maybe on macOS...");
processUri(e.getURI());
}
});
} catch (UnsupportedOperationException e) {
System.out.println("We are maybe on Windows...");
processUri(new URI(args[0]));
}
}
private static void processUri(URI uri) {
System.out.println("Do something with " + uri);
}
}
See too https://docs.oracle.com/javase/9/docs/api/java/awt/Desktop.html#setOpenURIHandler-java.awt.desktop.OpenURIHandler-.

MBROLA voices with FreeTTS - Windows

Using MBROLA voices in a Java program with FreeTTS...
I am working on a simple text-to-speech program in Java. I have decided to use FreeTTS, but the voices are not really what I was thinking, and I was looking to use a female voice anyway. So I started looking around, and decided that I would use MBROLA to change the voice of my text-to-speech program.
I read that "FreeTTS can use MBROLA voices", but I searched everywhere and couldn't find a clear guide how to set MBROLA up, and what files are needed to do so. There are many forums on MBROLA working alongside FreeTTS, however it also seems that none of the people have any idea what they are doing.
So the questions:
What files need to be downloaded?
Steps to include these into my program?
Simple FreeTTS example using MBROLA voices?
Answers to the questions above:
1. What files need to be downloaded?
FreeTTS with all the libraries (freeTTS 1.2.2-bin) - download here
MBROLA zip folder mbr301d.zip
Voices which can be found on the MBROLA website
1.1 The FreeTTS libraries (found in freetts-1.2.2-bin/freetts-1.2/lib):
cmu_time_awb.jar
cmu_us_kal.jar
cmudict04.jar
cmulex.jar
cmutimelex.jar
en_us.jar
freetts.jar
freetts-jsapi10.jar
mbrola.jar
1.2 The MBROLA zip folder will include:
mbrola.exe
mbr302a (folder)
readme.txt
1.3 The Voices are zipped folders that include a single folder named 'us1' or 'af1' etc.
2. Steps to include these into my program?
NOTE: I had the MBROLA Tooklit installed on my computer too, however I am unsure whether it has an impact on the program, but I suspect that it doesn't. EDIT: I have tested to see whether the MBROLA toolkit is needed to run MBROLA alongside FreeTTS, and it turns out that it is not needed.
Extract freetts-1.2.2-bin
Copy the libraries to your project and include in build path
Unzip the mbr301d.zip folder
Rename 'mbr301d' to 'mbrola'
Unzip the voices to the folder you named 'mbrola'
After this is done, your mbrola folder should look like this:
[mbr302a] - folder
[us1] - folder (name depends on the language you downloaded)
mbrola.exe - file
readme.txt - file
You can place all your languages in this folder, and they will just be called from your Java program.
3. Simple FreeTTS example using MBROLA voices?
I've seen many people get this error:
System property "mbrola.base" is undefined. Will not use MBROLA voices.
The mbrola.base refers to where your mbrola files are located on your computer, and without the property being pointed to the correct location, you will recieve this error.
To NON-MBROLA users who get this error: Simply remove the mbrola.jar from your referenced libraries if you're only using FreeTTS
To set the mbrola.base property, use:
System.setProperty("mbrola.base", "C:/Path/to/your/mbrola")
Below is a simple Example to use the MBROLA voices in your FreeTTS program. Note that the steps above must be done before this will work. Simply changing the name of the voice to "mbrola_us1" will not work if the base isn't set!
package com.madmob.test;
import com.sun.speech.freetts.Voice;
import com.sun.speech.freetts.VoiceManager;
public class TestTTS {
VoiceManager freettsVM;
Voice freettsVoice;
public TestTTS(String words) {
// Most important part!
System.setProperty("mbrola.base", "C:/mbrola");
freettsVM = VoiceManager.getInstance();
// Simply change to MBROLA voice
freettsVoice = freettsVM.getVoice("mbrola_us1");
// Allocate your chosen voice
freettsVoice.allocate();
sayWords(words);
}
public void sayWords(String words) {
// Make her speak!
freettsVoice.speak(words);
}
public static void main(String [] args) {
new TestTTS("Hello there! Now M BROLA and Free T T S work together!");
}
}
MBROLA and FreeTTS should now be working together! This code was copied right from my computer and has been tested before putting it down here.
Thanks to responses on this forum, I was finally able to make it working.
On windows 10; I carried out following steps to make it working:
Download freeTTS libraries and include them in my Java project in eclipse.
Download mbr301d.zip, extract it in a folder named mbrola within my project
Download mbrola database for us1, us2, us3 and en1 from http://www.tcts.fpms.ac.be/synthesis/mbrola/mbrcopybin.html
extract the voice DB zips downloaded in previous step directly in mbrola folder - don't change names of the folders.
include following code pieces to use it:
System.setProperty("mbrola.base", "ABSOLUTE_PATH_TO_mbrola_directory_ending_with_/");
voiceManager = VoiceManager.getInstance();
voice = voiceManager.getVoice("mbrola_us1");
Note: if your voice DB folder name is us1; then you should add it above as "mbrola_us1"; if it is en1, then it should be "mbrola_en1". This actually has done the trick for me.
Please find working example from here:
https://github.com/sunrise-projects/sphinx4/tree/glass
package com.sunriseprojects.freetts.demo;
import java.beans.PropertyVetoException;
import java.util.Locale;
import javax.speech.AudioException;
import javax.speech.Central;
import javax.speech.EngineException;
import javax.speech.EngineStateError;
import javax.speech.synthesis.Synthesizer;
import javax.speech.synthesis.SynthesizerModeDesc;
import javax.speech.synthesis.Voice;
public class SpeechUtils {
SynthesizerModeDesc desc;
Synthesizer synthesizer;
Voice voice;
public void init(String voiceName) throws EngineException, AudioException,
EngineStateError, PropertyVetoException {
if (desc == null) {
//default
// System.setProperty("freetts.voices",
// "com.sun.speech.freetts.en.us.cmu_us_kal.KevinVoiceDirectory");
//have to be setup
System.setProperty("freetts.voices",
"de.dfki.lt.freetts.en.us.MbrolaVoiceDirectory");
desc = new SynthesizerModeDesc(Locale.US);
Central.registerEngineCentral("com.sun.speech.freetts.jsapi.FreeTTSEngineCentral");
synthesizer = Central.createSynthesizer(desc);
synthesizer.allocate();
synthesizer.resume();
SynthesizerModeDesc smd = (SynthesizerModeDesc) synthesizer
.getEngineModeDesc();
Voice[] voices = smd.getVoices();
Voice voice = null;
for (int i = 0; i < voices.length; i++) {
if (voices[i].getName().equals(voiceName)) {
voice = voices[i];
break;
}
}
synthesizer.getSynthesizerProperties().setVoice(voice);
}
}
public void terminate() throws EngineException, EngineStateError {
synthesizer.deallocate();
}
public void doSpeak(String speakText) throws EngineException,
AudioException, IllegalArgumentException, InterruptedException {
synthesizer.speakPlainText(speakText, null);
synthesizer.waitEngineState(Synthesizer.QUEUE_EMPTY);
}
public static void main(String[] args) throws Exception {
System.setProperty("mbrola.base", "C:\\lnx1\\home\\ggon\\git-projects\\mbrola");
SpeechUtils su = new SpeechUtils();
//have to be setup on your env
su.init("mbrola_us1");
//default
//su.init("kevin16");
//su.init("kevin");
//su.doSpeak("Hello world!");
su.doSpeak(SAMPLE);
su.terminate();
}
final static String SAMPLE = "Wiki said, Floyd Mayweather, Jr. is an American professional boxer. He is currently undefeated as a professional and is a five-division world champion, having won ten world titles and the lineal championship in four different weight classes";
}

Add Java SE Classes to Java ME read PDF

I'm writing a Java ME application that uses iText to read PDF. When I write my code in standard Java including the iText libraries in the class-path, the application runs. However if I move the code into a java mobile application including the iText libraries in the class-path there is an error during compiling that says
error: cannot access URL
PdfReader reader = new PdfReader(pdfPath);
class file for java.net.URL not found
My problem is that I need a work around to read the PDF file. I've tried adding rt.jar as a library into my code which is the package that contains java.io but it is too big to be compiled. Please help me find a work around. My code is here
package PDFreaderpackage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.PdfTextExtractor;
import com.sun.lwuit.Display;
import com.sun.lwuit.Form;
import com.sun.lwuit.TextArea;
import javax.microedition.midlet.MIDlet;
public class Midlet extends MIDlet {
Form displayForm;
TextArea pdfText;
private String bookcontent;
public static String INPUTFILE = "c:/test.pdf";
public static int pageNumber = 1;
public void startApp() {
Display.init(this);
this.bookcontent = readPDF(INPUTFILE, pageNumber);
pdfText = new TextArea(bookcontent);
displayForm = new Form("Works");
displayForm.addComponent(pdfText);
displayForm.show();
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public String readPDF(String pdfPath, int pageNumber) {
try {
PdfReader reader = new PdfReader(pdfPath);
this.bookcontent = PdfTextExtractor.getTextFromPage(reader, pageNumber);
} catch (Exception e) {
System.out.println(e);
}
return bookcontent;
}
}
These classes aren't available on a mobile device and JavaME doesn't support Java 5 features. What you are trying to do is somewhat impractical. Codename One allows some more classes thanks to bytecode processing but even then this isn't close to a complete rt.jar.
If you have the time, you can try and create a Java ME compliant version of iText, but to properly open a PDF the library must use some form of Random Access File because of the xref table at the end of the file. This sort of file connection is not available in Java ME.
What the library can do is to fully load the PDF to memory, which is highly dependent on the file size and the handset memory available.
You better create a Web Service to receive your PDF and return, for example, PNG images from it.

Java: CaptureDeviceManager#getDeviceList() is empty?

I am trying to print out all of the capture devices that are supported using the #getDeviceList() method in the CaptureDeviceManager class and the returned Vector has a size of 0.
Why is that? I have a webcam that works - so there should be at least one. I am running Mac OS X Lion - using JMF 2.1.1e.
Thanks!
CaptureDeviceManager.getDeviceList(Format format) does not detect devices. Instead it reads from the JMF registry which is the jmf.properties file. It searches for the jmf.properties file in the classpath.
If your JMF install has succeeded, then the classpath would have been configured to include all the relevant JMF jars and directories. The JMF install comes with a jmf.properties file included in the 'lib' folder under the JMF installation directory. This means the jmf.properties would be located by JMStudio and you would usually see the JMStudio application executing correctly. (If your JMF install is under 'C:\Program Files', then run as administrator to get around UAC)
When you create your own application to detect the devices, the problem you described above might occur. I have seen a few questions related to the same problem. This is because your application's classpath might be different and might not include the environment classpath. Check out your IDE's properties here. The problem is that CaptureDeviceManager cannot find the jmf.properties file because it is not there.
As you have found out correctly, you can copy the jmf.properties file from the JMF installation folder. It would contain the correct device list since JMF detects it during the install (Check it out just to make sure anyway).
If you want do device detection yourself, then create an empty jmf.properties file and put it somewhere in your classpath (it might throw a java.io.EOFException initially during execution but that's properly handled by the JMF classes). Then use the following code for detecting webcams...
import javax.media.*;
import java.util.*;
public static void main(String[] args) {
VFWAuto vfwObj = new VFWAuto();
Vector devices = CaptureDeviceManager.getDeviceList(null);
Enumeration deviceEnum = devices.elements();
System.out.println("Device count : " + devices.size());
while (deviceEnum.hasMoreElements()) {
CaptureDeviceInfo cdi = (CaptureDeviceInfo) deviceEnum.nextElement();
System.out.println("Device : " + cdi.getName());
}
}
The code for the VFWAuto class is given below. This is part of the JMStudio source code. You can get a good idea on how the devices are detected and recorded in the registry. Put both classes in the same package when you test. Disregard the main method in the VFWAuto class.
import com.sun.media.protocol.vfw.VFWCapture;
import java.util.*;
import javax.media.*;
public class VFWAuto {
public VFWAuto() {
Vector devices = (Vector) CaptureDeviceManager.getDeviceList(null).clone();
Enumeration enum = devices.elements();
while (enum.hasMoreElements()) {
CaptureDeviceInfo cdi = (CaptureDeviceInfo) enum.nextElement();
String name = cdi.getName();
if (name.startsWith("vfw:"))
CaptureDeviceManager.removeDevice(cdi);
}
int nDevices = 0;
for (int i = 0; i < 10; i++) {
String name = VFWCapture.capGetDriverDescriptionName(i);
if (name != null && name.length() > 1) {
System.err.println("Found device " + name);
System.err.println("Querying device. Please wait...");
com.sun.media.protocol.vfw.VFWSourceStream.autoDetect(i);
nDevices++;
}
}
}
public static void main(String [] args) {
VFWAuto a = new VFWAuto();
System.exit(0);
}
}
Assuming you are on a Windows platform and you have a working web-cam, then this code should detect the device and populate the jmf.properties file. On the next run you can also comment out the VFWAuto section and it's object references and you can see that CaptureDeviceManager reads from the jmf.properties file.
The VFWAuto class is part of jmf.jar. You can also see the DirectSoundAuto and JavaSoundAuto classes for detecting audio devices in the JMStudio sample source code. Try it out the same way as you did for VFWAuto.
My configuration was Windows 7 64 bit + JMF 2.1.1e windows performance pack + a web-cam.
I had the same issue and I solved by invoking flush() on my ObjectInputStream object.
According to the API documentation for ObjectInputStream's constructor:
The stream header containing the magic number and version number are read from the stream and verified. This method will block until the corresponding ObjectOutputStream has written and flushed the header.
This is a very important point to be aware of when trying to send objects in both directions over a socket because opening the streams in the wrong order will cause deadlock.
Consider for example what would happen if both client and server tried to construct an ObjectInputStream from a socket's input stream, prior to either constructing the corresponding ObjectOutputStream. The ObjectInputStream constructor on the client would block, waiting for the magic number and version number to arrive over the connection, while at the same time the ObjectInputStream constructor on the server side would also block for the same reason. Hence, deadlock.
Because of this, you should always make it a practice in your code to open the ObjectOutputStream and flush it first, before you open the ObjectInputStream. The ObjectOutputStream constructor will not block, and invoking flush() will force the magic number and version number to travel over the wire. If you follow this practice in both your client and server, you shouldn't have a problem with deadlock.
Credit goes to Tim Rohaly and his explanation here.
Before calling CaptureDeviceManager.getDeviceList(), the available devices must be loaded into the memory first.
You can do it manually by running JMFRegistry after installing JMF.
or do it programmatically with the help of the extension library FMJ (Free Media in Java). Here is the code:
import java.lang.reflect.Field;
import java.util.Vector;
import javax.media.*;
import javax.media.format.RGBFormat;
import net.sf.fmj.media.cdp.GlobalCaptureDevicePlugger;
public class FMJSandbox {
static {
System.setProperty("java.library.path", "D:/fmj-sf/native/win32-x86/");
try {
final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths");
sysPathsField.setAccessible(true);
sysPathsField.set(null, null);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
GlobalCaptureDevicePlugger.addCaptureDevices();
Vector deviceInfo = CaptureDeviceManager.getDeviceList(new RGBFormat());
System.out.println(deviceInfo.size());
for (Object obj : deviceInfo ) {
System.out.println(obj);
}
}
}
Here is the output:
USB2.0 Camera : civil:\\?\usb#vid_5986&pid_02d3&mi_00#7&584a19f&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global
RGB, -1-bit, Masks=-1:-1:-1, PixelStride=-1, LineStride=-1

Get MS-Windows Installed Applications from Java

Is it possible to get a list of installed applications (like the list from the un-install programs) from a windows vista computer with java?
If you mean installed applications I don't think it's possible by directly using Java SDK (also because it's not a cross platform requirement).. what I think you can do is to use an external native API to interact with windows registry (like jRegistryKey) and retrieve the information you need..
Instead if you want to get all the running applications from a Java program you could parse tasklist.exe output as explained here.
Not a Solution but a workaround!!
Getting windows native information using java SDK is not possible without support of external APIs. Instead of using external APIs (which is mostly LGPL licensed and not completely open), we can use the shell commands to get the same.
For getting the installed softwares list, use ProcessBuilder or Runtime.exec to run one of the following PowerShell commands:
Get-WmiObject -class Win32_Product | Select-Object -Property Name - This is bit slower! It uses Win32_Product class.
Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName, DisplayVersion, Publisher, InstallDate - This is faster and can give additional details. This uses PS registry provider.
You can stream the output of these and process it.
This is just a workaround and it is as per my analysis. As java is completely platform independent, fetching native information becomes difficult and the use of platform native tools (like command shell,, power shell etc.,) is a must.
package Vishal;
import com.sun.jna.platform.win32.Advapi32Util;
import static com.sun.jna.platform.win32.WinReg.HKEY_LOCAL_MACHINE;
import java.util.ArrayList;
import java.util.TreeMap;
public class GenerateInstalledApplicationList
{
ArrayList<String> getlist()
{
ArrayList<String> arr = new ArrayList();
String [] keys = Advapi32Util.registryGetKeys(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall");
String temp;
for (String key : keys)
{
temp = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall" + "\\" +key;
TreeMap<String, Object> tr = Advapi32Util.registryGetValues(HKEY_LOCAL_MACHINE,temp);
if(tr.isEmpty())
{
if(!key.contains("Update"))//all the instances of update are not actually installed applications
{
arr.add(key);
}
}
else
{
if(tr.containsKey("DisplayName"))
{
String str = (String) tr.get("DisplayName");
if(!str.contains("Update"))
{
arr.add(str);
}
}
}
}
return arr;
}}
Just Copy and paste this code it will return all the installed applications
only thing you will need is the jna api.

Categories