package com.lastcalc.parsers.meta;
import java.io.*;
import java.net.*;
import java.util.Collection;
import com.lastcalc.*;
import com.lastcalc.Tokenizer.QuotedString;
import com.lastcalc.cache.ObjectCache;
import com.lastcalc.parsers.*;
public class ImportParser extends Parser {
private static TokenList template = TokenList.createD("import", QuotedString.class);
@Override
public TokenList getTemplate() {
return template;
}
@Override
public ParseResult parse(final TokenList tokens, final int templatePos, final ParserContext context) {
if (context.importDepth > 5)
return ParseResult.fail();
URL url;
try {
url = new URL(((QuotedString) tokens.get(templatePos + 1)).value);
} catch (final MalformedURLException e) {
return ParseResult.fail();
}
CachedImport cached = ObjectCache.getSlow(1000l * 60l * 60l * 24l, url);
if (cached == null ||
(System.currentTimeMillis() > cached.expires && System.currentTimeMillis() - cached.currentAt > 60l*1000l)) {
// More than a minute ago and after expires time, let's check to see
// whether the original URL is updated
try {
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Accept", "text/plain");
if (cached != null && cached.lastModifiedHeader != null) {
connection.setRequestProperty("If-Modified-Since", cached.lastModifiedHeader);
}
if (cached != null && cached.eTag != null) {
connection.setRequestProperty("If-None-Match", cached.eTag);
}
final int code = connection.getResponseCode();
if (code == 304) {
// It was cached, update
cached.currentAt = System.currentTimeMillis();
ObjectCache.put(1000l * 60l * 60l * 24l, cached, url);
} else {
final String contentType = connection.getContentType();
if (contentType.toLowerCase().contains("text/plain")) {
cached = new CachedImport();
final BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
final ParserContext pc = new ParserContext(context.parseEngine, context.timeout, context.importDepth + 1);
final SequentialParser sp = SequentialParser.create(pc);
while (true) {
final String nextLine = br.readLine();
if (nextLine == null) {
break;
}
sp.parseNext(nextLine);
}
cached = new CachedImport();
cached.userDefinedParsers = sp.getUserDefinedParsers().getParsers();
cached.currentAt = System.currentTimeMillis();
cached.lastModifiedHeader = connection.getHeaderField("Last-Modified");
cached.eTag = connection.getHeaderField("ETag");
cached.expires = connection.getHeaderFieldDate("Expires", 0);
ObjectCache.put(1000l * 60l * 60l * 24l, cached, url);
} else
return ParseResult.fail();
}
} catch (final IOException e) {
return ParseResult.fail();
}
}
return ParseResult.success(tokens.replaceWithTokens(templatePos, template.size(), cached.userDefinedParsers));
}
@Override
public int hashCode() {
// TODO Auto-generated method stub
return 0;
}
@Override
public boolean equals(final Object obj) {
// TODO Auto-generated method stub
return false;
}
public static class CachedImport implements Serializable {
private static final long serialVersionUID = -3304707639237443710L;
public long currentAt, expires;
public String eTag;
public String lastModifiedHeader;
public Collection<Parser> userDefinedParsers;
}
}