| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| package com.sun.star.script.framework.io; |
| |
| import com.sun.star.frame.XModel; |
| |
| import com.sun.star.container.XNameAccess; |
| |
| import com.sun.star.uno.XInterface; |
| import com.sun.star.uno.UnoRuntime; |
| |
| import com.sun.star.lang.XComponent; |
| |
| import com.sun.star.uno.AnyConverter; |
| |
| import com.sun.star.io.XStream; |
| import com.sun.star.io.XInputStream; |
| import com.sun.star.io.XOutputStream; |
| |
| import com.sun.star.embed.XStorage; |
| import com.sun.star.embed.XTransactedObject; |
| |
| import com.sun.star.document.XDocumentSubStorageSupplier; |
| |
| import com.sun.star.beans.XPropertySet; |
| |
| import com.sun.star.lang.XEventListener; |
| import com.sun.star.lang.EventObject; |
| |
| import com.sun.star.script.framework.log.LogUtils; |
| import com.sun.star.script.framework.provider.PathUtils; |
| |
| import java.util.*; |
| import java.io.*; |
| |
| |
| public class XStorageHelper implements XEventListener |
| { |
| XStorage[] xStorages; |
| XStream xStream; |
| XInputStream xIs = null; |
| XOutputStream xOs = null; |
| static Map modelMap = new HashMap(); |
| XModel xModel = null; |
| private static XStorageHelper listener = new XStorageHelper(); |
| |
| private XStorageHelper() {} |
| public XStorageHelper( String path, int mode, boolean create ) throws IOException |
| { |
| String modelUrl = null; |
| int indexOfScriptsDir = path.lastIndexOf( "Scripts" ); |
| if ( indexOfScriptsDir > -1 ) |
| { |
| modelUrl = path.substring( 0, indexOfScriptsDir - 1 ); |
| path = path.substring( indexOfScriptsDir, path.length()); |
| } |
| |
| LogUtils.DEBUG("XStorageHelper ctor, path: " + path); |
| this.xModel = getModelForURL( modelUrl ); |
| |
| try |
| { |
| StringTokenizer tokens = new StringTokenizer(path, "/"); |
| |
| if (tokens.countTokens() == 0) |
| { |
| throw new IOException("Invalid path"); |
| } |
| XDocumentSubStorageSupplier xDocumentSubStorageSupplier = |
| (XDocumentSubStorageSupplier) UnoRuntime.queryInterface( |
| XDocumentSubStorageSupplier.class, xModel); |
| xStorages = new XStorage[tokens.countTokens() ]; |
| LogUtils.DEBUG("XStorageHelper ctor, path chunks length: " + xStorages.length ); |
| |
| for ( int i = 0; i < xStorages.length; i++ ) |
| { |
| LogUtils.DEBUG("XStorageHelper, processing index " + i ); |
| String name = tokens.nextToken(); |
| LogUtils.DEBUG("XStorageHelper, getting: " + name); |
| XStorage storage = null; |
| if ( i == 0 ) |
| { |
| storage = xDocumentSubStorageSupplier.getDocumentSubStorage( name, mode ); |
| if ( storage == null ) |
| { |
| LogUtils.DEBUG("** boo hoo Storage is null " ); |
| } |
| XPropertySet xProps = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class,storage ); |
| if ( xProps != null ) |
| { |
| String mediaType = AnyConverter.toString( xProps.getPropertyValue( "MediaType" ) ); |
| LogUtils.DEBUG("***** media type is " + mediaType ); |
| if ( !mediaType.equals("scripts") ) |
| { |
| xProps.setPropertyValue("MediaType","scripts"); |
| } |
| } |
| } |
| else |
| { |
| XNameAccess xNameAccess = (XNameAccess) |
| UnoRuntime.queryInterface(XNameAccess.class, xStorages[i-1]); |
| if (xNameAccess == null ) |
| { |
| disposeObject(); |
| throw new IOException("No name access " + name); |
| } |
| else if ( !xNameAccess.hasByName(name) || !xStorages[i-1].isStorageElement(name) ) |
| { |
| if ( !create ) |
| { |
| disposeObject(); |
| throw new IOException("No subdir: " + name); |
| } |
| else |
| { |
| // attempt to create new storage |
| LogUtils.DEBUG("Attempt to create new storage for " + name ); |
| } |
| } |
| |
| storage = xStorages[i-1].openStorageElement( |
| name, mode ); |
| } |
| if ( storage == null ) |
| { |
| disposeObject(); |
| throw new IOException("storage not found: " + name); |
| } |
| xStorages[ i ] = storage; |
| |
| } |
| } |
| catch ( com.sun.star.io.IOException ioe) |
| { |
| disposeObject(); |
| } |
| catch (com.sun.star.uno.Exception e) |
| { |
| disposeObject(); |
| throw new IOException(e.getMessage()); |
| } |
| } |
| |
| public synchronized static void addNewModel( XModel model ) |
| { |
| // TODO needs to cater for model for untitled document |
| modelMap.put( PathUtils.getOidForModel( model ), model ); |
| XComponent xComp = (XComponent) |
| UnoRuntime.queryInterface(XComponent.class, model); |
| |
| if ( xComp != null ) |
| { |
| try |
| { |
| xComp.addEventListener( listener ); |
| } |
| catch ( Exception e ) |
| { |
| // What TODO here ? |
| LogUtils.DEBUG( LogUtils.getTrace( e ) ); |
| } |
| } |
| } |
| |
| public void disposing( EventObject Source ) |
| { |
| XModel model = (XModel) |
| UnoRuntime.queryInterface(XModel.class,Source.Source ); |
| |
| if ( model != null ) |
| { |
| LogUtils.DEBUG(" Disposing doc " + model.getURL() ); |
| Object result = modelMap.remove( model ); |
| result = null; |
| } |
| } |
| public XStorage getStorage() |
| { |
| return xStorages[ xStorages.length - 1 ]; |
| } |
| public XModel getModel() |
| { |
| return xModel; |
| } |
| public void disposeObject() |
| { |
| disposeObject( false ); |
| } |
| public void disposeObject( boolean shouldCommit ) |
| { |
| LogUtils.DEBUG("In disposeObject"); |
| |
| for ( int i = xStorages.length -1 ; i > -1; i-- ) |
| { |
| LogUtils.DEBUG("In disposeObject disposing storage " + i ); |
| try |
| { |
| XStorage xStorage = xStorages[i]; |
| if ( shouldCommit ) |
| { |
| commit(xStorage); |
| } |
| disposeObject(xStorage); |
| LogUtils.DEBUG("In disposeObject disposed storage " + i ); |
| } |
| catch( Exception ignore ) |
| { |
| LogUtils.DEBUG("Exception disposing storage " + i ); |
| } |
| |
| } |
| |
| } |
| static public void disposeObject( XInterface xInterface ) |
| { |
| if (xInterface == null) { |
| return; |
| } |
| |
| XComponent xComponent = (XComponent) |
| UnoRuntime.queryInterface(XComponent.class, xInterface); |
| |
| if (xComponent == null) { |
| return; |
| } |
| xComponent.dispose(); |
| } |
| static public void commit( XInterface xInterface ) |
| { |
| XTransactedObject xTrans = (XTransactedObject) |
| UnoRuntime.queryInterface(XTransactedObject.class, xInterface); |
| if ( xTrans != null ) |
| { |
| try |
| { |
| xTrans.commit(); |
| } |
| catch ( Exception e ) |
| { |
| LogUtils.DEBUG("Something went bellyup exception: " + e ); |
| } |
| } |
| } |
| |
| public XModel getModelForURL( String url ) |
| { |
| //TODO does not cater for untitled documents |
| return (XModel)modelMap.get( url ); |
| } |
| |
| } |
| |