xref: /trunk/main/scripting/source/storage/ScriptStorage.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_scripting.hxx"
26 #include <osl/file.hxx>
27 #include <osl/time.h>
28 #include <cppuhelper/implementationentry.hxx>
29 #include <com/sun/star/lang/IllegalArgumentException.hpp>
30 #include <com/sun/star/ucb/CommandAbortedException.hpp>
31 #include <com/sun/star/io/XActiveDataSource.hpp>
32 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
33 #include <com/sun/star/container/XNameAccess.hpp>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/beans/PropertyValue.hpp>
36 
37 #include <util/util.hxx>
38 #include <rtl/uri.hxx>
39 
40 
41 #include "ScriptData.hxx"
42 #include "ScriptInfo.hxx"
43 #include "ScriptStorage.hxx"
44 #include "ScriptElement.hxx"
45 #include "ScriptMetadataImporter.hxx"
46 #include "ScriptURI.hxx"
47 
48 using namespace ::rtl;
49 using namespace ::cppu;
50 using namespace ::com::sun::star;
51 using namespace ::com::sun::star::uno;
52 using namespace ::drafts::com::sun::star::script::framework;
53 
54 namespace scripting_impl
55 {
56 
57 ScriptLanguages_hash* ScriptStorage::mh_scriptLangs = NULL;
58 
59 const sal_Char* const SERVICE_NAME =
60     "drafts.com.sun.star.script.framework.storage.ScriptStorage";
61 const sal_Char* const IMPL_NAME =
62     "drafts.com.sun.star.script.framework.storage.ScriptStorage";
63 
64 const sal_Char * const SCRIPT_DIR = "/Scripts";
65 const sal_Char * const SCRIPT_PARCEL = "/parcel-descriptor.xml";
66 const sal_Char * const SCRIPT_PARCEL_NAME_ONLY = "parcel-descriptor";
67 
68 static OUString ss_implName = OUString::createFromAscii( IMPL_NAME );
69 static OUString ss_serviceName = OUString::createFromAscii( SERVICE_NAME );
70 static Sequence< OUString > ss_serviceNames =
71     Sequence< OUString >( &ss_serviceName, 1 );
72 
73 const sal_uInt16 NUMBER_STORAGE_INITIALIZE_ARGS = 3;
74 
75 //extern ::rtl_StandardModuleCount s_moduleCount;
76 
77 
78 
79 //*************************************************************************
ScriptStorage(const Reference<XComponentContext> & xContext)80 ScriptStorage::ScriptStorage( const Reference <
81                               XComponentContext > & xContext )
82         : m_xContext( xContext, UNO_SET_THROW ), m_bInitialised( false )
83 {
84     OSL_TRACE( "< ScriptStorage ctor called >\n" );
85 
86     m_xMgr.set( m_xContext->getServiceManager(), UNO_SET_THROW );
87 
88     if( !mh_scriptLangs )
89     {
90         ::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() );
91         if( !mh_scriptLangs )
92         {
93             mh_scriptLangs = new ScriptLanguages_hash();
94             Reference< lang::XMultiServiceFactory > xConfigProvFactory(
95                 m_xMgr->createInstanceWithContext( OUString::createFromAscii( "com.sun.star.configuration.ConfigurationProvider" ), m_xContext ),
96                 UNO_QUERY_THROW );
97             // create an instance of the ConfigurationAccess for accessing the
98             // scripting runtime settings
99             beans::PropertyValue configPath;
100             configPath.Name = ::rtl::OUString::createFromAscii( "nodepath" );
101             configPath.Value <<= ::rtl::OUString::createFromAscii( "org.openoffice.Office.Scripting/ScriptRuntimes" );
102             Sequence < Any > aargs( 1 );
103             aargs[ 0 ] <<= configPath;
104 
105             Reference< container::XNameAccess > xNameAccess(
106                 xConfigProvFactory->createInstanceWithArguments(
107                     OUString::createFromAscii( "com.sun.star.configuration.ConfigurationAccess" ),
108                     aargs
109                 ),
110                 UNO_QUERY_THROW );
111 
112             Sequence< OUString > names = xNameAccess->getElementNames();
113             for( int i = 0 ; i < names.getLength() ; i++ )
114             {
115                 OSL_TRACE(  "Getting propertyset for Lang=%s",
116                     ::rtl::OUStringToOString( names[i], RTL_TEXTENCODING_ASCII_US ).pData->buffer );
117                 Reference< beans::XPropertySet > xPropSet( xNameAccess->getByName( names[i] ), UNO_QUERY_THROW );
118                 Any aProp = xPropSet->getPropertyValue(
119                         OUString::createFromAscii( "SupportedFileExtensions") );
120                 Sequence< OUString > extns;
121                 if( sal_False == ( aProp >>= extns ) )
122                 {
123                     throw RuntimeException(
124                         OUSTR( "ScriptStorage:ScriptStorage: can't get runtime extensions" ),
125                         Reference< XInterface > () );
126                 }
127                 for( int j = 0 ; j < extns.getLength() ; j++ )
128                 {
129                     OSL_TRACE(  "Adding Lang=%s, Extn=%s\n",
130                         ::rtl::OUStringToOString( names[i], RTL_TEXTENCODING_ASCII_US ).pData->buffer,
131                         ::rtl::OUStringToOString( extns[j], RTL_TEXTENCODING_ASCII_US ).pData->buffer );
132                     (*mh_scriptLangs)[ extns[j] ] =
133                         names[i];
134                 }
135             }
136         }
137     }
138 //    s_moduleCount.modCnt.acquire( &s_moduleCount.modCnt );
139 }
140 
141 //*************************************************************************
~ScriptStorage()142 ScriptStorage::~ScriptStorage() SAL_THROW( () )
143 {
144     OSL_TRACE( "< ScriptStorage dtor called >\n" );
145 //    s_moduleCount.modCnt.release( &s_moduleCount.modCnt );
146 }
147 
148 //*************************************************************************
149 void
initialize(const Sequence<Any> & args)150 ScriptStorage::initialize( const Sequence <Any> & args )
151 {
152     OSL_TRACE( "Entering ScriptStorage::initialize\n" );
153 
154     // Should not be renitialized
155     if ( m_bInitialised )
156     {
157         throw RuntimeException(
158             OUSTR( "ScriptStorage::initialize already initialized" ),
159             Reference<XInterface> () );
160     }
161 
162     {   // Protect member variable writes
163         ::osl::Guard< osl::Mutex > aGuard( m_mutex );
164 
165         // Check args
166         if ( args.getLength() != NUMBER_STORAGE_INITIALIZE_ARGS )
167         {
168             OSL_TRACE( "ScriptStorage::initialize: got wrong number of args\n" );
169             throw RuntimeException(
170                 OUSTR( "Invalid number of arguments provided!" ),
171                 Reference< XInterface >() );
172         }
173 
174         if ( sal_False == ( args[ 0 ] >>= m_xSimpleFileAccess ) )
175         {
176             throw RuntimeException(
177                 OUSTR( "Invalid XSimpleFileAccess argument provided!" ),
178                 Reference< XInterface >() );
179         }
180 
181         if ( sal_False == ( args[ 1 ] >>= m_scriptStorageID ) )
182         {
183             throw RuntimeException(
184                 OUSTR( "Invalid ScriptStorage ID argument provided!" ),
185                 Reference< XInterface >() );
186 
187         }
188         if ( sal_False == ( args[ 2 ] >>= m_stringUri ) )
189         {
190             throw RuntimeException(
191                 OUSTR( "Invalid String Uri argument provided!" ),
192                 Reference< XInterface >() );
193         }
194     } // End - Protect member variable writes
195 
196     OSL_TRACE(  "uri: %s\n", ::rtl::OUStringToOString(
197         m_stringUri, RTL_TEXTENCODING_ASCII_US ).pData->buffer );
198 
199     try
200     {
201         // need to check for what???
202         // what we have is a URI for the filesystem or document
203         // we need to check of the last element in the path has an
204         // extension that is associated with a script (eg. .bsh, .js etc)
205         OUString fileExtension = getFileExtension( m_stringUri );
206         // and see if this is in our scripts map
207         ScriptLanguages_hash::iterator h_it = mh_scriptLangs->find( fileExtension );
208         if ( h_it != mh_scriptLangs->end() )
209         {
210             createForFilesystem( fileExtension );
211         }
212         else
213         {
214             create();
215         }
216     }
217     catch ( RuntimeException & re )
218     {
219         OSL_TRACE( "caught com::sun::star::uno::RuntimeException in ScriptStorage::initialize" );
220         throw RuntimeException(
221             OUSTR( "ScriptStorage::initialize RuntimeException: " ).concat( re.Message ),
222             Reference< XInterface > () );
223     }
224     catch ( Exception & ue )
225     {
226         OSL_TRACE( "caught com::sun::star::uno::Exception in ScriptStorage::initialize" );
227         throw RuntimeException(
228             OUSTR( "ScriptStorage::initialize Exception: " ).concat( ue.Message ),
229             Reference< XInterface > () );
230     }
231 #ifdef _DEBUG
232     catch ( ... )
233     {
234         OSL_TRACE( "caught unknown Exception in ScriptStorage::initialize" );
235         throw RuntimeException(
236             OUSTR( "ScriptStorage::initialize unknown exception: " ),
237             Reference< XInterface > () );
238     }
239 #endif
240 
241     OSL_TRACE( "Parsed the XML\n" );
242 
243     m_bInitialised = true;
244 }
245 
246 void
create()247 ScriptStorage::create()
248 {
249     ::osl::Guard< osl::Mutex > aGuard( m_mutex );
250     try
251     {
252         // clear existing hashmap - rebuilding from scratch to avoid having
253         // to search for deleted elements on refresh
254         mh_implementations.clear();
255 
256         OUString xStringUri(m_stringUri);
257 
258         ScriptMetadataImporter* SMI = new ScriptMetadataImporter( m_xContext );
259         Reference< xml::sax::XExtendedDocumentHandler > xSMI( SMI, UNO_SET_THROW );
260 
261         xStringUri = xStringUri.concat( ::rtl::OUString::createFromAscii(
262             SCRIPT_DIR ) );
263 
264        // No Scripts directory - just return
265        if ( ! m_xSimpleFileAccess->isFolder( xStringUri ) )
266        {
267             OSL_TRACE( "ScriptStorage::initialize: no Scripts dir for this storage - install problem\n" );
268            return;
269        }
270 
271         // get the list of language folders under the Scripts directory
272         Sequence< ::rtl::OUString > languageDirs =
273             m_xSimpleFileAccess->getFolderContents( xStringUri, true );
274 
275         Reference< io::XInputStream > xInput;
276         sal_Int32 languageDirsLength = languageDirs.getLength();
277         for ( sal_Int32 i = 0; i < languageDirsLength ; ++i )
278         {
279             OSL_TRACE(  "contains: %s\n", ::rtl::OUStringToOString(
280                 languageDirs[ i ], RTL_TEXTENCODING_ASCII_US ).pData->buffer );
281 
282             if ( ! m_xSimpleFileAccess->isFolder( languageDirs[ i ] ) )
283             {
284                 continue;
285             }
286 
287             //get the list of parcel folders for each language folder
288             // under Scripts
289             Sequence< ::rtl::OUString > parcelDirs =
290                 m_xSimpleFileAccess->getFolderContents( languageDirs[ i ], true );
291 
292             sal_Int32 parcelDirsLength = parcelDirs.getLength();
293             for ( sal_Int32 j = 0; j < parcelDirsLength ; ++j )
294             {
295                 OSL_TRACE(  "contains: %s\n",
296                     ::rtl::OUStringToOString( parcelDirs[ j ],
297                     RTL_TEXTENCODING_ASCII_US ).pData->buffer );
298 
299                 OUString parcelFile = parcelDirs[ j ].concat(
300                     ::rtl::OUString::createFromAscii( SCRIPT_PARCEL ) );
301 
302                 // Do not have a valid parcel.xml
303                 if ( !m_xSimpleFileAccess->exists( parcelFile ) ||
304                         m_xSimpleFileAccess->isFolder( parcelFile ) )
305                 {
306                     continue;
307                 }
308                 OSL_TRACE(  "parcel file: %s\n",
309                     ::rtl::OUStringToOString( parcelFile,
310                     RTL_TEXTENCODING_ASCII_US ).pData->buffer );
311 
312                 xInput = m_xSimpleFileAccess->openFileRead( parcelFile );
313                 // Failed to get input stream
314                 if ( !xInput.is() )
315                 {
316                     continue;
317                 }
318 
319                 OSL_TRACE( "Parse the metadata \n" );
320                 Datas_vec vScriptDatas;
321                 try
322                 {
323                     SMI->parseMetaData( xInput, parcelDirs[ j ], vScriptDatas );
324                 }
325                 catch ( xml::sax::SAXException & saxe )
326                 {
327                     if ( xInput.is() )
328                     {
329                         xInput->closeInput();
330                     }
331                     OSL_TRACE(
332                         "caught com::sun::star::xml::sax::SAXException in ScriptStorage::create %s",
333                         ::rtl::OUStringToOString( saxe.Message,
334                         RTL_TEXTENCODING_ASCII_US ).pData->buffer  );
335 
336                     continue;
337                 }
338                 catch ( io::IOException & ioe )
339                 {
340                     if ( xInput.is() )
341                     {
342                         xInput->closeInput();
343                     }
344                     OSL_TRACE(
345                         "caught com::sun::star::io::IOException in ScriptStorage::create" );
346                     continue;
347                 }
348                 xInput->closeInput();
349 
350                 updateMaps( vScriptDatas );
351             }
352         }
353     }
354     catch ( io::IOException & ioe )
355     {
356         //From ScriptMetadata Importer
357         OSL_TRACE( "caught com::sun::star::io::IOException in ScriptStorage::create" );
358         throw RuntimeException(
359             OUSTR( "ScriptStorage::create IOException: " ).concat( ioe.Message ),
360             Reference< XInterface > () );
361 
362     }
363     catch ( ucb::CommandAbortedException & cae )
364     {
365         OSL_TRACE( "caught com::sun::star::ucb::CommandAbortedException in ScriptStorage::create" );
366         throw RuntimeException(
367             OUSTR(
368                 "ScriptStorage::create CommandAbortedException: " ).concat( cae.Message ),
369             Reference< XInterface > () );
370     }
371     catch ( RuntimeException & re )
372     {
373         OSL_TRACE( "caught com::sun::star::uno::RuntimeException in ScriptStorage::create" );
374         throw RuntimeException(
375             OUSTR( "ScriptStorage::create RuntimeException: " ).concat( re.Message ),
376             Reference< XInterface > () );
377     }
378     catch ( Exception & ue )
379     {
380         OSL_TRACE( "caught com::sun::star::uno::Exception in ScriptStorage::create" );
381         throw RuntimeException(
382             OUSTR( "ScriptStorage::create Exception: " ).concat( ue.Message ),
383             Reference< XInterface > () );
384     }
385 #ifdef _DEBUG
386     catch ( ... )
387     {
388         OSL_TRACE( "caught unknown Exception in ScriptStorage::create" );
389         throw RuntimeException(
390             OUSTR( "ScriptStorage::initialize unknown exception: " ),
391             Reference< XInterface > () );
392     }
393 #endif
394 
395     OSL_TRACE( "Parsed the XML\n" );
396 
397     m_bInitialised = true;
398 }
399 
400 //*************************************************************************
401 // private method to create the usual data structures for scripts located
402 // on the filesystem.
403 // parcelURI = the path to the script
404 // functionName = the full filename with extension
405 // logicalName = the filename without the extension
406 void
createForFilesystem(const OUString & fileExtension)407 ScriptStorage::createForFilesystem( const OUString & fileExtension )
408 {
409     // need to decode as file urls are encoded
410     OUString xStringUri = ::rtl::Uri::decode( m_stringUri,
411         rtl_UriDecodeWithCharset, RTL_TEXTENCODING_ASCII_US );
412 
413     // no x-platform issues here as we are dealing with URLs
414     sal_Int32 lastFileSep = xStringUri.lastIndexOf( '/' );
415     // the char just after the filesep
416     lastFileSep += 1;
417     sal_Int32 lastFileExt = xStringUri.lastIndexOf( fileExtension );
418     OUString searchString = OUString::createFromAscii( "://" );
419     sal_Int32 searchStringLength = searchString.getLength();
420     sal_Int32 startPath = xStringUri.indexOf( searchString );
421     sal_Int32 uriLength = xStringUri.getLength();
422     OUString fileNameNoExt = xStringUri.copy( lastFileSep ,
423         lastFileExt - lastFileSep  - 1 );
424     OUString fileName = xStringUri.copy( lastFileSep, uriLength - lastFileSep );
425     OUString filePath = xStringUri.copy( startPath + searchStringLength,
426         lastFileSep - startPath - searchStringLength );
427     OUString filePathWithName = xStringUri.copy( startPath + searchStringLength,
428         uriLength - startPath - searchStringLength );
429 
430     ScriptData scriptData;
431     scriptData.language = mh_scriptLangs->find( fileExtension )->second;
432     OSL_TRACE( "\t language = %s", ::rtl::OUStringToOString(
433         scriptData.language, RTL_TEXTENCODING_ASCII_US ).pData->buffer );
434 
435     // do we need to encode this?
436     scriptData.functionname = fileName;
437     OSL_TRACE( "\t functionName = %s", ::rtl::OUStringToOString(
438         scriptData.functionname, RTL_TEXTENCODING_ASCII_US ).pData->buffer );
439     //scriptData.functionname = ::rtl::Uri::encode( fileName,
440         //rtl_UriCharClassUricNoSlash, rtl_UriEncodeCheckEscapes,
441         //RTL_TEXTENCODING_ASCII_US );
442 
443     scriptData.parcelURI = filePath;
444     OSL_TRACE( "\t parcelURI = %s", ::rtl::OUStringToOString(
445         scriptData.parcelURI, RTL_TEXTENCODING_ASCII_US ).pData->buffer );
446     scriptData.logicalname = fileNameNoExt;
447     OSL_TRACE( "\t logicalName = %s", ::rtl::OUStringToOString(
448         scriptData.logicalname, RTL_TEXTENCODING_ASCII_US ).pData->buffer );
449 
450     // and now push onto the usual structures
451     ScriptFunction_hash sfh;
452     sfh[ scriptData.functionname ] = scriptData;
453     mh_implementations[ scriptData.language ] = sfh;
454     m_bInitialised = true;
455 }
456 
457 //*************************************************************************
458 // private method to return the file extension, eg. bsh, js etc
459 OUString
getFileExtension(const OUString & stringUri)460 ScriptStorage::getFileExtension( const OUString & stringUri )
461 {
462     OUString fileExtension;
463     sal_Int32 lastDot = stringUri.lastIndexOf( '.' );
464     if( lastDot > 0 ) {
465         sal_Int32 stringUriLength = stringUri.getLength();
466         fileExtension = stringUri.copy( lastDot +1 , stringUriLength - lastDot - 1 );
467     }
468     else
469     {
470         fileExtension = OUString::createFromAscii("");
471     }
472     return fileExtension;
473 }
474 
475 //*************************************************************************
476 // private method for updating hashmaps
477 void
updateMaps(const Datas_vec & vScriptDatas)478 ScriptStorage::updateMaps( const Datas_vec & vScriptDatas )
479 {
480 
481     Datas_vec::const_iterator it_end = vScriptDatas.end();
482     // step through the vector of ScripImplInfos returned from parse
483     for ( Datas_vec::const_iterator it = vScriptDatas.begin() ; it != it_end; ++it )
484     {
485         //find the Datas_vec for this logical name
486         ScriptData_hash::iterator h_it = mh_implementations.find( it->language );
487 
488         if ( h_it == mh_implementations.end() )
489         {
490             //if it's null, need to create a new Datas_vec
491             OSL_TRACE(
492                      "updateMaps: new language: %s\n", rtl::OUStringToOString(
493                          it->language, RTL_TEXTENCODING_ASCII_US ).pData->buffer );
494             OSL_TRACE(
495                      "updateMaps: adding functionname: %s\n", rtl::OUStringToOString(
496                          it->functionname, RTL_TEXTENCODING_ASCII_US ).pData->buffer );
497 
498             ScriptFunction_hash sfh;
499             sfh[ it->functionname ] = *it;
500             mh_implementations[ it->language ] = sfh;
501         }
502         else
503         {
504             OSL_TRACE(
505                      "updateMaps: adding functionname: %s\n", rtl::OUStringToOString(
506                          it->functionname, RTL_TEXTENCODING_ASCII_US ).pData->buffer );
507             OSL_TRACE(  "                    language name: %s\n",
508                 rtl::OUStringToOString( it->functionname,
509                 RTL_TEXTENCODING_ASCII_US ).pData->buffer );
510 
511             h_it->second[ it->functionname ] = *it;
512         }
513     }
514 }
515 
516 //*************************************************************************
517 // XScriptStorageExport::save
518 void
save()519 ScriptStorage::save()
520 {
521     ::osl::Guard< osl::Mutex > aGuard( m_mutex );
522     Reference< io::XActiveDataSource > xSource;
523     Reference< io::XOutputStream > xOS;
524 
525     // xScriptInvocation = Reference<XScriptInvocation>(xx, UNO_QUERY_THROW);
526     Reference< xml::sax::XExtendedDocumentHandler > xHandler;
527 
528     OUString parcel_suffix = OUString::createFromAscii( SCRIPT_PARCEL );
529     OUString ou_parcel = OUString(
530         RTL_CONSTASCII_USTRINGPARAM( SCRIPT_PARCEL_NAME_ONLY ) );
531 
532     try
533     {
534         ScriptData_hash::iterator it_end = mh_implementations.end();
535         for ( ScriptData_hash::iterator it = mh_implementations.begin() ; it != it_end; ++it )
536         {
537             ::rtl::OUString logName = it->first;
538             ScriptFunction_hash::iterator it_sfh_end = it->second.end();
539             for ( ScriptFunction_hash::iterator it_sfh = it->second.begin();
540                     it_sfh != it_sfh_end ; ++it_sfh )
541             {
542                 ScriptOutput_hash::const_iterator it_parcels =
543                     mh_parcels.find( it_sfh->second.parcelURI );
544                 if ( it_parcels == mh_parcels.end() )
545                 {
546                     //create new outputstream
547                     OUString parcel_xml_path = it_sfh->second.parcelURI.concat(
548                         parcel_suffix );
549                     m_xSimpleFileAccess->kill( parcel_xml_path );
550                     xOS = m_xSimpleFileAccess->openFileWrite( parcel_xml_path );
551 
552                     OSL_TRACE(  "saving: %s\n", rtl::OUStringToOString(
553                         it_sfh->second.parcelURI.concat( OUString::createFromAscii(
554                         "/parcel.xml" ) ),
555                         RTL_TEXTENCODING_ASCII_US ).pData->buffer );
556 
557                     xHandler.set(
558                         m_xMgr->createInstanceWithContext(
559                             OUString::createFromAscii( "com.sun.star.xml.sax.Writer" ),
560                             m_xContext
561                         ),
562                         UNO_QUERY_THROW
563                     );
564                     xSource.set( xHandler, UNO_QUERY_THROW );
565                     xSource->setOutputStream( xOS );
566 
567                     writeMetadataHeader( xHandler );
568 
569                     mh_parcels[ it_sfh->second.parcelURI ] = xHandler;
570                 }
571                 else
572                 {
573                     xHandler = it_parcels->second;
574                 }
575 
576                 ScriptElement* pSE = new ScriptElement( it_sfh->second );
577                 // this is to get pSE released correctly
578                 Reference < xml::sax::XAttributeList > xal( pSE );
579                 pSE->dump( xHandler );
580             }
581         }
582 
583         ScriptOutput_hash::const_iterator out_it_end = mh_parcels.end();
584 
585         for ( ScriptOutput_hash::const_iterator out_it = mh_parcels.begin();
586                 out_it != out_it_end; ++out_it )
587         {
588             out_it->second->ignorableWhitespace( ::rtl::OUString() );
589             out_it->second->endDocument();
590             xSource.set( out_it->second, UNO_QUERY );
591             Reference< io::XOutputStream > xOS = xSource->getOutputStream();
592             xOS->closeOutput();
593 
594         }
595 
596         // clear the hash map, as all output streams have been closed.
597         // need to re-create on next save
598         mh_parcels.clear();
599     }
600     // *** TODO - other exception handling IO etc.
601     catch ( RuntimeException & re )
602     {
603         OSL_TRACE( "caught com::sun::star::uno::RuntimeException in ScriptStorage::save" );
604         throw RuntimeException(
605             OUSTR( "ScriptStorage::save RuntimeException: " ).concat(
606             re.Message ),
607             Reference< XInterface > () );
608     }
609 }
610 
611 //*************************************************************************
612 void
refresh()613 ScriptStorage::refresh()
614 {
615     OSL_TRACE("** => ScriptStorage: in refresh()\n");
616 
617     // guard against concurrent refreshes
618     ::osl::Guard< ::osl::Mutex > aGuard( m_mutex );
619 
620     try
621     {
622         create();
623 
624     }
625     catch ( RuntimeException & re )
626     {
627         OSL_TRACE( "caught com::sun::star::uno::RuntimeException in ScriptStorage::refresh" );
628         throw RuntimeException(
629             OUSTR( "ScriptStorage::refresh RuntimeException: " ).concat( re.Message ),
630             Reference< XInterface > () );
631     }
632     catch ( Exception & ue )
633     {
634         OSL_TRACE( "caught com::sun::star::uno::Exception in ScriptStorage::refresh" );
635         throw RuntimeException(
636             OUSTR( "ScriptStorage::refresh Exception: " ).concat( ue.Message ),
637             Reference< XInterface > () );
638     }
639 }
640 
641 //*************************************************************************
642 void
writeMetadataHeader(Reference<xml::sax::XExtendedDocumentHandler> & xHandler)643 ScriptStorage::writeMetadataHeader(
644     Reference <xml::sax::XExtendedDocumentHandler> & xHandler )
645 {
646     xHandler->startDocument();
647     OUString aDocTypeStr( RTL_CONSTASCII_USTRINGPARAM(
648         "<!DOCTYPE  parcel SYSTEM \"scripting.dtd\">" ) );
649     xHandler->unknown( aDocTypeStr );
650     xHandler->ignorableWhitespace( OUString() );
651 }
652 
653 
654 //*************************************************************************
655 Sequence< ::rtl::OUString >
getScriptLogicalNames()656 ScriptStorage::getScriptLogicalNames()
657 {
658     Sequence< ::rtl::OUString  > results;
659     // comment out the rest, and ultimately remove method
660     /*ScriptInfo_hash::iterator h_it = mh_implementations.begin();
661     ScriptInfo_hash::iterator h_itEnd =  mh_implementations.end();
662     if ( h_it == h_itEnd  )
663     {
664         OSL_TRACE( "ScriptStorage::getImplementations: EMPTY STORAGE");
665         return results;
666     }
667     results.realloc( mh_implementations.size() );
668 
669     //find the implementations for the given logical name
670     try
671     {
672 
673         ::osl::Guard< osl::Mutex > aGuard( m_mutex );
674 
675         for ( sal_Int32 count = 0; h_it != h_itEnd ; ++h_it )
676         {
677             ::rtl::OUString logicalName = h_it->first;
678             OSL_TRACE( "Adding %s at index %d ", ::rtl::OUStringToOString(
679                 logicalName, RTL_TEXTENCODING_ASCII_US ).pData->buffer, count);
680             results[ count++ ] = logicalName;
681         }
682 
683     }
684     catch ( RuntimeException & re )
685     {
686         throw RuntimeException(
687             OUSTR( "ScriptStorage::getScriptLogicalNames RuntimeException: " ).concat( re.Message ),
688             Reference< XInterface > () );
689     }
690     catch ( Exception & e )
691     {
692         throw RuntimeException( OUSTR(
693             "ScriptStorage::getScriptLogicalNames Exception: " ).concat(
694             e.Message ), Reference< XInterface > () );
695     } */
696     return results;
697 }
698 
699 //*************************************************************************
700 Sequence< Reference< storage::XScriptInfo > >
getImplementations(const::rtl::OUString & queryURI)701 ScriptStorage::getImplementations( const ::rtl::OUString & queryURI )
702 {
703     ::osl::Guard< osl::Mutex > aGuard( m_mutex );
704 // format is script:://[function_name]?language=[language]&location=[location]
705 // LogicalName is now not used anymore, further more the ScriptURI class
706 // will be retired also and a new UNO service will be used. Additionally the
707 // parcel-description will also need to be modified to remove logical name
708 // ScriptMetaDataImporter has been modified to ignore the Logical name
709 // defined in the parcel-desc.xml. As an interim temp solution the  Datas_vec
710 // structure that is returned from ScriptMetDataImporter sets the logicalname
711 // to the function name. ScriptURI class has been changed in the same way.
712 //
713     Sequence< Reference< storage::XScriptInfo > > results;
714     ScriptURI scriptURI( queryURI );
715     OSL_TRACE( "getting impl for language %s, function name: %s",
716         ::rtl::OUStringToOString( scriptURI.getLanguage(),
717         RTL_TEXTENCODING_ASCII_US ).pData->buffer,
718         ::rtl::OUStringToOString( scriptURI.getFunctionName(),
719         RTL_TEXTENCODING_ASCII_US ).pData->buffer );
720     ScriptData_hash::iterator h_itEnd =  mh_implementations.end();
721     ScriptData_hash::iterator h_it = mh_implementations.begin();
722     if ( h_it == h_itEnd )
723     {
724         OSL_TRACE( "ScriptStorage::getImplementations: EMPTY STORAGE" );
725         return results;
726     }
727 
728     //find the implementations for the given language
729     h_it = mh_implementations.find( scriptURI.getLanguage() );
730 
731     if ( h_it == h_itEnd )
732     {
733         OSL_TRACE( "ScriptStorage::getImplementations: no impls found for %s",
734             ::rtl::OUStringToOString( scriptURI.getLanguage(),
735             RTL_TEXTENCODING_ASCII_US ).pData->buffer );
736         return results;
737     }
738 
739     //find the implementations for the given language
740     ScriptFunction_hash::const_iterator it_datas = h_it->second.find(
741         scriptURI.getLogicalName() );
742     ScriptFunction_hash::const_iterator it_datas_end = h_it->second.end();
743 
744     if ( it_datas == it_datas_end )
745     {
746         OSL_TRACE( "ScriptStorage::getImplementations: no impls found for %s",
747             ::rtl::OUStringToOString( scriptURI.getFunctionName(),
748             RTL_TEXTENCODING_ASCII_US ).pData->buffer );
749         return results;
750     }
751 
752     results.realloc( 1 );
753     ScriptData scriptData = it_datas->second;
754     OSL_TRACE( "ScriptStorage::getImplementations: impls found for %s",
755         ::rtl::OUStringToOString( scriptData.functionname,
756         RTL_TEXTENCODING_ASCII_US ).pData->buffer );
757     Reference< storage::XScriptInfo > xScriptInfo =
758         new ScriptInfo ( scriptData, m_scriptStorageID );
759     results[ 0 ] = xScriptInfo;
760 
761     return results;
762 }
763 
764 //*************************************************************************
765 Sequence< Reference< storage::XScriptInfo > > SAL_CALL
getAllImplementations()766 ScriptStorage::getAllImplementations()
767 {
768     ::osl::Guard< osl::Mutex > aGuard( m_mutex );
769     Sequence< Reference< storage::XScriptInfo > > results;
770     ScriptData_hash::iterator h_itEnd =  mh_implementations.end();
771     ScriptData_hash::iterator h_it = mh_implementations.begin();
772     if ( h_it == h_itEnd )
773     {
774         OSL_TRACE( "ScriptStorage::getImplementations: EMPTY STORAGE" );
775         return results;
776     }
777 
778 
779     //iterate through each logical name and gather each implementation
780     //for that name
781     for ( sal_Int32 count = 0; h_it !=  h_itEnd; ++h_it )
782     {
783         results.realloc( h_it->second.size() + count );
784         OSL_TRACE( "Adding implementations for %s",
785             ::rtl::OUStringToOString( h_it->first,
786                 RTL_TEXTENCODING_ASCII_US ).pData->buffer );
787         ScriptFunction_hash::const_iterator it_sfh = h_it->second.begin();
788         ScriptFunction_hash::const_iterator it_sfh_end = h_it->second.end();
789         OSL_TRACE( "Adding %d to sequence of impls ", h_it->second.size() );
790         for ( ; it_sfh != it_sfh_end ; ++it_sfh )
791         {
792             Reference< storage::XScriptInfo > xScriptInfo = new ScriptInfo (
793             it_sfh->second, m_scriptStorageID );
794 
795             results[ count++ ] = xScriptInfo;
796         }
797     }
798     return results;
799 
800 }
801 
802 //*************************************************************************
getImplementationName()803 OUString SAL_CALL ScriptStorage::getImplementationName( )
804 {
805     return ss_implName;
806 }
807 
808 //*************************************************************************
supportsService(const OUString & serviceName)809 sal_Bool SAL_CALL ScriptStorage::supportsService( const OUString& serviceName )
810 {
811     OUString const * pNames = ss_serviceNames.getConstArray();
812     for ( sal_Int32 nPos = ss_serviceNames.getLength(); nPos--; )
813     {
814         if ( serviceName.equals( pNames[ nPos ] ) )
815         {
816             return sal_True;
817         }
818     }
819     return sal_False;
820 }
821 
822 //*************************************************************************
getSupportedServiceNames()823 Sequence<OUString> SAL_CALL ScriptStorage::getSupportedServiceNames( )
824 {
825     return ss_serviceNames;
826 }
827 
828 } // namespace scripting_impl
829 
830 
831 namespace scripting_runtimemgr
832 {
833 
834 //*************************************************************************
ss_create(const Reference<XComponentContext> & xCompC)835 Reference<XInterface> SAL_CALL ss_create(
836     const Reference< XComponentContext > & xCompC )
837 {
838     return ( cppu::OWeakObject * ) new ::scripting_impl::ScriptStorage( xCompC );
839 }
840 
841 //*************************************************************************
ss_getSupportedServiceNames()842 Sequence<OUString> ss_getSupportedServiceNames( )
843 SAL_THROW( () )
844 {
845     return ::scripting_impl::ss_serviceNames;
846 }
847 
848 //*************************************************************************
ss_getImplementationName()849 OUString ss_getImplementationName( )
850 SAL_THROW( () )
851 {
852     return ::scripting_impl::ss_implName;
853 }
854 }//end namespace
855