1 /*
2  * This file is part of the LibreOffice project.
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  *
8  * This file incorporates work covered by the following license notice:
9  *
10  *   Licensed to the Apache Software Foundation (ASF) under one or more
11  *   contributor license agreements. See the NOTICE file distributed
12  *   with this work for additional information regarding copyright
13  *   ownership. The ASF licenses this file to you under the Apache
14  *   License, Version 2.0 (the "License"); you may not use this file
15  *   except in compliance with the License. You may obtain a copy of
16  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
17  */
18 package com.sun.star.lib.uno.adapter;
19 
20 import java.io.IOException;
21 
22 import com.sun.star.io.XInputStream;
23 
24 import java.io.InputStream;
25 
26 /**
27  * The <code>XInputStreamToInputStreamAdapter</code> wraps
28  * the UNO <code>XInputStream</code> object in a Java
29  * <code>InputStream</code>.  This allows users to access
30  * an <code>XInputStream</code> as if it were an
31  * <code>InputStream</code>.
32  */
33 public final class XInputStreamToInputStreamAdapter extends InputStream {
34 
35     /**
36      *  Internal handle to the XInputStream
37      */
38     private final XInputStream xin;
39 
40     /**
41      *  Constructor.
42      *
43      *  @param  in  The <code>XInputStream</code> to be
44      *              accessed as an <code>InputStream</code>.
45      */
XInputStreamToInputStreamAdapter(XInputStream in)46     public XInputStreamToInputStreamAdapter (XInputStream in) {
47         xin = in;
48     }
49 
50     @Override
available()51     public int available() throws IOException {
52 
53         int bytesAvail;
54 
55         try {
56             bytesAvail = xin.available();
57         } catch (Exception e) {
58             IOException newEx = new IOException(e.getMessage());
59             newEx.initCause(e);
60             throw newEx;
61         }
62 
63         return bytesAvail;
64     }
65 
66     @Override
close()67     public void close() throws IOException {
68         try {
69             xin.closeInput();
70         } catch (Exception e) {
71             IOException newEx = new IOException(e.getMessage());
72             newEx.initCause(e);
73             throw newEx;
74         }
75     }
76 
77     @Override
read()78     public int read () throws IOException {
79         byte [][] tmp = new byte [1][1];
80         try {
81             long bytesRead = xin.readBytes(tmp, 1);
82 
83             if (bytesRead <= 0) {
84                return (-1);
85             } else {
86                 int tmpInt = tmp[0][0];
87                 if (tmpInt< 0 ){
88                     tmpInt = 256 +tmpInt;
89                 }
90                 return tmpInt;
91             }
92 
93         } catch (Exception e) {
94             IOException newEx = new IOException(e.getMessage());
95             newEx.initCause(e);
96             throw newEx;
97         }
98     }
99 
100     @Override
read(byte[] b)101     public int read (byte[] b) throws IOException {
102 
103         byte [][] tmp = new byte [1][b.length];
104         int bytesRead;
105 
106         try {
107             bytesRead = xin.readBytes(tmp, b.length);
108             if (bytesRead <= 0) {
109                 return -1;
110             } else if (bytesRead < b.length) {
111                 System.arraycopy(tmp[0], 0, b, 0, bytesRead);
112             } else {
113                 System.arraycopy(tmp[0], 0, b, 0, b.length);
114             }
115         } catch (Exception e) {
116             IOException newEx = new IOException(e.getMessage());
117             newEx.initCause(e);
118             throw newEx;
119         }
120 
121         return bytesRead;
122     }
123 
124     @Override
read(byte[] b, int off, int len)125     public int read(byte[] b, int off, int len) throws IOException {
126         byte [][] tmp = new byte [1][b.length];
127         try {
128             long bytesRead;
129             int av = xin.available();
130             if ( av != 0 && len > av) {
131                 bytesRead = xin.readBytes(tmp, av);
132             }
133             else{
134                 bytesRead = xin.readBytes(tmp,len);
135             }
136             // Casting bytesRead to an int is okay, since the user can
137             // only pass in an integer length to read, so the bytesRead
138             // must <= len.
139 
140             if (bytesRead <= 0) {
141                 return -1;
142             } else if (bytesRead < len) {
143                 System.arraycopy(tmp[0], 0, b, off, (int)bytesRead);
144             } else {
145                 System.arraycopy(tmp[0], 0, b, off, len);
146             }
147 
148             return ((int)bytesRead);
149         } catch (Exception e) {
150             IOException newEx = new IOException(e.getMessage());
151             newEx.initCause(e);
152             throw newEx;
153         }
154     }
155 
156     @Override
skip(long n)157     public long skip(long n) throws IOException {
158 
159         int avail;
160         long tmpLongVal = n;
161         int  tmpIntVal;
162 
163         try {
164             avail = xin.available();
165         } catch (Exception e) {
166             IOException newEx = new IOException(e.getMessage());
167             newEx.initCause(e);
168             throw newEx;
169         }
170 
171         do {
172             if (tmpLongVal >= Integer.MAX_VALUE) {
173                tmpIntVal = Integer.MAX_VALUE;
174             } else {
175                // Casting is safe here.
176                tmpIntVal = (int)tmpLongVal;
177             }
178             tmpLongVal -= tmpIntVal;
179 
180             try {
181                 xin.skipBytes(tmpIntVal);
182             } catch (Exception e) {
183                 IOException newEx = new IOException(e.getMessage());
184                 newEx.initCause(e);
185                 throw newEx;
186             }
187         } while (tmpLongVal > 0);
188 
189         if ( avail != 0 && avail < n) {
190             return avail;
191         } else {
192             return n;
193         }
194     }
195 
196    /**
197     *  Tests if this input stream supports the mark and reset methods.
198     *  The markSupported method of
199     *  <code>XInputStreamToInputStreamAdapter</code> returns false.
200     *
201     *  @return  false
202     */
203     @Override
markSupported()204     public boolean markSupported() {
205        return false;
206     }
207 
208     @Override
mark(int readlimit)209     public synchronized void mark(int readlimit) {
210         // Not supported.
211     }
212 
213     @Override
reset()214     public synchronized void reset() throws IOException {
215         // Not supported.
216     }
217 }
218 
219