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