sourceforge 1386454 now supporting return values in event handlers. also added visio example of this

This commit is contained in:
clay_shooter
2006-02-12 00:53:11 +00:00
parent da8e6f9985
commit 3a30d03be1
12 changed files with 597 additions and 31 deletions

View File

@@ -30,6 +30,11 @@
has been added to the DispatchEvents constructors that lets a user provide has been added to the DispatchEvents constructors that lets a user provide
the location of the OLB or EXE that contains the information required to the location of the OLB or EXE that contains the information required to
retrieve the events. retrieve the events.
<li>Event handlers can now return a value to calling MS Windows program.
The event handlers must return an objec of type Variant if they wish to return
a value. All
previous event handlers still work with a void return. (This change should be
backwards compatible)
</ul> </ul>
</li> </li>
@@ -53,7 +58,11 @@
</tr> </tr>
<tr> <tr>
<td width="100%" colspan="2"><b>Patches</b></td> <td width="100%" colspan="2"><b>Patches</b></td>
</tr>1394001 </tr>
<tr>
<td width="13%">1386454</td>
<td width="87%">Return values from event callbacks (pre4)</td>
</tr>
<tr> <tr>
<td width="13%">1394001</td> <td width="13%">1394001</td>
<td width="87%">Missing variable initialization (pre3)</td> <td width="87%">Missing variable initialization (pre3)</td>

View File

@@ -42,9 +42,15 @@ EventProxy::EventProxy(JNIEnv *env,
env->GetJavaVM(&jvm); env->GetJavaVM(&jvm);
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
AddRef(); AddRef();
Connect(env);
}
void EventProxy::Connect(JNIEnv *env) {
HRESULT hr = pCP->Advise(this, &dwEventCookie); HRESULT hr = pCP->Advise(this, &dwEventCookie);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
connected = 1;
} else { } else {
connected = 0;
ThrowComFail(env, "Advise failed", hr); ThrowComFail(env, "Advise failed", hr);
} }
} }
@@ -52,8 +58,8 @@ EventProxy::EventProxy(JNIEnv *env,
// unhook myself up as a listener and get rid of delegate // unhook myself up as a listener and get rid of delegate
EventProxy::~EventProxy() EventProxy::~EventProxy()
{ {
pCP->Unadvise(dwEventCookie);
JNIEnv *env; JNIEnv *env;
Disconnect();
// attach to the current running thread // attach to the current running thread
#ifdef JNI_VERSION_1_2 #ifdef JNI_VERSION_1_2
printf("using version 1.2 API\n"); printf("using version 1.2 API\n");
@@ -74,6 +80,12 @@ EventProxy::~EventProxy()
jvm->DetachCurrentThread(); jvm->DetachCurrentThread();
} }
void EventProxy::Disconnect() {
if (connected) {
pCP->Unadvise(dwEventCookie);
}
}
// I only support the eventIID interface which was passed in // I only support the eventIID interface which was passed in
// by the DispatchEvent wrapper who looked it up as the // by the DispatchEvent wrapper who looked it up as the
// source object's default source interface // source object's default source interface
@@ -106,6 +118,7 @@ STDMETHODIMP EventProxy::Invoke(DISPID dispID, REFIID riid,
const char *eventMethodName = NULL; //Sourceforge report 1394001 const char *eventMethodName = NULL; //Sourceforge report 1394001
JNIEnv *env = NULL; JNIEnv *env = NULL;
jobject retObj;
// map dispID to jmethodID // map dispID to jmethodID
for(int i=0;i<MethNum;i++) for(int i=0;i<MethNum;i++)
@@ -135,13 +148,12 @@ STDMETHODIMP EventProxy::Invoke(DISPID dispID, REFIID riid,
// find the class of the InvocationHandler // find the class of the InvocationHandler
jclass javaSinkClass = env->GetObjectClass(javaSinkObj); jclass javaSinkClass = env->GetObjectClass(javaSinkObj);
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
jmethodID invokeMethod = env->GetMethodID(javaSinkClass, "invoke", jmethodID invokeMethod;
"(Ljava/lang/String;[Lcom/jacob/com/Variant;)V"); invokeMethod = env->GetMethodID(javaSinkClass, "invoke", "(Ljava/lang/String;[Lcom/jacob/com/Variant;)Lcom/jacob/com/Variant;");
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
jstring eventMethodNameAsString = env->NewStringUTF(eventMethodName); jstring eventMethodNameAsString = env->NewStringUTF(eventMethodName);
// now do what we need for the variant // now do what we need for the variant
jmethodID getVariantMethod = jmethodID getVariantMethod = env->GetMethodID(javaSinkClass, "getVariant", "()Lcom/jacob/com/Variant;");
env->GetMethodID(javaSinkClass, "getVariant", "()Lcom/jacob/com/Variant;");
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
jobject aVariantObj = env->CallObjectMethod(javaSinkObj, getVariantMethod); jobject aVariantObj = env->CallObjectMethod(javaSinkObj, getVariantMethod);
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
@@ -169,8 +181,14 @@ STDMETHODIMP EventProxy::Invoke(DISPID dispID, REFIID riid,
env->DeleteLocalRef(arg); env->DeleteLocalRef(arg);
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
} }
env->CallVoidMethod(javaSinkObj, invokeMethod, // Set up the return value
jobject ret;
ret = env->CallObjectMethod(javaSinkObj, invokeMethod,
eventMethodNameAsString, varr); eventMethodNameAsString, varr);
if (!env->ExceptionOccurred() && ret != NULL) {
VariantCopy(pVarResult, extractVariant(env,ret));
}
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
// don't need the first variant we created to get the class // don't need the first variant we created to get the class
env->DeleteLocalRef(aVariantObj); env->DeleteLocalRef(aVariantObj);
@@ -182,6 +200,19 @@ STDMETHODIMP EventProxy::Invoke(DISPID dispID, REFIID riid,
jobject arg = env->GetObjectArrayElement(varr, j); jobject arg = env->GetObjectArrayElement(varr, j);
VARIANT *java = extractVariant(env, arg); VARIANT *java = extractVariant(env, arg);
VARIANT *com = &pDispParams->rgvarg[i]; VARIANT *com = &pDispParams->rgvarg[i];
convertJavaVariant(java, com);
zeroVariant(env, arg);
env->DeleteLocalRef(arg);
}
// End code from Jiffie team that copies parameters back from java to COM
// detach from thread
jvm->DetachCurrentThread();
return S_OK;
}
return E_NOINTERFACE;
}
void EventProxy::convertJavaVariant(VARIANT *java, VARIANT *com) {
switch (com->vt) switch (com->vt)
{ {
@@ -796,14 +827,5 @@ STDMETHODIMP EventProxy::Invoke(DISPID dispID, REFIID riid,
} }
zeroVariant(env, arg);
env->DeleteLocalRef(arg);
} }
// End code from Jiffie team that copies parameters back from java to COM
// detach from thread
jvm->DetachCurrentThread();
return S_OK;
}
return E_NOINTERFACE;
}

View File

@@ -37,6 +37,7 @@
class EventProxy : public IDispatch class EventProxy : public IDispatch
{ {
private: private:
int connected;
LONG m_cRef; // a reference counter LONG m_cRef; // a reference counter
CComPtr<IConnectionPoint> pCP; // the connection point CComPtr<IConnectionPoint> pCP; // the connection point
DWORD dwEventCookie; // connection point cookie DWORD dwEventCookie; // connection point cookie
@@ -47,6 +48,9 @@ private:
CComBSTR *MethName; // Array of method names CComBSTR *MethName; // Array of method names
DISPID *MethID; // Array of method ids, used to match invokations to method names DISPID *MethID; // Array of method ids, used to match invokations to method names
JavaVM *jvm; // The java vm we are running JavaVM *jvm; // The java vm we are running
void convertJavaVariant(VARIANT *java, VARIANT *com);
void Connect(JNIEnv *env);
void Disconnect();
public: public:
// constuct with a global JNI ref to a sink object // constuct with a global JNI ref to a sink object
// to which we will delegate event callbacks // to which we will delegate event callbacks
@@ -62,7 +66,8 @@ public:
// IUnknown methods // IUnknown methods
STDMETHODIMP_(ULONG) AddRef(void) STDMETHODIMP_(ULONG) AddRef(void)
{ {
return InterlockedIncrement(&m_cRef); LONG res = InterlockedIncrement(&m_cRef);
return res;
} }
STDMETHODIMP_(ULONG) Release(void) STDMETHODIMP_(ULONG) Release(void)

View File

@@ -0,0 +1,85 @@
package com.jacob.samples.visio;
import com.jacob.com.*;
import com.jacob.activeX.*;
import java.io.File;
/**
* Created as part of sourceforge 1386454 to demonstrate returning values in event handlers
* @author miles@rowansoftware.net
*
* This class represents the visio app itself
*/
public class VisioApp extends ActiveXComponent {
public VisioApp() throws VisioException {
super("Visio.Application");
setVisible(false);
}
/**
* creates a DispatchEvents boject to register o as a listener
* @param o
*/
public void addEventListener(VisioEventListener o) {
DispatchEvents events = new DispatchEvents(this, o);
if (events == null){
System.out.println("You should never get null back when creating a DispatchEvents object");
}
}
public void open(File f) throws VisioException {
try {
ActiveXComponent documents = new ActiveXComponent(getProperty("Documents").toDispatch());
Variant[] args = new Variant[1];
args[0] = new Variant(f.getPath());
documents.invoke("Open",args);
} catch (Exception e) {
e.printStackTrace();
throw new VisioException(e);
}
}
public void save() throws VisioException {
try {
ActiveXComponent document = new ActiveXComponent(getProperty("ActiveDocument").toDispatch());
document.invoke("Save");
} catch (Exception e) {
e.printStackTrace();
throw new VisioException(e);
}
}
/**
* terminates visio
*/
public void quit() {
System.out.println("Received quit()");
// there can't be any open documents for this to work
// you'll get a visio error if you don't close them
ActiveXComponent document = new ActiveXComponent(getProperty("ActiveDocument").toDispatch());
document.invoke("Close");
invoke("Quit");
}
public void export(File f) throws VisioException {
try {
ActiveXComponent document = new ActiveXComponent(getProperty("ActivePage").toDispatch());
Variant[] args = new Variant[1];
args[0] = new Variant(f.getPath());
document.invoke("Export",args);
} catch (Exception e) {
throw new VisioException(e);
}
}
public void setVisible(boolean b) throws VisioException {
try {
setProperty("Visible",new Variant(b));
} catch (Exception e) {
throw new VisioException(e);
}
}
}

View File

@@ -0,0 +1,120 @@
package com.jacob.samples.visio;
import java.io.*;
/**
* Created as part of sourceforge 1386454 to demonstrate returning values in event handlers
* @author miles@rowansoftware.net
*
* This singleton isolates the demo app from the Visio instance object so that
* you can't try and send messages to a dead Visio instance after quit() has been
* called. Direct consumption of VisioApp would mean you could quit but would
* still have a handle to the no longer connected application proxy
*
*/
public class VisioAppFacade {
private VisioApp app;
private static VisioAppFacade instance;
public static final String IMAGE_EXT = ".jpg";
public static final String VISIO_EXT = ".vsd";
public static final int BUFFER_SIZE = 2048;
private VisioAppFacade() throws VisioException {
this.app = new VisioApp();
app.addEventListener(new VisioEventAdapter(app));
}
public static VisioAppFacade getInstance() throws VisioException {
if (instance == null) {
instance = new VisioAppFacade();
}
return instance;
}
public byte[] createPreview(byte[] visioData) throws VisioException {
byte[] preview;
File tmpFile;
try {
tmpFile = getTempVisioFile();
OutputStream out = new FileOutputStream(tmpFile);
out.write(visioData);
out.close();
} catch (IOException ioe) {
throw new VisioException(ioe);
}
preview = createPreview(tmpFile);
tmpFile.delete();
return preview;
}
public byte[] createPreview(File visioFile) throws VisioException {
try {
File imageFile;
imageFile = getTempImageFile();
app.open(visioFile);
app.export(imageFile);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
FileInputStream fin = new FileInputStream(imageFile);
copy(fin, bout);
fin.close();
imageFile.delete();
bout.close();
return bout.toByteArray();
} catch (IOException ioe) {
throw new VisioException(ioe);
}
}
private void copy(InputStream in, OutputStream out) throws IOException {
byte[] buff = new byte[BUFFER_SIZE];
int read;
do {
read = in.read(buff);
if (read > 0) {
out.write(buff,0,read);
}
} while (read > 0);
}
public byte[] createPreview(InputStream in) throws VisioException {
byte[] preview;
//byte[] buff = new byte[2048];
//int read = 0;
OutputStream out;
File tmpFile;
try {
tmpFile = getTempVisioFile();
out = new FileOutputStream(tmpFile);
copy(in, out);
out.close();
} catch (IOException ioe) {
throw new VisioException(ioe);
}
preview = createPreview(tmpFile);
tmpFile.delete();
return preview;
}
public void editDiagram(File f) throws VisioException {
app.open(f);
app.setVisible(true);
}
private File getTempVisioFile() throws IOException {
return File.createTempFile("java",VISIO_EXT);
}
private File getTempImageFile() throws IOException {
return File.createTempFile("java",IMAGE_EXT);
}
public void quit() {
app.quit();
instance = null;
}
}

View File

@@ -0,0 +1,181 @@
package com.jacob.samples.visio;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import com.jacob.com.ComThread;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
/**
* Created as part of sourceforge 1386454 to demonstrate returning values in event handlers
* @author miles@rowansoftware.net
*
* This file contains the main() that runs the demo
*
* This can be run in Eclipse with options
* <pre>
* -Djava.library.path=d:/jacob/release -Dcom.jacob.autogc=false
* -Dcom.jacob.debug=false
* </pre>
*/
public class VisioDemo extends JFrame implements ActionListener, WindowListener {
/**
* Totally dummy value to make Eclipse quit complaining
*/
private static final long serialVersionUID = 1L;
JButton chooseButton;
JButton openButton;
JPanel buttons;
ImageIcon theImage;
JLabel theLabel; // the icon on the page is actually this button's icon
File selectedFile;
/** everyone should get this through getVisio() */
private VisioAppFacade visioProxy = null;
// put this up here so it remembers where we were on the last choose
JFileChooser chooser = null;
public class VisioFileFilter extends FileFilter {
public boolean accept(File f) {
if (f.isDirectory()){
return true;
} else {
return (f.getName().toUpperCase().endsWith(".VSD"));
}
}
public String getDescription() {
return "Visio Drawings";
}
}
public VisioDemo() {
super("Visio in Swing POC");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buttons = new JPanel();
getContentPane().setLayout(new BorderLayout());
chooseButton = new JButton("Choose file to display");
openButton = new JButton("Open file chosen file in Visio");
chooseButton.addActionListener(this);
openButton.addActionListener(this);
buttons.add(chooseButton);
buttons.add(openButton);
getContentPane().add(buttons, BorderLayout.SOUTH);
theLabel = new JLabel("");
getContentPane().add(theLabel, BorderLayout.CENTER);
addWindowListener(this);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
setSize(640,480);
this.setVisible(true);
}
public static void main(String args[]) throws Exception {
SwingUtilities.invokeLater(new Runnable(){
public void run(){
ComThread.InitSTA();
VisioDemo poc = new VisioDemo();
ComThread.Release();
if (poc == null){
System.out.println("poc== null? That should never happen!");
}
}
});
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == chooseButton) {
pickFile();
} else if (e.getSource() == openButton) {
try {
openFile();
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
} else {
System.out.println("Awesome!");
}
}
private void pickFile() {
try {
chooser = new JFileChooser();
// comment this out if you want it to always go to myDocuments
chooser.setCurrentDirectory(new File(System.getProperty("user.dir")));
chooser.setFileFilter(new VisioFileFilter());
int returnVal = chooser.showOpenDialog(this);
if(returnVal == JFileChooser.APPROVE_OPTION) {
selectedFile = chooser.getSelectedFile();
showSelectedFilePreview();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* use this private method instead of initializing on boot up so that instance
* and all listeners are created in this thread (event thread) rather than root thread
* @return
*/
private VisioAppFacade getVisio(){
if (visioProxy == null){
try {
visioProxy = VisioAppFacade.getInstance();
} catch (VisioException ve){
System.out.println("ailed to openFile()");
ve.printStackTrace();
}
}
return visioProxy;
}
private void showSelectedFilePreview() throws VisioException {
if (selectedFile != null) {
byte[] image = getVisio().createPreview(selectedFile);
theImage = new ImageIcon(image);
theLabel.setIcon(theImage);
}
}
private void openFile() throws VisioException {
try {
getVisio().editDiagram(selectedFile);
showSelectedFilePreview();
} catch (VisioException ve){
System.out.println("ailed to openFile()");
ve.printStackTrace();
}
}
public void windowActivated(WindowEvent e) {
}
public void windowClosed(WindowEvent e) {
System.out.println("WINDOW CLOSED");
if (visioProxy != null){
visioProxy.quit();
}
}
public void windowClosing(WindowEvent e){
}
public void windowDeactivated(WindowEvent e){
}
public void windowDeiconified(WindowEvent e){
}
public void windowIconified(WindowEvent e){
System.out.println("Fooboo");
}
public void windowOpened(WindowEvent e){
}
}

View File

@@ -0,0 +1,59 @@
package com.jacob.samples.visio;
import com.jacob.com.*;
/**
* Created as part of sourceforge 1386454 to demonstrate returning values in event handlers
* @author miles@rowansoftware.net
*
* You can subclass this class and only implement the methods you're interested in
*/
public class VisioEventAdapter implements VisioEventListener {
VisioApp app = null;
public VisioEventAdapter(VisioApp pApp){
app = pApp;
System.out.println("Event listener constructed");
}
public void BeforeQuit(Variant[] args){ }
public void DocumentChanged(Variant[] args){
System.out.println("documentChanged()");
}
public void DocumentCloseCanceled(Variant[] args){ }
public void DocumentCreated(Variant[] args){ }
public void DocumentOpened(Variant[] args){
System.out.println("DocumentOpened()");
}
public void DocumentSaved(Variant[] args){ }
public void DocumentSavedAs(Variant[] args){ }
public Variant QueryCancelDocumentClose(Variant[] args){
System.out.println("QueryCancelDocumentClose()");
return new Variant(false);
}
/**
* we don't actually let it quit. We block it so
* that we don't have to relaunch when we look at a new document
*/
public Variant QueryCancelQuit(Variant[] args) {
// these may throw VisioException
System.out.println("Saving document, hiding and telling visio not to quit");
try {
app.save();
app.setVisible(false);
} catch (VisioException ve){
System.out.println("ailed to openFile()");
ve.printStackTrace();
}
return new Variant(true);
}
}

View File

@@ -0,0 +1,33 @@
package com.jacob.samples.visio;
import com.jacob.com.*;
/**
* Created as part of sourceforge 1386454 to demonstrate returning values in event handlers
* @author miles@rowansoftware.net
*
* There are many more Visio events available. See the Microsoft
* Office SDK documentation. To receive an event, add a method to this interface
* whose name matches the event name and has only one parameter, Variant[].
* The JACOB library will use reflection to call that method when an event is received.
*/
public interface VisioEventListener {
public void BeforeQuit(Variant[] args);
public void DocumentChanged(Variant[] args);
public void DocumentCloseCanceled(Variant[] args);
public void DocumentCreated(Variant[] args);
public void DocumentOpened(Variant[] args);
public void DocumentSaved(Variant[] args);
public void DocumentSavedAs(Variant[] args);
public Variant QueryCancelQuit(Variant[] args);
}

View File

@@ -0,0 +1,22 @@
package com.jacob.samples.visio;
/**
* Created as part of sourceforge 1386454 to demonstrate returning values in event handlers
* @author miles@rowansoftware.net
*
* This extends runtime exception so that we can be sloppy and not put catch blocks everywhere
*/
public class VisioException extends Exception {
/**
* Totally dummy value to make Eclipse quit complaining
*/
private static final long serialVersionUID = 1L;
public VisioException(String msg) {
super(msg);
}
public VisioException(Throwable cause) {
super(cause);
}
}

View File

@@ -28,12 +28,17 @@ import java.lang.reflect.Method;
* *
* DispatchProxy wraps this class around any event handlers * DispatchProxy wraps this class around any event handlers
* before making the JNI call that sets up the link with EventProxy. * before making the JNI call that sets up the link with EventProxy.
* This means that EventProxy just calls invoke(String,Variant[]) * This means that EventProxy.cpp just calls invoke(String,Variant[])
* against the instance of this class. Then this class does * against the instance of this class. Then this class does
* reflection against the event listener to call the actual event methods. * reflection against the event listener to call the actual event methods.
* All Event methods have the signature * All Event methods have the signature
* *
* <code> void eventMethodName(Variant[])</code> * <code> void eventMethodName(Variant[])</code>
* or
* <code> Variant eventMethodName(Variant[])</code>
* The void returning signature is the standard legacy signature.
* The Variant returning signature was added in 1.10 to support event handlers
* returning values.
* *
*/ */
public class InvocationProxy { public class InvocationProxy {
@@ -78,17 +83,24 @@ public class InvocationProxy {
} }
/** /**
* the method actually invoked by EventProxy.cpp * The method actually invoked by EventProxy.cpp.
* The method name is calculated by the underlying JNI code from the MS windows
* Callback function name. The method is assumed to take an array of Variant
* objects. The method may return a Variant or be a void. Those are the only
* two options that will not blow up.
*
* @param methodName name of method in mTargetObject we will invoke * @param methodName name of method in mTargetObject we will invoke
* @param targetParameter Variant[] that is the single parameter to the method * @param targetParameter Variant[] that is the single parameter to the method
*/ */
public void invoke(String methodName, Variant targetParameter[]){ public Variant invoke(String methodName, Variant targetParameter[]){
Variant mVariantToBeReturned = null;
if (mTargetObject == null){ if (mTargetObject == null){
if (JacobObject.isDebugEnabled()){ if (JacobObject.isDebugEnabled()){
JacobObject.debug( JacobObject.debug(
"InvocationProxy: received notification with no target set"); "InvocationProxy: received notification ("+methodName+") with no target set");
} }
return; // structured programming guidlines say this return should not be up here
return null;
} }
Class targetClass = mTargetObject.getClass(); Class targetClass = mTargetObject.getClass();
if (methodName == null){ if (methodName == null){
@@ -103,24 +115,39 @@ public class InvocationProxy {
JacobObject.debug("InvocationProxy: trying to invoke "+methodName JacobObject.debug("InvocationProxy: trying to invoke "+methodName
+" on "+mTargetObject); +" on "+mTargetObject);
} }
Method targetMethod = targetClass.getMethod(methodName, Method targetMethod;
targetMethod = targetClass.getMethod(methodName,
new Class[] {Variant[].class}); new Class[] {Variant[].class});
if (targetMethod != null){ if (targetMethod != null){
// protected classes can't be invoked against even if they // protected classes can't be invoked against even if they
// let you grab the method. you could do targetMethod.setAccessible(true); // let you grab the method. you could do targetMethod.setAccessible(true);
// but that should be stopped by the security manager // but that should be stopped by the security manager
Object mReturnedByInvocation = null;
mReturnedByInvocation =
targetMethod.invoke(mTargetObject,new Object[] {targetParameter}); targetMethod.invoke(mTargetObject,new Object[] {targetParameter});
if (mReturnedByInvocation == null){
// so we do something in this block
mVariantToBeReturned = null;
} else if (!(mReturnedByInvocation instanceof Variant)){
throw new IllegalArgumentException(
"InvocationProxy: invokation of target method returned "
+"non-null non-variant object: "+mReturnedByInvocation);
} else {
mVariantToBeReturned = (Variant) mReturnedByInvocation;
}
} }
} catch (SecurityException e) { } catch (SecurityException e) {
e.printStackTrace(); e.printStackTrace();
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
// this happens whenever the listener doesn't implement all the methods // this happens whenever the listener doesn't implement all the methods
if (JacobObject.isDebugEnabled()){ if (JacobObject.isDebugEnabled()){
JacobObject.debug("InvocationProxy: listener doesn't implement " JacobObject.debug("InvocationProxy: listener ("+mTargetObject+") doesn't implement "
+ methodName); + methodName);
} }
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
e.printStackTrace(); e.printStackTrace();
// we can throw these inside the catch block so need to re-throw it
throw e;
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
if (JacobObject.isDebugEnabled()){ if (JacobObject.isDebugEnabled()){
JacobObject.debug("InvocationProxy: probably tried to access public method on non public class" JacobObject.debug("InvocationProxy: probably tried to access public method on non public class"
@@ -130,6 +157,7 @@ public class InvocationProxy {
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
e.printStackTrace(); e.printStackTrace();
} }
return mVariantToBeReturned;
} }
/** /**

View File

@@ -76,8 +76,9 @@ public class ExcelEventTest extends InvocationProxy {
/** /**
* override the invoke method to log all the events * override the invoke method to log all the events
*/ */
public void invoke(String methodName, Variant targetParameter[]) { public Variant invoke(String methodName, Variant targetParameter[]) {
System.out.println("Received event from Windows program" + methodName); System.out.println("Received event from Windows program" + methodName);
return null;
} }
} }

View File

@@ -68,8 +68,9 @@ public class WordEventTest extends InvocationProxy {
/** /**
* override the invoke method to loga ll the events * override the invoke method to loga ll the events
*/ */
public void invoke(String methodName, Variant targetParameter[]) { public Variant invoke(String methodName, Variant targetParameter[]) {
System.out.println("Received event from Windows program" + methodName); System.out.println("Received event from Windows program" + methodName);
return null;
} }
} }