1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  *  The Contents of this file are made available subject to the terms of
4*cdf0e10cSrcweir  *  the BSD license.
5*cdf0e10cSrcweir  *
6*cdf0e10cSrcweir  *  Copyright 2000, 2010 Oracle and/or its affiliates.
7*cdf0e10cSrcweir  *  All rights reserved.
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  *  Redistribution and use in source and binary forms, with or without
10*cdf0e10cSrcweir  *  modification, are permitted provided that the following conditions
11*cdf0e10cSrcweir  *  are met:
12*cdf0e10cSrcweir  *  1. Redistributions of source code must retain the above copyright
13*cdf0e10cSrcweir  *     notice, this list of conditions and the following disclaimer.
14*cdf0e10cSrcweir  *  2. Redistributions in binary form must reproduce the above copyright
15*cdf0e10cSrcweir  *     notice, this list of conditions and the following disclaimer in the
16*cdf0e10cSrcweir  *     documentation and/or other materials provided with the distribution.
17*cdf0e10cSrcweir  *  3. Neither the name of Sun Microsystems, Inc. nor the names of its
18*cdf0e10cSrcweir  *     contributors may be used to endorse or promote products derived
19*cdf0e10cSrcweir  *     from this software without specific prior written permission.
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22*cdf0e10cSrcweir  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23*cdf0e10cSrcweir  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24*cdf0e10cSrcweir  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25*cdf0e10cSrcweir  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26*cdf0e10cSrcweir  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27*cdf0e10cSrcweir  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28*cdf0e10cSrcweir  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29*cdf0e10cSrcweir  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30*cdf0e10cSrcweir  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31*cdf0e10cSrcweir  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32*cdf0e10cSrcweir  *
33*cdf0e10cSrcweir  *************************************************************************/
34*cdf0e10cSrcweir 
35*cdf0e10cSrcweir // __________ Imports __________
36*cdf0e10cSrcweir 
37*cdf0e10cSrcweir import com.sun.star.uno.UnoRuntime;
38*cdf0e10cSrcweir 
39*cdf0e10cSrcweir import java.lang.*;
40*cdf0e10cSrcweir import javax.swing.*;
41*cdf0e10cSrcweir import java.util.Vector;
42*cdf0e10cSrcweir 
43*cdf0e10cSrcweir // __________ Implementation __________
44*cdf0e10cSrcweir 
45*cdf0e10cSrcweir /**
46*cdf0e10cSrcweir  * This class can be used to intercept dispatched URL's
47*cdf0e10cSrcweir  * on any frame used in this demo application.
48*cdf0e10cSrcweir  * It intercept all URL's wich try to create a new empty frame.
49*cdf0e10cSrcweir  * (e.g. "private:factory/swriter")
50*cdf0e10cSrcweir  * Nobody can guarantee that this interception will be realy used -
51*cdf0e10cSrcweir  * because another interceptor (registered at a later time then this one!)
52*cdf0e10cSrcweir  * will be called before this one.
53*cdf0e10cSrcweir  * Implementation is executed inside a new thread to prevent application
54*cdf0e10cSrcweir  * against possible deadlocks. This deadlocks can occure if
55*cdf0e10cSrcweir  * synchronous/asynchronous ... normal ones and oneway calls are mixed.
56*cdf0e10cSrcweir  * Notifications of listener will be oneway mostly - her reactions can
57*cdf0e10cSrcweir  * be synchronous then. => deadlocks are possible
58*cdf0e10cSrcweir  *
59*cdf0e10cSrcweir  * @author     Andreas Schlüns
60*cdf0e10cSrcweir  * @created    06.03.2002 09:38
61*cdf0e10cSrcweir  */
62*cdf0e10cSrcweir public class Interceptor implements com.sun.star.frame.XFrameActionListener,
63*cdf0e10cSrcweir                                     com.sun.star.frame.XDispatchProviderInterceptor,
64*cdf0e10cSrcweir                                     com.sun.star.frame.XDispatchProvider,
65*cdf0e10cSrcweir                                     com.sun.star.frame.XDispatch,
66*cdf0e10cSrcweir                                     com.sun.star.frame.XInterceptorInfo,
67*cdf0e10cSrcweir                                     IShutdownListener,
68*cdf0e10cSrcweir                                     IOnewayLink
69*cdf0e10cSrcweir {
70*cdf0e10cSrcweir     // ____________________
71*cdf0e10cSrcweir 
72*cdf0e10cSrcweir     /**
73*cdf0e10cSrcweir      * const
74*cdf0e10cSrcweir      * All these URL's are intercepted by this implementation.
75*cdf0e10cSrcweir      */
76*cdf0e10cSrcweir     private static final String[] INTERCEPTED_URLS = { "private:factory/*" ,
77*cdf0e10cSrcweir                                                        ".uno:SaveAs"       ,
78*cdf0e10cSrcweir                                                        "slot:5300"         ,
79*cdf0e10cSrcweir                                                        ".uno:Quit"         };
80*cdf0e10cSrcweir 
81*cdf0e10cSrcweir     // ____________________
82*cdf0e10cSrcweir 
83*cdf0e10cSrcweir     /**
84*cdf0e10cSrcweir      * @member m_xMaster     use this interceptor if he doesn't handle queried dispatch request
85*cdf0e10cSrcweir      * @member m_xSlave      we can forward all unhandled requests to this slave interceptor
86*cdf0e10cSrcweir      * @member m_xFrame      intercepted frame
87*cdf0e10cSrcweir      * @member m_bDead       there exist more then one way to finish an object of this class - we must know it sometimes
88*cdf0e10cSrcweir      */
89*cdf0e10cSrcweir     private com.sun.star.frame.XDispatchProvider m_xMaster            ;
90*cdf0e10cSrcweir     private com.sun.star.frame.XDispatchProvider m_xSlave             ;
91*cdf0e10cSrcweir     private com.sun.star.frame.XFrame            m_xFrame             ;
92*cdf0e10cSrcweir     private boolean                              m_bIsActionListener  ;
93*cdf0e10cSrcweir     private boolean                              m_bIsRegistered      ;
94*cdf0e10cSrcweir     private boolean                              m_bDead              ;
95*cdf0e10cSrcweir 
96*cdf0e10cSrcweir     // ____________________
97*cdf0e10cSrcweir 
98*cdf0e10cSrcweir     /**
99*cdf0e10cSrcweir      * ctor
100*cdf0e10cSrcweir      * Initialize the new interceptor. Given frame reference can be used to
101*cdf0e10cSrcweir      * register this interceptor on it automaticly later.
102*cdf0e10cSrcweir      *
103*cdf0e10cSrcweir      * @seealso startListening()
104*cdf0e10cSrcweir      *
105*cdf0e10cSrcweir      * @param xFrame
106*cdf0e10cSrcweir      *          this interceptor will register himself at this frame to intercept dispatched URLs
107*cdf0e10cSrcweir      */
108*cdf0e10cSrcweir     Interceptor(/*IN*/ com.sun.star.frame.XFrame xFrame)
109*cdf0e10cSrcweir     {
110*cdf0e10cSrcweir         m_xFrame            = xFrame ;
111*cdf0e10cSrcweir         m_xSlave            = null   ;
112*cdf0e10cSrcweir         m_xMaster           = null   ;
113*cdf0e10cSrcweir         m_bIsRegistered     = false  ;
114*cdf0e10cSrcweir         m_bIsActionListener = false  ;
115*cdf0e10cSrcweir         m_bDead             = false  ;
116*cdf0e10cSrcweir     }
117*cdf0e10cSrcweir 
118*cdf0e10cSrcweir     //_____________________
119*cdf0e10cSrcweir 
120*cdf0e10cSrcweir     /**
121*cdf0e10cSrcweir      * start working as frame action listener realy.
122*cdf0e10cSrcweir      * We will be frame action listener here. In case
123*cdf0e10cSrcweir      * we get a frame action which indicates, that we should
124*cdf0e10cSrcweir      * update our interception. Because such using of an interecptor
125*cdf0e10cSrcweir      * isn't guaranteed - in case a newer one was registered ...
126*cdf0e10cSrcweir      */
127*cdf0e10cSrcweir     public void startListening()
128*cdf0e10cSrcweir     {
129*cdf0e10cSrcweir         com.sun.star.frame.XFrame xFrame = null;
130*cdf0e10cSrcweir         synchronized(this)
131*cdf0e10cSrcweir         {
132*cdf0e10cSrcweir             if (m_bDead)
133*cdf0e10cSrcweir                 return;
134*cdf0e10cSrcweir             if (m_xFrame==null)
135*cdf0e10cSrcweir                 return;
136*cdf0e10cSrcweir             if (m_bIsActionListener==true)
137*cdf0e10cSrcweir                 return;
138*cdf0e10cSrcweir             xFrame = m_xFrame;
139*cdf0e10cSrcweir         }
140*cdf0e10cSrcweir         m_xFrame.addFrameActionListener(this);
141*cdf0e10cSrcweir         synchronized(this)
142*cdf0e10cSrcweir         {
143*cdf0e10cSrcweir             m_bIsActionListener=true;
144*cdf0e10cSrcweir         }
145*cdf0e10cSrcweir     }
146*cdf0e10cSrcweir 
147*cdf0e10cSrcweir     //_____________________
148*cdf0e10cSrcweir 
149*cdf0e10cSrcweir     /**
150*cdf0e10cSrcweir      * In case we got an oneway listener callback - we had to use the office
151*cdf0e10cSrcweir      * asynchronous then. This method is the callback from the started thread
152*cdf0e10cSrcweir      * (started inside the original oneway method). We found all parameters of
153*cdf0e10cSrcweir      * the original request packed inside a vector. Here we unpack it and
154*cdf0e10cSrcweir      * call the right internal helper method, which implements the right
155*cdf0e10cSrcweir      * funtionality.
156*cdf0e10cSrcweir      *
157*cdf0e10cSrcweir      * @seealso frameAction()
158*cdf0e10cSrcweir      * @seealso dispatch()
159*cdf0e10cSrcweir      *
160*cdf0e10cSrcweir      * @param nRequest
161*cdf0e10cSrcweir      *          indicates, which was the original request (identifies the
162*cdf0e10cSrcweir      *          original called method)
163*cdf0e10cSrcweir      *
164*cdf0e10cSrcweir      * @param lParams
165*cdf0e10cSrcweir      *          the vector with all packed parameters of the original request
166*cdf0e10cSrcweir      */
167*cdf0e10cSrcweir     public void execOneway(/*IN*/ int nRequest,/*IN*/ Vector lParams )
168*cdf0e10cSrcweir     {
169*cdf0e10cSrcweir         synchronized(this)
170*cdf0e10cSrcweir         {
171*cdf0e10cSrcweir             if (m_bDead)
172*cdf0e10cSrcweir                 return;
173*cdf0e10cSrcweir         }
174*cdf0e10cSrcweir 
175*cdf0e10cSrcweir         // was it frameAction()?
176*cdf0e10cSrcweir         if (nRequest==OnewayExecutor.REQUEST_FRAMEACTION)
177*cdf0e10cSrcweir         {
178*cdf0e10cSrcweir             com.sun.star.frame.FrameActionEvent[] lOutAction   = new com.sun.star.frame.FrameActionEvent[1];
179*cdf0e10cSrcweir             Vector[]                              lInParams    = new Vector[1];
180*cdf0e10cSrcweir                                                   lInParams[0] = lParams;
181*cdf0e10cSrcweir 
182*cdf0e10cSrcweir             OnewayExecutor.codeFrameAction( OnewayExecutor.DECODE_PARAMS ,
183*cdf0e10cSrcweir                                             lInParams                    ,
184*cdf0e10cSrcweir                                             lOutAction                   );
185*cdf0e10cSrcweir             impl_frameAction(lOutAction[0]);
186*cdf0e10cSrcweir         }
187*cdf0e10cSrcweir         else
188*cdf0e10cSrcweir         // was it dispatch()?
189*cdf0e10cSrcweir         if (nRequest==OnewayExecutor.REQUEST_DISPATCH)
190*cdf0e10cSrcweir         {
191*cdf0e10cSrcweir             com.sun.star.util.URL[]              lOutURL      = new com.sun.star.util.URL[1];
192*cdf0e10cSrcweir             com.sun.star.beans.PropertyValue[][] lOutProps    = new com.sun.star.beans.PropertyValue[1][];
193*cdf0e10cSrcweir             Vector[]                             lInParams    = new Vector[1];
194*cdf0e10cSrcweir                                                  lInParams[0] = lParams;
195*cdf0e10cSrcweir 
196*cdf0e10cSrcweir             OnewayExecutor.codeDispatch( OnewayExecutor.DECODE_PARAMS ,
197*cdf0e10cSrcweir                                          lInParams                    ,
198*cdf0e10cSrcweir                                          lOutURL                      ,
199*cdf0e10cSrcweir                                          lOutProps                    );
200*cdf0e10cSrcweir             impl_dispatch(lOutURL[0],lOutProps[0]);
201*cdf0e10cSrcweir         }
202*cdf0e10cSrcweir     }
203*cdf0e10cSrcweir 
204*cdf0e10cSrcweir     // ____________________
205*cdf0e10cSrcweir 
206*cdf0e10cSrcweir     /**
207*cdf0e10cSrcweir      * call back for frame action events
208*cdf0e10cSrcweir      * We use it to update our interception. Because if a new component was loaded into
209*cdf0e10cSrcweir      * the frame or another interceptor was registered, we should refresh our connection
210*cdf0e10cSrcweir      * to the frame. Otherwhise we can't guarantee full functionality here.
211*cdf0e10cSrcweir      *
212*cdf0e10cSrcweir      * Note: Don't react synchronous in an asynchronous listener callback. So use a thread
213*cdf0e10cSrcweir      * here to update anything.
214*cdf0e10cSrcweir      *
215*cdf0e10cSrcweir      * @seealso impl_frameAction()
216*cdf0e10cSrcweir      *
217*cdf0e10cSrcweir      * @param aEvent
218*cdf0e10cSrcweir      *          describes the action
219*cdf0e10cSrcweir      */
220*cdf0e10cSrcweir     public /*ONEWAY*/  void frameAction(/*IN*/ com.sun.star.frame.FrameActionEvent aEvent)
221*cdf0e10cSrcweir     {
222*cdf0e10cSrcweir         synchronized(this)
223*cdf0e10cSrcweir         {
224*cdf0e10cSrcweir             if (m_bDead)
225*cdf0e10cSrcweir                 return;
226*cdf0e10cSrcweir         }
227*cdf0e10cSrcweir 
228*cdf0e10cSrcweir         boolean bHandle = false;
229*cdf0e10cSrcweir         switch(aEvent.Action.getValue())
230*cdf0e10cSrcweir         {
231*cdf0e10cSrcweir             case com.sun.star.frame.FrameAction.COMPONENT_ATTACHED_value   : bHandle=true; break;
232*cdf0e10cSrcweir             case com.sun.star.frame.FrameAction.COMPONENT_DETACHING_value  : bHandle=true; break;
233*cdf0e10cSrcweir             case com.sun.star.frame.FrameAction.COMPONENT_REATTACHED_value : bHandle=true; break;
234*cdf0e10cSrcweir             // Don't react for CONTEXT_CHANGED here. Ok it indicates, that may another interceptor
235*cdf0e10cSrcweir             // was registered at the frame ... but if we register ourself there - we get a context
236*cdf0e10cSrcweir             // changed too :-( Best way to produce a never ending recursion ...
237*cdf0e10cSrcweir             // May be that somewhere find a safe mechanism to detect own produced frame action events
238*cdf0e10cSrcweir             // and ignore it.
239*cdf0e10cSrcweir             case com.sun.star.frame.FrameAction.CONTEXT_CHANGED_value :
240*cdf0e10cSrcweir                     System.out.println("Time to update interception ... but may it will start a recursion. So I let it :-(");
241*cdf0e10cSrcweir                     bHandle=false;
242*cdf0e10cSrcweir                     break;
243*cdf0e10cSrcweir         }
244*cdf0e10cSrcweir 
245*cdf0e10cSrcweir         // ignore some events
246*cdf0e10cSrcweir         if (! bHandle)
247*cdf0e10cSrcweir             return;
248*cdf0e10cSrcweir 
249*cdf0e10cSrcweir         // pack the event and start thread - which call us back later
250*cdf0e10cSrcweir         Vector[]                              lOutParams   = new Vector[1];
251*cdf0e10cSrcweir         com.sun.star.frame.FrameActionEvent[] lInAction    = new com.sun.star.frame.FrameActionEvent[1];
252*cdf0e10cSrcweir                                               lInAction[0] = aEvent;
253*cdf0e10cSrcweir 
254*cdf0e10cSrcweir         OnewayExecutor.codeFrameAction( OnewayExecutor.ENCODE_PARAMS ,
255*cdf0e10cSrcweir                                         lOutParams                   ,
256*cdf0e10cSrcweir                                         lInAction                    );
257*cdf0e10cSrcweir         OnewayExecutor aExecutor = new OnewayExecutor( (IOnewayLink)this                  ,
258*cdf0e10cSrcweir                                                        OnewayExecutor.REQUEST_FRAMEACTION ,
259*cdf0e10cSrcweir                                                        lOutParams[0]                      );
260*cdf0e10cSrcweir         aExecutor.start();
261*cdf0e10cSrcweir     }
262*cdf0e10cSrcweir 
263*cdf0e10cSrcweir     // ____________________
264*cdf0e10cSrcweir 
265*cdf0e10cSrcweir     /**
266*cdf0e10cSrcweir      * Indicates using of us as an interceptor.
267*cdf0e10cSrcweir      * Now we have to react for the requests, we are registered.
268*cdf0e10cSrcweir      * That means: load new empty documents - triggered by the new menu of the office.
269*cdf0e10cSrcweir      * Because it's oneway - use thread for loading!
270*cdf0e10cSrcweir      *
271*cdf0e10cSrcweir      * @seealso impl_dispatch()
272*cdf0e10cSrcweir      *
273*cdf0e10cSrcweir      * @param aURL
274*cdf0e10cSrcweir      *          describes the document, which should be loaded
275*cdf0e10cSrcweir      *
276*cdf0e10cSrcweir      * @param lArguments
277*cdf0e10cSrcweir      *          optional parameters for loading
278*cdf0e10cSrcweir      */
279*cdf0e10cSrcweir     public /*ONEWAY*/ void dispatch(/*IN*/ com.sun.star.util.URL aURL,/*IN*/ com.sun.star.beans.PropertyValue[] lArguments)
280*cdf0e10cSrcweir     {
281*cdf0e10cSrcweir         synchronized(this)
282*cdf0e10cSrcweir         {
283*cdf0e10cSrcweir             if (m_bDead)
284*cdf0e10cSrcweir                 return;
285*cdf0e10cSrcweir         }
286*cdf0e10cSrcweir 
287*cdf0e10cSrcweir         Vector[]                             lOutParams      = new Vector[1];
288*cdf0e10cSrcweir         com.sun.star.util.URL[]              lInURL          = new com.sun.star.util.URL[1];
289*cdf0e10cSrcweir         com.sun.star.beans.PropertyValue[][] lInArguments    = new com.sun.star.beans.PropertyValue[1][];
290*cdf0e10cSrcweir                                              lInURL[0]       = aURL      ;
291*cdf0e10cSrcweir                                              lInArguments[0] = lArguments;
292*cdf0e10cSrcweir 
293*cdf0e10cSrcweir         OnewayExecutor.codeDispatch( OnewayExecutor.ENCODE_PARAMS ,
294*cdf0e10cSrcweir                                      lOutParams                   ,
295*cdf0e10cSrcweir                                      lInURL                       ,
296*cdf0e10cSrcweir                                      lInArguments                 );
297*cdf0e10cSrcweir         OnewayExecutor aExecutor = new OnewayExecutor( (IOnewayLink)this               ,
298*cdf0e10cSrcweir                                                        OnewayExecutor.REQUEST_DISPATCH ,
299*cdf0e10cSrcweir                                                        lOutParams[0]                   );
300*cdf0e10cSrcweir         aExecutor.start();
301*cdf0e10cSrcweir     }
302*cdf0e10cSrcweir 
303*cdf0e10cSrcweir 
304*cdf0e10cSrcweir     //_____________________
305*cdf0e10cSrcweir 
306*cdf0e10cSrcweir     /**
307*cdf0e10cSrcweir      * Internal call back for frame action events, triggered by the used
308*cdf0e10cSrcweir      * OnewayExecutor thread we started in frameAction().
309*cdf0e10cSrcweir      * We use it to update our interception on the internal saved frame.
310*cdf0e10cSrcweir      *
311*cdf0e10cSrcweir      * @param aEvent
312*cdf0e10cSrcweir      *          describes the action
313*cdf0e10cSrcweir      */
314*cdf0e10cSrcweir     public void impl_frameAction(/*IN*/ com.sun.star.frame.FrameActionEvent aEvent)
315*cdf0e10cSrcweir     {
316*cdf0e10cSrcweir         synchronized(this)
317*cdf0e10cSrcweir         {
318*cdf0e10cSrcweir             if (m_bDead)
319*cdf0e10cSrcweir                 return;
320*cdf0e10cSrcweir         }
321*cdf0e10cSrcweir 
322*cdf0e10cSrcweir         // deregistration will be done everytime ...
323*cdf0e10cSrcweir         // But may it's not neccessary to establish a new registration!
324*cdf0e10cSrcweir         // Don't look for ignoring actions - it was done already inside original frameAction() call!
325*cdf0e10cSrcweir         boolean bRegister = false;
326*cdf0e10cSrcweir 
327*cdf0e10cSrcweir         // analyze the event and decide which reaction is usefull
328*cdf0e10cSrcweir         switch(aEvent.Action.getValue())
329*cdf0e10cSrcweir         {
330*cdf0e10cSrcweir             case com.sun.star.frame.FrameAction.COMPONENT_ATTACHED_value   : bRegister = true ; break;
331*cdf0e10cSrcweir             case com.sun.star.frame.FrameAction.COMPONENT_REATTACHED_value : bRegister = true ; break;
332*cdf0e10cSrcweir             case com.sun.star.frame.FrameAction.COMPONENT_DETACHING_value  : bRegister = false; break;
333*cdf0e10cSrcweir         }
334*cdf0e10cSrcweir 
335*cdf0e10cSrcweir         com.sun.star.frame.XFrame xFrame        = null ;
336*cdf0e10cSrcweir         boolean                   bIsRegistered = false;
337*cdf0e10cSrcweir         synchronized(this)
338*cdf0e10cSrcweir         {
339*cdf0e10cSrcweir             bIsRegistered   = m_bIsRegistered;
340*cdf0e10cSrcweir             m_bIsRegistered = false;
341*cdf0e10cSrcweir             xFrame          = m_xFrame;
342*cdf0e10cSrcweir         }
343*cdf0e10cSrcweir 
344*cdf0e10cSrcweir         com.sun.star.frame.XDispatchProviderInterception xRegistration = (com.sun.star.frame.XDispatchProviderInterception)UnoRuntime.queryInterface(
345*cdf0e10cSrcweir             com.sun.star.frame.XDispatchProviderInterception.class,
346*cdf0e10cSrcweir             xFrame);
347*cdf0e10cSrcweir 
348*cdf0e10cSrcweir         if(xRegistration==null)
349*cdf0e10cSrcweir             return;
350*cdf0e10cSrcweir 
351*cdf0e10cSrcweir         if (bIsRegistered)
352*cdf0e10cSrcweir             xRegistration.releaseDispatchProviderInterceptor(this);
353*cdf0e10cSrcweir 
354*cdf0e10cSrcweir         if (! bRegister)
355*cdf0e10cSrcweir             return;
356*cdf0e10cSrcweir 
357*cdf0e10cSrcweir         xRegistration.registerDispatchProviderInterceptor(this);
358*cdf0e10cSrcweir         synchronized(this)
359*cdf0e10cSrcweir         {
360*cdf0e10cSrcweir             m_bIsRegistered = true;
361*cdf0e10cSrcweir         }
362*cdf0e10cSrcweir     }
363*cdf0e10cSrcweir 
364*cdf0e10cSrcweir     // ____________________
365*cdf0e10cSrcweir 
366*cdf0e10cSrcweir     /**
367*cdf0e10cSrcweir      * Implementation of interface XDispatchProviderInterceptor
368*cdf0e10cSrcweir      * These functions are used to build a list of interceptor objects
369*cdf0e10cSrcweir      * connected in both ways.
370*cdf0e10cSrcweir      * Searching for a right interceptor is made by forwarding any request
371*cdf0e10cSrcweir      * from toppest master to lowest slave of this hierarchy.
372*cdf0e10cSrcweir      * If an interceptor whish to handle the request he can break that
373*cdf0e10cSrcweir      * and return himself as a dispatcher.
374*cdf0e10cSrcweir      */
375*cdf0e10cSrcweir     public com.sun.star.frame.XDispatchProvider getSlaveDispatchProvider()
376*cdf0e10cSrcweir     {
377*cdf0e10cSrcweir         synchronized(this)
378*cdf0e10cSrcweir         {
379*cdf0e10cSrcweir             return m_xSlave;
380*cdf0e10cSrcweir         }
381*cdf0e10cSrcweir     }
382*cdf0e10cSrcweir 
383*cdf0e10cSrcweir     // ____________________
384*cdf0e10cSrcweir 
385*cdf0e10cSrcweir     public void setSlaveDispatchProvider(com.sun.star.frame.XDispatchProvider xSlave)
386*cdf0e10cSrcweir     {
387*cdf0e10cSrcweir         synchronized(this)
388*cdf0e10cSrcweir         {
389*cdf0e10cSrcweir             m_xSlave = xSlave;
390*cdf0e10cSrcweir         }
391*cdf0e10cSrcweir     }
392*cdf0e10cSrcweir 
393*cdf0e10cSrcweir     // ____________________
394*cdf0e10cSrcweir 
395*cdf0e10cSrcweir     public com.sun.star.frame.XDispatchProvider getMasterDispatchProvider()
396*cdf0e10cSrcweir     {
397*cdf0e10cSrcweir         synchronized(this)
398*cdf0e10cSrcweir         {
399*cdf0e10cSrcweir             return m_xMaster;
400*cdf0e10cSrcweir         }
401*cdf0e10cSrcweir     }
402*cdf0e10cSrcweir 
403*cdf0e10cSrcweir     // ____________________
404*cdf0e10cSrcweir 
405*cdf0e10cSrcweir     public void setMasterDispatchProvider(com.sun.star.frame.XDispatchProvider xMaster)
406*cdf0e10cSrcweir     {
407*cdf0e10cSrcweir         synchronized(this)
408*cdf0e10cSrcweir         {
409*cdf0e10cSrcweir             m_xMaster = xMaster;
410*cdf0e10cSrcweir         }
411*cdf0e10cSrcweir     }
412*cdf0e10cSrcweir 
413*cdf0e10cSrcweir     // ____________________
414*cdf0e10cSrcweir 
415*cdf0e10cSrcweir     /**
416*cdf0e10cSrcweir      * Implementation of interface XDispatchProvider
417*cdf0e10cSrcweir      * These functions are called from our master if he willn't handle the outstanding request.
418*cdf0e10cSrcweir      * Given parameter should be checked if they are right for us. If it's true, the returned
419*cdf0e10cSrcweir      * dispatcher should be this implementation himself; otherwise call should be forwarded
420*cdf0e10cSrcweir      * to the slave.
421*cdf0e10cSrcweir      *
422*cdf0e10cSrcweir      * @param aURL
423*cdf0e10cSrcweir      *          describes the request, which should be handled
424*cdf0e10cSrcweir      *
425*cdf0e10cSrcweir      * @param sTarget
426*cdf0e10cSrcweir      *          specifies the target frame for this request
427*cdf0e10cSrcweir      *
428*cdf0e10cSrcweir      * @param nSearchFlags
429*cdf0e10cSrcweir      *          optional search flags, if sTarget isn't a special one
430*cdf0e10cSrcweir      *
431*cdf0e10cSrcweir      * @return [XDispatch]
432*cdf0e10cSrcweir      *          a dispatch object, which can handle the given URL
433*cdf0e10cSrcweir      *          May be NULL!
434*cdf0e10cSrcweir      */
435*cdf0e10cSrcweir     public com.sun.star.frame.XDispatch queryDispatch(/*IN*/ com.sun.star.util.URL aURL,/*IN*/ String sTarget,/*IN*/ int nSearchFlags)
436*cdf0e10cSrcweir     {
437*cdf0e10cSrcweir         synchronized(this)
438*cdf0e10cSrcweir         {
439*cdf0e10cSrcweir             if (m_bDead)
440*cdf0e10cSrcweir                 return null;
441*cdf0e10cSrcweir         }
442*cdf0e10cSrcweir 
443*cdf0e10cSrcweir         // intercept loading empty documents into new created frames
444*cdf0e10cSrcweir         if(
445*cdf0e10cSrcweir             (sTarget.compareTo       ("_blank"         ) == 0   ) &&
446*cdf0e10cSrcweir             (aURL.Complete.startsWith("private:factory") == true)
447*cdf0e10cSrcweir           )
448*cdf0e10cSrcweir         {
449*cdf0e10cSrcweir             System.out.println("intercept private:factory");
450*cdf0e10cSrcweir             return this;
451*cdf0e10cSrcweir         }
452*cdf0e10cSrcweir 
453*cdf0e10cSrcweir         // intercept opening the SaveAs dialog
454*cdf0e10cSrcweir         if (aURL.Complete.startsWith(".uno:SaveAs") == true)
455*cdf0e10cSrcweir         {
456*cdf0e10cSrcweir             System.out.println("intercept SaveAs by returning null!");
457*cdf0e10cSrcweir             return null;
458*cdf0e10cSrcweir         }
459*cdf0e10cSrcweir 
460*cdf0e10cSrcweir         // intercept "File->Exit" inside the menu
461*cdf0e10cSrcweir         if (
462*cdf0e10cSrcweir             (aURL.Complete.startsWith("slot:5300") == true)  ||
463*cdf0e10cSrcweir             (aURL.Complete.startsWith(".uno:Quit") == true)
464*cdf0e10cSrcweir            )
465*cdf0e10cSrcweir         {
466*cdf0e10cSrcweir             System.out.println("intercept File->Exit");
467*cdf0e10cSrcweir             return this;
468*cdf0e10cSrcweir         }
469*cdf0e10cSrcweir 
470*cdf0e10cSrcweir         synchronized(this)
471*cdf0e10cSrcweir         {
472*cdf0e10cSrcweir             if (m_xSlave!=null)
473*cdf0e10cSrcweir                 return m_xSlave.queryDispatch(aURL, sTarget, nSearchFlags);
474*cdf0e10cSrcweir         }
475*cdf0e10cSrcweir 
476*cdf0e10cSrcweir         return null;
477*cdf0e10cSrcweir     }
478*cdf0e10cSrcweir 
479*cdf0e10cSrcweir     // ____________________
480*cdf0e10cSrcweir 
481*cdf0e10cSrcweir     public com.sun.star.frame.XDispatch[] queryDispatches(/*IN*/ com.sun.star.frame.DispatchDescriptor[] lDescriptor)
482*cdf0e10cSrcweir     {
483*cdf0e10cSrcweir         synchronized(this)
484*cdf0e10cSrcweir         {
485*cdf0e10cSrcweir             if (m_bDead)
486*cdf0e10cSrcweir                 return null;
487*cdf0e10cSrcweir         }
488*cdf0e10cSrcweir         // Resolve any request seperatly by using own "dispatch()" method.
489*cdf0e10cSrcweir         // Note: Don't pack return list if "null" objects occure!
490*cdf0e10cSrcweir         int                            nCount      = lDescriptor.length;
491*cdf0e10cSrcweir         com.sun.star.frame.XDispatch[] lDispatcher = new com.sun.star.frame.XDispatch[nCount];
492*cdf0e10cSrcweir         for(int i=0; i<nCount; ++i)
493*cdf0e10cSrcweir         {
494*cdf0e10cSrcweir             lDispatcher[i] = queryDispatch(lDescriptor[i].FeatureURL ,
495*cdf0e10cSrcweir                                            lDescriptor[i].FrameName  ,
496*cdf0e10cSrcweir                                            lDescriptor[i].SearchFlags);
497*cdf0e10cSrcweir         }
498*cdf0e10cSrcweir         return lDispatcher;
499*cdf0e10cSrcweir     }
500*cdf0e10cSrcweir 
501*cdf0e10cSrcweir     // ____________________
502*cdf0e10cSrcweir 
503*cdf0e10cSrcweir     /**
504*cdf0e10cSrcweir      * This method is called if this interceptor "wins the request".
505*cdf0e10cSrcweir      * We intercepted creation of new frames and loading of empty documents.
506*cdf0e10cSrcweir      * Do it now.
507*cdf0e10cSrcweir      *
508*cdf0e10cSrcweir      * @param aURL
509*cdf0e10cSrcweir      *          describes the document
510*cdf0e10cSrcweir      *
511*cdf0e10cSrcweir      * @param lArguments
512*cdf0e10cSrcweir      *          optional arguments for loading
513*cdf0e10cSrcweir      */
514*cdf0e10cSrcweir     public void impl_dispatch(/*IN*/ com.sun.star.util.URL aURL,/*IN*/ com.sun.star.beans.PropertyValue[] lArguments)
515*cdf0e10cSrcweir     {
516*cdf0e10cSrcweir         synchronized(this)
517*cdf0e10cSrcweir         {
518*cdf0e10cSrcweir             if (m_bDead)
519*cdf0e10cSrcweir                 return;
520*cdf0e10cSrcweir         }
521*cdf0e10cSrcweir 
522*cdf0e10cSrcweir         if (
523*cdf0e10cSrcweir             (aURL.Complete.startsWith("slot:5300") == true) ||
524*cdf0e10cSrcweir             (aURL.Complete.startsWith(".uno:Quit") == true)
525*cdf0e10cSrcweir            )
526*cdf0e10cSrcweir         {
527*cdf0e10cSrcweir             System.exit(0);
528*cdf0e10cSrcweir         }
529*cdf0e10cSrcweir         else
530*cdf0e10cSrcweir         if (aURL.Complete.startsWith("private:factory") == true)
531*cdf0e10cSrcweir         {
532*cdf0e10cSrcweir             // Create view frame for showing loaded documents on demand.
533*cdf0e10cSrcweir             // The visible state is neccessary for JNI functionality to get the HWND and plug office
534*cdf0e10cSrcweir             // inside a java window hierarchy!
535*cdf0e10cSrcweir             DocumentView aNewView = new DocumentView();
536*cdf0e10cSrcweir             aNewView.setVisible(true);
537*cdf0e10cSrcweir             aNewView.createFrame();
538*cdf0e10cSrcweir             aNewView.load(aURL.Complete,lArguments);
539*cdf0e10cSrcweir         }
540*cdf0e10cSrcweir     }
541*cdf0e10cSrcweir 
542*cdf0e10cSrcweir     // ____________________
543*cdf0e10cSrcweir 
544*cdf0e10cSrcweir     /**
545*cdf0e10cSrcweir      * Notification of status listener isn't guaranteed (instead of listener on XNotifyingDispatch interface).
546*cdf0e10cSrcweir      * So this interceptor doesn't support that realy ...
547*cdf0e10cSrcweir      */
548*cdf0e10cSrcweir     public /*ONEWAY*/ void addStatusListener(/*IN*/ com.sun.star.frame.XStatusListener xListener,/*IN*/ com.sun.star.util.URL aURL)
549*cdf0e10cSrcweir     {
550*cdf0e10cSrcweir /*        if (aURL.Complete.startsWith(".uno:SaveAs")==true)
551*cdf0e10cSrcweir         {
552*cdf0e10cSrcweir             com.sun.star.frame.FeatureStateEvent aEvent = new com.sun.star.frame.FeatureStateEvent(
553*cdf0e10cSrcweir                                                                 this,
554*cdf0e10cSrcweir                                                                 aURL,
555*cdf0e10cSrcweir                                                                 "",
556*cdf0e10cSrcweir                                                                 false,
557*cdf0e10cSrcweir                                                                 false,
558*cdf0e10cSrcweir                                                                 null);
559*cdf0e10cSrcweir             if (xListener!=null)
560*cdf0e10cSrcweir             {
561*cdf0e10cSrcweir                 System.out.println("interceptor disable SavAs by listener notify");
562*cdf0e10cSrcweir                 xListener.statusChanged(aEvent);
563*cdf0e10cSrcweir             }
564*cdf0e10cSrcweir         }*/
565*cdf0e10cSrcweir     }
566*cdf0e10cSrcweir 
567*cdf0e10cSrcweir     // ____________________
568*cdf0e10cSrcweir 
569*cdf0e10cSrcweir     public /*ONEWAY*/ void removeStatusListener(/*IN*/ com.sun.star.frame.XStatusListener xListener,/*IN*/ com.sun.star.util.URL aURL)
570*cdf0e10cSrcweir     {
571*cdf0e10cSrcweir     }
572*cdf0e10cSrcweir 
573*cdf0e10cSrcweir     // ____________________
574*cdf0e10cSrcweir 
575*cdf0e10cSrcweir     /**
576*cdf0e10cSrcweir      * Implements (optional!) optimization for interceptor mechanism.
577*cdf0e10cSrcweir      * Any interceptor which provides this special interface is called automaticly
578*cdf0e10cSrcweir      * at registration time on this method. Returned URL's will be used to
579*cdf0e10cSrcweir      * call this interceptor directly without calling his masters before, IF(!)
580*cdf0e10cSrcweir      * following rules will be true:
581*cdf0e10cSrcweir      *      (1) every master supports this optional interface too
582*cdf0e10cSrcweir      *      (2) nobody of these masters whish to intercept same URL then this one
583*cdf0e10cSrcweir      * This interceptor whish to intercept creation of new documents.
584*cdf0e10cSrcweir      */
585*cdf0e10cSrcweir     public String[] getInterceptedURLs()
586*cdf0e10cSrcweir     {
587*cdf0e10cSrcweir         return INTERCEPTED_URLS;
588*cdf0e10cSrcweir     }
589*cdf0e10cSrcweir 
590*cdf0e10cSrcweir     // ____________________
591*cdf0e10cSrcweir 
592*cdf0e10cSrcweir     /**
593*cdf0e10cSrcweir      * This class listen on the intercepted frame to free all used ressources on closing.
594*cdf0e10cSrcweir      * We forget the reference to the frame only here. Deregistration
595*cdf0e10cSrcweir      * isn't neccessary here - because this frame dies and wish to forgoten.
596*cdf0e10cSrcweir      *
597*cdf0e10cSrcweir      * @param aSource
598*cdf0e10cSrcweir      *          must be our internal saved frame, on which we listen for frame action events
599*cdf0e10cSrcweir      */
600*cdf0e10cSrcweir     public /*ONEAY*/ void disposing(/*IN*/ com.sun.star.lang.EventObject aSource)
601*cdf0e10cSrcweir     {
602*cdf0e10cSrcweir         synchronized(this)
603*cdf0e10cSrcweir         {
604*cdf0e10cSrcweir             if (m_bDead)
605*cdf0e10cSrcweir                 return;
606*cdf0e10cSrcweir             if (m_xFrame!=null && UnoRuntime.areSame(aSource.Source,m_xFrame))
607*cdf0e10cSrcweir             {
608*cdf0e10cSrcweir                 m_bIsActionListener = false;
609*cdf0e10cSrcweir                 m_xFrame            = null ;
610*cdf0e10cSrcweir             }
611*cdf0e10cSrcweir         }
612*cdf0e10cSrcweir         shutdown();
613*cdf0e10cSrcweir     }
614*cdf0e10cSrcweir 
615*cdf0e10cSrcweir     // ____________________
616*cdf0e10cSrcweir 
617*cdf0e10cSrcweir     /**
618*cdf0e10cSrcweir      * If this java application shutdown - we must cancel all current existing
619*cdf0e10cSrcweir      * listener connections. Otherwhise the office will run into some
620*cdf0e10cSrcweir      * DisposedExceptions if it tries to use these forgotten listener references.
621*cdf0e10cSrcweir      * And of course it can die doing that.
622*cdf0e10cSrcweir      * We are registered at a central object to be informed if the VM will exit.
623*cdf0e10cSrcweir      * So we can react.
624*cdf0e10cSrcweir      */
625*cdf0e10cSrcweir     public void shutdown()
626*cdf0e10cSrcweir     {
627*cdf0e10cSrcweir         com.sun.star.frame.XFrame xFrame            = null ;
628*cdf0e10cSrcweir         boolean                   bIsRegistered     = false;
629*cdf0e10cSrcweir         boolean                   bIsActionListener = false;
630*cdf0e10cSrcweir         synchronized(this)
631*cdf0e10cSrcweir         {
632*cdf0e10cSrcweir             // don't react a second time here!
633*cdf0e10cSrcweir             if (m_bDead)
634*cdf0e10cSrcweir                 return;
635*cdf0e10cSrcweir             m_bDead = true;
636*cdf0e10cSrcweir 
637*cdf0e10cSrcweir             bIsRegistered       = m_bIsRegistered;
638*cdf0e10cSrcweir             m_bIsRegistered     = false;
639*cdf0e10cSrcweir 
640*cdf0e10cSrcweir             bIsActionListener   = m_bIsActionListener;
641*cdf0e10cSrcweir             m_bIsActionListener = false;
642*cdf0e10cSrcweir 
643*cdf0e10cSrcweir             xFrame              = m_xFrame;
644*cdf0e10cSrcweir             m_xFrame            = null;
645*cdf0e10cSrcweir         }
646*cdf0e10cSrcweir 
647*cdf0e10cSrcweir         // it's a good idead to cancel listening for frame action events
648*cdf0e10cSrcweir         // before(!) we deregister us as an interceptor.
649*cdf0e10cSrcweir         // Because registration and deregistratio nof interceptor objects
650*cdf0e10cSrcweir         // will force sending of frame action events ...!
651*cdf0e10cSrcweir         if (bIsActionListener)
652*cdf0e10cSrcweir             xFrame.removeFrameActionListener(this);
653*cdf0e10cSrcweir 
654*cdf0e10cSrcweir         if (bIsRegistered)
655*cdf0e10cSrcweir         {
656*cdf0e10cSrcweir             com.sun.star.frame.XDispatchProviderInterception xRegistration = (com.sun.star.frame.XDispatchProviderInterception)UnoRuntime.queryInterface(
657*cdf0e10cSrcweir                 com.sun.star.frame.XDispatchProviderInterception.class,
658*cdf0e10cSrcweir                 xFrame);
659*cdf0e10cSrcweir 
660*cdf0e10cSrcweir             if(xRegistration!=null)
661*cdf0e10cSrcweir                 xRegistration.releaseDispatchProviderInterceptor(this);
662*cdf0e10cSrcweir         }
663*cdf0e10cSrcweir 
664*cdf0e10cSrcweir         xFrame = null;
665*cdf0e10cSrcweir 
666*cdf0e10cSrcweir         synchronized(this)
667*cdf0e10cSrcweir         {
668*cdf0e10cSrcweir             m_xMaster = null;
669*cdf0e10cSrcweir             m_xSlave  = null;
670*cdf0e10cSrcweir         }
671*cdf0e10cSrcweir     }
672*cdf0e10cSrcweir }
673