1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * The Contents of this file are made available subject to the terms of
7 * Copyright 2000, 2010 Oracle and/or its affiliates.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of Sun Microsystems, Inc. nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
29 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
31 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
32 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *************************************************************************/
36 import com
.sun
.star
.uno
.XComponentContext
;
37 import com
.sun
.star
.lib
.uno
.helper
.Factory
;
38 import com
.sun
.star
.lib
.uno
.helper
.WeakBase
;
39 import com
.sun
.star
.lang
.XServiceInfo
;
40 import com
.sun
.star
.task
.*;
41 import com
.sun
.star
.uno
.*;
43 /** it implements a simple job component.
45 * Such jobs are executable in different ways:
47 * <li>registered for a special URL schema "vnd.sun.star.jobs:*" and used from the generic dispatch framework</li>
48 * <li>the global com.sun.star.task.JobExecutor service and registered for special events.</li>
51 public class AsyncJob
extends WeakBase
implements XServiceInfo
, XAsyncJob
53 public final XComponentContext m_xCmpCtx
;
55 /** the const list of supported uno service names. */
56 public static final String
[] SERVICENAMES
= {"com.sun.star.task.AsyncJob"};
58 /** the const uno implementation name.
59 * It must be a unique value! The best naming schema seems to use
60 * a registered domain in reverse order ...
62 public static final String IMPLEMENTATIONNAME
= "com.sun.star.comp.framework.java.services.AsyncJob";
67 /** initialize a new instance of this class with default values. */
68 public AsyncJob( XComponentContext xCompContext
)
70 m_xCmpCtx
= xCompContext
;
75 /** starts execution of this job.
78 * list which contains:
80 * <li>generic job configuration data</li>
81 * <li>job specific configuration data</li>
82 * <li>some environment information</li>
83 * <li>may optional arguments of a corresponding dispatch request</li>
87 * callback to the executor of this job, which control our life time
89 * @throws com.sun.star.lang.IllegalArgumentException
90 * if given argument list seems to be wrong
92 public synchronized void executeAsync(com
.sun
.star
.beans
.NamedValue
[] lArgs
,
93 com
.sun
.star
.task
.XJobListener xListener
)
94 throws com
.sun
.star
.lang
.IllegalArgumentException
96 // For asynchronous jobs a valid listener reference is guaranteed normally ...
97 if (xListener
== null)
98 throw new com
.sun
.star
.lang
.IllegalArgumentException("invalid listener");
100 // extract all possible sub list of given argument list
101 com
.sun
.star
.beans
.NamedValue
[] lGenericConfig
= null;
102 com
.sun
.star
.beans
.NamedValue
[] lJobConfig
= null;
103 com
.sun
.star
.beans
.NamedValue
[] lEnvironment
= null;
104 com
.sun
.star
.beans
.NamedValue
[] lDynamicData
= null;
106 int c
= lArgs
.length
;
107 for (int i
=0; i
<c
; ++i
)
109 if (lArgs
[i
].Name
.equals("Config"))
110 lGenericConfig
= (com
.sun
.star
.beans
.NamedValue
[])com
.sun
.star
.uno
.AnyConverter
.toArray(lArgs
[i
].Value
);
112 if (lArgs
[i
].Name
.equals("JobConfig"))
113 lJobConfig
= (com
.sun
.star
.beans
.NamedValue
[])com
.sun
.star
.uno
.AnyConverter
.toArray(lArgs
[i
].Value
);
115 if (lArgs
[i
].Name
.equals("Environment"))
116 lEnvironment
= (com
.sun
.star
.beans
.NamedValue
[])com
.sun
.star
.uno
.AnyConverter
.toArray(lArgs
[i
].Value
);
118 if (lArgs
[i
].Name
.equals("DynamicData"))
119 lDynamicData
= (com
.sun
.star
.beans
.NamedValue
[])com
.sun
.star
.uno
.AnyConverter
.toArray(lArgs
[i
].Value
);
122 // Analyze the environment info. This sub list is the only guaranteed one!
123 if (lEnvironment
== null)
124 throw new com
.sun
.star
.lang
.IllegalArgumentException("no environment");
126 String sEnvType
= null;
127 String sEventName
= null;
128 com
.sun
.star
.frame
.XFrame xFrame
= null;
129 c
= lEnvironment
.length
;
130 for (int i
=0; i
<c
; ++i
)
132 if (lEnvironment
[i
].Name
.equals("EnvType"))
133 sEnvType
= com
.sun
.star
.uno
.AnyConverter
.toString(lEnvironment
[i
].Value
);
135 if (lEnvironment
[i
].Name
.equals("EventName"))
136 sEventName
= com
.sun
.star
.uno
.AnyConverter
.toString(lEnvironment
[i
].Value
);
138 if (lEnvironment
[i
].Name
.equals("Frame"))
139 xFrame
= (com
.sun
.star
.frame
.XFrame
)com
.sun
.star
.uno
.AnyConverter
.toObject(
140 new com
.sun
.star
.uno
.Type(com
.sun
.star
.frame
.XFrame
.class),
141 lEnvironment
[i
].Value
);
144 // Further the environment property "EnvType" is required as minimum.
148 (!sEnvType
.equals("EXECUTOR")) &&
149 (!sEnvType
.equals("DISPATCH"))
153 String sMessage
= "\"" + sEnvType
+ "\" isn't a valid value for EnvType";
154 throw new com
.sun
.star
.lang
.IllegalArgumentException(sMessage
);
157 // Analyze the set of shared config data.
158 if (lGenericConfig
!=null)
160 c
= lGenericConfig
.length
;
161 for (int i
=0; i
<c
; ++i
)
163 if (lGenericConfig
[i
].Name
.equals("Alias"))
164 com
.sun
.star
.uno
.AnyConverter
.toString(lGenericConfig
[i
].Value
);
169 // Here we print out all found arguments.
170 String sOut
= formatOutArgs(lGenericConfig
, lJobConfig
, lEnvironment
, lDynamicData
);
172 showInfoModal(xFrame
.getContainerWindow(), "Arguments of AsyncJob initialization ...", sOut
);
174 showInfoNonModal("Arguments of AsyncJob initialization ...", sOut
);
176 // use return value to start different actions
177 // But look for the right environment. Some options make no sense inside the wrong env.
178 com
.sun
.star
.beans
.NamedValue aDeactivation
= null;
179 com
.sun
.star
.beans
.NamedValue aDispatchResult
= null;
180 com
.sun
.star
.beans
.NamedValue aSaveRequest
= null;
182 // SaveArguments will be made everytimes!
185 if (lJobConfig
==null)
186 lJobConfig
= new com
.sun
.star
.beans
.NamedValue
[1];
187 lJobConfig
[0] = new com
.sun
.star
.beans
.NamedValue();
188 lJobConfig
[0].Name
= "arg_1";
189 lJobConfig
[0].Value
= "val_1";
191 aSaveRequest
= new com
.sun
.star
.beans
.NamedValue();
192 aSaveRequest
.Name
= "SaveArguments";
193 aSaveRequest
.Value
= lJobConfig
;
195 // Deactivation is useful inside EXECUTOR environment only
196 if (sEnvType
.equals("EXECUTOR"))
199 aDeactivation
= new com
.sun
.star
.beans
.NamedValue();
200 aDeactivation
.Name
= "Deactivate";
201 aDeactivation
.Value
= Boolean
.TRUE
;
204 // Sending of result events is useful inside DISPATCH environment only
205 if (sEnvType
.equals("DISPATCH"))
208 aDispatchResult
= new com
.sun
.star
.beans
.NamedValue();
209 aDispatchResult
.Name
= "SendDispatchResult";
210 aDispatchResult
.Value
= new com
.sun
.star
.frame
.DispatchResultEvent(this, com
.sun
.star
.frame
.DispatchResultState
.SUCCESS
, null);
213 // pack it together for return
215 com
.sun
.star
.beans
.NamedValue
[] lReturn
= new com
.sun
.star
.beans
.NamedValue
[c
];
216 lReturn
[i
++] = aSaveRequest
;
217 if (aDeactivation
!=null)
218 lReturn
[i
++] = aDeactivation
;
219 if (aDispatchResult
!=null)
220 lReturn
[i
++] = aDispatchResult
;
222 xListener
.jobFinished(this, lReturn
);
227 /** show an info box with the UNO based toolkit.
229 * It tries to use the container window of a may well know
230 * office frame as parent. If such parent window could be located,
231 * the info box can be shown in modal mode. If a parent is missing
232 * (because this job is called inside an EXECUTOR environment, which
233 * does not set any frame context here) the info box can't be created!
234 * Because the toolkit needs parents for non top level windows...
235 * In that case the only way is to implement this info box
236 * native or make it non modal using java dialogs inside its own thread...
237 * (see showInfoNonModal() too)
240 * used as parent window of the shown info box.
243 * is shown as title of the info box.
246 * included the message body, which is shown as info.
249 private void showInfoModal( com
.sun
.star
.awt
.XWindow xParent
,
255 // get access to the office toolkit environment
256 com
.sun
.star
.awt
.XToolkit xKit
= UnoRuntime
.queryInterface(
257 com
.sun
.star
.awt
.XToolkit
.class,
258 m_xCmpCtx
.getServiceManager().createInstanceWithContext("com.sun.star.awt.Toolkit",
261 // describe the info box ini its parameters
262 com
.sun
.star
.awt
.WindowDescriptor aDescriptor
= new com
.sun
.star
.awt
.WindowDescriptor();
263 aDescriptor
.WindowServiceName
= "infobox";
264 aDescriptor
.Bounds
= new com
.sun
.star
.awt
.Rectangle(0,0,300,200);
265 aDescriptor
.WindowAttributes
= com
.sun
.star
.awt
.WindowAttribute
.BORDER
|
266 com
.sun
.star
.awt
.WindowAttribute
.MOVEABLE
|
267 com
.sun
.star
.awt
.WindowAttribute
.CLOSEABLE
;
268 aDescriptor
.Type
= com
.sun
.star
.awt
.WindowClass
.MODALTOP
;
269 aDescriptor
.ParentIndex
= 1;
270 aDescriptor
.Parent
= UnoRuntime
.queryInterface(
271 com
.sun
.star
.awt
.XWindowPeer
.class,
274 // create the info box window
275 com
.sun
.star
.awt
.XWindowPeer xPeer
= xKit
.createWindow(aDescriptor
);
276 com
.sun
.star
.awt
.XMessageBox xInfoBox
= UnoRuntime
.queryInterface(
277 com
.sun
.star
.awt
.XMessageBox
.class,
279 if (xInfoBox
== null)
282 // fill it with all given information and show it
283 xInfoBox
.setCaptionText(sTitle
);
284 xInfoBox
.setMessageText(sMessage
);
287 catch(Throwable exIgnore
)
289 // ignore any problem, which can occur here.
290 // It's not really a bug for this example job, if
291 // it's message could not be printed out!
297 private void showInfoNonModal( String sTitle
,
300 // Couldn't be implemented really using the toolkit...
301 // Because we need a parent anytime.
302 // And showing e.g. a Java dialog can make some trouble
303 // inside office... but we have no chance here.
304 final String sFinalTitle
= sTitle
;
305 final String sFinalMessage
= sMessage
;
307 // On macOS, AWT/Swing must not be accessed from the AppKit thread, so call
308 // SwingUtilities.invokeLater always on a fresh thread to avoid that problem
309 // (also, the current thread must not wait for that fresh thread to terminate,
310 // as that would cause a deadlock if this thread is the AppKit thread):
311 final Runnable doRun
= new Runnable() {
313 javax
.swing
.JOptionPane
.showMessageDialog(null, sFinalMessage
, sFinalTitle
, javax
.swing
.JOptionPane
.INFORMATION_MESSAGE
);
317 new Thread( doRun
) {
319 public void run() { javax
.swing
.SwingUtilities
.invokeLater(doRun
); }
325 /** helper to print out the given argument list.
327 * @param lGenericConfig
328 * contains all shared configuration items for a job
331 * contains all job specific configuration items
333 * @param lEnvironment
334 * contains some environment information
336 * @param lDynamicData
337 * contains optional data of a might corresponding dispatch() request
340 private String
formatOutArgs(com
.sun
.star
.beans
.NamedValue
[] lGenericConfig
,
341 com
.sun
.star
.beans
.NamedValue
[] lJobConfig
,
342 com
.sun
.star
.beans
.NamedValue
[] lEnvironment
,
343 com
.sun
.star
.beans
.NamedValue
[] lDynamicData
)
345 StringBuffer sOut
= new StringBuffer(1024);
347 sOut
.append("list \"Config\": ");
348 if (lGenericConfig
==null)
349 sOut
.append("0 items\n");
352 int c
= lGenericConfig
.length
;
353 sOut
.append(c
+" items\n");
354 for (int i
=0; i
<c
; ++i
)
355 sOut
.append("\t["+i
+"] \""+lGenericConfig
[i
].Name
+"\" = {"+lGenericConfig
[i
].Value
+"}\n");
357 sOut
.append("list \"JobConfig\": ");
358 if (lJobConfig
==null)
359 sOut
.append("0 items\n");
362 int c
= lJobConfig
.length
;
363 sOut
.append(c
+" items\n");
364 for (int i
=0; i
<c
; ++i
)
365 sOut
.append("\t["+i
+"] \""+lJobConfig
[i
].Name
+"\" = {"+lJobConfig
[i
].Value
+"}\n");
367 sOut
.append("list \"Environment\": ");
368 if (lEnvironment
==null)
369 sOut
.append("0 items\n");
372 int c
= lEnvironment
.length
;
373 sOut
.append(c
+" items\n");
374 for (int i
=0; i
<c
; ++i
)
375 sOut
.append("\t["+i
+"] \""+lEnvironment
[i
].Name
+"\" = {"+lEnvironment
[i
].Value
+"}\n");
377 sOut
.append("list \"DynamicData\": ");
378 if (lDynamicData
==null)
379 sOut
.append("0 items\n");
382 int c
= lDynamicData
.length
;
383 sOut
.append(c
+" items\n");
384 for (int i
=0; i
<c
; ++i
)
385 sOut
.append("\t["+i
+"] \""+lDynamicData
[i
].Name
+"\" = {"+lDynamicData
[i
].Value
+"}\n");
388 return sOut
.toString();
391 public String
[] getSupportedServiceNames() {
395 public boolean supportsService( String sService
) {
396 int len
= SERVICENAMES
.length
;
398 for( int i
=0; i
< len
; i
++) {
399 if ( sService
.equals( SERVICENAMES
[i
] ) )
406 public String
getImplementationName() {
407 return( AsyncJob
.class.getName() );
413 public synchronized static com
.sun
.star
.lang
.XSingleComponentFactory
__getComponentFactory(String sImplName
)
415 com
.sun
.star
.lang
.XSingleComponentFactory xFactory
= null;
416 if (sImplName
.equals(AsyncJob
.IMPLEMENTATIONNAME
))
417 xFactory
= Factory
.createComponentFactory(AsyncJob
.class, SERVICENAMES
);
425 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */