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