DaemonService.java

  1. /*
  2.  * Copyright (C) 2008-2009, Google Inc.
  3.  * Copyright (C) 2009, Robin Rosenberg <robin.rosenberg@dewire.com> and others
  4.  *
  5.  * This program and the accompanying materials are made available under the
  6.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  7.  * https://www.eclipse.org/org/documents/edl-v10.php.
  8.  *
  9.  * SPDX-License-Identifier: BSD-3-Clause
  10.  */

  11. package org.eclipse.jgit.transport;

  12. import java.io.IOException;
  13. import java.util.Collection;

  14. import org.eclipse.jgit.annotations.Nullable;
  15. import org.eclipse.jgit.lib.Config;
  16. import org.eclipse.jgit.lib.Config.SectionParser;
  17. import org.eclipse.jgit.lib.Repository;
  18. import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
  19. import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;

  20. /**
  21.  * A service exposed by {@link org.eclipse.jgit.transport.Daemon} over anonymous
  22.  * <code>git://</code>.
  23.  */
  24. public abstract class DaemonService {
  25.     private final String command;

  26.     private final SectionParser<ServiceConfig> configKey;

  27.     private boolean enabled;

  28.     private boolean overridable;

  29.     DaemonService(String cmdName, String cfgName) {
  30.         command = cmdName.startsWith("git-") ? cmdName : "git-" + cmdName; //$NON-NLS-1$ //$NON-NLS-2$
  31.         configKey = cfg -> new ServiceConfig(DaemonService.this, cfg, cfgName);
  32.         overridable = true;
  33.     }

  34.     private static class ServiceConfig {
  35.         final boolean enabled;

  36.         ServiceConfig(final DaemonService service, final Config cfg,
  37.                 final String name) {
  38.             enabled = cfg.getBoolean("daemon", name, service.isEnabled()); //$NON-NLS-1$
  39.         }
  40.     }

  41.     /**
  42.      * Whether this service is enabled for invocation.
  43.      *
  44.      * @return whether this service is enabled for invocation.
  45.      */
  46.     public boolean isEnabled() {
  47.         return enabled;
  48.     }

  49.     /**
  50.      * Set if it is allowed to use this service
  51.      *
  52.      * @param on
  53.      *            {@code true} to allow this service to be used; {@code false}
  54.      *            to deny it.
  55.      */
  56.     public void setEnabled(boolean on) {
  57.         enabled = on;
  58.     }

  59.     /** @return can this service be configured in the repository config file? */
  60.     /**
  61.      * Whether this service can be configured in the repository config file
  62.      *
  63.      * @return whether this service can be configured in the repository config
  64.      *         file
  65.      */
  66.     public boolean isOverridable() {
  67.         return overridable;
  68.     }

  69.     /**
  70.      * Whether to permit repositories to override this service's enabled state
  71.      * with the <code>daemon.servicename</code> config setting.
  72.      *
  73.      * @param on
  74.      *            {@code true} to permit repositories to override this service's
  75.      *            enabled state with the <code>daemon.servicename</code> config
  76.      *            setting.
  77.      */
  78.     public void setOverridable(boolean on) {
  79.         overridable = on;
  80.     }

  81.     /**
  82.      * Get name of the command requested by clients.
  83.      *
  84.      * @return name of the command requested by clients.
  85.      */
  86.     public String getCommandName() {
  87.         return command;
  88.     }

  89.     /**
  90.      * Determine if this service can handle the requested command.
  91.      *
  92.      * @param commandLine
  93.      *            input line from the client.
  94.      * @return true if this command can accept the given command line.
  95.      */
  96.     public boolean handles(String commandLine) {
  97.         return command.length() + 1 < commandLine.length()
  98.                 && commandLine.charAt(command.length()) == ' '
  99.                 && commandLine.startsWith(command);
  100.     }

  101.     void execute(DaemonClient client, String commandLine,
  102.             @Nullable Collection<String> extraParameters)
  103.             throws IOException, ServiceNotEnabledException,
  104.             ServiceNotAuthorizedException {
  105.         final String name = commandLine.substring(command.length() + 1);
  106.         try (Repository db = client.getDaemon().openRepository(client, name)) {
  107.             if (isEnabledFor(db)) {
  108.                 execute(client, db, extraParameters);
  109.             }
  110.         } catch (ServiceMayNotContinueException e) {
  111.             // An error when opening the repo means the client is expecting a ref
  112.             // advertisement, so use that style of error.
  113.             PacketLineOut pktOut = new PacketLineOut(client.getOutputStream());
  114.             pktOut.writeString("ERR " + e.getMessage() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
  115.         }
  116.     }

  117.     private boolean isEnabledFor(Repository db) {
  118.         if (isOverridable())
  119.             return db.getConfig().get(configKey).enabled;
  120.         return isEnabled();
  121.     }

  122.     abstract void execute(DaemonClient client, Repository db,
  123.             @Nullable Collection<String> extraParameters)
  124.             throws IOException, ServiceNotEnabledException,
  125.             ServiceNotAuthorizedException;
  126. }