1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <jobs/jobdata.hxx>
21 #include <classes/converter.hxx>
25 #include <com/sun/star/beans/XPropertySet.hpp>
26 #include <com/sun/star/beans/XMultiHierarchicalPropertySet.hpp>
27 #include <com/sun/star/container/XNameAccess.hpp>
28 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
30 #include <tools/wldcrd.hxx>
31 #include <unotools/configpaths.hxx>
32 #include <vcl/svapp.hxx>
38 @descr It initialize this new instance.
39 But for real working it's necessary to call setAlias() or setService() later.
40 Because we need the job data ...
43 reference to the uno service manager
45 JobData::JobData( const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
)
46 : m_xContext (rxContext
)
48 // share code for member initialization with defaults!
54 @descr Sometimes such job data container must be moved from one using place
55 to another one. Then a copy ctor and copy operator must be available.
58 the original instance, from which we must copy all data
60 JobData::JobData( const JobData
& rCopy
)
62 // use the copy operator to share the same code
67 @short operator for coping JobData instances
68 @descr Sometimes such job data container must be moved from one using place
69 to another one. Then a copy ctor and copy operator must be available.
72 the original instance, from which we must copy all data
74 void JobData::operator=( const JobData
& rCopy
)
77 // Please don't copy the uno service manager reference.
78 // That can change the uno context, which isn't a good idea!
79 m_eMode
= rCopy
.m_eMode
;
80 m_eEnvironment
= rCopy
.m_eEnvironment
;
81 m_sAlias
= rCopy
.m_sAlias
;
82 m_sService
= rCopy
.m_sService
;
83 m_sContext
= rCopy
.m_sContext
;
84 m_sEvent
= rCopy
.m_sEvent
;
85 m_lArguments
= rCopy
.m_lArguments
;
86 m_aLastExecutionResult
= rCopy
.m_aLastExecutionResult
;
90 @short let this instance die
91 @descr There is no chance any longer to work. We have to
92 release all used resources and free used memory.
100 @short initalize this instance as a job with configuration
101 @descr They given alias can be used to address some configuration data.
102 We read it and fill our internal structures. Of course old information
103 will be lost doing so.
106 the alias name of this job, used to locate job properties inside cfg
108 void JobData::setAlias( const OUString
& sAlias
)
111 // delete all old information! Otherwhise we mix it with the new one ...
114 // take over the new information
118 // try to open the configuration set of this job directly and get a property access to it
119 // We open it readonly here
120 ConfigAccess
aConfig(
122 ("/org.openoffice.Office.Jobs/Jobs/"
123 + utl::wrapConfigurationElementName(m_sAlias
)));
124 aConfig
.open(ConfigAccess::E_READONLY
);
125 if (aConfig
.getMode()==ConfigAccess::E_CLOSED
)
131 css::uno::Reference
< css::beans::XPropertySet
> xJobProperties(aConfig
.cfg(), css::uno::UNO_QUERY
);
132 if (xJobProperties
.is())
134 css::uno::Any aValue
;
136 // read uno implementation name
137 aValue
= xJobProperties
->getPropertyValue("Service");
138 aValue
>>= m_sService
;
140 // read module context list
141 aValue
= xJobProperties
->getPropertyValue("Context");
142 aValue
>>= m_sContext
;
144 // read whole argument list
145 aValue
= xJobProperties
->getPropertyValue("Arguments");
146 css::uno::Reference
< css::container::XNameAccess
> xArgumentList
;
148 (aValue
>>= xArgumentList
) &&
149 (xArgumentList
.is() )
152 css::uno::Sequence
< OUString
> lArgumentNames
= xArgumentList
->getElementNames();
153 sal_Int32 nCount
= lArgumentNames
.getLength();
154 m_lArguments
.realloc(nCount
);
155 for (sal_Int32 i
=0; i
<nCount
; ++i
)
157 m_lArguments
[i
].Name
= lArgumentNames
[i
];
158 m_lArguments
[i
].Value
= xArgumentList
->getByName(m_lArguments
[i
].Name
);
167 @short initalize this instance as a job without configuration
168 @descr This job has no configuration data. We have to forget all old information
169 and set only some of them new, so this instance can work.
172 the uno service name of this "non configured" job
174 void JobData::setService( const OUString
& sService
)
177 // delete all old information! Otherwhise we mix it with the new one ...
179 // take over the new information
180 m_sService
= sService
;
185 @short initialize this instance with new job values.
186 @descr It reads automatically all properties of the specified
187 job (using it's alias name) and "register it" for the
188 given event. This registration will not be validated against
189 the underlying configuration! (That must be done from outside.
190 Because the caller must have the configuration already open to
191 get the values for sEvent and sAlias! And doing so it can perform
192 only, if the time stanp values are readed outside too.
193 Further it make no sense to initialize and start a disabled job.
194 So this initialization method will be called for enabled jobs only.)
197 the triggered event, for which this job should be started
200 mark the required job inside event registration list
202 void JobData::setEvent( const OUString
& sEvent
,
203 const OUString
& sAlias
)
205 // share code to read all job properties!
209 // take over the new information - which differ against set on of method setAlias()!
215 @short set the new job specific arguments
216 @descr If a job finish his work, it can give us a new list of arguments (which
217 will not interpreted by us). We write it back to the configuration only
218 (if this job has it's own configuration!).
219 So a job can have persistent data without implementing anything
220 or define own config areas for that.
223 list of arguments, which should be set for this job
225 void JobData::setJobConfig( const css::uno::Sequence
< css::beans::NamedValue
>& lArguments
)
230 m_lArguments
= lArguments
;
232 // update the configuration ... if possible!
233 if (m_eMode
==E_ALIAS
)
235 // It doesn't matter if this config object was already opened before.
236 // It doesn nothing here then ... or it change the mode automatically, if
237 // it was opened using another one before.
238 ConfigAccess
aConfig(
240 ("/org.openoffice.Office.Jobs/Jobs/"
241 + utl::wrapConfigurationElementName(m_sAlias
)));
242 aConfig
.open(ConfigAccess::E_READWRITE
);
243 if (aConfig
.getMode()==ConfigAccess::E_CLOSED
)
246 css::uno::Reference
< css::beans::XMultiHierarchicalPropertySet
> xArgumentList(aConfig
.cfg(), css::uno::UNO_QUERY
);
247 if (xArgumentList
.is())
249 sal_Int32 nCount
= m_lArguments
.getLength();
250 css::uno::Sequence
< OUString
> lNames (nCount
);
251 css::uno::Sequence
< css::uno::Any
> lValues(nCount
);
253 for (sal_Int32 i
=0; i
<nCount
; ++i
)
255 lNames
[i
] = m_lArguments
[i
].Name
;
256 lValues
[i
] = m_lArguments
[i
].Value
;
259 xArgumentList
->setHierarchicalPropertyValues(lNames
, lValues
);
266 @short set a new excution result
267 @descr Every executed job can have returned a result.
268 We set it here, so our user can use it may be later.
269 But the outside code can use it too, to analyze it and
270 adopt the configuration of this job too. Because the
271 result uses a protocol, which allow that. And we provide
272 right functionality to save it.
275 the result of last execution
277 void JobData::setResult( const JobResult
& aResult
)
281 // overwrite the last saved result
282 m_aLastExecutionResult
= aResult
;
284 // Don't use his information to update
285 // e.g. the arguments of this job. It must be done
286 // from outside! Here we save this information only.
290 @short set a new environment descriptor for this job
291 @descr It must(!) be done every time this container is initialized
292 with new job datas e.g.: setAlias()/setEvent()/setService() ...
293 Otherwhise the environment will be unknown!
295 void JobData::setEnvironment( EEnvironment eEnvironment
)
298 m_eEnvironment
= eEnvironment
;
302 @short these functions provides access to our internal members
303 @descr These member represent any information about the job
304 and can be used from outside to e.g. start a job.
306 JobData::EMode
JobData::getMode() const
312 JobData::EEnvironment
JobData::getEnvironment() const
315 return m_eEnvironment
;
318 OUString
JobData::getEnvironmentDescriptor() const
320 OUString sDescriptor
;
322 switch(m_eEnvironment
)
325 sDescriptor
= "EXECUTOR";
329 sDescriptor
= "DISPATCH";
332 case E_DOCUMENTEVENT
:
333 sDescriptor
= "DOCUMENTEVENT";
341 OUString
JobData::getService() const
347 OUString
JobData::getEvent() const
353 css::uno::Sequence
< css::beans::NamedValue
> JobData::getJobConfig() const
359 css::uno::Sequence
< css::beans::NamedValue
> JobData::getConfig() const
362 css::uno::Sequence
< css::beans::NamedValue
> lConfig
;
363 if (m_eMode
==E_ALIAS
)
368 lConfig
[i
].Name
= "Alias";
369 lConfig
[i
].Value
<<= m_sAlias
;
372 lConfig
[i
].Name
= "Service";
373 lConfig
[i
].Value
<<= m_sService
;
376 lConfig
[i
].Name
= "Context";
377 lConfig
[i
].Value
<<= m_sContext
;
384 @short return information, if this job is part of the global configuration package
385 org.openoffice.Office.Jobs
386 @descr Because jobs can be executed by the dispatch framework using an uno service name
387 directly - an executed job must not have any configuration really. Such jobs
388 must provide the right interfaces only! But after finishing jobs can return
389 some information (e.g. for updating her configuration ...). We must know
390 if such request is valid or not then.
392 @return sal_True if the represented job is part of the underlying configuration package.
394 bool JobData::hasConfig() const
397 return (m_eMode
==E_ALIAS
|| m_eMode
==E_EVENT
);
401 @short mark a job as non startable for further requests
402 @descr We don't remove the configuration entry! We set a timestamp value only.
403 And there exist two of them: one for an administrator ... and one for the
404 current user. We change it for the user layer only. So this JobDispatch can't be
405 started any more ... till the administrator change his timestamp.
406 That can be useful for post setup scenarios, which must run one time only.
408 Note: This method don't do anything, if this represented job doesn't have a configuration!
410 void JobData::disableJob()
414 // No configuration - not used from EXECUTOR and not triggered from an event => no chance!
415 if (m_eMode
!=E_EVENT
)
418 // update the configuration
419 // It doesn't matter if this config object was already opened before.
420 // It doesn nothing here then ... or it change the mode automatically, if
421 // it was opened using another one before.
422 ConfigAccess
aConfig(
424 ("/org.openoffice.Office.Jobs/Events/"
425 + utl::wrapConfigurationElementName(m_sEvent
) + "/JobList/"
426 + utl::wrapConfigurationElementName(m_sAlias
)));
427 aConfig
.open(ConfigAccess::E_READWRITE
);
428 if (aConfig
.getMode()==ConfigAccess::E_CLOSED
)
431 css::uno::Reference
< css::beans::XPropertySet
> xPropSet(aConfig
.cfg(), css::uno::UNO_QUERY
);
434 // Convert and write the user timestamp to the configuration.
435 css::uno::Any aValue
;
436 aValue
<<= Converter::convert_DateTime2ISO8601(DateTime( DateTime::SYSTEM
));
437 xPropSet
->setPropertyValue("UserTime", aValue
);
445 bool isEnabled( const OUString
& sAdminTime
,
446 const OUString
& sUserTime
)
449 To prevent interpreting of TriGraphs inside next const string value,
450 we have to encode all '?' signs. Otherwhise e.g. "??-" will be translated
453 static const char PATTERN_ISO8601
[] = "\?\?\?\?-\?\?-\?\?*";
454 WildCard
aISOPattern(PATTERN_ISO8601
);
456 bool bValidAdmin
= aISOPattern
.Matches(sAdminTime
);
457 bool bValidUser
= aISOPattern
.Matches(sUserTime
);
459 // We check for "isEnabled()" here only.
460 // Note further: ISO8601 formatted strings can be compared as strings directly!
461 // FIXME: this is not true! "T1215" is the same time as "T12:15" or "T121500"
463 (!bValidAdmin
&& !bValidUser
) ||
464 ( bValidAdmin
&& bValidUser
&& sAdminTime
>=sUserTime
)
470 void JobData::appendEnabledJobsForEvent( const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
,
471 const OUString
& sEvent
,
472 ::std::vector
< JobData::TJob2DocEventBinding
>& lJobs
)
474 css::uno::Sequence
< OUString
> lAdditionalJobs
= JobData::getEnabledJobsForEvent(rxContext
, sEvent
);
475 sal_Int32 c
= lAdditionalJobs
.getLength();
480 JobData::TJob2DocEventBinding
aBinding(lAdditionalJobs
[i
], sEvent
);
481 lJobs
.push_back(aBinding
);
487 bool JobData::hasCorrectContext(const OUString
& rModuleIdent
) const
489 sal_Int32 nContextLen
= m_sContext
.getLength();
490 sal_Int32 nModuleIdLen
= rModuleIdent
.getLength();
492 if ( nContextLen
== 0 )
495 if ( nModuleIdLen
> 0 )
497 sal_Int32 nIndex
= m_sContext
.indexOf( rModuleIdent
);
498 if ( nIndex
>= 0 && ( nIndex
+nModuleIdLen
<= nContextLen
))
500 OUString sContextModule
= m_sContext
.copy( nIndex
, nModuleIdLen
);
501 return sContextModule
.equals( rModuleIdent
);
510 css::uno::Sequence
< OUString
> JobData::getEnabledJobsForEvent( const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
,
511 const OUString
& sEvent
)
513 // create a config access to "/org.openoffice.Office.Jobs/Events"
514 ConfigAccess
aConfig(rxContext
, "/org.openoffice.Office.Jobs/Events");
515 aConfig
.open(ConfigAccess::E_READONLY
);
516 if (aConfig
.getMode()==ConfigAccess::E_CLOSED
)
517 return css::uno::Sequence
< OUString
>();
519 css::uno::Reference
< css::container::XHierarchicalNameAccess
> xEventRegistry(aConfig
.cfg(), css::uno::UNO_QUERY
);
520 if (!xEventRegistry
.is())
521 return css::uno::Sequence
< OUString
>();
523 // check if the given event exist inside list of registered ones
524 OUString
sPath(sEvent
+ "/JobList");
525 if (!xEventRegistry
->hasByHierarchicalName(sPath
))
526 return css::uno::Sequence
< OUString
>();
528 // step to the job list, which is a child of the event node inside cfg
529 // e.g. "/org.openoffice.Office.Jobs/Events/<event name>/JobList"
530 css::uno::Any aJobList
= xEventRegistry
->getByHierarchicalName(sPath
);
531 css::uno::Reference
< css::container::XNameAccess
> xJobList
;
532 if (!(aJobList
>>= xJobList
) || !xJobList
.is())
533 return css::uno::Sequence
< OUString
>();
535 // get all alias names of jobs, which are part of this job list
536 // But Some of them can be disabled by it's time stamp values.
537 // We create an additional job name list with the same size, then the original list ...
538 // step over all job entries ... check her time stamps ... and put only job names to the
539 // destination list, which represent an enabled job.
540 css::uno::Sequence
< OUString
> lAllJobs
= xJobList
->getElementNames();
541 OUString
* pAllJobs
= lAllJobs
.getArray();
542 sal_Int32 c
= lAllJobs
.getLength();
544 css::uno::Sequence
< OUString
> lEnabledJobs(c
);
545 OUString
* pEnabledJobs
= lEnabledJobs
.getArray();
548 for (sal_Int32 s
=0; s
<c
; ++s
)
550 css::uno::Reference
< css::beans::XPropertySet
> xJob
;
552 !(xJobList
->getByName(pAllJobs
[s
]) >>= xJob
) ||
560 xJob
->getPropertyValue("AdminTime") >>= sAdminTime
;
563 xJob
->getPropertyValue("UserTime") >>= sUserTime
;
565 if (!isEnabled(sAdminTime
, sUserTime
))
568 pEnabledJobs
[d
] = pAllJobs
[s
];
571 lEnabledJobs
.realloc(d
);
579 @short reset all internal structures
580 @descr If someone recycles this instance, he can switch from one
581 using mode to another one. But then we have to reset all currently
582 used information. Otherwhise we mix it and they can make trouble.
584 But note: that does not set defaults for internal used members, which
585 does not relate to any job property! e.g. the reference to the global
586 uno service manager. Such information is used for internal processes only
587 and are necessary for our work.
589 void JobData::impl_reset()
592 m_eMode
= E_UNKNOWN_MODE
;
593 m_eEnvironment
= E_UNKNOWN_ENVIRONMENT
;
598 m_lArguments
= css::uno::Sequence
< css::beans::NamedValue
>();
601 } // namespace framework
603 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */