1 /* 2 * Copyright (C) 2008-2009, Google Inc. 3 * Copyright (C) 2009, Robin Rosenberg <robin.rosenberg@dewire.com> 4 * and other copyright owners as documented in the project's IP log. 5 * 6 * This program and the accompanying materials are made available 7 * under the terms of the Eclipse Distribution License v1.0 which 8 * accompanies this distribution, is reproduced below, and is 9 * available at http://www.eclipse.org/org/documents/edl-v10.php 10 * 11 * All rights reserved. 12 * 13 * Redistribution and use in source and binary forms, with or 14 * without modification, are permitted provided that the following 15 * conditions are met: 16 * 17 * - Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 20 * - Redistributions in binary form must reproduce the above 21 * copyright notice, this list of conditions and the following 22 * disclaimer in the documentation and/or other materials provided 23 * with the distribution. 24 * 25 * - Neither the name of the Eclipse Foundation, Inc. nor the 26 * names of its contributors may be used to endorse or promote 27 * products derived from this software without specific prior 28 * written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 31 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 32 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 33 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 34 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 35 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 36 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 37 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 39 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 41 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 42 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 43 */ 44 45 package org.eclipse.jgit.transport; 46 47 import java.io.IOException; 48 49 import org.eclipse.jgit.lib.Config; 50 import org.eclipse.jgit.lib.Config.SectionParser; 51 import org.eclipse.jgit.lib.Repository; 52 import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException; 53 import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; 54 55 /** A service exposed by {@link Daemon} over anonymous <code>git://</code>. */ 56 public abstract class DaemonService { 57 private final String command; 58 59 private final SectionParser<ServiceConfig> configKey; 60 61 private boolean enabled; 62 63 private boolean overridable; 64 65 DaemonService(final String cmdName, final String cfgName) { 66 command = cmdName.startsWith("git-") ? cmdName : "git-" + cmdName; //$NON-NLS-1$ //$NON-NLS-2$ 67 configKey = cfg -> new ServiceConfig(DaemonService.this, cfg, cfgName); 68 overridable = true; 69 } 70 71 private static class ServiceConfig { 72 final boolean enabled; 73 74 ServiceConfig(final DaemonService service, final Config cfg, 75 final String name) { 76 enabled = cfg.getBoolean("daemon", name, service.isEnabled()); //$NON-NLS-1$ 77 } 78 } 79 80 /** @return is this service enabled for invocation? */ 81 public boolean isEnabled() { 82 return enabled; 83 } 84 85 /** 86 * @param on 87 * true to allow this service to be used; false to deny it. 88 */ 89 public void setEnabled(final boolean on) { 90 enabled = on; 91 } 92 93 /** @return can this service be configured in the repository config file? */ 94 public boolean isOverridable() { 95 return overridable; 96 } 97 98 /** 99 * @param on 100 * true to permit repositories to override this service's enabled 101 * state with the <code>daemon.servicename</code> config setting. 102 */ 103 public void setOverridable(final boolean on) { 104 overridable = on; 105 } 106 107 /** @return name of the command requested by clients. */ 108 public String getCommandName() { 109 return command; 110 } 111 112 /** 113 * Determine if this service can handle the requested command. 114 * 115 * @param commandLine 116 * input line from the client. 117 * @return true if this command can accept the given command line. 118 */ 119 public boolean handles(final String commandLine) { 120 return command.length() + 1 < commandLine.length() 121 && commandLine.charAt(command.length()) == ' ' 122 && commandLine.startsWith(command); 123 } 124 125 void execute(final DaemonClient client, final String commandLine) 126 throws IOException, ServiceNotEnabledException, 127 ServiceNotAuthorizedException { 128 final String name = commandLine.substring(command.length() + 1); 129 Repository db; 130 try { 131 db = client.getDaemon().openRepository(client, name); 132 } catch (ServiceMayNotContinueException e) { 133 // An error when opening the repo means the client is expecting a ref 134 // advertisement, so use that style of error. 135 PacketLineOut pktOut = new PacketLineOut(client.getOutputStream()); 136 pktOut.writeString("ERR " + e.getMessage() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$ 137 db = null; 138 } 139 if (db == null) 140 return; 141 try { 142 if (isEnabledFor(db)) 143 execute(client, db); 144 } finally { 145 db.close(); 146 } 147 } 148 149 private boolean isEnabledFor(final Repository db) { 150 if (isOverridable()) 151 return db.getConfig().get(configKey).enabled; 152 return isEnabled(); 153 } 154 155 abstract void execute(DaemonClient client, Repository db) 156 throws IOException, ServiceNotEnabledException, 157 ServiceNotAuthorizedException; 158 }