/******************************************************************************* * Copyright (c) 2012, 2014 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.orion.server.git.servlets; import java.io.File; import java.io.IOException; import java.util.Map.Entry; import java.util.Set; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.storage.file.FileRepositoryBuilder; import org.eclipse.orion.internal.server.servlets.ServletResourceHandler; import org.eclipse.orion.internal.server.servlets.workspace.authorization.AuthorizationService; import org.eclipse.orion.server.core.LogHelper; import org.eclipse.orion.server.core.ServerStatus; import org.eclipse.orion.server.git.GitActivator; import org.eclipse.orion.server.git.servlets.GitUtils.Traverse; import org.eclipse.orion.server.servlets.OrionServlet; import org.eclipse.osgi.util.NLS; import org.json.JSONException; import org.json.JSONObject; public abstract class AbstractGitHandler extends ServletResourceHandler<String> { class RequestInfo { HttpServletRequest request; HttpServletResponse response; Repository db; String gitSegment; String relativePath; IPath filePath; Git git; JSONObject jsonRequest; public RequestInfo(HttpServletRequest request, HttpServletResponse response, Repository db, String gitSegment, String relativePath, IPath filePath) { this.request = request; this.response = response; this.db = db; this.gitSegment = gitSegment; this.relativePath = relativePath; this.filePath = filePath; this.git = new Git(db); } public JSONObject getJSONRequest() { if (jsonRequest == null) jsonRequest = readJSONRequest(); return jsonRequest; } private JSONObject readJSONRequest() { try { return OrionServlet.readJSONRequest(request); } catch (IOException e) { LogHelper.log(new Status(IStatus.WARNING, GitActivator.PI_GIT, 1, "An error occured when getting JSON request", e)); return new JSONObject(); } catch (JSONException e) { LogHelper.log(new Status(IStatus.WARNING, GitActivator.PI_GIT, 1, "An error occured when getting JSON request", e)); return new JSONObject(); } } } protected ServletResourceHandler<IStatus> statusHandler; AbstractGitHandler(ServletResourceHandler<IStatus> statusHandler) { this.statusHandler = statusHandler; } @Override public boolean handleRequest(HttpServletRequest request, HttpServletResponse response, String path) throws ServletException { Repository db = null; try { IPath p = new Path(path); String gitSegment = null; if (p.segment(1).equals("file")) { //$NON-NLS-1$ gitSegment = GitUtils.decode(p.segment(0)); p = p.removeFirstSegments(1); } IPath filePath = p; if (!AuthorizationService.checkRights(request.getRemoteUser(), "/" + filePath.toString(), request.getMethod())) { response.sendError(HttpServletResponse.SC_FORBIDDEN); return true; } IPath gitSearchPath = filePath.hasTrailingSeparator() ? filePath : filePath.removeLastSegments(1); Set<Entry<IPath, File>> gitDirsFound = GitUtils.getGitDirs(gitSearchPath, Traverse.GO_UP).entrySet(); if (gitDirsFound.size() == 0) { String msg = NLS.bind("Could not find repository for {0}", filePath); return statusHandler.handleRequest(request, response, new ServerStatus(IStatus.ERROR, HttpServletResponse.SC_BAD_REQUEST, msg, null)); } Entry<IPath, File> firstGitDir = gitDirsFound.iterator().next(); File gitDir = firstGitDir.getValue(); if (gitDir == null) { String msg = NLS.bind("Could not find repository for {0}", filePath); return statusHandler.handleRequest(request, response, new ServerStatus(IStatus.ERROR, HttpServletResponse.SC_BAD_REQUEST, msg, null)); } String relativePath = GitUtils.getRelativePath(filePath, firstGitDir.getKey()); db = FileRepositoryBuilder.create(gitDir); RequestInfo requestInfo = new RequestInfo(request, response, db, gitSegment, relativePath, filePath); switch (getMethod(request)) { case GET: return handleGet(requestInfo); case POST: return handlePost(requestInfo); case PUT: return handlePut(requestInfo); case DELETE: return handleDelete(requestInfo); case OPTIONS: case HEAD: default: return false; } } catch (IOException e) { String msg = NLS.bind("Failed to process a git request for {0}", path); return statusHandler.handleRequest(request, response, new ServerStatus(IStatus.ERROR, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, msg, e)); } catch (CoreException e) { String msg = NLS.bind("Failed to process a git request for {0}", path); return statusHandler.handleRequest(request, response, new ServerStatus(IStatus.ERROR, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, msg, e)); } finally { if (db != null) { // close the git repository db.close(); } } } protected boolean handleGet(RequestInfo requestInfo) throws ServletException { return false; } protected boolean handlePost(RequestInfo requestInfo) throws ServletException { return false; } protected boolean handlePut(RequestInfo requestInfo) throws ServletException { return false; } protected boolean handleDelete(RequestInfo requestInfo) throws ServletException { return false; } }