package slacknotifications.teamcity.settings; import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.text.StringUtil; import jetbrains.buildServer.configuration.ChangeListener; import jetbrains.buildServer.configuration.FileWatcher; import jetbrains.buildServer.serverSide.ServerPaths; import jetbrains.buildServer.util.FileUtil; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; import slacknotifications.SlackNotificationProxyConfig; import slacknotifications.teamcity.Loggers; import java.io.File; import java.io.IOException; public class SlackNotificationMainConfig implements ChangeListener { public static final String DEFAULT_BOTNAME = "TeamCity"; public static final String DEFAULT_ICONURL = "https://raw.githubusercontent.com/PeteGoo/tcSlackBuildNotifier/master/docs/TeamCity72x72.png"; private static final String TOKEN = "token"; private static final String DEFAULT_CHANNEL = "defaultChannel"; private static final String ICON_URL = "iconurl"; private static final String BOT_NAME = "botname"; private static final String SHOW_BUILD_AGENT = "showBuildAgent"; private static final String SHOW_COMMITS = "showCommits"; private static final String SHOW_COMMITTERS = "showCommitters"; private static final String SHOW_FAILURE_REASON = "showFailureReason"; private static final String MAX_COMMITS_TO_DISPLAY = "maxCommitsToDisplay"; private static final String SHOW_ELAPSED_BUILD_TIME = "showElapsedBuildTime"; private static final String HTTPS = "https://"; private static final String HTTP = "http://"; private static final String PROXY = "proxy"; private static final String USERNAME = "username"; private static final String PASSWORD = "password"; private static final String ENABLED = "enabled"; private static final String TEAM_NAME = "teamName"; private final FileWatcher myChangeObserver; private final File myConfigDir; private final File myConfigFile; private String slacknotificationInfoUrl = null; private String slacknotificationInfoText = null; private Boolean slacknotificationShowFurtherReading = true; private Integer proxyPort = null; private String proxyHost = null; private String proxyUsername = null; private String proxyPassword = null; private String defaultChannel = null; private String teamName; private String token; private Boolean proxyShortNames = false; private boolean enabled = true; public final String SINGLE_HOST_REGEX = "^[^./~`'\"]+(?:/.*)?$"; public final String HOSTNAME_ONLY_REGEX = "^([^/]+)(?:/.*)?$"; private SlackNotificationContentConfig content; private boolean configFileExists; public SlackNotificationMainConfig(ServerPaths serverPaths) { this.content = new SlackNotificationContentConfig(); this.myConfigDir = new File(serverPaths.getConfigDir(), "slack"); this.myConfigFile = new File(this.myConfigDir, "slack-config.xml"); configFileExists = this.myConfigFile.exists(); reloadConfiguration(); this.myChangeObserver = new FileWatcher(this.myConfigFile); this.myChangeObserver.setSleepingPeriod(10000L); this.myChangeObserver.registerListener(this); this.myChangeObserver.start(); } public void refresh(){ reloadConfiguration(); } private void reloadConfiguration() { Loggers.ACTIVITIES.info("Loading configuration file: " + this.myConfigFile.getAbsolutePath()); myConfigDir.mkdirs(); FileUtil.copyResourceIfNotExists(getClass(), "/config_templates/slack-config.xml", new File(this.myConfigDir, "slack-config.xml")); Document document = parseFile(this.myConfigFile); if (document != null) { Element rootElement = document.getRootElement(); readConfigurationFromXmlElement(rootElement); } } private Document parseFile(File configFile) { try { if (configFile.isFile()) { return JDOMUtil.loadDocument(configFile); } } catch (JDOMException e) { Loggers.ACTIVITIES.error("Failed to parse xml configuration file: " + configFile.getAbsolutePath(), e); } catch (IOException e) { Loggers.ACTIVITIES.error("I/O error occurred on attempt to parse xml configuration file: " + configFile.getAbsolutePath(), e); } return null; } public String getProxySettingsAsString(){ return " host:" + this.proxyHost + " port: " + this.proxyPort; } public String stripProtocolFromUrl(String url){ String tmpURL = url; if(tmpURL.length() > HTTPS.length() && HTTPS.equalsIgnoreCase(tmpURL.substring(0,HTTPS.length()))) { tmpURL = tmpURL.substring(HTTPS.length()); } else if (tmpURL.length() > HTTP.length() && HTTP.equalsIgnoreCase(tmpURL.substring(0,HTTP.length()))) { tmpURL = tmpURL.substring(HTTP.length()); } return tmpURL; } public Element getInfoUrlAsElement(){ /* <info url="http://acme.com/" text="Using SlackNotifications in Acme Inc." /> */ if (this.slacknotificationInfoUrl != null && this.slacknotificationInfoUrl.length() > 0){ Element e = new Element("info"); e.setAttribute("url", slacknotificationInfoUrl); if (this.slacknotificationInfoText != null && this.slacknotificationInfoText.length() > 0){ e.setAttribute("text", slacknotificationInfoText); } else { e.setAttribute("text", slacknotificationInfoUrl); } e.setAttribute("show-reading", slacknotificationShowFurtherReading.toString()); return e; } return null; } public Element getProxyAsElement(){ /* <proxy host="myproxy.mycompany.com" port="8080" > <noproxy url=".mycompany.com" /> <noproxy url="192.168.0." /> </proxy> */ if (this.getProxyHost() == null || this.getProxyPort() == null){ return null; } Element el = new Element(PROXY); el.setAttribute("host", this.getProxyHost()); el.setAttribute("port", String.valueOf(this.getProxyPort())); if ( this.proxyPassword != null && this.proxyPassword.length() > 0 && this.proxyUsername != null && this.proxyUsername.length() > 0 ) { el.setAttribute(USERNAME, this.getProxyUsername()); el.setAttribute(PASSWORD, this.getProxyPassword()); } return el; } public String getDefaultChannel() { return defaultChannel; } public void setDefaultChannel(String defaultChannel) { this.defaultChannel = defaultChannel; } public String getTeamName() { return teamName; } public void setTeamName(String teamName) { this.teamName = teamName; } public String getToken() { return token; } public void setToken(String token) { this.token = token; } public Integer getProxyPort() { return proxyPort; } public void setProxyPort(Integer proxyPort) { this.proxyPort = proxyPort; } public String getProxyHost() { return proxyHost; } public void setProxyHost(String proxyHost) { this.proxyHost = proxyHost; } public String getProxyUsername() { return proxyUsername; } public void setProxyUsername(String proxyUsername) { this.proxyUsername = proxyUsername; } public String getProxyPassword() { return proxyPassword; } public void setProxyPassword(String proxyPassword) { this.proxyPassword = proxyPassword; } public Boolean isProxyShortNames() { return proxyShortNames; } public void setProxyShortNames(Boolean proxyShortNames) { this.proxyShortNames = proxyShortNames; } public String getSlackNotificationInfoUrl() { return slacknotificationInfoUrl; } public String getSlackNotificationInfoText() { return slacknotificationInfoText; } public boolean getEnabled() { return enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; } public void setSlackNotificationInfoUrl(String slacknotificationInfoUrl) { this.slacknotificationInfoUrl = slacknotificationInfoUrl; } public void setSlackNotificationInfoText(String slacknotificationInfoText) { this.slacknotificationInfoText = slacknotificationInfoText; } public void setSlackNotificationShowFurtherReading(Boolean slacknotificationShowFurtherReading) { this.slacknotificationShowFurtherReading = slacknotificationShowFurtherReading; } public Boolean getSlackNotificationShowFurtherReading() { return slacknotificationShowFurtherReading; } public synchronized void save() { this.myChangeObserver.runActionWithDisabledObserver(new Runnable() { public void run() { FileUtil.processXmlFile(SlackNotificationMainConfig.this.myConfigFile, new FileUtil.Processor() { public void process(Element rootElement) { rootElement.setAttribute("enabled", Boolean.toString(SlackNotificationMainConfig.this.enabled)); rootElement.setAttribute(TEAM_NAME, emptyIfNull(SlackNotificationMainConfig.this.teamName)); rootElement.setAttribute(DEFAULT_CHANNEL, emptyIfNull(SlackNotificationMainConfig.this.defaultChannel)); rootElement.setAttribute(TEAM_NAME, emptyIfNull(SlackNotificationMainConfig.this.teamName)); rootElement.setAttribute(TOKEN, emptyIfNull(SlackNotificationMainConfig.this.token)); rootElement.setAttribute(ICON_URL, emptyIfNull(SlackNotificationMainConfig.this.content.getIconUrl())); rootElement.setAttribute(BOT_NAME, emptyIfNull(SlackNotificationMainConfig.this.content.getBotName())); rootElement.setAttribute(ENABLED, Boolean.toString(SlackNotificationMainConfig.this.enabled)); rootElement.setAttribute(TEAM_NAME, emptyIfNull(SlackNotificationMainConfig.this.teamName)); rootElement.setAttribute("defaultChannel", emptyIfNull(SlackNotificationMainConfig.this.defaultChannel)); rootElement.setAttribute(TEAM_NAME, emptyIfNull(SlackNotificationMainConfig.this.teamName)); rootElement.setAttribute("token", emptyIfNull(SlackNotificationMainConfig.this.token)); rootElement.setAttribute("iconurl", emptyIfNull(SlackNotificationMainConfig.this.content.getIconUrl())); rootElement.setAttribute("botname", emptyIfNull(SlackNotificationMainConfig.this.content.getBotName())); if(SlackNotificationMainConfig.this.content.getShowBuildAgent() != null){ rootElement.setAttribute(SHOW_BUILD_AGENT, Boolean.toString(SlackNotificationMainConfig.this.content.getShowBuildAgent())); } if(SlackNotificationMainConfig.this.content.getShowElapsedBuildTime() != null) { rootElement.setAttribute(SHOW_ELAPSED_BUILD_TIME, Boolean.toString(SlackNotificationMainConfig.this.content.getShowElapsedBuildTime())); } if(SlackNotificationMainConfig.this.content.getShowCommits() != null) { rootElement.setAttribute(SHOW_COMMITS, Boolean.toString(SlackNotificationMainConfig.this.content.getShowCommits())); } if(SlackNotificationMainConfig.this.content.getShowCommitters() != null) { rootElement.setAttribute(SHOW_COMMITTERS, Boolean.toString(SlackNotificationMainConfig.this.content.getShowCommitters())); } if(SlackNotificationMainConfig.this.content.getShowFailureReason() != null) { rootElement.setAttribute(SHOW_FAILURE_REASON, Boolean.toString(SlackNotificationMainConfig.this.content.getShowFailureReason())); } rootElement.setAttribute(MAX_COMMITS_TO_DISPLAY, Integer.toString(SlackNotificationMainConfig.this.content.getMaxCommitsToDisplay())); rootElement.removeChildren(PROXY); rootElement.removeChildren("info"); if(getProxyHost() != null && getProxyHost().length() > 0 && getProxyPort() != null && getProxyPort() > 0 ) { rootElement.addContent(getProxyAsElement()); Loggers.SERVER.debug(SlackNotificationMainConfig.class.getName() + "writeTo :: proxyHost " + getProxyHost()); Loggers.SERVER.debug(SlackNotificationMainConfig.class.getName() + "writeTo :: proxyPort " + getProxyPort()); } if(getInfoUrlAsElement() != null){ rootElement.addContent(getInfoUrlAsElement()); Loggers.SERVER.debug(SlackNotificationMainConfig.class.getName() + "writeTo :: infoText " + getSlackNotificationInfoText()); Loggers.SERVER.debug(SlackNotificationMainConfig.class.getName() + "writeTo :: InfoUrl " + getSlackNotificationInfoUrl()); Loggers.SERVER.debug(SlackNotificationMainConfig.class.getName() + "writeTo :: show-reading " + getSlackNotificationShowFurtherReading().toString()); } } }); } }); } private String emptyIfNull(String str){ return str == null ? "" : str; } @Override public void changeOccured(String s) { reloadConfiguration(); } public boolean getConfigFileExists() { return configFileExists; } void readConfigurationFromXmlElement(Element slackNotificationsElement) { if(slackNotificationsElement != null){ content.setEnabled(true); if(slackNotificationsElement.getAttribute(ENABLED) != null) { setEnabled(Boolean.parseBoolean(slackNotificationsElement.getAttributeValue(ENABLED))); } if(slackNotificationsElement.getAttribute(DEFAULT_CHANNEL) != null) { setDefaultChannel(slackNotificationsElement.getAttributeValue(DEFAULT_CHANNEL)); } if(slackNotificationsElement.getAttribute(TEAM_NAME) != null) { setTeamName(slackNotificationsElement.getAttributeValue(TEAM_NAME)); } if(slackNotificationsElement.getAttribute(TOKEN) != null) { setToken(slackNotificationsElement.getAttributeValue(TOKEN)); } if(slackNotificationsElement.getAttribute(ICON_URL) != null) { content.setIconUrl(slackNotificationsElement.getAttributeValue(ICON_URL)); } if(slackNotificationsElement.getAttribute(BOT_NAME) != null) { content.setBotName(slackNotificationsElement.getAttributeValue(BOT_NAME)); } if(slackNotificationsElement.getAttribute(SHOW_BUILD_AGENT) != null) { content.setShowBuildAgent(Boolean.parseBoolean(slackNotificationsElement.getAttributeValue(SHOW_BUILD_AGENT))); } if(slackNotificationsElement.getAttribute(SHOW_ELAPSED_BUILD_TIME) != null) { content.setShowElapsedBuildTime(Boolean.parseBoolean(slackNotificationsElement.getAttributeValue(SHOW_ELAPSED_BUILD_TIME))); } if(slackNotificationsElement.getAttribute(SHOW_COMMITS) != null) { content.setShowCommits(Boolean.parseBoolean(slackNotificationsElement.getAttributeValue(SHOW_COMMITS))); } if(slackNotificationsElement.getAttribute(SHOW_COMMITTERS) != null) { content.setShowCommitters(Boolean.parseBoolean(slackNotificationsElement.getAttributeValue(SHOW_COMMITTERS))); } if(slackNotificationsElement.getAttribute(MAX_COMMITS_TO_DISPLAY) != null) { content.setMaxCommitsToDisplay(Integer.parseInt(slackNotificationsElement.getAttributeValue(MAX_COMMITS_TO_DISPLAY))); } if(slackNotificationsElement.getAttribute(SHOW_FAILURE_REASON) != null) { content.setShowFailureReason(Boolean.parseBoolean(slackNotificationsElement.getAttributeValue(SHOW_FAILURE_REASON))); } Element proxyElement = slackNotificationsElement.getChild(PROXY); if(proxyElement != null) { if (proxyElement.getAttribute("proxyShortNames") != null){ setProxyShortNames(Boolean.parseBoolean(proxyElement.getAttributeValue("proxyShortNames"))); } if (proxyElement.getAttribute("host") != null){ setProxyHost(proxyElement.getAttributeValue("host")); } if (proxyElement.getAttribute("port") != null){ setProxyPort(Integer.parseInt(proxyElement.getAttributeValue("port"))); } if (proxyElement.getAttribute(USERNAME) != null){ setProxyUsername(proxyElement.getAttributeValue(USERNAME)); } if (proxyElement.getAttribute(PASSWORD) != null){ setProxyPassword(proxyElement.getAttributeValue(PASSWORD)); } } else { setProxyHost(null); setProxyPort(null); setProxyUsername(null); setProxyPassword(null); } } } public SlackNotificationProxyConfig getProxyConfig() { return new SlackNotificationProxyConfig(proxyHost, proxyPort, proxyUsername, proxyPassword); } public SlackNotificationContentConfig getContent() { if(content == null){ this.content = new SlackNotificationContentConfig(); } return content; } }