command.line/java/com/jetbrains/teamcity/command/CommandRegistry.java (118 lines of code) (raw):
package com.jetbrains.teamcity.command;
import com.jetbrains.teamcity.Debug;
import com.jetbrains.teamcity.Server;
import com.jetbrains.teamcity.Storage;
import com.jetbrains.teamcity.resources.TCAccess;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.text.MessageFormat;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jetbrains.buildServer.util.FileUtil;
class CommandRegistry {
public static final Pattern COMMAND_EXTENSION_JAR_PATTERN = Pattern.compile(".*tc\\.command.*");
private static CommandRegistry ourInstance;
private final HashMap<String, ICommand> ourRegistry = new HashMap<String, ICommand>();
private CommandRegistry() {
// try to find any ICommand and register
registerCommands();
}
void registerCommands() {
// register default
register(new Help());
register(new ListCommand());
register(new Login());
register(new Logout());
register(new RemoteRun());
// register(new Share());
// register(new Unshare());
// scan for new
// final Collection<ICommand> extensions = findCommand();
// for(final ICommand command : extensions){
// register(command);
// }
}
Collection<ICommand> commands() {
return Collections.unmodifiableCollection(ourRegistry.values());
}
private Collection<ICommand> findCommand() {
final HashSet<ICommand> result = new HashSet<ICommand>();
if (getClass().getClassLoader() instanceof URLClassLoader) {
final URLClassLoader loader = (URLClassLoader) getClass().getClassLoader();
for (URL url : loader.getURLs()) {
final File file = new File(url.getFile());
if (file.isDirectory()) {
final ArrayList<File> children = new ArrayList<File>();
FileUtil.collectMatchedFiles(file, Pattern.compile(".*\\.class"), children);
for (File child : children) {
if (isSimpleClass(child.getPath())) {// do not touch inner classes
final String classFilePath = FileUtil.getRelativePath(file, child);
final String className = getClassName(classFilePath);
final ICommand instance = createCommand(className);
if (instance != null) {
result.add(instance);
}
}
}
} else {
// jars
try {
final JarFile jar = new JarFile(file);
if (!isCommandExtensionJar(jar.getName())) {
Debug.getInstance().debug(CommandRegistry.class, MessageFormat.format("New commans jar found: {0}", jar.getName()));
final Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
final String fileName = entries.nextElement().getName();
if (isSimpleClass(fileName)) {
final String className = getClassName(fileName);
final ICommand instance = createCommand(className);
if (instance != null) {
result.add(instance);
}
}
}
}
} catch (IOException e) {
// do nothing
}
}
}
}
return result;
}
boolean isCommandExtensionJar(final String jarName) {
Matcher matcher = COMMAND_EXTENSION_JAR_PATTERN.matcher(jarName);
return !matcher.matches();
}
private ICommand createCommand(final String className) {
try {
if (!isIgnored(className)) {// do not instantiate self
final Class<?> clazz = getClass().getClassLoader().loadClass(className);
Object instance = clazz.newInstance();
if (instance instanceof ICommand) {
return (ICommand) instance;
}
}
} catch (Throwable e) {
// do nothing
}
return null;
}
private boolean isSimpleClass(final String fileName) {
return fileName.endsWith(".class") && !fileName.contains("$");
}
private String getClassName(final String classFilePath) {
return classFilePath.replace("\\", ".").replace("/", ".").substring(0, classFilePath.lastIndexOf(".class"));
}
private boolean isIgnored(final String className) {
return getClass().getName().equals(className) || TCAccess.class.getName().equals(className) || Storage.class.getName().equals(className) ||
Server.class.getName().equals(className) || CommandRunner.class.getName().equals(className);
}
public static synchronized CommandRegistry getInstance() {
if (ourInstance == null) {
ourInstance = new CommandRegistry();
}
return ourInstance;
}
synchronized void register(final ICommand command) {
if (!ourRegistry.containsKey(command.getId())) {
ourRegistry.put(command.getId(), command);
}
}
synchronized ICommand getCommand(final String id) {
return ourRegistry.get(id);
}
}