1 /* 2 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> 3 * and other copyright owners as documented in the project's IP log. 4 * 5 * This program and the accompanying materials are made available 6 * under the terms of the Eclipse Distribution License v1.0 which 7 * accompanies this distribution, is reproduced below, and is 8 * available at http://www.eclipse.org/org/documents/edl-v10.php 9 * 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or 13 * without modification, are permitted provided that the following 14 * conditions are met: 15 * 16 * - Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 19 * - Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials provided 22 * with the distribution. 23 * 24 * - Neither the name of the Eclipse Foundation, Inc. nor the 25 * names of its contributors may be used to endorse or promote 26 * products derived from this software without specific prior 27 * written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 30 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 32 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 34 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 38 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 41 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 */ 43 44 package org.eclipse.jgit.pgm; 45 46 import java.lang.reflect.Constructor; 47 import java.lang.reflect.InvocationTargetException; 48 import java.text.MessageFormat; 49 50 import org.eclipse.jgit.pgm.internal.CLIText; 51 52 /** 53 * Description of a command (a {@link org.eclipse.jgit.pgm.TextBuiltin} 54 * subclass). 55 * <p> 56 * These descriptions are lightweight compared to creating a command instance 57 * and are therefore suitable for catalogs of "known" commands without linking 58 * the command's implementation and creating a dummy instance of the command. 59 */ 60 public class CommandRef { 61 private final Class<? extends TextBuiltin> impl; 62 63 private final String name; 64 65 private String usage; 66 67 boolean common; 68 69 CommandRef(Class<? extends TextBuiltin> clazz) { 70 this(clazz, guessName(clazz)); 71 } 72 73 CommandRef(Class<? extends TextBuiltin> clazz, Command cmd) { 74 this(clazz, cmd.name().length() > 0 ? cmd.name() : guessName(clazz)); 75 usage = cmd.usage(); 76 common = cmd.common(); 77 } 78 79 private CommandRef(Class<? extends TextBuiltin> clazz, String cn) { 80 impl = clazz; 81 name = cn; 82 usage = ""; //$NON-NLS-1$ 83 } 84 85 private static String guessName(Class<? extends TextBuiltin> clazz) { 86 final StringBuilder s = new StringBuilder(); 87 if (clazz.getName().startsWith("org.eclipse.jgit.pgm.debug.")) //$NON-NLS-1$ 88 s.append("debug-"); //$NON-NLS-1$ 89 90 boolean lastWasDash = true; 91 for (char c : clazz.getSimpleName().toCharArray()) { 92 if (Character.isUpperCase(c)) { 93 if (!lastWasDash) 94 s.append('-'); 95 lastWasDash = !lastWasDash; 96 s.append(Character.toLowerCase(c)); 97 } else { 98 s.append(c); 99 lastWasDash = false; 100 } 101 } 102 return s.toString(); 103 } 104 105 /** 106 * Get the <code>name</code>. 107 * 108 * @return name the command is invoked as from the command line. 109 */ 110 public String getName() { 111 return name; 112 } 113 114 /** 115 * Get <code>usage</code>. 116 * 117 * @return one line description of the command's feature set. 118 */ 119 public String getUsage() { 120 return usage; 121 } 122 123 /** 124 * Is this command commonly used 125 * 126 * @return true if this command is considered to be commonly used. 127 */ 128 public boolean isCommon() { 129 return common; 130 } 131 132 /** 133 * Get implementation class name 134 * 135 * @return name of the Java class which implements this command. 136 */ 137 public String getImplementationClassName() { 138 return impl.getName(); 139 } 140 141 /** 142 * Get implementation class loader 143 * 144 * @return loader for {@link #getImplementationClassName()}. 145 */ 146 public ClassLoader getImplementationClassLoader() { 147 return impl.getClassLoader(); 148 } 149 150 /** 151 * Create an instance of the command implementation 152 * 153 * @return a new instance of the command implementation. 154 */ 155 public TextBuiltin create() { 156 final Constructor<? extends TextBuiltin> c; 157 try { 158 c = impl.getDeclaredConstructor(); 159 } catch (SecurityException | NoSuchMethodException e) { 160 throw new RuntimeException(MessageFormat 161 .format(CLIText.get().cannotCreateCommand, getName(), e)); 162 } 163 c.setAccessible(true); 164 165 final TextBuiltin r; 166 try { 167 r = c.newInstance(); 168 } catch (InstantiationException | IllegalAccessException 169 | IllegalArgumentException | InvocationTargetException e) { 170 throw new RuntimeException(MessageFormat 171 .format(CLIText.get().cannotCreateCommand, getName(), e)); 172 } 173 r.setCommandName(getName()); 174 return r; 175 } 176 177 /** {@inheritDoc} */ 178 @SuppressWarnings("nls") 179 @Override 180 public String toString() { 181 return "CommandRef [impl=" + impl + ", name=" + name + ", usage=" 182 + CLIText.get().resourceBundle().getString(usage) + ", common=" 183 + common + "]"; 184 } 185 }