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 package com.sun.star.script.framework.container;
24 
25 import com.sun.star.script.framework.log.LogUtils;
26 import com.sun.star.script.framework.provider.PathUtils;
27 import com.sun.star.script.framework.io.XOutputStreamWrapper;
28 import com.sun.star.script.framework.io.XInputStreamWrapper;
29 
30 import java.util.Map;
31 import java.util.HashMap;
32 import java.io.OutputStream;
33 import java.io.InputStream;
34 
35 import com.sun.star.uno.XComponentContext;
36 
37 import com.sun.star.uno.UnoRuntime;
38 
39 import com.sun.star.io.XOutputStream;
40 import com.sun.star.io.XTruncate;
41 
42 import com.sun.star.deployment.XPackage;
43 import com.sun.star.deployment.ExtensionRemovedException;
44 
45 public class UnoPkgContainer extends ParcelContainer
46 {
47 
48     private Map registeredPackages = new HashMap();
49     protected String extensionDb;
50     protected String extensionRepository;
51 
UnoPkgContainer( XComponentContext xCtx, String locationURL, String _extensionDb, String _extensionRepository, String language )52     public UnoPkgContainer(  XComponentContext xCtx, String locationURL,
53             String _extensionDb, String _extensionRepository, String language ) throws com.sun.star.lang.IllegalArgumentException, com.sun.star.lang.WrappedTargetException
54     {
55         super( xCtx, locationURL, language, false );
56         extensionDb = _extensionDb;
57         extensionRepository = _extensionRepository;
58         init();
59     }
60 
61     // gets the ParcelContainer for persisted uno packages
getRegisteredUnoPkgContainer( String url )62     public ParcelContainer getRegisteredUnoPkgContainer( String url )
63     {
64         if (!url.endsWith("/"))
65         {
66             url += "/";
67         }
68 
69         LogUtils.DEBUG("** getRegisterPackage ctx = " + containerUrl  );
70         LogUtils.DEBUG("** getRegisterPackage  for uri " + url );
71         LogUtils.DEBUG("** getRegisterPackage  for langugage " + language );
72         ParcelContainer result = (ParcelContainer)registeredPackages.get( url );
73         LogUtils.DEBUG("getRegisterPackage result is  " + result );
74         return result;
75     }
76 
hasRegisteredUnoPkgContainer( String url )77     public boolean hasRegisteredUnoPkgContainer( String url )
78     {
79         boolean result = false;
80         if ( getRegisteredUnoPkgContainer( url ) != null )
81         {
82             result = true;
83         }
84         return result;
85     }
86 
registerPackageContainer( String url, ParcelContainer c )87     private void registerPackageContainer( String url, ParcelContainer c )
88     {
89         if (!url.endsWith("/"))
90         {
91             url += "/";
92         }
93 
94         LogUtils.DEBUG("RegisterPackage ctx = " + containerUrl  );
95         LogUtils.DEBUG("RegisterPackage language = " + language  );
96         LogUtils.DEBUG("RegisterPackage " + c + " for url " + url );
97         registeredPackages.put( url, c );
98     }
99 
deRegisterPackageContainer( String url )100     public void deRegisterPackageContainer( String url )
101     {
102         if (!url.endsWith("/"))
103         {
104             url += "/";
105         }
106 
107         LogUtils.DEBUG("In deRegisterPackageContainer for " + url );
108         if ( hasRegisteredUnoPkgContainer( url ) )
109         {
110             try
111             {
112                 DeployedUnoPackagesDB db = getUnoPackagesDB();
113                 if ( db != null )
114                 {
115                     if ( db.removePackage( language, url ) )
116                     {
117                         writeUnoPackageDB( db );
118                         ParcelContainer container =
119                             ( ParcelContainer ) registeredPackages.get( url );
120                         if ( !container.hasElements() )
121                         {
122                            // When all libraries within a package bundle
123                            // ( for this language ) are removed also
124                            // remove the container from its parent
125                            // Otherwise, a container ( with no containees )
126                            // representing the uno package bundle will
127                            // still exist and so will get displayed
128                            if ( container.parent() != null )
129                            {
130                                container.parent().removeChildContainer( container );
131                            }
132                        }
133                        registeredPackages.remove( url );
134                    }
135                }
136            }
137            catch (Exception e)
138            {
139                //TODO revisit exception handling and exception here
140                //means something very wrong
141                LogUtils.DEBUG("***** deRegisterPackageContainer() got exception " + e );
142            }
143         }
144         LogUtils.DEBUG("Leaving deRegisterPackageContainer for " + url );
145     }
146 
init()147     private void init() throws com.sun.star.lang.IllegalArgumentException, com.sun.star.lang.WrappedTargetException
148     {
149         LogUtils.DEBUG("getting container for  " + containerUrl );
150         DeployedUnoPackagesDB db =  null;
151         try
152         {
153             db = getUnoPackagesDB();
154             if ( db != null )
155             {
156                 String[] packages = db.getDeployedPackages( language );
157 
158                 for ( int i=0; i<packages.length;i++)
159                 {
160                     try
161                     {
162                         processUnoPackage( packages[i], language );
163                     }
164                     catch ( com.sun.star.lang.IllegalArgumentException ila)
165                     {
166                         LogUtils.DEBUG("Failed to process " +  packages[i] + " for " + language);
167                         LogUtils.DEBUG("   Reason: " + ila );
168                     }
169                     catch( Exception e )
170                     {
171                         // TODO proper exception or do we wish
172                         // to ignore errors here
173                         LogUtils.DEBUG("Something very wrong!!!!!");
174                         LogUtils.DEBUG("Failed to process " +  packages[i] + " for " + language);
175                         LogUtils.DEBUG("   Reason: " + e );
176                     }
177                 }
178             }
179         }
180         catch ( com.sun.star.lang.WrappedTargetException e )
181         {
182             // no deployed packages
183            LogUtils.DEBUG("No deployed uno-packages for " + containerUrl );
184         }
185     }
186 
187 
findScript( ParsedScriptUri psu )188     public ScriptMetaData findScript( ParsedScriptUri psu ) throws com.sun.star.container.NoSuchElementException, com.sun.star.lang.WrappedTargetException
189 
190     {
191         ScriptMetaData scriptData = null;
192 
193         String language = psu.language;
194         String functionName = psu.function;
195         String parcelName = psu.parcel;
196         String location = psu.location;
197 
198         LogUtils.DEBUG("*** UnoPkgContainer.findScript() ***" +
199             "\ncontainerUrl = " + containerUrl +
200             "\nfunction = " + functionName +
201             "\nlocation = " + location +
202             "\nparcel = " + parcelName );
203 
204         ParcelContainer pc = getChildContainer( location );
205 
206         if (  pc  == null )
207         {
208             throw new com.sun.star.lang.WrappedTargetException( "Failed to resolve script " , null, new com.sun.star.lang.IllegalArgumentException( "Cannot resolve script location for script = " + functionName ) );
209         }
210 
211         scriptData = pc.findScript( psu );
212         return scriptData;
213 
214     }
215 
getUnoPackagesDB()216     private DeployedUnoPackagesDB getUnoPackagesDB() throws com.sun.star.lang.WrappedTargetException
217     {
218         InputStream is = null;
219         DeployedUnoPackagesDB dp = null;
220         try
221         {
222 //            String path = containerUrl.substring( 0, containerUrl.lastIndexOf("/") );
223             String packagesUrl = PathUtils.make_url( extensionDb, "/Scripts/" + extensionRepository + "-extension-desc.xml" );
224             LogUtils.DEBUG("getUnoPackagesDB() looking for existing db in " + packagesUrl );
225             if ( m_xSFA.exists( packagesUrl ) )
226             {
227                 if ( packagesUrl.startsWith( "vnd.sun.star.tdoc" ) )
228                 {
229                     // handles using XStorage directly
230                     throw new com.sun.star.lang.WrappedTargetException("Can't handle documents yet");
231                 }
232 
233                 is = new XInputStreamWrapper( m_xSFA.openFileRead( packagesUrl ) );
234                 dp = new DeployedUnoPackagesDB( is );
235                 try
236                 {
237                     is.close();
238                     is = null;
239                 }
240                 catch ( Exception ignore )
241                 {
242                 }
243             }
244             else
245             {
246                 LogUtils.DEBUG("getUnoPackagesDB() " + packagesUrl + " does not exist");
247             }
248         }
249         catch( Exception e )
250         {
251             LogUtils.DEBUG("getUnoPackagesDB() caught Exception: " + e  );
252             LogUtils.DEBUG( LogUtils.getTrace( e ) );
253             throw new com.sun.star.lang.WrappedTargetException( e.toString());
254         }
255         finally
256         {
257             if ( is != null )
258             {
259                 try
260                 {
261                     is.close();
262                     is = null;
263                 }
264                 catch ( Exception ignore )
265                 {
266                 }
267             }
268         }
269 
270         return dp;
271     }
272 
writeUnoPackageDB( DeployedUnoPackagesDB dp )273     private  void writeUnoPackageDB( DeployedUnoPackagesDB dp ) throws com.sun.star.lang.IllegalArgumentException,  com.sun.star.lang.WrappedTargetException
274     {
275         LogUtils.DEBUG("In writeUnoPackageDB() ");
276 
277         XOutputStream xos = null;
278         OutputStream os = null;
279         try
280         {
281 //            String path = containerUrl.substring( 0, containerUrl.lastIndexOf("/") );
282             String packagesUrl = PathUtils.make_url( extensionDb, "/Scripts/" + extensionRepository + "-extension-desc.xml" );
283             xos =  m_xSFA.openFileWrite( packagesUrl );
284             XTruncate xTrc = (XTruncate) UnoRuntime.queryInterface( XTruncate.class, xos );
285             if (  xTrc != null )
286             {
287                 LogUtils.DEBUG("In writeUnoPackageDB() Truncating...." );
288                 xTrc.truncate();
289             }
290             else
291             {
292                 LogUtils.DEBUG("In writeUnoPackageDB() CAN'T Truncate...." );
293             }
294             os = new XOutputStreamWrapper( xos );
295             dp.write( os );
296             try
297             {
298                 os.close(); // will close xos
299                 os = null;
300             }
301             catch( Exception ignore )
302             {
303             }
304         }
305         catch( Exception e )
306         {
307             LogUtils.DEBUG("In writeUnoPackageDB() Exception: " + e  );
308             throw new com.sun.star.lang.WrappedTargetException( e.toString());
309         }
310         finally
311         {
312             if ( os != null )
313             {
314                 try
315                 {
316                     os.close(); // will close xos
317                     os = null;
318                 }
319                 catch ( Exception ignore )
320                 {
321                 }
322             }
323         }
324     }
325 
processUnoPackage( XPackage dPackage, String language )326     public  void processUnoPackage( XPackage dPackage, String language ) throws com.sun.star.lang.IllegalArgumentException,  com.sun.star.lang.WrappedTargetException, com.sun.star.container.ElementExistException
327     {
328         LogUtils.DEBUG("** in processUnoPackage " );
329         String uri = null;
330         DeployedUnoPackagesDB db = null;
331         uri =  dPackage.getURL();
332 
333         if ( !uri.endsWith( "/" ) )
334         {
335             uri += "/";
336         }
337 
338         LogUtils.DEBUG("** processUnoPackage getURL() -> " + uri );
339         LogUtils.DEBUG("** processUnoPackage getName() -> " + dPackage.getName() );
340         LogUtils.DEBUG("** processUnoPackage getMediaType() -> " + dPackage.getPackageType().getMediaType() );
341         try
342         {
343             LogUtils.DEBUG("** processUnoPackage getDisplayName() -> " + dPackage.getDisplayName() );
344         }
345         catch (com.sun.star.deployment.ExtensionRemovedException e)
346         {
347             throw new com.sun.star.lang.WrappedTargetException(e.toString(), this, e);
348         }
349 
350         processUnoPackage( uri, language );
351 
352         db = getUnoPackagesDB();
353         if ( db == null )
354         {
355             try
356             {
357                 db = new DeployedUnoPackagesDB();
358             }
359             catch ( java.io.IOException ioe )
360             {
361                 throw new com.sun.star.lang.WrappedTargetException( ioe.toString());
362             }
363         }
364         db.addPackage( language, uri );
365         writeUnoPackageDB( db );
366     }
367 
processUnoPackage( String uri, String language )368     private  void processUnoPackage( String uri, String language ) throws com.sun.star.lang.IllegalArgumentException,  com.sun.star.lang.WrappedTargetException, com.sun.star.container.ElementExistException
369     {
370         if ( hasRegisteredUnoPkgContainer( uri ) )
371         {
372             throw new com.sun.star.container.ElementExistException( "Already a registered uno package " + uri + " for language " + language );
373         }
374         LogUtils.DEBUG("processUnoPackage - URL = " + uri );
375         LogUtils.DEBUG("processUnoPackage - script library package");
376         String parentUrl = uri;
377 
378         if ( uri.indexOf( "%2Funo_packages%2F" ) > -1 ||
379              uri.indexOf( "/uno_packages/" ) > -1 ||
380              uri.indexOf("$UNO_USER_PACKAGES_CACHE/") > -1 ||
381              uri.indexOf("$UNO_SHARED_PACKAGES_CACHE/") > -1 ||
382              uri.indexOf("$BUNDLED_EXTENSIONS/") > -1 )
383         {
384             //its in a bundle need to determine the uno-package file its in
385             LogUtils.DEBUG("processUnoPackage - is part of a uno bundle");
386 
387             int index = uri.lastIndexOf("/");
388             if ( uri.endsWith("/") )
389             {
390                 uri = uri.substring( 0, index );
391                 index = uri.lastIndexOf("/");
392             }
393 
394             if ( index > -1 )
395             {
396                 parentUrl = uri.substring( 0, index  );
397                 LogUtils.DEBUG("processUnoPackage - composition is contained in " + parentUrl);
398             }
399 
400             ParcelContainer pkgContainer = getChildContainerForURL( parentUrl );
401             if ( pkgContainer == null )
402             {
403                 pkgContainer = new ParcelContainer( this, m_xCtx, parentUrl, language, false );
404                 if ( pkgContainer.loadParcel( uri ) == null )
405                 {
406                     throw new com.sun.star.lang.IllegalArgumentException( "Couldn't load script library from composition package " + uri + " for language " + language );
407 
408                 }
409                 addChildContainer( pkgContainer );
410             }
411             else
412             {
413                 if ( pkgContainer.loadParcel( uri ) == null )
414                 {
415                     throw new com.sun.star.lang.IllegalArgumentException( "Couldn't load script library from composition package " + uri + " for language " + language );
416                 }
417 
418             }
419             registerPackageContainer( uri,  pkgContainer );
420         }
421         else
422         {
423             // stand-alone library package, e.g. not contained in
424             // an uno package
425             if ( loadParcel( uri ) == null )
426             {
427                 throw new com.sun.star.lang.IllegalArgumentException( "Couldn't load script library package " + uri + " for language " + language );
428             }
429             registerPackageContainer( uri, this );
430         }
431 
432     }
433 
434 }
435