com.cloudbees.sdk.Bees Maven / Gradle / Ivy
/*
* Copyright 2010-2013, CloudBees Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cloudbees.sdk;
import com.cloudbees.api.BeesClientException;
import com.cloudbees.sdk.cli.ACommand;
import com.cloudbees.sdk.cli.CommandScope;
import com.cloudbees.sdk.cli.CommandService;
import com.cloudbees.sdk.cli.DirectoryStructure;
import com.cloudbees.sdk.extensibility.AnnotationLiteral;
import com.cloudbees.sdk.maven.RemoteRepositoryDecorator;
import com.cloudbees.sdk.maven.RepositorySystemModule;
import com.cloudbees.sdk.utils.Helper;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.staxnet.appserver.utils.XmlHelper;
import com.staxnet.repository.LocalRepository;
import hudson.util.VersionNumber;
import org.apache.commons.cli.UnrecognizedOptionException;
import org.apache.commons.io.IOUtils;
import org.w3c.dom.*;
import javax.inject.Inject;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
/**
* @author Fabian Donze
* @author Kohsuke Kawaguchi
*/
public class Bees {
public static String BOOTSTRAP_VERSION = "1.3.2";
/**
* Version of the bees CLI.
*/
public static VersionNumber version = loadVersion();
private final static String app_template_xml_url = "http://cloudbees-downloads.s3.amazonaws.com/";
private final static String app_template_xml_name = "sdk/cloudbees-sdk-config-5.xml";
private final static String app_template_xml_desc = "CloudBees SDK configuration";
private static final long CHECK_INTERVAL = 1000 * 60 * 60 * 12; // 12 hours
public final static String CHECK_FILE = "sdk/check-5.dat";
public static final String SDK_PLUGIN_INSTALL = "plugin:install";
@Inject
private CommandService commandService;
@Inject
private PluginsToInstallList pluginsToInstallList;
/**
* Entry point to all the components.
*/
private final Injector injector;
private final ClassLoader extLoader;
public Bees() throws Exception {
extLoader = getClass().getClassLoader();
// container that includes all the things that make a bees CLI.
Injector injector = Guice.createInjector(
new AbstractModule() {
@Override
protected void configure() {
bind(CommandService.class).to(CommandServiceImpl.class);
bind(ClassLoader.class).annotatedWith(AnnotationLiteral.of(ExtensionClassLoader.class)).toInstance(extLoader);
bindScope(CommandScope.class, new CommandScopeImpl());
bind(RemoteRepositoryDecorator.class).to(RemoteRepositoryDecoratorImpl.class);
}
},
new RepositorySystemModule()
);
this.injector = injector;
this.injector.injectMembers(this);
CommandServiceImpl service = (CommandServiceImpl) commandService;
service.loadCommandProperties();
if (service.getCount() == 0) {
throw new RuntimeException("Cannot find bees commands");
}
}
public int run(String[] args) throws Exception {
reportTime("Bees.run");
// Load command definitions
if (args.length == 0) args = new String[]{"help"};
Object context = CommandScopeImpl.begin();
try {
// If it is the init command, execute before anything else
if (args[0].equalsIgnoreCase("init")) {
// Setup the configuration file
ACommand setupCommand = commandService.getCommand(args[0]);
if (setupCommand == null)
throw new Error("Panic: init error");
setupCommand.run(Arrays.asList(args));
// Initialize the SDK
initialize(false);
// Install plugins
installPlugins(args);
return 0;
} else {
// Initialize the SDK
initialize(false);
// Install plugins
installPlugins(args);
ACommand command = commandService.getCommand(args[0]);
if (command == null) {
// no such command. print help
System.err.println("No such command: " + args[0]);
command = commandService.getCommand("help");
if (command == null)
throw new Error("Panic: command " + args[0] + " was not found, and even the help command was not found");
}
int r = command.run(Arrays.asList(args));
if (r == 99) {
initialize(true);
}
return r;
}
} finally {
CommandScopeImpl.end(context);
}
}
private String getHome() {
return System.getProperty("bees.home");
}
private void initialize(boolean force) throws Exception {
LocalRepository localRepository = new LocalRepository();
String beesRepoPath = localRepository.getRepositoryPath();
File lastCheckFile = new File(beesRepoPath, CHECK_FILE);
boolean checkVersion = true;
Properties p = new Properties();
if (!force && Helper.loadProperties(lastCheckFile, p)) {
String str = p.getProperty("last");
if (str != null) {
long interval = System.currentTimeMillis() - Long.parseLong(str);
if (interval < CHECK_INTERVAL)
checkVersion = false;
}
}
if (checkVersion) {
// Check SDK version
File sdkConfig = getURLAsFile(localRepository, app_template_xml_url + app_template_xml_name,
app_template_xml_name, app_template_xml_desc);
Document doc = XmlHelper.readXMLFromFile(sdkConfig.getCanonicalPath());
Element e = doc.getDocumentElement();
String availVersion = e.getAttribute("version");
String minVersion = e.getAttribute("min-version");
VersionNumber currentVersion = new VersionNumber(BOOTSTRAP_VERSION);
VersionNumber availableVersion = new VersionNumber(availVersion);
VersionNumber minimumVersion = new VersionNumber(minVersion);
if (currentVersion.compareTo(availableVersion) < 0) {
System.out.println();
if (currentVersion.compareTo(minimumVersion) < 0) {
throw new AbortException("ERROR - This version of the CloudBees SDK is no longer supported," + "" +
" please install the latest version (" + availVersion + ").");
} else if (currentVersion.compareTo(availableVersion) < 0) {
System.out.println("WARNING - A new version of the CloudBees SDK is available, please install the latest version (" + availVersion + ").");
}
String hRef = e.getAttribute("href");
String homeRef = "www.cloudbees.com";
NodeList nodeList = e.getElementsByTagName("link");
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
NamedNodeMap nodeMap = node.getAttributes();
Node rel = nodeMap.getNamedItem("rel");
Node href = nodeMap.getNamedItem("href");
if (rel != null && rel.getTextContent().trim().equalsIgnoreCase("alternate") && href != null) {
homeRef = href.getTextContent();
}
}
NodeList libsNL = e.getElementsByTagName("libraries");
Node libsNode = null;
if (libsNL.getLength() > 0) {
libsNode = libsNL.item(0);
}
if (libsNode != null) {
NodeList libNL = e.getElementsByTagName("library");
for (int i = 0; i < libNL.getLength(); i++) {
Node node = libNL.item(i);
NamedNodeMap nodeMap = node.getAttributes();
Node nameNode = nodeMap.getNamedItem("name");
Node refNode = nodeMap.getNamedItem("href");
if (nameNode != null && refNode != null) {
String libName = nameNode.getTextContent();
String libUrlString = refNode.getTextContent().trim();
int idx = libUrlString.lastIndexOf('/');
String libFileName = libUrlString.substring(idx);
localRepository.getURLAsFile(libUrlString, "lib1" + libFileName, libName);
}
}
}
System.out.println(" SDK home: " + homeRef);
System.out.println(" SDK download: " + hRef);
System.out.println();
}
// Check plugins version
NodeList pluginsNL = e.getElementsByTagName("plugins");
Node pluginsNode = null;
if (pluginsNL.getLength() > 0) {
pluginsNode = pluginsNL.item(0);
}
if (pluginsNode != null) {
NodeList pluginNL = e.getElementsByTagName("plugin");
CommandServiceImpl service = (CommandServiceImpl) commandService;
for (int i = 0; i < pluginNL.getLength(); i++) {
Node node = pluginNL.item(i);
NamedNodeMap nodeMap = node.getAttributes();
Node nameNode = nodeMap.getNamedItem("artifact");
if (nameNode != null) {
Node n = nodeMap.getNamedItem("required");
boolean forceInstall = (n != null && Boolean.parseBoolean(n.getTextContent()));
String pluginArtifact = nameNode.getTextContent();
GAV gav = new GAV(pluginArtifact);
VersionNumber pluginVersion = new VersionNumber(gav.version);
Plugin plugin = service.getPlugin(gav.artifactId);
if (plugin != null) {
forceInstall = false;
GAV pgav = new GAV(plugin.getArtifact());
VersionNumber currentPluginVersion = new VersionNumber(pgav.version);
if (currentPluginVersion.compareTo(pluginVersion) < 0) {
Node nf = nodeMap.getNamedItem("force-upgrade");
boolean forced = (nf != null && Boolean.parseBoolean(nf.getTextContent()));
if (forced) {
forceInstall = true;
} else {
System.out.println();
System.out.println("WARNING - A newer version of the [" + gav.artifactId + "] plugin is available, please update with:");
System.out.println(" > bees plugin:update " + gav.artifactId);
System.out.println();
}
}
}
if (forceInstall)
pluginsToInstallList.put(gav.artifactId, gav);
}
}
}
// Update last check
p.setProperty("last", "" + System.currentTimeMillis());
lastCheckFile.getParentFile().mkdirs();
FileOutputStream fos = new FileOutputStream(lastCheckFile);
p.store(fos, "CloudBees SDK check");
fos.close();
}
}
private void installPlugins(String[] args) throws Exception {
Set> set = pluginsToInstallList.entrySet();
if (set.size() > 0) {
ACommand installPluginCmd = commandService.getCommand(SDK_PLUGIN_INSTALL);
Iterator> it = set.iterator();
while (it.hasNext()) {
Map.Entry entry = it.next();
System.out.println("Installing plugin: " + entry.getValue());
List piArgs;
if (isVerbose(args))
piArgs = Arrays.asList(SDK_PLUGIN_INSTALL, entry.getValue().toString(), "-f", "-v");
else
piArgs = Arrays.asList(SDK_PLUGIN_INSTALL, entry.getValue().toString(), "-f");
installPluginCmd.run(piArgs);
pluginsToInstallList.remove(entry.getKey());
}
// Reload the plugins commands
CommandServiceImpl service = (CommandServiceImpl) commandService;
service.loadCommandProperties();
}
}
private File getURLAsFile(LocalRepository localRepository, String urlStr, String localCachePath, String description) throws IOException {
try {
DirectoryStructure ds = new DirectoryStructure();
Properties properties = new Properties();
if (Helper.loadProperties(new File(ds.localRepository, "bees.config"), properties)) {
Helper.setJVMProxySettings(properties);
}
return localRepository.getURLAsFile(urlStr, localCachePath, description);
} catch (Exception e) {
throw (IOException) new IOException("Failed to retrieve " + urlStr).initCause(e);
}
}
public static void main(String[] args) {
reportTime("Bees");
boolean verbose = isVerbose(args);
if (verbose || isHelp(args) || isPluginCmd(args)) {
System.out.println("# CloudBees SDK version: " + BOOTSTRAP_VERSION);
System.out.println("# CloudBees Driver version: " + version);
if (verbose) System.out.println(System.getProperties());
}
try {
new Bees().run(args);
} catch (BeesClientException e) {
System.err.println();
String errCode = e.getError().getErrorCode();
if (errCode != null && errCode.equals("AuthFailure")) {
if (e.getError().getMessage() != null)
System.err.println("ERROR: " + e.getError().getMessage());
else
System.err.println("ERROR: Authentication failure, please check credentials!");
} else
System.err.println("ERROR: " + e.getMessage());
// e.printStackTrace();
System.exit(2);
} catch (UnrecognizedOptionException e) {
System.err.println();
System.err.println("ERROR: " + e.getMessage());
System.exit(2);
} catch (IllegalArgumentException e) {
System.err.println();
System.err.println("ERROR: " + e.getMessage());
System.exit(2);
} catch (BeesSecurityException e) {
System.err.println();
System.err.println("ERROR: " + e.getMessage());
System.exit(2);
} catch (Throwable e) {
System.err.println();
System.err.println("ERROR: " + e.getMessage());
if (isVerbose(args))
e.printStackTrace();
System.exit(2);
}
}
/**
* Parses the version number of SDK from the resource file that Maven produces.
*
* To support running this from IDE and elsewhere, work gracefully if the version
* is not available or not filtered.
*/
private static VersionNumber loadVersion() {
Properties props = new Properties();
InputStream in = Bees.class.getResourceAsStream("version.properties");
if (in != null) {
try {
props.load(in);
} catch (IOException e) {
throw new Error(e);
} finally {
IOUtils.closeQuietly(in);
}
}
Object v = props.get("version");
if (v != null)
try {
return new VersionNumber(v.toString());
} catch (Exception e) {
// fall through
}
return new VersionNumber("0");
}
private static boolean isVerbose(String[] args) {
for (String arg : args) {
if (arg.equalsIgnoreCase("-v") || arg.equalsIgnoreCase("--verbose"))
return true;
}
return false;
}
private static boolean isHelp(String[] args) {
if (args.length == 0) return true;
for (String arg : args) {
if (arg.equalsIgnoreCase("help"))
return true;
}
return false;
}
private static boolean isPluginCmd(String[] args) {
if (args.length == 0) return false;
for (String arg : args) {
if (arg.startsWith("plugin:"))
return true;
}
return false;
}
private static void reportTime(String caption) {
String profile = System.getProperty("profile");
if (profile !=null) {
System.out.println(caption+": "+(System.nanoTime()-Long.valueOf(profile))/1000000L+"ms");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy