src/main/java/WEB-INF/web.xml
@@ -35,271 +35,4 @@ </display-name> <!-- PARAMS --> <!-- Gitblit Context Listener --><!-- STRIP <listener> <listener-class>com.gitblit.GitBlit</listener-class> </listener>STRIP --> <!-- Git Servlet <url-pattern> MUST match: * GitFilter * com.gitblit.Constants.GIT_PATH * Wicket Filter ignorePaths parameter --> <servlet> <servlet-name>GitServlet</servlet-name> <servlet-class>com.gitblit.git.GitServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>GitServlet</servlet-name> <url-pattern>/git/*</url-pattern> </servlet-mapping> <!-- SparkleShare Invite Servlet <url-pattern> MUST match: * com.gitblit.Constants.SPARKLESHARE_INVITE_PATH * Wicket Filter ignorePaths parameter --> <servlet> <servlet-name>SparkleShareInviteServlet</servlet-name> <servlet-class>com.gitblit.SparkleShareInviteServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>SparkleShareInviteServlet</servlet-name> <url-pattern>/sparkleshare/*</url-pattern> </servlet-mapping> <!-- Syndication Servlet <url-pattern> MUST match: * SyndicationFilter * com.gitblit.Constants.SYNDICATION_PATH * Wicket Filter ignorePaths parameter --> <servlet> <servlet-name>SyndicationServlet</servlet-name> <servlet-class>com.gitblit.SyndicationServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>SyndicationServlet</servlet-name> <url-pattern>/feed/*</url-pattern> </servlet-mapping> <!-- Zip Servlet <url-pattern> MUST match: * ZipServlet * com.gitblit.Constants.ZIP_PATH * Wicket Filter ignorePaths parameter --> <servlet> <servlet-name>ZipServlet</servlet-name> <servlet-class>com.gitblit.DownloadZipServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>ZipServlet</servlet-name> <url-pattern>/zip/*</url-pattern> </servlet-mapping> <!-- Federation Servlet <url-pattern> MUST match: * com.gitblit.Constants.FEDERATION_PATH * Wicket Filter ignorePaths parameter --> <servlet> <servlet-name>FederationServlet</servlet-name> <servlet-class>com.gitblit.FederationServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>FederationServlet</servlet-name> <url-pattern>/federation/*</url-pattern> </servlet-mapping> <!-- Rpc Servlet <url-pattern> MUST match: * com.gitblit.Constants.RPC_PATH * Wicket Filter ignorePaths parameter --> <servlet> <servlet-name>RpcServlet</servlet-name> <servlet-class>com.gitblit.RpcServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>RpcServlet</servlet-name> <url-pattern>/rpc/*</url-pattern> </servlet-mapping> <!-- Pages Servlet <url-pattern> MUST match: * PagesFilter * com.gitblit.Constants.PAGES_PATH * Wicket Filter ignorePaths parameter --> <servlet> <servlet-name>PagesServlet</servlet-name> <servlet-class>com.gitblit.PagesServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>PagesServlet</servlet-name> <url-pattern>/pages/*</url-pattern> </servlet-mapping> <!-- Logo Servlet <url-pattern> MUST match: * Wicket Filter ignorePaths parameter --> <servlet> <servlet-name>LogoServlet</servlet-name> <servlet-class>com.gitblit.LogoServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LogoServlet</servlet-name> <url-pattern>/logo.png</url-pattern> </servlet-mapping> <!-- Branch Graph Servlet <url-pattern> MUST match: * Wicket Filter ignorePaths parameter --> <servlet> <servlet-name>BranchGraphServlet</servlet-name> <servlet-class>com.gitblit.BranchGraphServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>BranchGraphServlet</servlet-name> <url-pattern>/graph/*</url-pattern> </servlet-mapping> <!-- Robots.txt Servlet <url-pattern> MUST match: * Wicket Filter ignorePaths parameter --> <servlet> <servlet-name>RobotsTxtServlet</servlet-name> <servlet-class>com.gitblit.RobotsTxtServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>RobotsTxtServlet</servlet-name> <url-pattern>/robots.txt</url-pattern> </servlet-mapping> <!-- Git Access Restriction Filter <url-pattern> MUST match: * GitServlet * com.gitblit.Constants.GIT_PATH * Wicket Filter ignorePaths parameter --> <filter> <filter-name>GitFilter</filter-name> <filter-class>com.gitblit.GitFilter</filter-class> </filter> <filter-mapping> <filter-name>GitFilter</filter-name> <url-pattern>/git/*</url-pattern> </filter-mapping> <!-- Syndication Restriction Filter <url-pattern> MUST match: * SyndicationServlet * com.gitblit.Constants.SYNDICATION_PATH * Wicket Filter ignorePaths parameter --> <filter> <filter-name>SyndicationFilter</filter-name> <filter-class>com.gitblit.SyndicationFilter</filter-class> </filter> <filter-mapping> <filter-name>SyndicationFilter</filter-name> <url-pattern>/feed/*</url-pattern> </filter-mapping> <!-- Download Zip Restriction Filter <url-pattern> MUST match: * DownloadZipServlet * com.gitblit.Constants.ZIP_PATH * Wicket Filter ignorePaths parameter --> <filter> <filter-name>ZipFilter</filter-name> <filter-class>com.gitblit.DownloadZipFilter</filter-class> </filter> <filter-mapping> <filter-name>ZipFilter</filter-name> <url-pattern>/zip/*</url-pattern> </filter-mapping> <!-- Rpc Restriction Filter <url-pattern> MUST match: * RpcServlet * com.gitblit.Constants.RPC_PATH * Wicket Filter ignorePaths parameter --> <filter> <filter-name>RpcFilter</filter-name> <filter-class>com.gitblit.RpcFilter</filter-class> </filter> <filter-mapping> <filter-name>RpcFilter</filter-name> <url-pattern>/rpc/*</url-pattern> </filter-mapping> <!-- Pges Restriction Filter <url-pattern> MUST match: * PagesServlet * com.gitblit.Constants.PAGES_PATH * Wicket Filter ignorePaths parameter --> <filter> <filter-name>PagesFilter</filter-name> <filter-class>com.gitblit.PagesFilter</filter-class> </filter> <filter-mapping> <filter-name>PagesFilter</filter-name> <url-pattern>/pages/*</url-pattern> </filter-mapping> <filter> <filter-name>EnforceAuthenticationFilter</filter-name> <filter-class>com.gitblit.EnforceAuthenticationFilter</filter-class> </filter> <filter-mapping> <filter-name>EnforceAuthenticationFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- Wicket Filter --> <filter> <filter-name>wicketFilter</filter-name> <filter-class> com.gitblit.wicket.GitblitWicketFilter </filter-class> <init-param> <param-name>applicationClassName</param-name> <param-value>com.gitblit.wicket.GitBlitWebApp</param-value> </init-param> <init-param> <param-name>ignorePaths</param-name> <!-- Paths should match * SyndicationFilter <url-pattern> * SyndicationServlet <url-pattern> * com.gitblit.Constants.SYNDICATION_PATH * GitFilter <url-pattern> * GitServlet <url-pattern> * com.gitblit.Constants.GIT_PATH * SparkleshareInviteServlet <url-pattern> * com.gitblit.Constants.SPARKLESHARE_INVITE_PATH * Zipfilter <url-pattern> * ZipServlet <url-pattern> * com.gitblit.Constants.ZIP_PATH * FederationServlet <url-pattern> * RpcFilter <url-pattern> * RpcServlet <url-pattern> * PagesFilter <url-pattern> * PagesServlet <url-pattern> * com.gitblit.Constants.PAGES_PATH --> <param-value>git/,feed/,zip/,federation/,rpc/,pages/,robots.txt,logo.png,graph/,sparkleshare/</param-value> </init-param> </filter> <filter-mapping> <filter-name>wicketFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app> src/main/java/com/gitblit/DownloadZipFilter.java
@@ -29,6 +29,9 @@ */ public class DownloadZipFilter extends AccessRestrictionFilter { public DownloadZipFilter() { } /** * Extract the repository name from the url. * src/main/java/com/gitblit/EnforceAuthenticationFilter.java
@@ -46,6 +46,9 @@ protected transient Logger logger = LoggerFactory.getLogger(getClass()); public EnforceAuthenticationFilter() { } /* * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) */ src/main/java/com/gitblit/GitBlit.java
@@ -66,7 +66,7 @@ import javax.naming.NamingException; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -83,7 +83,6 @@ import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.gitblit.Constants.AccessPermission; import com.gitblit.Constants.AccessRestrictionType; @@ -100,6 +99,7 @@ import com.gitblit.fanout.FanoutService; import com.gitblit.fanout.FanoutSocketService; import com.gitblit.git.GitDaemon; import com.gitblit.git.GitServlet; import com.gitblit.manager.IFederationManager; import com.gitblit.manager.IGitblitManager; import com.gitblit.manager.INotificationManager; @@ -144,6 +144,7 @@ import com.gitblit.utils.TimeUtils; import com.gitblit.utils.X509Utils.X509Metadata; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.GitblitWicketFilter; import com.gitblit.wicket.WicketUtils; import com.google.gson.Gson; import com.google.gson.JsonIOException; @@ -153,21 +154,18 @@ /** * GitBlit is the servlet context listener singleton that acts as the core for * the web ui and the servlets. This class is either directly instantiated by * the GitBlitServer class (Gitblit GO) or is reflectively instantiated from the * definition in the web.xml file (Gitblit WAR). * the GitBlitServer class (Gitblit GO) or is reflectively instantiated by the * servlet 3 container (Gitblit WAR or Express). * * This class is the central logic processor for Gitblit. All settings, user * object, and repository object operations pass through this class. * * Repository Resolution. There are two pathways for finding repositories. One * pathway, for web ui display and repository authentication & authorization, is * within this class. The other pathway is through the standard GitServlet. * * @author James Moger * */ public class GitBlit implements ServletContextListener, IRuntimeManager, @WebListener public class GitBlit extends InjectionContextListener implements IRuntimeManager, INotificationManager, IUserManager, ISessionManager, @@ -179,8 +177,6 @@ private static GitBlit gitblit; private final IStoredSettings goSettings; private final Logger logger = LoggerFactory.getLogger(GitBlit.class); private final ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(10); @@ -204,8 +200,6 @@ private final ObjectCache<String> projectMarkdownCache = new ObjectCache<String>(); private final ObjectCache<String> projectRepositoriesMarkdownCache = new ObjectCache<String>(); private ServletContext servletContext; private File baseFolder; @@ -3718,11 +3712,9 @@ * @see ServletContextListener.contextInitialize(ServletContextEvent) */ @Override public void contextInitialized(ServletContextEvent contextEvent) { servletContext = contextEvent.getServletContext(); protected void beforeServletInjection(ServletContext context) { if (settings == null) { // Gitblit is running in a servlet container ServletContext context = contextEvent.getServletContext(); WebXmlSettings webxmlSettings = new WebXmlSettings(context); String contextRealPath = context.getRealPath("/"); File contextFolder = (contextRealPath != null) ? new File(contextRealPath) : null; @@ -3807,7 +3799,7 @@ } settingsModel = loadSettingModels(); serverStatus.servletContainer = servletContext.getServerInfo(); serverStatus.servletContainer = context.getServerInfo(); } protected void extractResources(ServletContext context, String path, File toDir) { @@ -4059,4 +4051,35 @@ setCookie(response, null); userService.logout(user); } /** * Instantiate and inject all filters and servlets into the container using * the servlet 3 specification. */ @Override protected void injectServlets(ServletContext context) { // access restricted servlets serve(context, Constants.GIT_PATH, GitServlet.class, GitFilter.class); serve(context, Constants.PAGES, PagesServlet.class, PagesFilter.class); serve(context, Constants.RPC_PATH, RpcServlet.class, RpcFilter.class); serve(context, Constants.ZIP_PATH, DownloadZipServlet.class, DownloadZipFilter.class); serve(context, Constants.SYNDICATION_PATH, SyndicationServlet.class, SyndicationFilter.class); // servlets serve(context, Constants.FEDERATION_PATH, FederationServlet.class); serve(context, Constants.SPARKLESHARE_INVITE_PATH, SparkleShareInviteServlet.class); serve(context, Constants.BRANCH_GRAPH_PATH, BranchGraphServlet.class); file(context, "/robots.txt", RobotsTxtServlet.class); file(context, "/logo.png", LogoServlet.class); // optional force basic authentication filter(context, "/*", EnforceAuthenticationFilter.class, null); // Wicket String toIgnore = StringUtils.flattenStrings(getRegisteredPaths(), ","); Map<String, String> params = new HashMap<String, String>(); params.put(GitblitWicketFilter.FILTER_MAPPING_PARAM, "/*"); params.put(GitblitWicketFilter.IGNORE_PATHS_PARAM, toIgnore); filter(context, "/*", GitblitWicketFilter.class, params); } } src/main/java/com/gitblit/GitFilter.java
@@ -42,6 +42,9 @@ protected static final String[] suffixes = { gitReceivePack, gitUploadPack, "/info/refs", "/HEAD", "/objects" }; public GitFilter() { } /** * Extract the repository name from the url. * src/main/java/com/gitblit/InjectionContextListener.java
New file @@ -0,0 +1,241 @@ /* * Copyright 2013 gitblit.com. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.gitblit; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; import java.util.Map; import javax.servlet.DispatcherType; import javax.servlet.Filter; import javax.servlet.FilterRegistration; import javax.servlet.Servlet; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.ServletRegistration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Injection context listener instantiates and injects servlets, filters, and * anything else you might want into a servlet context. This class provides * convenience methods for servlet & filter registration and also tracks * registered paths. * * @author James Moger * */ public abstract class InjectionContextListener implements ServletContextListener { protected final Logger logger = LoggerFactory.getLogger(getClass()); private final List<String> registeredPaths = new ArrayList<String>(); protected final List<String> getRegisteredPaths() { return registeredPaths; } /** * Hook for subclasses to manipulate context initialization before * standard initialization procedure. * * @param context */ protected void beforeServletInjection(ServletContext context) { // NOOP } /** * Hook for subclasses to instantiate and inject servlets and filters * into the servlet context. * * @param context */ protected abstract void injectServlets(ServletContext context); /** * Hook for subclasses to manipulate context initialization after * servlet registration. * * @param context */ protected void afterServletInjection(ServletContext context) { // NOOP } /** * Configure Gitblit from the web.xml, if no configuration has already been * specified. * * @see ServletContextListener.contextInitialize(ServletContextEvent) */ @Override public final void contextInitialized(ServletContextEvent contextEvent) { ServletContext context = contextEvent.getServletContext(); beforeServletInjection(context); injectServlets(context); afterServletInjection(context); } /** * Registers a file path. * * @param context * @param file * @param servletClass */ protected void file(ServletContext context, String file, Class<? extends Servlet> servletClass) { file(context, file, servletClass, null); } /** * Registers a file path with init parameters. * * @param context * @param file * @param servletClass * @param initParams */ protected void file(ServletContext context, String file, Class<? extends Servlet> servletClass, Map<String, String> initParams) { Servlet servlet = instantiate(context, servletClass); ServletRegistration.Dynamic d = context.addServlet(sanitize(servletClass.getSimpleName() + file), servlet); d.addMapping(file); if (initParams != null) { d.setInitParameters(initParams); } registeredPaths.add(file); } /** * Serves a path (trailing wildcard will be appended). * * @param context * @param route * @param servletClass */ protected void serve(ServletContext context, String route, Class<? extends Servlet> servletClass) { serve(context, route, servletClass, (Class<Filter>) null); } /** * Serves a path (trailing wildcard will be appended) with init parameters. * * @param context * @param route * @param servletClass * @param initParams */ protected void serve(ServletContext context, String route, Class<? extends Servlet> servletClass, Map<String, String> initParams) { Servlet servlet = instantiate(context, servletClass); ServletRegistration.Dynamic d = context.addServlet(sanitize(servletClass.getSimpleName() + route), servlet); d.addMapping(route + "*"); if (initParams != null) { d.setInitParameters(initParams); } registeredPaths.add(route); } /** * Serves a path (trailing wildcard will be appended) and also maps a filter * to that path. * * @param context * @param route * @param servletClass * @param filterClass */ protected void serve(ServletContext context, String route, Class<? extends Servlet> servletClass, Class<? extends Filter> filterClass) { Servlet servlet = instantiate(context, servletClass); ServletRegistration.Dynamic d = context.addServlet(sanitize(servletClass.getSimpleName() + route), servlet); d.addMapping(route + "*"); if (filterClass != null) { filter(context, route + "*", filterClass); } registeredPaths.add(route); } /** * Registers a path filter. * * @param context * @param route * @param filterClass */ protected void filter(ServletContext context, String route, Class<? extends Filter> filterClass) { filter(context, route, filterClass, null); } /** * Registers a path filter with init parameters. * * @param context * @param route * @param filterClass * @param initParams */ protected void filter(ServletContext context, String route, Class<? extends Filter> filterClass, Map<String, String> initParams) { Filter filter = instantiate(context, filterClass); FilterRegistration.Dynamic d = context.addFilter(sanitize(filterClass.getSimpleName() + route), filter); d.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, route); if (initParams != null) { d.setInitParameters(initParams); } } /** * Limit the generated servlet/filter names to alpha-numeric values with a * handful of acceptable other characters. * * @param name * @return a sanitized name */ protected String sanitize(String name) { StringBuilder sb = new StringBuilder(); for (char c : name.toCharArray()) { if (Character.isLetterOrDigit(c)) { sb.append(c); } else if ('-' == c) { sb.append(c); } else if ('*' == c) { sb.append("all"); } else if ('.' == c) { sb.append('.'); } else { sb.append('_'); } } return sb.toString(); } /** * Instantiates an object. * * @param clazz * @return the object */ protected <X> X instantiate(ServletContext context, Class<X> clazz) { try { return clazz.newInstance(); } catch (Throwable t) { logger.error(null, t); } return null; } } src/main/java/com/gitblit/PagesFilter.java
@@ -31,6 +31,9 @@ */ public class PagesFilter extends AccessRestrictionFilter { public PagesFilter() { } /** * Extract the repository name from the url. * src/main/java/com/gitblit/RpcFilter.java
@@ -44,6 +44,9 @@ */ public class RpcFilter extends AuthenticationFilter { public RpcFilter() { } /** * doFilter does the actual work of preprocessing the request to ensure that * the user may proceed. src/main/java/com/gitblit/SyndicationFilter.java
@@ -43,6 +43,9 @@ */ public class SyndicationFilter extends AuthenticationFilter { public SyndicationFilter() { } /** * Extract the repository name from the url. * src/main/java/com/gitblit/SyndicationServlet.java
@@ -59,6 +59,9 @@ private transient Logger logger = LoggerFactory.getLogger(SyndicationServlet.class); public SyndicationServlet() { } /** * Create a feed link for the specified repository and branch/tag/commit id. * src/main/java/com/gitblit/git/GitServlet.java
@@ -33,6 +33,9 @@ private static final long serialVersionUID = 1L; public GitServlet() { } @Override public void init(ServletConfig config) throws ServletException { IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class); src/main/java/com/gitblit/wicket/GitblitWicketFilter.java
@@ -19,6 +19,8 @@ import javax.servlet.http.HttpServletRequest; import org.apache.wicket.protocol.http.IWebApplicationFactory; import org.apache.wicket.protocol.http.WebApplication; import org.apache.wicket.protocol.http.WicketFilter; import org.apache.wicket.util.string.Strings; import org.eclipse.jgit.lib.Repository; @@ -45,6 +47,19 @@ */ public class GitblitWicketFilter extends WicketFilter { public GitblitWicketFilter() { } @Override protected IWebApplicationFactory getApplicationFactory() { return new IWebApplicationFactory() { @Override public WebApplication createApplication(WicketFilter filter) { return new GitBlitWebApp(); } }; } /** * Determines the last-modified date of the requested resource. * @@ -54,8 +69,9 @@ @Override protected long getLastModified(final HttpServletRequest servletRequest) { final String pathInfo = getRelativePath(servletRequest); if (Strings.isEmpty(pathInfo)) if (Strings.isEmpty(pathInfo)) { return -1; } long lastModified = super.getLastModified(servletRequest); if (lastModified > -1) { return lastModified;