package org.qrone.r7.github;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.arnx.jsonic.JSON;
import org.apache.commons.codec.binary.Base64;
import org.ho.yaml.Yaml;
import org.qrone.r7.fetcher.HTTPFetcher;
import org.qrone.r7.handler.URIHandler;
import org.qrone.r7.resolver.AbstractURIResolver;
import org.qrone.r7.resolver.URIResolver;
import org.qrone.util.QrONEUtils;
import org.qrone.util.Stream;
public class GitHubResolver extends AbstractURIResolver implements URIHandler {
private static final Logger log = Logger.getLogger(GitHubResolver.class.getName());
private HTTPFetcher fetcher;
private URIResolver cacheresolver;
private String user;
private String repo;
private String treesha;
private Map<String,String> blobs;
private Map<String,String> trees;
public GitHubResolver(HTTPFetcher fetcher, URIResolver cacheresolver, String user, String repo, String treesha){
this.fetcher = fetcher;
this.cacheresolver = cacheresolver;
this.user = QrONEUtils.escape(user);
this.repo = QrONEUtils.escape(repo);
this.treesha = QrONEUtils.escape(treesha);
}
public void clear(){
blobs = null;
}
private Map<String,String> getFiles(){
if(blobs == null){
try {
Map map = (Map)JSON.decode(fetcher.fetch("https://api.github.com/repos/"
+ user + "/" + repo + "/git/trees/" + treesha + "?recursive=1"));
List<Map> list = (List<Map>)map.get("tree");
blobs = new HashMap<String, String>();
trees = new HashMap<String, String>();
for (Map o : list) {
if(o.get("type").equals("blob")){
blobs.put(o.get("path").toString(), o.get("url").toString());
}else{
trees.put(o.get("path").toString(), o.get("url").toString());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
return blobs;
}
public boolean exist() {
return getFiles() != null;
}
@Override
public boolean exist(String path) {
getFiles();
if(cacheresolver.exist(path)) return true;
if(blobs != null)
return blobs.containsKey("htdocs" + path);
return false;
}
@Override
public boolean existPath(String path) {
getFiles();
if(trees != null)
return trees.containsKey("htdocs" + path);
return false;
}
@Override
public InputStream getInputStream(URI uri) throws IOException {
Map<String,String> map = getFiles();
String url = map.get("htdocs" + uri.toString());
InputStream in = cacheresolver.getInputStream(uri);
if(in != null) return in;
if(map != null){
if(url != null){
InputStream fin = fetcher.fetch(url);
Map m = JSON.decode(fin);
String encoding = m.get("encoding").toString();
byte[] bytes = null;
if(encoding.equals("base64")){
bytes = Base64.decodeBase64(m.get("content").toString());
}else{
bytes = m.get("content").toString().getBytes();
}
OutputStream out = cacheresolver.getOutputStream(uri);
out.write(bytes);
out.flush();
out.close();
return new ByteArrayInputStream(bytes);
}
}
return null;
}
@Override
public OutputStream getOutputStream(URI uri) throws IOException {
return null;
}
@Override
public boolean handle(HttpServletRequest request,
HttpServletResponse response, String uri, String path, String pathArg, List<String> arg) {
if(path.equals("/system/github-post-receive")){
try {
log.config("Github post-receive hooks.");
blobs = null;
Map map = (Map)JSON.decode(request.getParameter("payload"));
Map repository = (Map)map.get("repository");
if(repository.get("name").equals(repo)
&& ((Map)repository.get("owner")).get("name").equals(user)){
List<Map> list = (List)map.get("commits");
for (Map m : list) {
List<String> removed = (List)m.get("removed");
for (String p : removed) {
try {
log.config("removed: /" + p);
URI u = new URI("/" + p);
cacheresolver.remove(u);
fireUpdate(u);
} catch (URISyntaxException e) {}
}
List<String> modified = (List)m.get("modified");
for (String p : modified) {
try {
log.config("modified: /" + p);
URI u = new URI("/" + p);
cacheresolver.remove(u);
fireUpdate(u);
} catch (URISyntaxException e) {}
}
}
return true;
}
} catch (ClassCastException e) {
}
}
return false;
}
@Override
public boolean remove(URI uri) {
return false;
}
public void reset() {
blobs = null;
}
}