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 package com.sun.star.script.framework.io;
25 
26 import com.sun.star.frame.XModel;
27 
28 import com.sun.star.container.XNameAccess;
29 
30 import com.sun.star.uno.XInterface;
31 import com.sun.star.uno.UnoRuntime;
32 
33 import com.sun.star.lang.XComponent;
34 
35 import com.sun.star.uno.AnyConverter;
36 
37 import com.sun.star.io.XStream;
38 import com.sun.star.io.XInputStream;
39 import com.sun.star.io.XOutputStream;
40 
41 import com.sun.star.embed.XStorage;
42 import com.sun.star.embed.XTransactedObject;
43 
44 import com.sun.star.document.XDocumentSubStorageSupplier;
45 
46 import com.sun.star.beans.XPropertySet;
47 
48 import com.sun.star.lang.XEventListener;
49 import com.sun.star.lang.EventObject;
50 
51 import com.sun.star.script.framework.log.LogUtils;
52 import com.sun.star.script.framework.provider.PathUtils;
53 
54 import java.util.*;
55 import java.io.*;
56 
57 
58 public class XStorageHelper implements XEventListener
59 {
60     XStorage[] xStorages;
61     XStream xStream;
62     XInputStream xIs = null;
63     XOutputStream xOs = null;
64     static Map modelMap = new HashMap();
65     XModel xModel = null;
66     private static XStorageHelper listener = new XStorageHelper();
67 
XStorageHelper()68     private XStorageHelper() {}
XStorageHelper( String path, int mode, boolean create )69     public XStorageHelper(  String path, int mode, boolean create ) throws IOException
70     {
71         String modelUrl = null;
72         int indexOfScriptsDir = path.lastIndexOf( "Scripts" );
73         if ( indexOfScriptsDir > -1 )
74         {
75             modelUrl = path.substring( 0, indexOfScriptsDir - 1 );
76             path = path.substring( indexOfScriptsDir, path.length());
77         }
78 
79         LogUtils.DEBUG("XStorageHelper ctor, path: " + path);
80         this.xModel =  getModelForURL( modelUrl );
81 
82         try
83         {
84             StringTokenizer tokens = new StringTokenizer(path, "/");
85 
86             if (tokens.countTokens() == 0)
87             {
88                throw new IOException("Invalid path");
89             }
90             XDocumentSubStorageSupplier xDocumentSubStorageSupplier =
91                 (XDocumentSubStorageSupplier) UnoRuntime.queryInterface(
92                     XDocumentSubStorageSupplier.class, xModel);
93             xStorages =  new XStorage[tokens.countTokens()  ];
94             LogUtils.DEBUG("XStorageHelper ctor, path chunks length: " + xStorages.length );
95 
96             for ( int i = 0; i < xStorages.length; i++ )
97             {
98                 LogUtils.DEBUG("XStorageHelper, processing index " + i );
99                 String name = tokens.nextToken();
100                 LogUtils.DEBUG("XStorageHelper, getting: " + name);
101                 XStorage storage = null;
102                 if ( i == 0 )
103                 {
104                     storage  = xDocumentSubStorageSupplier.getDocumentSubStorage( name, mode );
105                     if ( storage == null )
106                     {
107                         LogUtils.DEBUG("** boo hoo Storage is null " );
108                     }
109                     XPropertySet xProps = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class,storage );
110                     if ( xProps != null )
111                     {
112                         String mediaType = AnyConverter.toString( xProps.getPropertyValue( "MediaType" ) );
113                         LogUtils.DEBUG("***** media type is " + mediaType );
114                         if ( !mediaType.equals("scripts") )
115                         {
116                             xProps.setPropertyValue("MediaType","scripts");
117                         }
118                     }
119                 }
120                 else
121                 {
122                     XNameAccess xNameAccess = (XNameAccess)
123                     UnoRuntime.queryInterface(XNameAccess.class, xStorages[i-1]);
124                     if (xNameAccess == null )
125                     {
126                         disposeObject();
127                         throw new IOException("No name access " + name);
128                     }
129                     else if ( !xNameAccess.hasByName(name) || !xStorages[i-1].isStorageElement(name) )
130                     {
131                         if ( !create )
132                         {
133                             disposeObject();
134                             throw new IOException("No subdir: " + name);
135                         }
136                         else
137                         {
138                             // attempt to create new storage
139                             LogUtils.DEBUG("Attempt to create new storage for " + name );
140                         }
141                     }
142 
143                     storage = xStorages[i-1].openStorageElement(
144                         name, mode );
145                 }
146                 if ( storage == null )
147                 {
148                     disposeObject();
149                     throw new IOException("storage not found: " + name);
150                 }
151                 xStorages[ i ] = storage;
152 
153             }
154         }
155         catch ( com.sun.star.io.IOException ioe)
156         {
157             disposeObject();
158         }
159         catch (com.sun.star.uno.Exception e)
160         {
161             disposeObject();
162             throw new IOException(e.getMessage());
163         }
164     }
165 
addNewModel( XModel model )166     public synchronized static void addNewModel( XModel model )
167     {
168         // TODO needs to cater for model for untitled document
169         modelMap.put( PathUtils.getOidForModel( model ), model );
170         XComponent xComp = (XComponent)
171              UnoRuntime.queryInterface(XComponent.class, model);
172 
173         if ( xComp != null )
174         {
175             try
176             {
177                 xComp.addEventListener( listener );
178             }
179             catch ( Exception e )
180             {
181                 // What TODO here ?
182                 LogUtils.DEBUG( LogUtils.getTrace( e ) );
183             }
184         }
185     }
186 
disposing( EventObject Source )187     public void disposing( EventObject Source )
188     {
189         XModel model = (XModel)
190             UnoRuntime.queryInterface(XModel.class,Source.Source );
191 
192         if ( model != null )
193         {
194             LogUtils.DEBUG(" Disposing doc " + model.getURL() );
195             Object result = modelMap.remove( model );
196             result = null;
197         }
198     }
getStorage()199     public XStorage getStorage()
200     {
201         return xStorages[ xStorages.length - 1 ];
202     }
getModel()203     public XModel getModel()
204     {
205         return xModel;
206     }
disposeObject()207     public void disposeObject()
208     {
209         disposeObject( false );
210     }
disposeObject( boolean shouldCommit )211     public void disposeObject( boolean shouldCommit )
212     {
213         LogUtils.DEBUG("In disposeObject");
214 
215         for ( int i = xStorages.length -1 ; i > -1; i-- )
216         {
217             LogUtils.DEBUG("In disposeObject disposing storage " + i );
218             try
219             {
220                 XStorage xStorage = xStorages[i];
221                 if ( shouldCommit )
222                 {
223                     commit(xStorage);
224                 }
225                 disposeObject(xStorage);
226                 LogUtils.DEBUG("In disposeObject disposed storage " + i );
227             }
228             catch( Exception ignore )
229             {
230                 LogUtils.DEBUG("Exception disposing storage " + i );
231             }
232 
233         }
234 
235     }
disposeObject( XInterface xInterface )236     static public void disposeObject( XInterface xInterface )
237     {
238         if (xInterface == null) {
239             return;
240         }
241 
242         XComponent xComponent = (XComponent)
243         UnoRuntime.queryInterface(XComponent.class, xInterface);
244 
245         if (xComponent == null) {
246             return;
247         }
248         xComponent.dispose();
249     }
commit( XInterface xInterface )250     static public void commit( XInterface xInterface )
251     {
252         XTransactedObject xTrans = (XTransactedObject)
253         UnoRuntime.queryInterface(XTransactedObject.class, xInterface);
254         if ( xTrans != null )
255         {
256             try
257             {
258                 xTrans.commit();
259             }
260             catch ( Exception e )
261             {
262                 LogUtils.DEBUG("Something went bellyup exception: " + e );
263             }
264         }
265     }
266 
getModelForURL( String url )267     public XModel getModelForURL( String url )
268     {
269        //TODO does not cater for untitled documents
270        return (XModel)modelMap.get( url );
271     }
272 
273 }
274 
275