| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| package com.sun.star.lib.uno.environments.remote; |
| |
| |
| import java.io.PrintWriter; |
| import java.io.StringWriter; |
| |
| |
| import java.lang.reflect.InvocationTargetException; |
| |
| import com.sun.star.lib.uno.typedesc.MethodDescription; |
| import com.sun.star.uno.Any; |
| import com.sun.star.uno.IMethodDescription; |
| import com.sun.star.uno.Type; |
| import com.sun.star.uno.UnoRuntime; |
| import com.sun.star.uno.XCurrentContext; |
| |
| /** |
| * The Job is an abstraction for tasks which have to be done |
| * remotely because of a method invocation. |
| * <p> |
| * @version $Revision: 1.17 $ $ $Date: 2008-04-11 11:21:00 $ |
| * @author Kay Ramme |
| * @see com.sun.star.lib.uno.environments.remote.ThreadID |
| * @see com.sun.star.lib.uno.environments.remote.IReceiver |
| * @since UDK1.0 |
| */ |
| public class Job { |
| protected Job _next; |
| |
| protected IReceiver _iReceiver; |
| protected Message _iMessage; |
| Object _disposeId; |
| |
| protected Object _object; |
| |
| public Job(Object object, IReceiver iReceiver, Message iMessage) { |
| _object = object; |
| _iReceiver = iReceiver; |
| _iMessage = iMessage; |
| } |
| |
| /** |
| * Dispatches a <code>queryInterface</code> call |
| * <p> |
| * @return the result of the call (should be an <code>Any</code>) |
| * @param message the parameter for the call |
| * @param resultClass the result type as an out parameter |
| * @param status the status as an out parameter |
| * @param o_outs the out parameters of the call as out parameters |
| * @param o_out_sig the out signature as an out parameter |
| */ |
| protected Object dispatch_queryInterface(Type type) { |
| Class zInterface = type.getTypeDescription().getZClass(); |
| |
| Object result = null; |
| |
| Object face = UnoRuntime.queryInterface(zInterface, _object); |
| // the hell knows why, but empty interfaces a given back as void anys |
| if(face != null) |
| result = new Any(type, face); |
| return result; |
| } |
| |
| /** |
| * Execute the job. |
| * |
| * @return the result of the message. |
| */ |
| public Object execute() throws Throwable { |
| Object msgResult = _iMessage.getResult(); |
| if (_iMessage.isRequest()) { |
| Object result = null; |
| Throwable exception = null; |
| IMethodDescription md = _iMessage.getMethod(); |
| Object[] args = _iMessage.getArguments(); |
| XCurrentContext oldCC = UnoRuntime.getCurrentContext(); |
| UnoRuntime.setCurrentContext(_iMessage.getCurrentContext()); |
| try { |
| result = md.getIndex() == MethodDescription.ID_QUERY_INTERFACE |
| ? dispatch_queryInterface((Type) args[0]) |
| : md.getMethod().invoke(_object, args); |
| } catch (InvocationTargetException e) { |
| exception = e.getTargetException(); |
| if (exception == null) { |
| exception = e; |
| } |
| } catch (Exception e) { |
| exception = e; |
| } finally { |
| UnoRuntime.setCurrentContext(oldCC); |
| } |
| if (_iMessage.isSynchronous()) { |
| if (exception == null) { |
| _iReceiver.sendReply( |
| false, _iMessage.getThreadId(), result); |
| } else { |
| // Here we have to be aware of non-UNO exceptions, because |
| // they may kill a remote side which does not know anything |
| // about their types: |
| if (exception != null |
| && !(exception instanceof com.sun.star.uno.Exception) |
| && !(exception instanceof |
| com.sun.star.uno.RuntimeException)) |
| { |
| StringWriter writer = new StringWriter(); |
| exception.printStackTrace(new PrintWriter(writer)); |
| exception = new com.sun.star.uno.RuntimeException( |
| "Java exception: <" + writer + ">", null); |
| } |
| _iReceiver.sendReply( |
| true, _iMessage.getThreadId(), exception); |
| } |
| } |
| return null; |
| } else if (_iMessage.isAbnormalTermination()) { |
| throw remoteUnoRequestRaisedException(_iMessage.getResult()); |
| } else { |
| return _iMessage.getResult(); |
| } |
| } |
| |
| public ThreadId getThreadId() { |
| return _iMessage.getThreadId(); |
| } |
| |
| public boolean isRequest() { |
| return _iMessage.isRequest(); |
| } |
| |
| public boolean isSynchronous() { |
| return _iMessage.isSynchronous(); |
| } |
| |
| public void dispose() { |
| // _oId = null; |
| // _iReceiver = null; |
| // _threadId = null; |
| // _object = null; |
| // _operation = null; |
| // _param = null; |
| // _exception = null; |
| // _zInterface = null; |
| // _disposeId = null; |
| } |
| |
| // The name of this method is chosen to generate a somewhat self-explanatory |
| // stack trace: |
| private Exception remoteUnoRequestRaisedException(Object exception) { |
| Exception e = (Exception) exception; |
| e.fillInStackTrace(); |
| return e; |
| } |
| } |