1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
31 //________________________________
33 #include <jobs/jobdata.hxx>
34 #include <threadhelp/readguard.hxx>
35 #include <threadhelp/writeguard.hxx>
36 #include <classes/converter.hxx>
40 //________________________________
42 #include <com/sun/star/beans/XPropertySet.hpp>
43 #include <com/sun/star/beans/XMultiHierarchicalPropertySet.hpp>
44 #include <com/sun/star/container/XNameAccess.hpp>
45 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
47 //________________________________
48 // includes of other projects
49 #include <tools/wldcrd.hxx>
50 #include <unotools/configpathes.hxx>
51 #include <rtl/ustrbuf.hxx>
52 #include <vcl/svapp.hxx>
54 //________________________________
59 //________________________________
62 const sal_Char
* JobData::JOBCFG_ROOT
= "/org.openoffice.Office.Jobs/Jobs/" ;
63 const sal_Char
* JobData::JOBCFG_PROP_SERVICE
= "Service" ;
64 const sal_Char
* JobData::JOBCFG_PROP_ARGUMENTS
= "Arguments" ;
66 const sal_Char
* JobData::EVENTCFG_ROOT
= "/org.openoffice.Office.Jobs/Events/" ;
67 const sal_Char
* JobData::EVENTCFG_PATH_JOBLIST
= "/JobList" ;
68 const sal_Char
* JobData::EVENTCFG_PROP_ADMINTIME
= "AdminTime" ;
69 const sal_Char
* JobData::EVENTCFG_PROP_USERTIME
= "UserTime" ;
71 const sal_Char
* JobData::PROPSET_CONFIG
= "Config" ;
72 const sal_Char
* JobData::PROPSET_OWNCONFIG
= "JobConfig" ;
73 const sal_Char
* JobData::PROPSET_ENVIRONMENT
= "Environment" ;
74 const sal_Char
* JobData::PROPSET_DYNAMICDATA
= "DynamicData" ;
76 const sal_Char
* JobData::PROP_ALIAS
= "Alias" ;
77 const sal_Char
* JobData::PROP_EVENTNAME
= "EventName" ;
78 const sal_Char
* JobData::PROP_ENVTYPE
= "EnvType" ;
79 const sal_Char
* JobData::PROP_FRAME
= "Frame" ;
80 const sal_Char
* JobData::PROP_MODEL
= "Model" ;
81 const sal_Char
* JobData::PROP_SERVICE
= "Service" ;
83 //________________________________
84 // non exported definitions
86 //________________________________
89 //________________________________
92 @descr It initialize this new instance.
93 But for real working it's neccessary to call setAlias() or setService() later.
94 Because we need the job data ...
97 reference to the uno service manager
99 JobData::JobData( const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xSMGR
)
100 : ThreadHelpBase(&Application::GetSolarMutex())
103 // share code for member initialization with defaults!
107 //________________________________
110 @descr Sometimes such job data container must be moved from one using place
111 to another one. Then a copy ctor and copy operator must be available.
114 the original instance, from which we must copy all data
116 JobData::JobData( const JobData
& rCopy
)
117 : ThreadHelpBase(&Application::GetSolarMutex())
119 // use the copy operator to share the same code
123 //________________________________
125 @short operator for coping JobData instances
126 @descr Sometimes such job data container must be moved from one using place
127 to another one. Then a copy ctor and copy operator must be available.
130 the original instance, from which we must copy all data
132 void JobData::operator=( const JobData
& rCopy
)
135 WriteGuard
aWriteLock(m_aLock
);
136 // Please don't copy the uno service manager reference.
137 // That can change the uno context, which isn't a good idea!
138 m_eMode
= rCopy
.m_eMode
;
139 m_eEnvironment
= rCopy
.m_eEnvironment
;
140 m_sAlias
= rCopy
.m_sAlias
;
141 m_sService
= rCopy
.m_sService
;
142 m_sEvent
= rCopy
.m_sEvent
;
143 m_lArguments
= rCopy
.m_lArguments
;
144 m_aLastExecutionResult
= rCopy
.m_aLastExecutionResult
;
149 //________________________________
151 @short let this instance die
152 @descr There is no chance any longer to work. We have to
153 release all used ressources and free used memory.
160 //________________________________
162 @short initalize this instance as a job with configuration
163 @descr They given alias can be used to adress some configuraton data.
164 We read it and fill our internal structures. Of course old informations
165 will be lost doing so.
168 the alias name of this job, used to locate job properties inside cfg
170 void JobData::setAlias( const ::rtl::OUString
& sAlias
)
173 WriteGuard
aWriteLock(m_aLock
);
174 // delete all old informations! Otherwhise we mix it with the new one ...
177 // take over the new informations
181 // try to open the configuration set of this job directly and get a property access to it
182 // We open it readonly here
183 ::rtl::OUString sKey
;
184 sKey
= ::rtl::OUString::createFromAscii(JOBCFG_ROOT
);
185 sKey
+= ::utl::wrapConfigurationElementName(m_sAlias
);
187 ConfigAccess
aConfig(m_xSMGR
, sKey
);
188 aConfig
.open(ConfigAccess::E_READONLY
);
189 if (aConfig
.getMode()==ConfigAccess::E_CLOSED
)
195 css::uno::Reference
< css::beans::XPropertySet
> xJobProperties(aConfig
.cfg(), css::uno::UNO_QUERY
);
196 if (xJobProperties
.is())
198 css::uno::Any aValue
;
200 // read uno implementation name
201 aValue
= xJobProperties
->getPropertyValue(::rtl::OUString::createFromAscii(JOBCFG_PROP_SERVICE
));
202 aValue
>>= m_sService
;
204 // read whole argument list
205 aValue
= xJobProperties
->getPropertyValue(::rtl::OUString::createFromAscii(JOBCFG_PROP_ARGUMENTS
));
206 css::uno::Reference
< css::container::XNameAccess
> xArgumentList
;
208 (aValue
>>= xArgumentList
) &&
209 (xArgumentList
.is() )
212 css::uno::Sequence
< ::rtl::OUString
> lArgumentNames
= xArgumentList
->getElementNames();
213 sal_Int32 nCount
= lArgumentNames
.getLength();
214 m_lArguments
.realloc(nCount
);
215 for (sal_Int32 i
=0; i
<nCount
; ++i
)
217 m_lArguments
[i
].Name
= lArgumentNames
[i
];
218 m_lArguments
[i
].Value
= xArgumentList
->getByName(m_lArguments
[i
].Name
);
228 //________________________________
230 @short initalize this instance as a job without configuration
231 @descr This job has no configuration data. We have to forget all old informations
232 and set only some of them new, so this instance can work.
235 the uno service name of this "non configured" job
237 void JobData::setService( const ::rtl::OUString
& sService
)
240 WriteGuard
aWriteLock(m_aLock
);
242 // delete all old informations! Otherwhise we mix it with the new one ...
244 // take over the new informations
245 m_sService
= sService
;
252 //________________________________
254 @short initialize this instance with new job values.
255 @descr It reads automaticly all properties of the specified
256 job (using it's alias name) and "register it" for the
257 given event. This registration will not be validated against
258 the underlying configuration! (That must be done from outside.
259 Because the caller must have the configuration already open to
260 get the values for sEvent and sAlias! And doing so it can perform
261 only, if the time stanp values are readed outside too.
262 Further it make no sense to initialize and start a disabled job.
263 So this initialization method will be called for enabled jobs only.)
266 the triggered event, for which this job should be started
269 mark the required job inside event registration list
271 void JobData::setEvent( const ::rtl::OUString
& sEvent
,
272 const ::rtl::OUString
& sAlias
)
274 // share code to read all job properties!
278 WriteGuard
aWriteLock(m_aLock
);
280 // take over the new informations - which differ against set on of method setAlias()!
288 //________________________________
290 @short set the new job specific arguments
291 @descr If a job finish his work, it can give us a new list of arguments (which
292 will not interpreted by us). We write it back to the configuration only
293 (if this job has it's own configuration!).
294 So a job can have persistent data without implementing anything
295 or define own config areas for that.
298 list of arguments, which should be set for this job
300 void JobData::setJobConfig( const css::uno::Sequence
< css::beans::NamedValue
>& lArguments
)
303 WriteGuard
aWriteLock(m_aLock
);
306 m_lArguments
= lArguments
;
308 // update the configuration ... if possible!
309 if (m_eMode
==E_ALIAS
)
311 // It doesn't matter if this config object was already opened before.
312 // It doesn nothing here then ... or it change the mode automaticly, if
313 // it was opened using another one before.
314 ::rtl::OUString sKey
;
315 sKey
= ::rtl::OUString::createFromAscii(JOBCFG_ROOT
);
316 sKey
+= ::utl::wrapConfigurationElementName(m_sAlias
);
318 ConfigAccess
aConfig(m_xSMGR
, sKey
);
319 aConfig
.open(ConfigAccess::E_READWRITE
);
320 if (aConfig
.getMode()==ConfigAccess::E_CLOSED
)
323 css::uno::Reference
< css::beans::XMultiHierarchicalPropertySet
> xArgumentList(aConfig
.cfg(), css::uno::UNO_QUERY
);
324 if (xArgumentList
.is())
326 sal_Int32 nCount
= m_lArguments
.getLength();
327 css::uno::Sequence
< ::rtl::OUString
> lNames (nCount
);
328 css::uno::Sequence
< css::uno::Any
> lValues(nCount
);
330 for (sal_Int32 i
=0; i
<nCount
; ++i
)
332 lNames
[i
] = m_lArguments
[i
].Name
;
333 lValues
[i
] = m_lArguments
[i
].Value
;
336 xArgumentList
->setHierarchicalPropertyValues(lNames
, lValues
);
345 //________________________________
347 @short set a new excution result
348 @descr Every executed job can have returned a result.
349 We set it here, so our user can use it may be later.
350 But the outside code can use it too, to analyze it and
351 adopt the configuration of this job too. Because the
352 result uses a protocol, which allow that. And we provide
353 right functionality to save it.
356 the result of last execution
358 void JobData::setResult( const JobResult
& aResult
)
361 WriteGuard
aWriteLock(m_aLock
);
363 // overwrite the last saved result
364 m_aLastExecutionResult
= aResult
;
366 // Don't use his informations to update
367 // e.g. the arguments of this job. It must be done
368 // from outside! Here we save this information only.
374 //________________________________
376 @short set a new environment descriptor for this job
377 @descr It must(!) be done everytime this container is initialized
378 with new job datas e.g.: setAlias()/setEvent()/setService() ...
379 Otherwhise the environment will be unknown!
381 void JobData::setEnvironment( EEnvironment eEnvironment
)
384 WriteGuard
aWriteLock(m_aLock
);
385 m_eEnvironment
= eEnvironment
;
390 //________________________________
392 @short these functions provides access to our internal members
393 @descr These member represent any information about the job
394 and can be used from outside to e.g. start a job.
396 JobData::EMode
JobData::getMode() const
399 ReadGuard
aReadLock(m_aLock
);
404 //________________________________
406 JobData::EEnvironment
JobData::getEnvironment() const
409 ReadGuard
aReadLock(m_aLock
);
410 return m_eEnvironment
;
414 //________________________________
416 ::rtl::OUString
JobData::getEnvironmentDescriptor() const
418 ::rtl::OUString sDescriptor
;
420 ReadGuard
aReadLock(m_aLock
);
421 switch(m_eEnvironment
)
424 sDescriptor
= ::rtl::OUString::createFromAscii("EXECUTOR");
428 sDescriptor
= ::rtl::OUString::createFromAscii("DISPATCH");
431 case E_DOCUMENTEVENT
:
432 sDescriptor
= ::rtl::OUString::createFromAscii("DOCUMENTEVENT");
441 //________________________________
443 ::rtl::OUString
JobData::getService() const
446 ReadGuard
aReadLock(m_aLock
);
451 //________________________________
453 ::rtl::OUString
JobData::getEvent() const
456 ReadGuard
aReadLock(m_aLock
);
461 //________________________________
463 css::uno::Sequence
< css::beans::NamedValue
> JobData::getJobConfig() const
466 ReadGuard
aReadLock(m_aLock
);
471 //________________________________
473 css::uno::Sequence
< css::beans::NamedValue
> JobData::getConfig() const
476 ReadGuard
aReadLock(m_aLock
);
477 css::uno::Sequence
< css::beans::NamedValue
> lConfig
;
478 if (m_eMode
==E_ALIAS
)
483 lConfig
[i
].Name
= ::rtl::OUString::createFromAscii(PROP_ALIAS
);
484 lConfig
[i
].Value
<<= m_sAlias
;
487 lConfig
[i
].Name
= ::rtl::OUString::createFromAscii(PROP_SERVICE
);
488 lConfig
[i
].Value
<<= m_sService
;
496 //________________________________
498 @short return information, if this job is part of the global configuration package
499 org.openoffice.Office.Jobs
500 @descr Because jobs can be executed by the dispatch framework using an uno service name
501 directly - an executed job must not have any configuration realy. Such jobs
502 must provide the right interfaces only! But after finishing jobs can return
503 some informations (e.g. for updating her configuration ...). We must know
504 if such request is valid or not then.
506 @return TRUE if the represented job is part of the underlying configuration package.
508 sal_Bool
JobData::hasConfig() const
511 ReadGuard
aReadLock(m_aLock
);
512 return (m_eMode
==E_ALIAS
|| m_eMode
==E_EVENT
);
516 //________________________________
518 @short mark a job as non startable for further requests
519 @descr We don't remove the configuration entry! We set a timestamp value only.
520 And there exist two of them: one for an administrator ... and one for the
521 current user. We change it for the user layer only. So this JobDispatch can't be
522 started any more ... till the administrator change his timestamp.
523 That can be usefull for post setup scenarios, which must run one time only.
525 Note: This method don't do anything, if ths represented job doesn't have a configuration!
527 void JobData::disableJob()
530 WriteGuard
aWriteLock(m_aLock
);
532 // No configuration - not used from EXECUTOR and not triggered from an event => no chance!
533 if (m_eMode
!=E_EVENT
)
536 // update the configuration
537 // It doesn't matter if this config object was already opened before.
538 // It doesn nothing here then ... or it change the mode automaticly, if
539 // it was opened using another one before.
540 ::rtl::OUStringBuffer
sKey(256);
541 sKey
.appendAscii(JobData::EVENTCFG_ROOT
);
542 sKey
.append (::utl::wrapConfigurationElementName(m_sEvent
));
543 sKey
.appendAscii(JobData::EVENTCFG_PATH_JOBLIST
);
544 sKey
.appendAscii("/" );
545 sKey
.append (::utl::wrapConfigurationElementName(m_sAlias
));
547 ConfigAccess
aConfig(m_xSMGR
, sKey
.makeStringAndClear());
548 aConfig
.open(ConfigAccess::E_READWRITE
);
549 if (aConfig
.getMode()==ConfigAccess::E_CLOSED
)
552 css::uno::Reference
< css::beans::XPropertySet
> xPropSet(aConfig
.cfg(), css::uno::UNO_QUERY
);
555 // Convert and write the user timestamp to the configuration.
556 css::uno::Any aValue
;
557 aValue
<<= Converter::convert_DateTime2ISO8601(DateTime());
558 xPropSet
->setPropertyValue(::rtl::OUString::createFromAscii(EVENTCFG_PROP_USERTIME
), aValue
);
567 //________________________________
570 sal_Bool
isEnabled( const ::rtl::OUString
& sAdminTime
,
571 const ::rtl::OUString
& sUserTime
)
574 To prevent interpreting of TriGraphs inside next const string value,
575 we have to encode all '?' signs. Otherwhise e.g. "??-" will be translated
578 static ::rtl::OUString PATTERN_ISO8601
= ::rtl::OUString::createFromAscii("\?\?\?\?-\?\?-\?\?*\0");
579 WildCard
aISOPattern(PATTERN_ISO8601
);
581 sal_Bool bValidAdmin
= aISOPattern
.Matches(sAdminTime
);
582 sal_Bool bValidUser
= aISOPattern
.Matches(sUserTime
);
584 // We check for "isEnabled()" here only.
585 // Note further: ISO8601 formated strings can be compared as strings directly!
587 (!bValidAdmin
&& !bValidUser
) ||
588 ( bValidAdmin
&& bValidUser
&& sAdminTime
>=sUserTime
)
592 //________________________________
595 void JobData::appendEnabledJobsForEvent( const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xSMGR
,
596 const ::rtl::OUString
& sEvent
,
597 ::comphelper::SequenceAsVector
< JobData::TJob2DocEventBinding
>& lJobs
)
599 css::uno::Sequence
< ::rtl::OUString
> lAdditionalJobs
= JobData::getEnabledJobsForEvent(xSMGR
, sEvent
);
600 sal_Int32 c
= lAdditionalJobs
.getLength();
605 JobData::TJob2DocEventBinding
aBinding(lAdditionalJobs
[i
], sEvent
);
606 lJobs
.push_back(aBinding
);
610 //________________________________
613 css::uno::Sequence
< ::rtl::OUString
> JobData::getEnabledJobsForEvent( const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xSMGR
,
614 const ::rtl::OUString
& sEvent
)
616 // these static values may perform following loop for reading time stamp values ...
617 static ::rtl::OUString ADMINTIME
= ::rtl::OUString::createFromAscii(JobData::EVENTCFG_PROP_ADMINTIME
);
618 static ::rtl::OUString USERTIME
= ::rtl::OUString::createFromAscii(JobData::EVENTCFG_PROP_USERTIME
);
619 static ::rtl::OUString ROOT
= ::rtl::OUString::createFromAscii(JobData::EVENTCFG_ROOT
);
620 static ::rtl::OUString JOBLIST
= ::rtl::OUString::createFromAscii(JobData::EVENTCFG_PATH_JOBLIST
);
622 // create a config access to "/org.openoffice.Office.Jobs/Events"
623 ConfigAccess
aConfig(xSMGR
,ROOT
);
624 aConfig
.open(ConfigAccess::E_READONLY
);
625 if (aConfig
.getMode()==ConfigAccess::E_CLOSED
)
626 return css::uno::Sequence
< ::rtl::OUString
>();
628 css::uno::Reference
< css::container::XHierarchicalNameAccess
> xEventRegistry(aConfig
.cfg(), css::uno::UNO_QUERY
);
629 if (!xEventRegistry
.is())
630 return css::uno::Sequence
< ::rtl::OUString
>();
632 // check if the given event exist inside list of registered ones
633 ::rtl::OUString
sPath(sEvent
);
635 if (!xEventRegistry
->hasByHierarchicalName(sPath
))
636 return css::uno::Sequence
< ::rtl::OUString
>();
638 // step to the job list, which is a child of the event node inside cfg
639 // e.g. "/org.openoffice.Office.Jobs/Events/<event name>/JobList"
640 css::uno::Any aJobList
= xEventRegistry
->getByHierarchicalName(sPath
);
641 css::uno::Reference
< css::container::XNameAccess
> xJobList
;
642 if (!(aJobList
>>= xJobList
) || !xJobList
.is())
643 return css::uno::Sequence
< ::rtl::OUString
>();
645 // get all alias names of jobs, which are part of this job list
646 // But Some of them can be disabled by it's time stamp values.
647 // We create an additional job name list iwth the same size, then the original list ...
648 // step over all job entries ... check her time stamps ... and put only job names to the
649 // destination list, which represent an enabled job.
650 css::uno::Sequence
< ::rtl::OUString
> lAllJobs
= xJobList
->getElementNames();
651 ::rtl::OUString
* pAllJobs
= lAllJobs
.getArray();
652 sal_Int32 c
= lAllJobs
.getLength();
654 css::uno::Sequence
< ::rtl::OUString
> lEnabledJobs(c
);
655 ::rtl::OUString
* pEnabledJobs
= lEnabledJobs
.getArray();
658 for (sal_Int32 s
=0; s
<c
; ++s
)
660 css::uno::Reference
< css::beans::XPropertySet
> xJob
;
662 !(xJobList
->getByName(pAllJobs
[s
]) >>= xJob
) ||
669 ::rtl::OUString sAdminTime
;
670 xJob
->getPropertyValue(ADMINTIME
) >>= sAdminTime
;
672 ::rtl::OUString sUserTime
;
673 xJob
->getPropertyValue(USERTIME
) >>= sUserTime
;
675 if (!isEnabled(sAdminTime
, sUserTime
))
678 pEnabledJobs
[d
] = pAllJobs
[s
];
681 lEnabledJobs
.realloc(d
);
688 //________________________________
690 @short reset all internal structures
691 @descr If somehwere recycle this instance, he can switch from one
692 using mode to another one. But then we have to reset all currently
693 used informations. Otherwhise we mix it and they can make trouble.
695 But note: that does not set defaults for internal used members, which
696 does not relate to any job property! e.g. the reference to the global
697 uno service manager. Such informations are used for internal processes only
698 and are neccessary for our work.
700 void JobData::impl_reset()
703 WriteGuard
aWriteLock(m_aLock
);
704 m_eMode
= E_UNKNOWN_MODE
;
705 m_eEnvironment
= E_UNKNOWN_ENVIRONMENT
;
706 m_sAlias
= ::rtl::OUString();
707 m_sService
= ::rtl::OUString();
708 m_sEvent
= ::rtl::OUString();
709 m_lArguments
= css::uno::Sequence
< css::beans::NamedValue
>();
714 } // namespace framework