/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* 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.intellij.openapi.application.impl;
import com.intellij.openapi.application.ApplicationInfo;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.ex.ApplicationInfoEx;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.BuildNumber;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.text.StringUtil;
import consulo.annotations.DeprecationInfo;
import org.jdom.Document;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import java.awt.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class ApplicationInfoImpl extends ApplicationInfoEx {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.application.impl.ApplicationInfoImpl");
@NonNls
@Deprecated
@DeprecationInfo(value = "Use consulo.ide.webService.WebServiceApi")
private static final String DEFAULT_STATISTICS_HOST = "http://must-be.org/consulo/statistics/";
private String myMajorVersion = null;
private String myMinorVersion = null;
private String myBuildNumber = null;
private String myCompanyName = "Must-Be";
private String myCompanyUrl = "https://consulo.io";
private Color myAboutForeground = Color.black;
private Color myAboutLinkColor = null;
private String myAboutImageUrl = null;
private Calendar myBuildDate = null;
private String myDocumentationUrl;
private String mySupportUrl;
private String myEAPFeedbackUrl;
private String myReleaseFeedbackUrl;
private String myStatisticsUrl;
private String myWhatsNewUrl;
private String myWinKeymapUrl;
private String myMacKeymapUrl;
private boolean myEAP;
private boolean myHasHelp = true;
private boolean myHasContextHelp = true;
@NonNls private String myHelpFileName = "ideahelp.jar";
@NonNls private String myHelpRootName = "idea";
@NonNls private String myWebHelpUrl = "https://github.com/consulo/consulo/wiki";
private Rectangle myAboutLogoRect;
@NonNls private static final String ELEMENT_VERSION = "version";
@NonNls private static final String ATTRIBUTE_MAJOR = "major";
@NonNls private static final String ATTRIBUTE_MINOR = "minor";
@NonNls private static final String ATTRIBUTE_NAME = "name";
@NonNls private static final String ELEMENT_BUILD = "build";
@NonNls private static final String ELEMENT_COMPANY = "company";
@NonNls private static final String ATTRIBUTE_NUMBER = "number";
@NonNls private static final String ATTRIBUTE_DATE = "date";
@NonNls private static final String ATTRIBUTE_URL = "url";
@NonNls private static final String ATTRIBUTE_ABOUT_FOREGROUND_COLOR = "foreground";
@NonNls private static final String ATTRIBUTE_ABOUT_LINK_COLOR = "linkColor";
@NonNls private static final String ELEMENT_ABOUT = "about";
@NonNls private static final String ATTRIBUTE_EAP = "eap";
@NonNls private static final String HELP_ELEMENT_NAME = "help";
@NonNls private static final String ATTRIBUTE_HELP_FILE = "file";
@NonNls private static final String ATTRIBUTE_HELP_ROOT = "root";
@NonNls private static final String ELEMENT_DOCUMENTATION = "documentation";
@NonNls private static final String ELEMENT_SUPPORT = "support";
@NonNls private static final String ELEMENT_FEEDBACK = "feedback";
@NonNls private static final String ATTRIBUTE_RELEASE_URL = "release-url";
@NonNls private static final String ATTRIBUTE_EAP_URL = "eap-url";
@NonNls private static final String ATTRIBUTE_WEBHELP_URL = "webhelp-url";
@NonNls private static final String ATTRIBUTE_HAS_HELP = "has-help";
@NonNls private static final String ATTRIBUTE_HAS_CONTEXT_HELP = "has-context-help";
@NonNls private static final String ELEMENT_WHATSNEW = "whatsnew";
@NonNls private static final String ELEMENT_KEYMAP = "keymap";
@NonNls private static final String ATTRIBUTE_WINDOWS_URL = "win";
@NonNls private static final String ATTRIBUTE_MAC_URL = "mac";
public ApplicationInfoImpl() {
load();
}
@Override
public Calendar getBuildDate() {
return myBuildDate;
}
@Override
public BuildNumber getBuild() {
return BuildNumber.fromString(myBuildNumber);
}
@Override
public String getMajorVersion() {
return myMajorVersion;
}
@Override
public String getMinorVersion() {
return myMinorVersion;
}
@Override
public String getVersionName() {
return ApplicationNamesInfo.getInstance().getFullProductName();
}
@Override
@NonNls
public String getHelpURL() {
return "jar:file:///" + getHelpJarPath() + "!/" + myHelpRootName;
}
@Override
public String getCompanyName() {
return myCompanyName;
}
@Override
public String getCompanyURL() {
return myCompanyUrl;
}
@NonNls
private String getHelpJarPath() {
return PathManager.getHomePath() + File.separator + "help" + File.separator + myHelpFileName;
}
@Override
public String getAboutImageUrl() {
return myAboutImageUrl;
}
@Override
public boolean isEAP() {
return myEAP;
}
@Override
public String getDocumentationUrl() {
return myDocumentationUrl;
}
@Override
public String getSupportUrl() {
return mySupportUrl;
}
@Override
public String getEAPFeedbackUrl() {
return myEAPFeedbackUrl;
}
@Override
public String getReleaseFeedbackUrl() {
return myReleaseFeedbackUrl;
}
@Override
public String getStatisticsUrl() {
return myStatisticsUrl;
}
@Override
public String getWebHelpUrl() {
return myWebHelpUrl;
}
@Override
public boolean hasHelp() {
return myHasHelp;
}
@Override
public boolean hasContextHelp() {
return myHasContextHelp;
}
@Override
public String getWhatsNewUrl() {
return myWhatsNewUrl;
}
@Override
public String getWinKeymapUrl() {
return myWinKeymapUrl;
}
@Override
public String getMacKeymapUrl() {
return myMacKeymapUrl;
}
@Override
public Color getAboutForeground() {
return myAboutForeground;
}
public Color getAboutLinkColor() {
return myAboutLinkColor;
}
@Override
public String getFullApplicationName() {
@NonNls StringBuilder buffer = new StringBuilder();
buffer.append(getVersionName());
buffer.append(" ");
buffer.append(getMajorVersion());
String minorVersion = getMinorVersion();
if (!StringUtil.isEmpty(minorVersion)){
buffer.append(".");
buffer.append(getMinorVersion());
}
if (isEAP() || isBetaOrRC()) {
buffer.append(" #");
buffer.append(getBuild().asString());
}
return buffer.toString();
}
@Override
public Rectangle getAboutLogoRect() {
return myAboutLogoRect;
}
private static ApplicationInfoImpl ourShadowInstance;
public boolean isBetaOrRC() {
String minor = getMinorVersion();
if (minor != null) {
if (minor.contains("RC") || minor.contains("Beta") || minor.contains("beta")) {
return true;
}
}
return false;
}
public static ApplicationInfoEx getShadowInstance() {
if (ourShadowInstance == null) {
ourShadowInstance = new ApplicationInfoImpl();
}
return ourShadowInstance;
}
private void load() {
try {
Document doc = JDOMUtil.loadDocument(ApplicationInfoImpl.class, ApplicationInfo.ABSOLUTE_APPLICATION_INFO_XML);
readExternal(doc.getRootElement());
}
catch (FileNotFoundException e) {
LOG.error("Resource is not in classpath", e);
}
catch (Exception e) {
LOG.error(e);
}
}
private void readExternal(Element parentNode) throws InvalidDataException {
Element versionElement = parentNode.getChild(ELEMENT_VERSION);
if (versionElement != null) {
myMajorVersion = versionElement.getAttributeValue(ATTRIBUTE_MAJOR);
myMinorVersion = versionElement.getAttributeValue(ATTRIBUTE_MINOR);
myEAP = Boolean.parseBoolean(versionElement.getAttributeValue(ATTRIBUTE_EAP));
}
Element companyElement = parentNode.getChild(ELEMENT_COMPANY);
if (companyElement != null) {
myCompanyName = companyElement.getAttributeValue(ATTRIBUTE_NAME, myCompanyName);
myCompanyUrl = companyElement.getAttributeValue(ATTRIBUTE_URL, myCompanyUrl);
}
Element buildElement = parentNode.getChild(ELEMENT_BUILD);
if (buildElement != null) {
myBuildNumber = buildElement.getAttributeValue(ATTRIBUTE_NUMBER);
String dateString = buildElement.getAttributeValue(ATTRIBUTE_DATE);
if (dateString.equals("__BUILD_DATE__")) {
myBuildDate = new GregorianCalendar();
try {
final JarFile bootJar = new JarFile(PathManager.getHomePath() + File.separator + "lib" + File.separator + "boot.jar");
try {
final JarEntry jarEntry = bootJar.entries().nextElement(); // /META-INF is always updated on build
myBuildDate.setTime(new Date(jarEntry.getTime()));
}
finally {
bootJar.close();
}
}
catch (Exception ignore) { }
}
else {
myBuildDate = parseDate(dateString);
}
}
String consuloBuildNumber = System.getProperty("consulo.build.number");
if(consuloBuildNumber != null) {
myBuildNumber = consuloBuildNumber;
}
Thread currentThread = Thread.currentThread();
currentThread.setName(currentThread.getName() + " " + myMajorVersion + "." + myMinorVersion + "#" + myBuildNumber + ", eap:" + myEAP);
Element aboutLogoElement = parentNode.getChild(ELEMENT_ABOUT);
if (aboutLogoElement != null) {
myAboutImageUrl = aboutLogoElement.getAttributeValue(ATTRIBUTE_URL);
String v = aboutLogoElement.getAttributeValue(ATTRIBUTE_ABOUT_FOREGROUND_COLOR);
if (v != null) {
myAboutForeground = parseColor(v);
}
String c = aboutLogoElement.getAttributeValue(ATTRIBUTE_ABOUT_LINK_COLOR);
if (c != null) {
myAboutLinkColor = parseColor(c);
}
String logoX = aboutLogoElement.getAttributeValue("logoX");
String logoY = aboutLogoElement.getAttributeValue("logoY");
String logoW = aboutLogoElement.getAttributeValue("logoW");
String logoH = aboutLogoElement.getAttributeValue("logoH");
if (logoX != null && logoY != null && logoW != null && logoH != null) {
try {
myAboutLogoRect =
new Rectangle(Integer.parseInt(logoX), Integer.parseInt(logoY), Integer.parseInt(logoW), Integer.parseInt(logoH));
}
catch (NumberFormatException nfe) {
// ignore
}
}
}
Element helpElement = parentNode.getChild(HELP_ELEMENT_NAME);
if (helpElement != null) {
myHelpFileName = helpElement.getAttributeValue(ATTRIBUTE_HELP_FILE);
myHelpRootName = helpElement.getAttributeValue(ATTRIBUTE_HELP_ROOT);
final String webHelpUrl = helpElement.getAttributeValue(ATTRIBUTE_WEBHELP_URL);
if (webHelpUrl != null) {
myWebHelpUrl = webHelpUrl;
}
String attValue = helpElement.getAttributeValue(ATTRIBUTE_HAS_HELP);
myHasHelp = attValue == null || Boolean.parseBoolean(attValue); // Default is true
attValue = helpElement.getAttributeValue(ATTRIBUTE_HAS_CONTEXT_HELP);
myHasContextHelp = attValue == null || Boolean.parseBoolean(attValue); // Default is true
}
Element documentationElement = parentNode.getChild(ELEMENT_DOCUMENTATION);
if (documentationElement != null) {
myDocumentationUrl = documentationElement.getAttributeValue(ATTRIBUTE_URL);
}
Element supportElement = parentNode.getChild(ELEMENT_SUPPORT);
if (supportElement != null) {
mySupportUrl = supportElement.getAttributeValue(ATTRIBUTE_URL);
}
Element feedbackElement = parentNode.getChild(ELEMENT_FEEDBACK);
if (feedbackElement != null) {
myEAPFeedbackUrl = feedbackElement.getAttributeValue(ATTRIBUTE_EAP_URL);
myReleaseFeedbackUrl = feedbackElement.getAttributeValue(ATTRIBUTE_RELEASE_URL);
}
Element whatsnewElement = parentNode.getChild(ELEMENT_WHATSNEW);
if (whatsnewElement != null) {
myWhatsNewUrl = whatsnewElement.getAttributeValue(ATTRIBUTE_URL);
}
myStatisticsUrl = StringUtil.notNullize(System.getProperty("consulo.statistics.host"), DEFAULT_STATISTICS_HOST) + "post";
Element keymapElement = parentNode.getChild(ELEMENT_KEYMAP);
if (keymapElement != null) {
myWinKeymapUrl = keymapElement.getAttributeValue(ATTRIBUTE_WINDOWS_URL);
myMacKeymapUrl = keymapElement.getAttributeValue(ATTRIBUTE_MAC_URL);
}
}
private static GregorianCalendar parseDate(final String dateString) {
@SuppressWarnings("MultipleVariablesInDeclaration")
int year = 0, month = 0, day = 0, hour = 0, minute = 0;
try {
year = Integer.parseInt(dateString.substring(0, 4));
month = Integer.parseInt(dateString.substring(4, 6));
day = Integer.parseInt(dateString.substring(6, 8));
if (dateString.length() > 8) {
hour = Integer.parseInt(dateString.substring(8, 10));
minute = Integer.parseInt(dateString.substring(10, 12));
}
}
catch (Exception ignore) { }
if (month > 0) month--;
return new GregorianCalendar(year, month, day, hour, minute);
}
private static Color parseColor(final String colorString) {
final long rgb = Long.parseLong(colorString, 16);
return new Color((int)rgb, rgb > 0xffffff);
}
private static volatile boolean myInPerformanceTest;
public static boolean isInPerformanceTest() {
return myInPerformanceTest;
}
public static void setInPerformanceTest(boolean inPerformanceTest) {
myInPerformanceTest = inPerformanceTest;
}
}