package php.runtime.ext.core.classes.stream;
import php.runtime.Memory;
import php.runtime.env.Environment;
import php.runtime.memory.ArrayMemory;
import php.runtime.memory.BinaryMemory;
import php.runtime.memory.LongMemory;
import php.runtime.memory.StringMemory;
import php.runtime.reflection.ClassEntity;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Arrays;
import java.util.Enumeration;
import static php.runtime.annotation.Reflection.*;
@Name("php\\io\\ResourceStream")
public class ResourceStream extends Stream {
protected InputStream stream;
protected long position = 0;
protected boolean eof = false;
protected URL url;
public ResourceStream(Environment env, InputStream stream) {
super(env);
this.stream = stream;
}
public ResourceStream(Environment env, ClassEntity clazz) {
super(env, clazz);
}
public URL getUrl() {
return url;
}
public InputStream getInputStream() {
return this.stream;
}
@Override
@Signature({@Arg("path")})
public Memory __construct(Environment env, Memory... args) throws IOException {
super.__construct(env, args[0], StringMemory.valueOf("r"));
String path = this.getPath().replace('\\', '/').replace("//", "/");
if (path.startsWith("/")) {
path = path.substring(1);
}
setPath("res://" + path);
url = env.getScope().getClassLoader().getResource(path);
if (url == null) {
throw new IOException("Resource not found - " + getPath());
}
stream = url.openStream();
return Memory.NULL;
}
@Signature
public Memory toExternalForm(Environment env, Memory... args) {
return StringMemory.valueOf(url.toExternalForm());
}
@Override
@Signature
public Memory write(Environment env, Memory... args) throws IOException {
throw new IOException("Stream only for reading");
}
@Override
@Signature
public Memory read(Environment env, Memory... args) throws IOException {
int len = args[0].toInteger();
if (len <= 0)
return Memory.FALSE;
byte[] buff = new byte[len];
int read;
read = stream.read(buff, 0, len);
eof = read == -1;
if (read == -1)
return Memory.NULL;
position += read;
if (read != buff.length){
buff = Arrays.copyOf(buff, read);
}
return new BinaryMemory(buff);
}
@Override
@Signature
public Memory readFully(Environment env, Memory... args) throws IOException {
ByteArrayOutputStream tmp = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int read;
while ((read = stream.read(buf)) > 0) {
tmp.write(buf, 0, read);
position += read;
}
return new BinaryMemory(tmp.toByteArray());
}
@Override
@Signature
public Memory eof(Environment env, Memory... args) {
return eof ? Memory.TRUE : Memory.FALSE;
}
@Override
@Signature
public Memory seek(Environment env, Memory... args) throws IOException {
throw new IOException("Cannot seek");
}
@Override
@Signature
public Memory getPosition(Environment env, Memory... args) {
return LongMemory.valueOf(position);
}
@Override
@Signature
public Memory close(Environment env, Memory... args) throws IOException {
stream.close();
return Memory.NULL;
}
@Signature(@Arg("name"))
public static Memory exists(Environment env, Memory... args) throws IOException {
String name = args[0].toString();
if (name.startsWith("res:///")) {
name = name.substring(7);
} else if (name.startsWith("res://")) {
name = name.substring(6);
}
return env.getScope().getClassLoader().getResource(name) == null ? Memory.FALSE : Memory.TRUE;
}
@Signature(@Arg("name"))
public static Memory getResources(Environment env, Memory... args) throws IOException {
Enumeration<URL> list = env.getScope().getClassLoader().getResources(args[0].toString());
ArrayMemory r = new ArrayMemory();
while (list.hasMoreElements()) {
URL url = list.nextElement();
if (url != null) {
ResourceStream rs = new ResourceStream(env, url.openStream());
rs.setPath("res://" + args[0]);
r.add(rs);
}
}
return r.toConstant();
}
}