1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: jobdata.cxx,v $
10 * $Revision: 1.10.82.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_framework.hxx"
34 //________________________________
36 #include <jobs/jobdata.hxx>
37 #include <threadhelp/readguard.hxx>
38 #include <threadhelp/writeguard.hxx>
39 #include <classes/converter.hxx>
43 //________________________________
45 #include <com/sun/star/beans/XPropertySet.hpp>
46 #include <com/sun/star/beans/XMultiHierarchicalPropertySet.hpp>
47 #include <com/sun/star/container/XNameAccess.hpp>
48 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
50 //________________________________
51 // includes of other projects
52 #include <tools/wldcrd.hxx>
53 #include <unotools/configpathes.hxx>
54 #include <rtl/ustrbuf.hxx>
55 #include <vcl/svapp.hxx>
57 //________________________________
62 //________________________________
65 const sal_Char
* JobData::JOBCFG_ROOT
= "/org.openoffice.Office.Jobs/Jobs/" ;
66 const sal_Char
* JobData::JOBCFG_PROP_SERVICE
= "Service" ;
67 const sal_Char
* JobData::JOBCFG_PROP_ARGUMENTS
= "Arguments" ;
69 const sal_Char
* JobData::EVENTCFG_ROOT
= "/org.openoffice.Office.Jobs/Events/" ;
70 const sal_Char
* JobData::EVENTCFG_PATH_JOBLIST
= "/JobList" ;
71 const sal_Char
* JobData::EVENTCFG_PROP_ADMINTIME
= "AdminTime" ;
72 const sal_Char
* JobData::EVENTCFG_PROP_USERTIME
= "UserTime" ;
74 const sal_Char
* JobData::PROPSET_CONFIG
= "Config" ;
75 const sal_Char
* JobData::PROPSET_OWNCONFIG
= "JobConfig" ;
76 const sal_Char
* JobData::PROPSET_ENVIRONMENT
= "Environment" ;
77 const sal_Char
* JobData::PROPSET_DYNAMICDATA
= "DynamicData" ;
79 const sal_Char
* JobData::PROP_ALIAS
= "Alias" ;
80 const sal_Char
* JobData::PROP_EVENTNAME
= "EventName" ;
81 const sal_Char
* JobData::PROP_ENVTYPE
= "EnvType" ;
82 const sal_Char
* JobData::PROP_FRAME
= "Frame" ;
83 const sal_Char
* JobData::PROP_MODEL
= "Model" ;
84 const sal_Char
* JobData::PROP_SERVICE
= "Service" ;
86 //________________________________
87 // non exported definitions
89 //________________________________
92 //________________________________
95 @descr It initialize this new instance.
96 But for real working it's neccessary to call setAlias() or setService() later.
97 Because we need the job data ...
100 reference to the uno service manager
102 JobData::JobData( const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xSMGR
)
103 : ThreadHelpBase(&Application::GetSolarMutex())
106 // share code for member initialization with defaults!
110 //________________________________
113 @descr Sometimes such job data container must be moved from one using place
114 to another one. Then a copy ctor and copy operator must be available.
117 the original instance, from which we must copy all data
119 JobData::JobData( const JobData
& rCopy
)
120 : ThreadHelpBase(&Application::GetSolarMutex())
122 // use the copy operator to share the same code
126 //________________________________
128 @short operator for coping JobData instances
129 @descr Sometimes such job data container must be moved from one using place
130 to another one. Then a copy ctor and copy operator must be available.
133 the original instance, from which we must copy all data
135 void JobData::operator=( const JobData
& rCopy
)
138 WriteGuard
aWriteLock(m_aLock
);
139 // Please don't copy the uno service manager reference.
140 // That can change the uno context, which isn't a good idea!
141 m_eMode
= rCopy
.m_eMode
;
142 m_eEnvironment
= rCopy
.m_eEnvironment
;
143 m_sAlias
= rCopy
.m_sAlias
;
144 m_sService
= rCopy
.m_sService
;
145 m_sEvent
= rCopy
.m_sEvent
;
146 m_lArguments
= rCopy
.m_lArguments
;
147 m_aLastExecutionResult
= rCopy
.m_aLastExecutionResult
;
152 //________________________________
154 @short let this instance die
155 @descr There is no chance any longer to work. We have to
156 release all used ressources and free used memory.
163 //________________________________
165 @short initalize this instance as a job with configuration
166 @descr They given alias can be used to adress some configuraton data.
167 We read it and fill our internal structures. Of course old informations
168 will be lost doing so.
171 the alias name of this job, used to locate job properties inside cfg
173 void JobData::setAlias( const ::rtl::OUString
& sAlias
)
176 WriteGuard
aWriteLock(m_aLock
);
177 // delete all old informations! Otherwhise we mix it with the new one ...
180 // take over the new informations
184 // try to open the configuration set of this job directly and get a property access to it
185 // We open it readonly here
186 ::rtl::OUString sKey
;
187 sKey
= ::rtl::OUString::createFromAscii(JOBCFG_ROOT
);
188 sKey
+= ::utl::wrapConfigurationElementName(m_sAlias
);
190 ConfigAccess
aConfig(m_xSMGR
, sKey
);
191 aConfig
.open(ConfigAccess::E_READONLY
);
192 if (aConfig
.getMode()==ConfigAccess::E_CLOSED
)
198 css::uno::Reference
< css::beans::XPropertySet
> xJobProperties(aConfig
.cfg(), css::uno::UNO_QUERY
);
199 if (xJobProperties
.is())
201 css::uno::Any aValue
;
203 // read uno implementation name
204 aValue
= xJobProperties
->getPropertyValue(::rtl::OUString::createFromAscii(JOBCFG_PROP_SERVICE
));
205 aValue
>>= m_sService
;
207 // read whole argument list
208 aValue
= xJobProperties
->getPropertyValue(::rtl::OUString::createFromAscii(JOBCFG_PROP_ARGUMENTS
));
209 css::uno::Reference
< css::container::XNameAccess
> xArgumentList
;
211 (aValue
>>= xArgumentList
) &&
212 (xArgumentList
.is() )
215 css::uno::Sequence
< ::rtl::OUString
> lArgumentNames
= xArgumentList
->getElementNames();
216 sal_Int32 nCount
= lArgumentNames
.getLength();
217 m_lArguments
.realloc(nCount
);
218 for (sal_Int32 i
=0; i
<nCount
; ++i
)
220 m_lArguments
[i
].Name
= lArgumentNames
[i
];
221 m_lArguments
[i
].Value
= xArgumentList
->getByName(m_lArguments
[i
].Name
);
231 //________________________________
233 @short initalize this instance as a job without configuration
234 @descr This job has no configuration data. We have to forget all old informations
235 and set only some of them new, so this instance can work.
238 the uno service name of this "non configured" job
240 void JobData::setService( const ::rtl::OUString
& sService
)
243 WriteGuard
aWriteLock(m_aLock
);
245 // delete all old informations! Otherwhise we mix it with the new one ...
247 // take over the new informations
248 m_sService
= sService
;
255 //________________________________
257 @short initialize this instance with new job values.
258 @descr It reads automaticly all properties of the specified
259 job (using it's alias name) and "register it" for the
260 given event. This registration will not be validated against
261 the underlying configuration! (That must be done from outside.
262 Because the caller must have the configuration already open to
263 get the values for sEvent and sAlias! And doing so it can perform
264 only, if the time stanp values are readed outside too.
265 Further it make no sense to initialize and start a disabled job.
266 So this initialization method will be called for enabled jobs only.)
269 the triggered event, for which this job should be started
272 mark the required job inside event registration list
274 void JobData::setEvent( const ::rtl::OUString
& sEvent
,
275 const ::rtl::OUString
& sAlias
)
277 // share code to read all job properties!
281 WriteGuard
aWriteLock(m_aLock
);
283 // take over the new informations - which differ against set on of method setAlias()!
291 //________________________________
293 @short set the new job specific arguments
294 @descr If a job finish his work, it can give us a new list of arguments (which
295 will not interpreted by us). We write it back to the configuration only
296 (if this job has it's own configuration!).
297 So a job can have persistent data without implementing anything
298 or define own config areas for that.
301 list of arguments, which should be set for this job
303 void JobData::setJobConfig( const css::uno::Sequence
< css::beans::NamedValue
>& lArguments
)
306 WriteGuard
aWriteLock(m_aLock
);
309 m_lArguments
= lArguments
;
311 // actualize the configuration ... if possible!
312 if (m_eMode
==E_ALIAS
)
314 // It doesn't matter if this config object was already opened before.
315 // It doesn nothing here then ... or it change the mode automaticly, if
316 // it was opened using another one before.
317 ::rtl::OUString sKey
;
318 sKey
= ::rtl::OUString::createFromAscii(JOBCFG_ROOT
);
319 sKey
+= ::utl::wrapConfigurationElementName(m_sAlias
);
321 ConfigAccess
aConfig(m_xSMGR
, sKey
);
322 aConfig
.open(ConfigAccess::E_READWRITE
);
323 if (aConfig
.getMode()==ConfigAccess::E_CLOSED
)
326 css::uno::Reference
< css::beans::XMultiHierarchicalPropertySet
> xArgumentList(aConfig
.cfg(), css::uno::UNO_QUERY
);
327 if (xArgumentList
.is())
329 sal_Int32 nCount
= m_lArguments
.getLength();
330 css::uno::Sequence
< ::rtl::OUString
> lNames (nCount
);
331 css::uno::Sequence
< css::uno::Any
> lValues(nCount
);
333 for (sal_Int32 i
=0; i
<nCount
; ++i
)
335 lNames
[i
] = m_lArguments
[i
].Name
;
336 lValues
[i
] = m_lArguments
[i
].Value
;
339 xArgumentList
->setHierarchicalPropertyValues(lNames
, lValues
);
348 //________________________________
350 @short set a new excution result
351 @descr Every executed job can have returned a result.
352 We set it here, so our user can use it may be later.
353 But the outside code can use it too, to analyze it and
354 adopt the configuration of this job too. Because the
355 result uses a protocol, which allow that. And we provide
356 right functionality to save it.
359 the result of last execution
361 void JobData::setResult( const JobResult
& aResult
)
364 WriteGuard
aWriteLock(m_aLock
);
366 // overwrite the last saved result
367 m_aLastExecutionResult
= aResult
;
369 // Don't use his informations to actualize
370 // e.g. the arguments of this job. It must be done
371 // from outside! Here we save this information only.
377 //________________________________
379 @short set a new environment descriptor for this job
380 @descr It must(!) be done everytime this container is initialized
381 with new job datas e.g.: setAlias()/setEvent()/setService() ...
382 Otherwhise the environment will be unknown!
384 void JobData::setEnvironment( EEnvironment eEnvironment
)
387 WriteGuard
aWriteLock(m_aLock
);
388 m_eEnvironment
= eEnvironment
;
393 //________________________________
395 @short these functions provides access to our internal members
396 @descr These member represent any information about the job
397 and can be used from outside to e.g. start a job.
399 JobData::EMode
JobData::getMode() const
402 ReadGuard
aReadLock(m_aLock
);
407 //________________________________
409 JobData::EEnvironment
JobData::getEnvironment() const
412 ReadGuard
aReadLock(m_aLock
);
413 return m_eEnvironment
;
417 //________________________________
419 ::rtl::OUString
JobData::getEnvironmentDescriptor() const
421 ::rtl::OUString sDescriptor
;
423 ReadGuard
aReadLock(m_aLock
);
424 switch(m_eEnvironment
)
427 sDescriptor
= ::rtl::OUString::createFromAscii("EXECUTOR");
431 sDescriptor
= ::rtl::OUString::createFromAscii("DISPATCH");
434 case E_DOCUMENTEVENT
:
435 sDescriptor
= ::rtl::OUString::createFromAscii("DOCUMENTEVENT");
444 //________________________________
446 ::rtl::OUString
JobData::getService() const
449 ReadGuard
aReadLock(m_aLock
);
454 //________________________________
456 ::rtl::OUString
JobData::getEvent() const
459 ReadGuard
aReadLock(m_aLock
);
464 //________________________________
466 css::uno::Sequence
< css::beans::NamedValue
> JobData::getJobConfig() const
469 ReadGuard
aReadLock(m_aLock
);
474 //________________________________
476 css::uno::Sequence
< css::beans::NamedValue
> JobData::getConfig() const
479 ReadGuard
aReadLock(m_aLock
);
480 css::uno::Sequence
< css::beans::NamedValue
> lConfig
;
481 if (m_eMode
==E_ALIAS
)
486 lConfig
[i
].Name
= ::rtl::OUString::createFromAscii(PROP_ALIAS
);
487 lConfig
[i
].Value
<<= m_sAlias
;
490 lConfig
[i
].Name
= ::rtl::OUString::createFromAscii(PROP_SERVICE
);
491 lConfig
[i
].Value
<<= m_sService
;
499 //________________________________
501 @short return information, if this job is part of the global configuration package
502 org.openoffice.Office.Jobs
503 @descr Because jobs can be executed by the dispatch framework using an uno service name
504 directly - an executed job must not have any configuration realy. Such jobs
505 must provide the right interfaces only! But after finishing jobs can return
506 some informations (e.g. for updating her configuration ...). We must know
507 if such request is valid or not then.
509 @return TRUE if the represented job is part of the underlying configuration package.
511 sal_Bool
JobData::hasConfig() const
514 ReadGuard
aReadLock(m_aLock
);
515 return (m_eMode
==E_ALIAS
|| m_eMode
==E_EVENT
);
519 //________________________________
521 @short mark a job as non startable for further requests
522 @descr We don't remove the configuration entry! We set a timestamp value only.
523 And there exist two of them: one for an administrator ... and one for the
524 current user. We change it for the user layer only. So this JobDispatch can't be
525 started any more ... till the administrator change his timestamp.
526 That can be usefull for post setup scenarios, which must run one time only.
528 Note: This method don't do anything, if ths represented job doesn't have a configuration!
530 void JobData::disableJob()
533 WriteGuard
aWriteLock(m_aLock
);
535 // No configuration - not used from EXECUTOR and not triggered from an event => no chance!
536 if (m_eMode
!=E_EVENT
)
539 // actualize the configuration
540 // It doesn't matter if this config object was already opened before.
541 // It doesn nothing here then ... or it change the mode automaticly, if
542 // it was opened using another one before.
543 ::rtl::OUStringBuffer
sKey(256);
544 sKey
.appendAscii(JobData::EVENTCFG_ROOT
);
545 sKey
.append (::utl::wrapConfigurationElementName(m_sEvent
));
546 sKey
.appendAscii(JobData::EVENTCFG_PATH_JOBLIST
);
547 sKey
.appendAscii("/" );
548 sKey
.append (::utl::wrapConfigurationElementName(m_sAlias
));
550 ConfigAccess
aConfig(m_xSMGR
, sKey
.makeStringAndClear());
551 aConfig
.open(ConfigAccess::E_READWRITE
);
552 if (aConfig
.getMode()==ConfigAccess::E_CLOSED
)
555 css::uno::Reference
< css::beans::XPropertySet
> xPropSet(aConfig
.cfg(), css::uno::UNO_QUERY
);
558 // Convert and write the user timestamp to the configuration.
559 css::uno::Any aValue
;
560 aValue
<<= Converter::convert_DateTime2ISO8601(DateTime());
561 xPropSet
->setPropertyValue(::rtl::OUString::createFromAscii(EVENTCFG_PROP_USERTIME
), aValue
);
570 //________________________________
573 sal_Bool
isEnabled( const ::rtl::OUString
& sAdminTime
,
574 const ::rtl::OUString
& sUserTime
)
577 To prevent interpreting of TriGraphs inside next const string value,
578 we have to encode all '?' signs. Otherwhise e.g. "??-" will be translated
581 static ::rtl::OUString PATTERN_ISO8601
= ::rtl::OUString::createFromAscii("\?\?\?\?-\?\?-\?\?*\0");
582 WildCard
aISOPattern(PATTERN_ISO8601
);
584 sal_Bool bValidAdmin
= aISOPattern
.Matches(sAdminTime
);
585 sal_Bool bValidUser
= aISOPattern
.Matches(sUserTime
);
587 // We check for "isEnabled()" here only.
588 // Note further: ISO8601 formated strings can be compared as strings directly!
590 (!bValidAdmin
&& !bValidUser
) ||
591 ( bValidAdmin
&& bValidUser
&& sAdminTime
>=sUserTime
)
595 //________________________________
598 void JobData::appendEnabledJobsForEvent( const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xSMGR
,
599 const ::rtl::OUString
& sEvent
,
600 ::comphelper::SequenceAsVector
< JobData::TJob2DocEventBinding
>& lJobs
)
602 css::uno::Sequence
< ::rtl::OUString
> lAdditionalJobs
= JobData::getEnabledJobsForEvent(xSMGR
, sEvent
);
603 sal_Int32 c
= lAdditionalJobs
.getLength();
608 JobData::TJob2DocEventBinding
aBinding(lAdditionalJobs
[i
], sEvent
);
609 lJobs
.push_back(aBinding
);
613 //________________________________
616 css::uno::Sequence
< ::rtl::OUString
> JobData::getEnabledJobsForEvent( const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xSMGR
,
617 const ::rtl::OUString
& sEvent
)
619 // these static values may perform following loop for reading time stamp values ...
620 static ::rtl::OUString ADMINTIME
= ::rtl::OUString::createFromAscii(JobData::EVENTCFG_PROP_ADMINTIME
);
621 static ::rtl::OUString USERTIME
= ::rtl::OUString::createFromAscii(JobData::EVENTCFG_PROP_USERTIME
);
622 static ::rtl::OUString ROOT
= ::rtl::OUString::createFromAscii(JobData::EVENTCFG_ROOT
);
623 static ::rtl::OUString JOBLIST
= ::rtl::OUString::createFromAscii(JobData::EVENTCFG_PATH_JOBLIST
);
625 // create a config access to "/org.openoffice.Office.Jobs/Events"
626 ConfigAccess
aConfig(xSMGR
,ROOT
);
627 aConfig
.open(ConfigAccess::E_READONLY
);
628 if (aConfig
.getMode()==ConfigAccess::E_CLOSED
)
629 return css::uno::Sequence
< ::rtl::OUString
>();
631 css::uno::Reference
< css::container::XHierarchicalNameAccess
> xEventRegistry(aConfig
.cfg(), css::uno::UNO_QUERY
);
632 if (!xEventRegistry
.is())
633 return css::uno::Sequence
< ::rtl::OUString
>();
635 // check if the given event exist inside list of registered ones
636 ::rtl::OUString
sPath(sEvent
);
638 if (!xEventRegistry
->hasByHierarchicalName(sPath
))
639 return css::uno::Sequence
< ::rtl::OUString
>();
641 // step to the job list, which is a child of the event node inside cfg
642 // e.g. "/org.openoffice.Office.Jobs/Events/<event name>/JobList"
643 css::uno::Any aJobList
= xEventRegistry
->getByHierarchicalName(sPath
);
644 css::uno::Reference
< css::container::XNameAccess
> xJobList
;
645 if (!(aJobList
>>= xJobList
) || !xJobList
.is())
646 return css::uno::Sequence
< ::rtl::OUString
>();
648 // get all alias names of jobs, which are part of this job list
649 // But Some of them can be disabled by it's time stamp values.
650 // We create an additional job name list iwth the same size, then the original list ...
651 // step over all job entries ... check her time stamps ... and put only job names to the
652 // destination list, which represent an enabled job.
653 css::uno::Sequence
< ::rtl::OUString
> lAllJobs
= xJobList
->getElementNames();
654 ::rtl::OUString
* pAllJobs
= lAllJobs
.getArray();
655 sal_Int32 c
= lAllJobs
.getLength();
657 css::uno::Sequence
< ::rtl::OUString
> lEnabledJobs(c
);
658 ::rtl::OUString
* pEnabledJobs
= lEnabledJobs
.getArray();
661 for (sal_Int32 s
=0; s
<c
; ++s
)
663 css::uno::Reference
< css::beans::XPropertySet
> xJob
;
665 !(xJobList
->getByName(pAllJobs
[s
]) >>= xJob
) ||
672 ::rtl::OUString sAdminTime
;
673 xJob
->getPropertyValue(ADMINTIME
) >>= sAdminTime
;
675 ::rtl::OUString sUserTime
;
676 xJob
->getPropertyValue(USERTIME
) >>= sUserTime
;
678 if (!isEnabled(sAdminTime
, sUserTime
))
681 pEnabledJobs
[d
] = pAllJobs
[s
];
684 lEnabledJobs
.realloc(d
);
691 //________________________________
693 @short reset all internal structures
694 @descr If somehwere recycle this instance, he can switch from one
695 using mode to another one. But then we have to reset all currently
696 used informations. Otherwhise we mix it and they can make trouble.
698 But note: that does not set defaults for internal used members, which
699 does not relate to any job property! e.g. the reference to the global
700 uno service manager. Such informations are used for internal processes only
701 and are neccessary for our work.
703 void JobData::impl_reset()
706 WriteGuard
aWriteLock(m_aLock
);
707 m_eMode
= E_UNKNOWN_MODE
;
708 m_eEnvironment
= E_UNKNOWN_ENVIRONMENT
;
709 m_sAlias
= ::rtl::OUString();
710 m_sService
= ::rtl::OUString();
711 m_sEvent
= ::rtl::OUString();
712 m_lArguments
= css::uno::Sequence
< css::beans::NamedValue
>();
717 } // namespace framework