LCOV - code coverage report
Current view: top level - httpd/plugins - LfsPluginServlet.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 18 54 33.3 %
Date: 2022-11-19 15:00:39 Functions: 6 11 54.5 %

          Line data    Source code
       1             : // Copyright (C) 2015 The Android Open Source Project
       2             : //
       3             : // Licensed under the Apache License, Version 2.0 (the "License");
       4             : // you may not use this file except in compliance with the License.
       5             : // You may obtain a copy of the License at
       6             : //
       7             : // http://www.apache.org/licenses/LICENSE-2.0
       8             : //
       9             : // Unless required by applicable law or agreed to in writing, software
      10             : // distributed under the License is distributed on an "AS IS" BASIS,
      11             : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             : // See the License for the specific language governing permissions and
      13             : // limitations under the License.
      14             : 
      15             : package com.google.gerrit.httpd.plugins;
      16             : 
      17             : import static com.google.gerrit.extensions.api.lfs.LfsDefinitions.CONTENTTYPE_VND_GIT_LFS_JSON;
      18             : import static java.nio.charset.StandardCharsets.UTF_8;
      19             : import static javax.servlet.http.HttpServletResponse.SC_NOT_IMPLEMENTED;
      20             : 
      21             : import com.google.common.flogger.FluentLogger;
      22             : import com.google.gerrit.common.Nullable;
      23             : import com.google.gerrit.httpd.resources.Resource;
      24             : import com.google.gerrit.server.config.GerritServerConfig;
      25             : import com.google.gerrit.server.plugins.Plugin;
      26             : import com.google.gerrit.server.plugins.ReloadPluginListener;
      27             : import com.google.gerrit.server.plugins.StartPluginListener;
      28             : import com.google.gerrit.util.http.CacheHeaders;
      29             : import com.google.inject.Inject;
      30             : import com.google.inject.Singleton;
      31             : import com.google.inject.servlet.GuiceFilter;
      32             : import java.io.BufferedWriter;
      33             : import java.io.IOException;
      34             : import java.io.OutputStreamWriter;
      35             : import java.io.Writer;
      36             : import java.util.ArrayList;
      37             : import java.util.List;
      38             : import java.util.concurrent.atomic.AtomicReference;
      39             : import javax.servlet.FilterChain;
      40             : import javax.servlet.ServletConfig;
      41             : import javax.servlet.ServletContext;
      42             : import javax.servlet.ServletException;
      43             : import javax.servlet.http.HttpServlet;
      44             : import javax.servlet.http.HttpServletRequest;
      45             : import javax.servlet.http.HttpServletResponse;
      46             : import org.eclipse.jgit.lib.Config;
      47             : 
      48             : @Singleton
      49             : public class LfsPluginServlet extends HttpServlet
      50             :     implements StartPluginListener, ReloadPluginListener {
      51             :   private static final long serialVersionUID = 1L;
      52             : 
      53          99 :   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
      54             : 
      55             :   private static final String MESSAGE_LFS_NOT_CONFIGURED =
      56             :       "{\"message\":\"No LFS plugin is configured to handle LFS requests.\"}";
      57             : 
      58          99 :   private List<Plugin> pending = new ArrayList<>();
      59             :   private final String pluginName;
      60             :   private final FilterChain chain;
      61             :   private AtomicReference<GuiceFilter> filter;
      62             : 
      63             :   @Inject
      64          99 :   LfsPluginServlet(@GerritServerConfig Config cfg) {
      65          99 :     this.pluginName = cfg.getString("lfs", null, "plugin");
      66          99 :     this.chain =
      67           0 :         (req, res) -> Resource.NOT_FOUND.send((HttpServletRequest) req, (HttpServletResponse) res);
      68          99 :     this.filter = new AtomicReference<>();
      69          99 :   }
      70             : 
      71             :   @Override
      72             :   protected void service(HttpServletRequest req, HttpServletResponse res)
      73             :       throws ServletException, IOException {
      74           0 :     if (filter.get() == null) {
      75           0 :       responseLfsNotConfigured(res);
      76           0 :       return;
      77             :     }
      78           0 :     filter.get().doFilter(req, res, chain);
      79           0 :   }
      80             : 
      81             :   @Override
      82             :   public synchronized void init(ServletConfig config) throws ServletException {
      83          99 :     super.init(config);
      84             : 
      85          99 :     for (Plugin plugin : pending) {
      86           0 :       install(plugin);
      87           0 :     }
      88          99 :     pending = null;
      89          99 :   }
      90             : 
      91             :   @Override
      92             :   public synchronized void onStartPlugin(Plugin plugin) {
      93           9 :     if (pending != null) {
      94           0 :       pending.add(plugin);
      95             :     } else {
      96           9 :       install(plugin);
      97             :     }
      98           9 :   }
      99             : 
     100             :   @Override
     101             :   public void onReloadPlugin(Plugin oldPlugin, Plugin newPlugin) {
     102           1 :     install(newPlugin);
     103           1 :   }
     104             : 
     105             :   private void responseLfsNotConfigured(HttpServletResponse res) throws IOException {
     106           0 :     CacheHeaders.setNotCacheable(res);
     107           0 :     res.setContentType(CONTENTTYPE_VND_GIT_LFS_JSON);
     108           0 :     res.setStatus(SC_NOT_IMPLEMENTED);
     109           0 :     Writer w = new BufferedWriter(new OutputStreamWriter(res.getOutputStream(), UTF_8));
     110           0 :     w.write(MESSAGE_LFS_NOT_CONFIGURED);
     111           0 :     w.flush();
     112           0 :   }
     113             : 
     114             :   private void install(Plugin plugin) {
     115           9 :     if (!plugin.getName().equals(pluginName)) {
     116           9 :       return;
     117             :     }
     118           0 :     final GuiceFilter guiceFilter = load(plugin);
     119           0 :     plugin.add(() -> filter.compareAndSet(guiceFilter, null));
     120           0 :     filter.set(guiceFilter);
     121           0 :   }
     122             : 
     123             :   @Nullable
     124             :   private GuiceFilter load(Plugin plugin) {
     125           0 :     if (plugin.getHttpInjector() != null) {
     126           0 :       final String name = plugin.getName();
     127             :       final GuiceFilter guiceFilter;
     128             :       try {
     129           0 :         guiceFilter = plugin.getHttpInjector().getInstance(GuiceFilter.class);
     130           0 :       } catch (RuntimeException e) {
     131           0 :         logger.atWarning().withCause(e).log("Plugin %s cannot load GuiceFilter", name);
     132           0 :         return null;
     133           0 :       }
     134             : 
     135             :       try {
     136           0 :         ServletContext ctx = PluginServletContext.create(plugin, "/");
     137           0 :         guiceFilter.init(new WrappedFilterConfig(ctx));
     138           0 :       } catch (ServletException e) {
     139           0 :         logger.atWarning().withCause(e).log("Plugin %s failed to initialize HTTP", name);
     140           0 :         return null;
     141           0 :       }
     142             : 
     143           0 :       plugin.add(guiceFilter::destroy);
     144           0 :       return guiceFilter;
     145             :     }
     146           0 :     return null;
     147             :   }
     148             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750