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