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