blob: 9eb8614505604794966686935f24b7ae2a106f19 [file] [log] [blame]
/**************************************************************
*
* 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 java.net.*;
import java.io.*;
import java.util.*;
import java.util.zip.*;
import com.sun.star.uno.XComponentContext;
import com.sun.star.ucb.XSimpleFileAccess;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.io.XInputStream;
import com.sun.star.io.XOutputStream;
import com.sun.star.io.XTruncate;
import com.sun.star.script.framework.log.LogUtils;
import com.sun.star.script.framework.provider.PathUtils;
public class UCBStreamHandler extends URLStreamHandler {
public final static String separator = "/ucb/";
private XComponentContext m_xContext = null;
private XMultiComponentFactory m_xMultiComponentFactory = null;
private XSimpleFileAccess m_xSimpleFileAccess = null;
private HashMap m_jarStreamMap = new HashMap(12);
public static String m_ucbscheme;
public UCBStreamHandler( XComponentContext ctxt, String scheme, XSimpleFileAccess xSFA )
{
LogUtils.DEBUG( "UCBStreamHandler ctor, scheme = " + scheme );
this.m_xContext = ctxt;
this.m_ucbscheme = scheme;
this.m_xSimpleFileAccess = xSFA;
}
public void parseURL(URL url, String spec, int start, int limit) {
LogUtils.DEBUG("**XUCBStreamHandler, parseURL: " + url + " spec: " + spec + " start: " + start + " limit: " + limit );
String file = url.getFile();
if (file == null)
file = spec.substring(start, limit);
else
file += spec.substring(start, limit);
LogUtils.DEBUG("**For scheme = " + m_ucbscheme );
LogUtils.DEBUG("**Setting path = " + file );
setURL(url, m_ucbscheme, null, -1, null, null, file, null, null);
}
public URLConnection openConnection(URL u) throws IOException {
return new UCBConnection(u);
}
private class UCBConnection extends URLConnection {
public UCBConnection(URL url) {
super(url);
}
public void connect() {
}
public InputStream getInputStream() throws IOException {
LogUtils.DEBUG("UCBConnectionHandler GetInputStream on " + url );
String sUrl = url.toString();
if (sUrl.lastIndexOf(separator) == -1) {
LogUtils.DEBUG("getInputStream straight file load" );
return getFileStreamFromUCB(sUrl);
}
else {
String path = sUrl.substring(0, sUrl.lastIndexOf(separator) );
String file = sUrl.substring(
sUrl.lastIndexOf(separator) + separator.length());
LogUtils.DEBUG("getInputStream, load of file from another file eg. " + file + " from " + path );
return getUCBStream(file, path);
}
}
public OutputStream getOutputStream() throws IOException {
LogUtils.DEBUG("UCBConnectionHandler getOutputStream on " + url );
OutputStream os = null;
try
{
String sUrl = url.toString();
if ( !( sUrl.lastIndexOf(separator) == -1) ) {
String path = sUrl.substring(0, sUrl.lastIndexOf(separator));
String file = sUrl.substring(
sUrl.lastIndexOf(separator) + separator.length());
if ( m_xSimpleFileAccess.isReadOnly( path ) )
{
throw new java.io.IOException("File is read only");
}
LogUtils.DEBUG("getOutputStream, create o/p stream for file eg. " + path );
// we will only deal with simple file write
XOutputStream xos = m_xSimpleFileAccess.openFileWrite( path );
XTruncate xtrunc = ( XTruncate ) UnoRuntime.queryInterface( XTruncate.class, xos );
if ( xtrunc != null )
{
xtrunc.truncate();
}
os = new XOutputStreamWrapper( xos );
}
if ( os == null )
{
throw new IOException("Failed to get OutputStream for " + sUrl );
}
}
catch ( com.sun.star.ucb.CommandAbortedException cae )
{
LogUtils.DEBUG("caught exception: " + cae.toString() + " getting writable stream from " + url );
throw new IOException( cae.toString() );
}
catch ( com.sun.star.uno.Exception e )
{
LogUtils.DEBUG("caught unknown exception: " + e.toString() + " getting writable stream from " + url );
throw new IOException( e.toString() );
}
return os;
}
}
private InputStream getUCBStream(String file, String path)
throws IOException
{
InputStream is = null;
InputStream result = null;
try {
if (path.endsWith(".jar")) {
is = (InputStream)m_jarStreamMap.get(path);
if (is == null) {
is = getFileStreamFromUCB(path);
m_jarStreamMap.put(path, is);
}
else {
try {
is.reset();
}
catch (IOException e) {
is.close();
is = getFileStreamFromUCB(path);
m_jarStreamMap.put(path, is);
}
}
result = getFileStreamFromJarStream(file, is);
}
else
{
String fileUrl = PathUtils.make_url(path,file);
result = getFileStreamFromUCB(fileUrl);
}
}
finally {
if (is != null) {
try {
is.close();
}
catch (IOException ioe) {
LogUtils.DEBUG("Caught exception closing stream: " +
ioe.getMessage());
}
}
}
return result;
}
private InputStream getFileStreamFromJarStream(String file, InputStream is)
throws IOException
{
ZipInputStream zis = null;
ZipEntry entry = null;
boolean found = false;
zis = new ZipInputStream(is);
while (zis.available() != 0) {
entry = (ZipEntry)zis.getNextEntry();
if (entry.getName().equals(file)) {
return zis;
}
}
return null;
}
private InputStream getFileStreamFromUCB(String path)
throws IOException
{
InputStream result = null;
XInputStream xInputStream = null;
try {
LogUtils.DEBUG("Trying to read from " + path );
xInputStream = m_xSimpleFileAccess.openFileRead(path);
LogUtils.DEBUG("sfa appeared to read file " );
byte[][] inputBytes = new byte[1][];
int ln = 0;
int sz = m_xSimpleFileAccess.getSize(path);
// TODO don't depend on result of available() or size()
// just read stream 'till complete
if ( sz == 0 )
{
if ( xInputStream.available() > 0 )
{
sz = xInputStream.available();
}
}
LogUtils.DEBUG("size of file " + path + " is " + sz );
LogUtils.DEBUG("available = " + xInputStream.available() );
inputBytes[0] = new byte[sz];
ln = xInputStream.readBytes(inputBytes, sz);
if (ln != sz) {
throw new IOException(
"Failed to read " + sz + " bytes from XInputStream");
}
result = new ByteArrayInputStream(inputBytes[0]);
}
catch (com.sun.star.io.IOException ioe) {
LogUtils.DEBUG("caught exception " + ioe );
throw new IOException(ioe.getMessage());
}
catch (com.sun.star.uno.Exception e) {
LogUtils.DEBUG("caught exception " + e );
throw new IOException(e.getMessage());
}
finally
{
if (xInputStream != null) {
try {
xInputStream.closeInput();
}
catch (Exception e2) {
LogUtils.DEBUG(
"Error closing XInputStream:" + e2.getMessage());
}
}
}
return result;
}
private String convertClassNameToFileName(String name) {
return name.replace('.', File.separatorChar) + ".class";
}
}