1 /*
2  * URLStream.java
3  *
4  * Copyright (C) 2010 Mark Evenson
5  * $Id$
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20  *
21  * As a special exception, the copyright holders of this library give you
22  * permission to link this library with independent modules to produce an
23  * executable, regardless of the license terms of these independent
24  * modules, and to copy and distribute the resulting executable under
25  * terms of your choice, provided that you also meet, for each linked
26  * independent module, the terms and conditions of the license of that
27  * module.  An independent module is a module which is not derived from
28  * or based on this library.  If you modify this library, you may extend
29  * this exception to your version of the library, but you are not
30  * obligated to do so.  If you do not wish to do so, delete this
31  * exception statement from your version.
32  */
33 
34 package org.armedbear.lisp;
35 
36 import static org.armedbear.lisp.Lisp.*;
37 
38 import java.io.File;
39 import java.io.InputStream;
40 import java.io.Reader;
41 import java.io.FileNotFoundException;
42 import java.io.IOException;
43 import java.io.InputStreamReader;
44 import java.io.BufferedReader;
45 
46 /**
47  * Stream interface for a URL.
48  *
49  * Currently only supports reading from the stream.
50  */
51 public final class URLStream extends Stream
52 {
53     private final Pathname pathname;
54     private final InputStream input;
55     private final Reader reader;
56     private final int bytesPerUnit;
57 
URLStream(Pathname pathname, LispObject elementType, LispObject direction, LispObject ifExists, LispObject format)58     public URLStream(Pathname pathname,
59                      LispObject elementType, LispObject direction,
60                      LispObject ifExists, LispObject format)
61         throws IOException
62     {
63         super(Symbol.URL_STREAM);
64         Debug.assertTrue(direction == Keyword.INPUT);
65         isInputStream = true;
66 
67         super.setExternalFormat(format);
68 
69         this.pathname = pathname;
70         this.elementType = elementType;
71 
72         this.input = pathname.getInputStream();
73         if (elementType == Symbol.CHARACTER || elementType == Symbol.BASE_CHAR) {
74             isCharacterStream = true;
75             bytesPerUnit = 1;
76             InputStreamReader isr = new InputStreamReader(input);
77             this.reader = (Reader) new BufferedReader(isr);
78             initAsCharacterInputStream(this.reader);
79         } else {
80             isBinaryStream = true;
81             int width = Fixnum.getValue(elementType.cadr());
82             bytesPerUnit = width / 8;
83             this.reader = null;
84             initAsBinaryInputStream(this.input);
85         }
86     }
87 
88     @Override
typeOf()89     public LispObject typeOf()
90     {
91         return Symbol.URL_STREAM;
92     }
93 
94     @Override
classOf()95     public LispObject classOf()
96     {
97         return BuiltInClass.URL_STREAM;
98     }
99 
100     @Override
typep(LispObject typeSpecifier)101     public LispObject typep(LispObject typeSpecifier)
102     {
103         if (typeSpecifier == Symbol.URL_STREAM)
104             return T;
105         if (typeSpecifier == BuiltInClass.URL_STREAM)
106             return T;
107         return super.typep(typeSpecifier);
108     }
109 
110     @Override
setExternalFormat(LispObject format)111     public void setExternalFormat(LispObject format) {
112         super.setExternalFormat(format);
113     }
114 
getPathname()115     public Pathname getPathname()
116     {
117         return pathname;
118     }
119 
120     // unused 20200418 ME
getReader()121     public Reader getReader()
122     {
123         return reader;
124     }
125 
126     /**
127      * Accessing the underlying java.io.InputStream can be helpful
128      * when utlizing Java-side frameworks like Apache Jena built on
129      * the java.io abstractions.  State should only be mutated if you
130      * know what you are doing.
131      *
132      * c.f. <https://gitlab.common-lisp.net/mevenson/jeannie/>
133      **/
getInputStream()134     public InputStream getInputStream()
135     {
136         return input;
137     }
138 
139     // unused 20200418 ME
getBytesPerUnit()140     public int getBytesPerUnit() {
141         return bytesPerUnit;
142     }
143     @Override
_close()144     public void _close()
145     {
146         try {
147             if (input != null) {
148                 input.close();
149             }
150             if (reader != null) {
151                 reader.close();
152             }
153             setOpen(false);
154         }
155         catch (IOException e) {
156             error(new StreamError(this, e));
157         }
158     }
159 
160     @Override
printObject()161     public String printObject()
162     {
163         StringBuffer sb = new StringBuffer();
164         sb.append(Symbol.URL_STREAM.printObject());
165         String namestring = pathname.getNamestring();
166         if (namestring != null) {
167             sb.append(" ");
168             sb.append(namestring);
169         }
170         return unreadableString(sb.toString());
171     }
172 }
173