StringTokenizer pathTokens = new StringTokenizer(path,"/");
while(pathTokens.hasMoreTokens()) {
String pathElement = pathTokens.nextToken();
// Treat * and ? as wildcard unless they match a literal filename
if((pathElement.contains("?") || pathElement.contains("*"))
&& inBase && !(new FilePath(root, (_base.length() > 0 ? _base + "/" : "") + pathElement).exists()))
inBase = false;
if(pathElement.equals("*zip*")) {
// the expected syntax is foo/bar/*zip*/bar.zip
// the last 'bar.zip' portion is to causes browses to set a good default file name.
// so the 'rest' portion ends here.
zip=true;
break;
}
if(pathElement.equals("*plain*")) {
plain = true;
break;
}
StringBuilder sb = inBase?_base:_rest;
if(sb.length()>0) sb.append('/');
sb.append(pathElement);
if(!inBase)
restSize++;
}
}
restSize = Math.max(restSize,0);
String base = _base.toString();
String rest = _rest.toString();
// this is the base file/directory
FilePath baseFile = new FilePath(root,base);
if(baseFile.isDirectory()) {
if(zip) {
rsp.setContentType("application/zip");
baseFile.zip(rsp.getOutputStream(),rest);
return;
}
if (plain) {
rsp.setContentType("text/plain;charset=UTF-8");
OutputStream os = rsp.getOutputStream();
try {
for (String kid : baseFile.act(new SimpleChildList())) {
os.write(kid.getBytes("UTF-8"));
os.write('\n');
}
os.flush();
} finally {
os.close();
}
return;
}
if(rest.length()==0) {
// if the target page to be displayed is a directory and the path doesn't end with '/', redirect
StringBuffer reqUrl = req.getRequestURL();
if(reqUrl.charAt(reqUrl.length()-1)!='/') {
rsp.sendRedirect2(reqUrl.append('/').toString());
return;
}
}
FileCallable<List<List<Path>>> glob = null;
if(rest.length()>0) {
// the rest is Ant glob pattern
glob = new PatternScanner(rest,createBackRef(restSize));
} else
if(serveDirIndex) {
// serve directory index
glob = new ChildPathBuilder(req.getLocale());
}
if(glob!=null) {
// serve glob
req.setAttribute("it", this);
List<Path> parentPaths = buildParentPath(base,restSize);
req.setAttribute("parentPath",parentPaths);
req.setAttribute("backPath", createBackRef(restSize));
req.setAttribute("topPath", createBackRef(parentPaths.size()+restSize));
req.setAttribute("files", baseFile.act(glob));
req.setAttribute("icon", icon);
req.setAttribute("path", path);
req.setAttribute("pattern",rest);
req.setAttribute("dir", baseFile);
req.getView(this,"dir.jelly").forward(req, rsp);
return;
}
// convert a directory service request to a single file service request by serving
// 'index.html'
baseFile = baseFile.child(indexFileName);
}
//serve a single file
if(!baseFile.exists()) {
rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
boolean view = rest.equals("*view*");
if(rest.equals("*fingerprint*")) {
rsp.forward(Jenkins.getInstance().getFingerprint(baseFile.digest()),"/",req);
return;
}
ContentInfo ci = baseFile.act(new ContentInfo());
if(LOGGER.isLoggable(Level.FINE))
LOGGER.fine("Serving "+baseFile+" with lastModified="+ci.lastModified+", contentLength="+ci.contentLength);
InputStream in = baseFile.read();
if (view) {
// for binary files, provide the file name for download
rsp.setHeader("Content-Disposition", "inline; filename=" + baseFile.getName());
// pseudo file name to let the Stapler set text/plain
rsp.serveFile(req, in, ci.lastModified, -1, ci.contentLength, "plain.txt");
} else {
rsp.serveFile(req, in, ci.lastModified, -1, ci.contentLength, baseFile.getName() );
}
}