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 java.net.*; 27 import java.io.*; 28 import java.util.*; 29 import java.util.zip.*; 30 31 import com.sun.star.uno.XComponentContext; 32 import com.sun.star.ucb.XSimpleFileAccess; 33 import com.sun.star.uno.UnoRuntime; 34 import com.sun.star.lang.XMultiComponentFactory; 35 import com.sun.star.io.XInputStream; 36 import com.sun.star.io.XOutputStream; 37 import com.sun.star.io.XTruncate; 38 39 import com.sun.star.script.framework.log.LogUtils; 40 import com.sun.star.script.framework.provider.PathUtils; 41 42 public class UCBStreamHandler extends URLStreamHandler { 43 44 public final static String separator = "/ucb/"; 45 46 private XComponentContext m_xContext = null; 47 private XMultiComponentFactory m_xMultiComponentFactory = null; 48 private XSimpleFileAccess m_xSimpleFileAccess = null; 49 private HashMap m_jarStreamMap = new HashMap(12); 50 public static String m_ucbscheme; 51 UCBStreamHandler( XComponentContext ctxt, String scheme, XSimpleFileAccess xSFA )52 public UCBStreamHandler( XComponentContext ctxt, String scheme, XSimpleFileAccess xSFA ) 53 { 54 LogUtils.DEBUG( "UCBStreamHandler ctor, scheme = " + scheme ); 55 this.m_xContext = ctxt; 56 this.m_ucbscheme = scheme; 57 this.m_xSimpleFileAccess = xSFA; 58 } 59 parseURL(URL url, String spec, int start, int limit)60 public void parseURL(URL url, String spec, int start, int limit) { 61 LogUtils.DEBUG("**XUCBStreamHandler, parseURL: " + url + " spec: " + spec + " start: " + start + " limit: " + limit ); 62 63 String file = url.getFile(); 64 if (file == null) 65 file = spec.substring(start, limit); 66 else 67 file += spec.substring(start, limit); 68 69 LogUtils.DEBUG("**For scheme = " + m_ucbscheme ); 70 LogUtils.DEBUG("**Setting path = " + file ); 71 setURL(url, m_ucbscheme, null, -1, null, null, file, null, null); 72 } 73 openConnection(URL u)74 public URLConnection openConnection(URL u) throws IOException { 75 return new UCBConnection(u); 76 } 77 78 private class UCBConnection extends URLConnection { 79 UCBConnection(URL url)80 public UCBConnection(URL url) { 81 super(url); 82 } 83 connect()84 public void connect() { 85 } 86 getInputStream()87 public InputStream getInputStream() throws IOException { 88 LogUtils.DEBUG("UCBConnectionHandler GetInputStream on " + url ); 89 String sUrl = url.toString(); 90 if (sUrl.lastIndexOf(separator) == -1) { 91 LogUtils.DEBUG("getInputStream straight file load" ); 92 return getFileStreamFromUCB(sUrl); 93 } 94 else { 95 String path = sUrl.substring(0, sUrl.lastIndexOf(separator) ); 96 String file = sUrl.substring( 97 sUrl.lastIndexOf(separator) + separator.length()); 98 LogUtils.DEBUG("getInputStream, load of file from another file eg. " + file + " from " + path ); 99 return getUCBStream(file, path); 100 } 101 } getOutputStream()102 public OutputStream getOutputStream() throws IOException { 103 LogUtils.DEBUG("UCBConnectionHandler getOutputStream on " + url ); 104 OutputStream os = null; 105 try 106 { 107 String sUrl = url.toString(); 108 if ( !( sUrl.lastIndexOf(separator) == -1) ) { 109 String path = sUrl.substring(0, sUrl.lastIndexOf(separator)); 110 String file = sUrl.substring( 111 sUrl.lastIndexOf(separator) + separator.length()); 112 113 if ( m_xSimpleFileAccess.isReadOnly( path ) ) 114 { 115 throw new java.io.IOException("File is read only"); 116 } 117 118 LogUtils.DEBUG("getOutputStream, create o/p stream for file eg. " + path ); 119 120 // we will only deal with simple file write 121 XOutputStream xos = m_xSimpleFileAccess.openFileWrite( path ); 122 XTruncate xtrunc = ( XTruncate ) UnoRuntime.queryInterface( XTruncate.class, xos ); 123 if ( xtrunc != null ) 124 { 125 xtrunc.truncate(); 126 } 127 os = new XOutputStreamWrapper( xos ); 128 } 129 if ( os == null ) 130 { 131 throw new IOException("Failed to get OutputStream for " + sUrl ); 132 } 133 } 134 catch ( com.sun.star.ucb.CommandAbortedException cae ) 135 { 136 LogUtils.DEBUG("caught exception: " + cae.toString() + " getting writable stream from " + url ); 137 throw new IOException( cae.toString() ); 138 } 139 catch ( com.sun.star.uno.Exception e ) 140 { 141 LogUtils.DEBUG("caught unknown exception: " + e.toString() + " getting writable stream from " + url ); 142 throw new IOException( e.toString() ); 143 } 144 return os; 145 } 146 } 147 148 getUCBStream(String file, String path)149 private InputStream getUCBStream(String file, String path) 150 throws IOException 151 { 152 InputStream is = null; 153 InputStream result = null; 154 155 try { 156 if (path.endsWith(".jar")) { 157 is = (InputStream)m_jarStreamMap.get(path); 158 159 if (is == null) { 160 is = getFileStreamFromUCB(path); 161 m_jarStreamMap.put(path, is); 162 } 163 else { 164 try { 165 is.reset(); 166 } 167 catch (IOException e) { 168 is.close(); 169 is = getFileStreamFromUCB(path); 170 m_jarStreamMap.put(path, is); 171 } 172 } 173 result = getFileStreamFromJarStream(file, is); 174 } 175 else 176 { 177 String fileUrl = PathUtils.make_url(path,file); 178 result = getFileStreamFromUCB(fileUrl); 179 } 180 } 181 finally { 182 if (is != null) { 183 try { 184 is.close(); 185 } 186 catch (IOException ioe) { 187 LogUtils.DEBUG("Caught exception closing stream: " + 188 ioe.getMessage()); 189 } 190 } 191 } 192 return result; 193 } 194 getFileStreamFromJarStream(String file, InputStream is)195 private InputStream getFileStreamFromJarStream(String file, InputStream is) 196 throws IOException 197 { 198 ZipInputStream zis = null; 199 ZipEntry entry = null; 200 boolean found = false; 201 202 zis = new ZipInputStream(is); 203 204 while (zis.available() != 0) { 205 entry = (ZipEntry)zis.getNextEntry(); 206 207 if (entry.getName().equals(file)) { 208 return zis; 209 } 210 } 211 return null; 212 } 213 getFileStreamFromUCB(String path)214 private InputStream getFileStreamFromUCB(String path) 215 throws IOException 216 { 217 InputStream result = null; 218 XInputStream xInputStream = null; 219 220 try { 221 LogUtils.DEBUG("Trying to read from " + path ); 222 xInputStream = m_xSimpleFileAccess.openFileRead(path); 223 LogUtils.DEBUG("sfa appeared to read file " ); 224 byte[][] inputBytes = new byte[1][]; 225 226 int ln = 0; 227 int sz = m_xSimpleFileAccess.getSize(path); 228 // TODO don't depend on result of available() or size() 229 // just read stream 'till complete 230 if ( sz == 0 ) 231 { 232 if ( xInputStream.available() > 0 ) 233 { 234 sz = xInputStream.available(); 235 } 236 } 237 LogUtils.DEBUG("size of file " + path + " is " + sz ); 238 LogUtils.DEBUG("available = " + xInputStream.available() ); 239 inputBytes[0] = new byte[sz]; 240 241 ln = xInputStream.readBytes(inputBytes, sz); 242 243 if (ln != sz) { 244 throw new IOException( 245 "Failed to read " + sz + " bytes from XInputStream"); 246 } 247 248 result = new ByteArrayInputStream(inputBytes[0]); 249 } 250 catch (com.sun.star.io.IOException ioe) { 251 LogUtils.DEBUG("caught exception " + ioe ); 252 throw new IOException(ioe.getMessage()); 253 } 254 catch (com.sun.star.uno.Exception e) { 255 LogUtils.DEBUG("caught exception " + e ); 256 throw new IOException(e.getMessage()); 257 } 258 finally 259 { 260 if (xInputStream != null) { 261 try { 262 xInputStream.closeInput(); 263 } 264 catch (Exception e2) { 265 LogUtils.DEBUG( 266 "Error closing XInputStream:" + e2.getMessage()); 267 } 268 } 269 } 270 return result; 271 } 272 convertClassNameToFileName(String name)273 private String convertClassNameToFileName(String name) { 274 return name.replace('.', File.separatorChar) + ".class"; 275 } 276 277 } 278