Merge remote-tracking branch 'origin/master'
[idea/community.git] / platform / core-impl / src / com / intellij / openapi / application / impl / ApplicationInfoImpl.java
1 /*
2  * Copyright 2000-2014 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.openapi.application.impl;
17
18 import com.intellij.ide.plugins.PluginManagerCore;
19 import com.intellij.openapi.application.ApplicationNamesInfo;
20 import com.intellij.openapi.application.PathManager;
21 import com.intellij.openapi.application.ex.ApplicationInfoEx;
22 import com.intellij.openapi.components.ApplicationComponent;
23 import com.intellij.openapi.diagnostic.Logger;
24 import com.intellij.openapi.util.*;
25 import com.intellij.openapi.util.text.StringUtil;
26 import com.intellij.ui.JBColor;
27 import com.intellij.util.PlatformUtilsCore;
28 import org.jdom.Document;
29 import org.jdom.Element;
30 import org.jetbrains.annotations.NonNls;
31 import org.jetbrains.annotations.NotNull;
32 import org.jetbrains.annotations.Nullable;
33
34 import javax.swing.*;
35 import java.awt.*;
36 import java.io.File;
37 import java.io.FileNotFoundException;
38 import java.util.*;
39 import java.util.List;
40 import java.util.jar.JarEntry;
41 import java.util.jar.JarFile;
42
43 public class ApplicationInfoImpl extends ApplicationInfoEx implements JDOMExternalizable, ApplicationComponent {
44   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.application.impl.ApplicationInfoImpl");
45
46   private String myCodeName = null;
47   private String myMajorVersion = null;
48   private String myMinorVersion = null;
49   private String myBuildNumber = null;
50   private String myApiVersion = null;
51   private String myCompanyName = "JetBrains s.r.o.";
52   private String myCompanyUrl = "http://www.jetbrains.com/";
53   private Color myProgressColor = null;
54   private Color myCopyrightForeground = JBColor.BLACK;
55   private Color myAboutForeground = JBColor.BLACK;
56   private Color myAboutLinkColor = null;
57   private String myProgressTailIconName = null;
58   private Icon myProgressTailIcon = null;
59
60   private int myProgressY = 350;
61   private String mySplashImageUrl = null;
62   private String myAboutImageUrl = null;
63   private Color mySplashTextColor = new Color(0, 35, 135);  // idea blue
64   @NonNls private String myIconUrl = "/icon.png";
65   @NonNls private String mySmallIconUrl = "/icon_small.png";
66   @NonNls private String myBigIconUrl = null;
67   @NonNls private String myOpaqueIconUrl = "/icon.png";
68   @NonNls private String myToolWindowIconUrl = "/toolwindows/toolWindowProject.png";
69   private String myWelcomeScreenLogoUrl = null;
70   private String myEditorBackgroundImageUrl = null;
71
72   private Calendar myBuildDate = null;
73   private Calendar myMajorReleaseBuildDate = null;
74   private String myPackageCode = null;
75   private boolean myShowLicensee = true;
76   private String myWelcomeScreenCaptionUrl;
77   private String myWelcomeScreenDeveloperSloganUrl;
78   private UpdateUrls myUpdateUrls;
79   private String myDocumentationUrl;
80   private String mySupportUrl;
81   private String myEAPFeedbackUrl;
82   private String myReleaseFeedbackUrl;
83   private String myPluginManagerUrl;
84   private String myPluginsListUrl;
85   private String myPluginsDownloadUrl;
86   private String myBuiltinPluginsUrl;
87   private String myWhatsNewUrl;
88   private String myWinKeymapUrl;
89   private String myMacKeymapUrl;
90   private boolean myEAP;
91   private boolean myHasHelp = true;
92   private boolean myHasContextHelp = true;
93   @NonNls private String myHelpFileName = "ideahelp.jar";
94   @NonNls private String myHelpRootName = "idea";
95   @NonNls private String myWebHelpUrl = "http://www.jetbrains.com/idea/webhelp/";
96   private List<PluginChooserPage> myPluginChooserPages = new ArrayList<PluginChooserPage>();
97   private String myStatisticsSettingsUrl;
98   private String myStatisticsServiceUrl;
99   private String myStatisticsServiceKey;
100   private String myThirdPartySoftwareUrl;
101
102   private Rectangle myAboutLogoRect;
103
104   @NonNls private static final String IDEA_PATH = "/idea/";
105   @NonNls private static final String ELEMENT_VERSION = "version";
106   @NonNls private static final String ATTRIBUTE_MAJOR = "major";
107   @NonNls private static final String ATTRIBUTE_MINOR = "minor";
108   @NonNls private static final String ATTRIBUTE_CODENAME = "codename";
109   @NonNls private static final String ATTRIBUTE_NAME = "name";
110   @NonNls private static final String ELEMENT_BUILD = "build";
111   @NonNls private static final String ELEMENT_COMPANY = "company";
112   @NonNls private static final String ATTRIBUTE_NUMBER = "number";
113   @NonNls private static final String ATTRIBUTE_API_VERSION = "apiVersion";
114   @NonNls private static final String ATTRIBUTE_DATE = "date";
115   @NonNls private static final String ATTRIBUTE_MAJOR_RELEASE_DATE = "majorReleaseDate";
116   @NonNls private static final String ELEMENT_LOGO = "logo";
117   @NonNls private static final String ATTRIBUTE_URL = "url";
118   @NonNls private static final String ATTRIBUTE_TEXT_COLOR = "textcolor";
119   @NonNls private static final String ATTRIBUTE_PROGRESS_COLOR = "progressColor";
120   @NonNls private static final String ATTRIBUTE_ABOUT_FOREGROUND_COLOR = "foreground";
121   @NonNls private static final String ATTRIBUTE_ABOUT_COPYRIGHT_FOREGROUND_COLOR = "copyrightForeground";
122   @NonNls private static final String ATTRIBUTE_ABOUT_LINK_COLOR = "linkColor";
123   @NonNls private static final String ATTRIBUTE_PROGRESS_Y = "progressY";
124   @NonNls private static final String ATTRIBUTE_PROGRESS_TAIL_ICON = "progressTailIcon";
125   @NonNls private static final String ELEMENT_ABOUT = "about";
126   @NonNls private static final String ELEMENT_ICON = "icon";
127   @NonNls private static final String ATTRIBUTE_SIZE32 = "size32";
128   @NonNls private static final String ATTRIBUTE_SIZE128 = "size128";
129   @NonNls private static final String ATTRIBUTE_SIZE16 = "size16";
130   @NonNls private static final String ATTRIBUTE_SIZE12 = "size12";
131   @NonNls private static final String ATTRIBUTE_SIZE32OPAQUE = "size32opaque";
132   @NonNls private static final String ELEMENT_PACKAGE = "package";
133   @NonNls private static final String ATTRIBUTE_CODE = "code";
134   @NonNls private static final String ELEMENT_LICENSEE = "licensee";
135   @NonNls private static final String ATTRIBUTE_SHOW = "show";
136   @NonNls private static final String WELCOME_SCREEN_ELEMENT_NAME = "welcome-screen";
137   @NonNls private static final String CAPTION_URL_ATTR = "caption-url";
138   @NonNls private static final String LOGO_URL_ATTR = "logo-url";
139   @NonNls private static final String SLOGAN_URL_ATTR = "slogan-url";
140   @NonNls private static final String ELEMENT_EDITOR = "editor";
141   @NonNls private static final String BACKGROUND_URL_ATTR = "background-url";
142   @NonNls private static final String UPDATE_URLS_ELEMENT_NAME = "update-urls";
143   @NonNls private static final String XML_EXTENSION = ".xml";
144   @NonNls private static final String ATTRIBUTE_EAP = "eap";
145   @NonNls private static final String HELP_ELEMENT_NAME = "help";
146   @NonNls private static final String ATTRIBUTE_HELP_FILE = "file";
147   @NonNls private static final String ATTRIBUTE_HELP_ROOT = "root";
148   @NonNls private static final String PLUGINS_PAGE_ELEMENT_NAME = "plugins-page";
149   @NonNls private static final String ELEMENT_DOCUMENTATION = "documentation";
150   @NonNls private static final String ELEMENT_SUPPORT = "support";
151   @NonNls private static final String ELEMENT_FEEDBACK = "feedback";
152   @NonNls private static final String ATTRIBUTE_RELEASE_URL = "release-url";
153   @NonNls private static final String ATTRIBUTE_EAP_URL = "eap-url";
154   @NonNls private static final String ELEMENT_PLUGINS = "plugins";
155   @NonNls private static final String ATTRIBUTE_LIST_URL = "list-url";
156   @NonNls private static final String ATTRIBUTE_DOWNLOAD_URL = "download-url";
157   @NonNls private static final String ATTRIBUTE_BUILTIN_URL = "builtin-url";
158   @NonNls private static final String ATTRIBUTE_WEBHELP_URL = "webhelp-url";
159   @NonNls private static final String ATTRIBUTE_HAS_HELP = "has-help";
160   @NonNls private static final String ATTRIBUTE_HAS_CONTEXT_HELP = "has-context-help";
161   @NonNls private static final String ELEMENT_WHATSNEW = "whatsnew";
162   @NonNls private static final String ELEMENT_KEYMAP = "keymap";
163   @NonNls private static final String ATTRIBUTE_WINDOWS_URL = "win";
164   @NonNls private static final String ATTRIBUTE_MAC_URL = "mac";
165   @NonNls private static final String DEFAULT_PLUGINS_HOST = "http://plugins.jetbrains.com";
166
167   @NonNls private static final String ELEMENT_STATISTICS = "statistics";
168   @NonNls private static final String ATTRIBUTE_STATISTICS_SETTINGS = "settings";
169   @NonNls private static final String ATTRIBUTE_STATISTICS_SERVICE = "service";
170   @NonNls private static final String ATTRIBUTE_STATISTICS_SERVICE_KEY = "service-key";
171
172   @NonNls private static final String ELEMENT_THIRD_PARTY = "third-party";
173
174
175   public void initComponent() { }
176
177   public void disposeComponent() { }
178
179   public Calendar getBuildDate() {
180     return myBuildDate;
181   }
182
183   public Calendar getMajorReleaseBuildDate() {
184     return myMajorReleaseBuildDate != null ? myMajorReleaseBuildDate : myBuildDate;
185   }
186
187   @Override
188   public BuildNumber getBuild() {
189     return BuildNumber.fromString(myBuildNumber, getProductPrefix());
190   }
191
192   private static String getProductPrefix() {
193     String prefix = null;
194     if (PlatformUtilsCore.isCommunity()) {
195       prefix = "IC";
196     }
197     else if (PlatformUtilsCore.isIdea()) {
198       prefix = "IU";
199     }
200     return prefix;
201   }
202
203   @Override
204   public String getApiVersion() {
205     if (myApiVersion != null) {
206       return BuildNumber.fromString(myApiVersion, getProductPrefix()).asString();
207     }
208     return getBuild().asString();
209   }
210
211   public String getMajorVersion() {
212     return myMajorVersion;
213   }
214
215   public String getMinorVersion() {
216     return myMinorVersion;
217   }
218
219   public String getVersionName() {
220     final String fullName = ApplicationNamesInfo.getInstance().getFullProductName();
221     if (myEAP && !StringUtil.isEmptyOrSpaces(myCodeName)) {
222       return fullName + " (" + myCodeName + ")";
223     }
224     return fullName;
225   }
226
227   @NonNls
228   public String getHelpURL() {
229     return "jar:file:///" + getHelpJarPath() + "!/" + myHelpRootName;
230   }
231
232   @Override
233   public String getCompanyName() {
234     return myCompanyName;
235   }
236
237   @Override
238   public String getCompanyURL() {
239     return myCompanyUrl;
240   }
241
242   @NonNls
243   private String getHelpJarPath() {
244     return PathManager.getHomePath() + File.separator + "help" + File.separator + myHelpFileName;
245   }
246
247   public String getSplashImageUrl() {
248     return mySplashImageUrl;
249   }
250
251   public Color getSplashTextColor() {
252     return mySplashTextColor;
253   }
254
255   public String getAboutImageUrl() {
256     return myAboutImageUrl;
257   }
258
259   public Color getProgressColor() {
260     return myProgressColor;
261   }
262
263   public Color getCopyrightForeground() {
264     return myCopyrightForeground;
265   }
266
267   public int getProgressY() {
268     return myProgressY;
269   }
270
271   @Nullable
272   public Icon getProgressTailIcon() {
273     if (myProgressTailIcon == null && myProgressTailIconName != null) {
274       myProgressTailIcon = IconLoader.getIcon(myProgressTailIconName);
275     }
276     return myProgressTailIcon;
277   }
278
279   public String getIconUrl() {
280     return myIconUrl;
281   }
282
283   public String getSmallIconUrl() {
284     return mySmallIconUrl;
285   }
286
287   @Override
288   @Nullable
289   public String getBigIconUrl() {
290     return myBigIconUrl;
291   }
292
293   public String getOpaqueIconUrl() {
294     return myOpaqueIconUrl;
295   }
296
297   public String getToolWindowIconUrl() {
298     return myToolWindowIconUrl;
299   }
300
301   public String getWelcomeScreenCaptionUrl() {
302     return myWelcomeScreenCaptionUrl;
303   }
304
305   public String getWelcomeScreenDeveloperSloganUrl() {
306     return myWelcomeScreenDeveloperSloganUrl;
307   }
308
309   @Override
310   public String getWelcomeScreenLogoUrl() {
311     return myWelcomeScreenLogoUrl;
312   }
313
314   @Override
315   public String getEditorBackgroundImageUrl() {
316     return myEditorBackgroundImageUrl;
317   }
318
319   public String getPackageCode() {
320     return myPackageCode;
321   }
322
323   public boolean isEAP() {
324     return myEAP;
325   }
326
327   public UpdateUrls getUpdateUrls() {
328     return myUpdateUrls;
329   }
330
331   public String getDocumentationUrl() {
332     return myDocumentationUrl;
333   }
334
335   public String getSupportUrl() {
336     return mySupportUrl;
337   }
338
339   public String getEAPFeedbackUrl() {
340     return myEAPFeedbackUrl;
341   }
342
343   public String getReleaseFeedbackUrl() {
344     return myReleaseFeedbackUrl;
345   }
346
347   @Override
348   public String getPluginManagerUrl() {
349     return myPluginManagerUrl;
350   }
351
352   public String getPluginsListUrl() {
353     return myPluginsListUrl;
354   }
355
356   public String getPluginsDownloadUrl() {
357     return myPluginsDownloadUrl;
358   }
359
360   public String getBuiltinPluginsUrl() {
361     return myBuiltinPluginsUrl;
362   }
363
364   public String getWebHelpUrl() {
365     return myWebHelpUrl;
366   }
367
368   @Override
369   public boolean hasHelp() {
370     return myHasHelp;
371   }
372
373   @Override
374   public boolean hasContextHelp() {
375     return myHasContextHelp;
376   }
377
378   public String getWhatsNewUrl() {
379     return myWhatsNewUrl;
380   }
381
382   public String getWinKeymapUrl() {
383     return myWinKeymapUrl;
384   }
385
386   public String getMacKeymapUrl() {
387     return myMacKeymapUrl;
388   }
389
390   @Override
391   public Color getAboutForeground() {
392     return myAboutForeground;
393   }
394
395   public Color getAboutLinkColor() {
396     return myAboutLinkColor;
397   }
398
399   public String getFullApplicationName() {
400     @NonNls StringBuilder buffer = new StringBuilder();
401     buffer.append(getVersionName());
402     buffer.append(" ");
403     if (getMajorVersion() != null && !isEAP() && !isBetaOrRC()) {
404       buffer.append(getMajorVersion());
405
406       if (getMinorVersion() != null && getMinorVersion().length() > 0){
407         buffer.append(".");
408         buffer.append(getMinorVersion());
409       }
410     }
411     else {
412       buffer.append(getBuild().asStringWithAllDetails());
413     }
414     return buffer.toString();
415   }
416
417   public boolean showLicenseeInfo() {
418     return myShowLicensee;
419   }
420
421   public String getStatisticsSettingsUrl() {
422     return myStatisticsSettingsUrl;
423   }
424
425   public String getStatisticsServiceUrl() {
426     return myStatisticsServiceUrl;
427   }
428
429   public String getStatisticsServiceKey() {
430     return myStatisticsServiceKey;
431   }
432
433   @Override
434   public String getThirdPartySoftwareURL() {
435     return myThirdPartySoftwareUrl;
436   }
437
438   @Override
439   public Rectangle getAboutLogoRect() {
440     return myAboutLogoRect;
441   }
442
443   private static ApplicationInfoImpl ourShadowInstance;
444
445   public boolean isBetaOrRC() {
446     String minor = getMinorVersion();
447     if (minor != null) {
448       if (minor.contains("RC") || minor.contains("Beta") || minor.contains("beta")) {
449         return true;
450       }
451     }
452     return false;
453   }
454
455   public static ApplicationInfoEx getShadowInstance() {
456     if (ourShadowInstance == null) {
457       ourShadowInstance = new ApplicationInfoImpl();
458       try {
459         Document doc = JDOMUtil.loadDocument(ApplicationInfoImpl.class, IDEA_PATH + ApplicationNamesInfo.getComponentName() + XML_EXTENSION);
460         ourShadowInstance.readExternal(doc.getRootElement());
461       }
462       catch (FileNotFoundException e) {
463         LOG.error("Resource is not in classpath or wrong platform prefix: " + System.getProperty(PlatformUtilsCore.PLATFORM_PREFIX_KEY), e);
464       }
465       catch (Exception e) {
466         LOG.error(e);
467       }
468     }
469     return ourShadowInstance;
470   }
471
472   public void readExternal(Element parentNode) throws InvalidDataException {
473     Element versionElement = parentNode.getChild(ELEMENT_VERSION);
474     if (versionElement != null) {
475       myMajorVersion = versionElement.getAttributeValue(ATTRIBUTE_MAJOR);
476       myMinorVersion = versionElement.getAttributeValue(ATTRIBUTE_MINOR);
477       myCodeName = versionElement.getAttributeValue(ATTRIBUTE_CODENAME);
478       myEAP = Boolean.parseBoolean(versionElement.getAttributeValue(ATTRIBUTE_EAP));
479     }
480
481     Element companyElement = parentNode.getChild(ELEMENT_COMPANY);
482     if (companyElement != null) {
483       myCompanyName = companyElement.getAttributeValue(ATTRIBUTE_NAME, myCompanyName);
484       myCompanyUrl = companyElement.getAttributeValue(ATTRIBUTE_URL, myCompanyUrl);
485     }
486
487     Element buildElement = parentNode.getChild(ELEMENT_BUILD);
488     if (buildElement != null) {
489       myBuildNumber = buildElement.getAttributeValue(ATTRIBUTE_NUMBER);
490       myApiVersion = buildElement.getAttributeValue(ATTRIBUTE_API_VERSION);
491       PluginManagerCore.BUILD_NUMBER = myApiVersion != null ? myApiVersion : myBuildNumber;
492       String dateString = buildElement.getAttributeValue(ATTRIBUTE_DATE);
493       if (dateString.equals("__BUILD_DATE__")) {
494         myBuildDate = new GregorianCalendar();
495         try {
496           final JarFile bootJar = new JarFile(PathManager.getHomePath() + File.separator + "lib" + File.separator + "boot.jar");
497           try {
498             final JarEntry jarEntry = bootJar.entries().nextElement(); // /META-INF is always updated on build
499             myBuildDate.setTime(new Date(jarEntry.getTime()));
500           }
501           finally {
502             bootJar.close();
503           }
504         }
505         catch (Exception ignore) { }
506       }
507       else {
508         myBuildDate = parseDate(dateString);
509       }
510       String majorReleaseDateString = buildElement.getAttributeValue(ATTRIBUTE_MAJOR_RELEASE_DATE);
511       if (majorReleaseDateString != null) {
512         myMajorReleaseBuildDate = parseDate(majorReleaseDateString);
513       }
514     }
515
516     Thread currentThread = Thread.currentThread();
517     currentThread.setName(currentThread.getName() + " " + myMajorVersion + "." + myMinorVersion + "#" + myBuildNumber + ", eap:" + myEAP);
518
519     Element logoElement = parentNode.getChild(ELEMENT_LOGO);
520     if (logoElement != null) {
521       mySplashImageUrl = logoElement.getAttributeValue(ATTRIBUTE_URL);
522       mySplashTextColor = parseColor(logoElement.getAttributeValue(ATTRIBUTE_TEXT_COLOR));
523       String v = logoElement.getAttributeValue(ATTRIBUTE_PROGRESS_COLOR);
524       if (v != null) {
525         myProgressColor = parseColor(v);
526       }
527
528       v = logoElement.getAttributeValue(ATTRIBUTE_PROGRESS_TAIL_ICON);
529       if (v != null) {
530         myProgressTailIconName = v;
531       }
532
533       v = logoElement.getAttributeValue(ATTRIBUTE_PROGRESS_Y);
534       if (v != null) {
535         myProgressY = Integer.parseInt(v);
536       }
537     }
538
539     Element aboutLogoElement = parentNode.getChild(ELEMENT_ABOUT);
540     if (aboutLogoElement != null) {
541       myAboutImageUrl = aboutLogoElement.getAttributeValue(ATTRIBUTE_URL);
542
543       String v = aboutLogoElement.getAttributeValue(ATTRIBUTE_ABOUT_FOREGROUND_COLOR);
544       if (v != null) {
545         myAboutForeground = parseColor(v);
546       }
547       v = aboutLogoElement.getAttributeValue(ATTRIBUTE_ABOUT_COPYRIGHT_FOREGROUND_COLOR);
548       if (v != null) {
549         myCopyrightForeground = parseColor(v);
550       }
551
552       String c = aboutLogoElement.getAttributeValue(ATTRIBUTE_ABOUT_LINK_COLOR);
553       if (c != null) {
554         myAboutLinkColor = parseColor(c);
555       }
556
557       String logoX = aboutLogoElement.getAttributeValue("logoX");
558       String logoY = aboutLogoElement.getAttributeValue("logoY");
559       String logoW = aboutLogoElement.getAttributeValue("logoW");
560       String logoH = aboutLogoElement.getAttributeValue("logoH");
561       if (logoX != null && logoY != null && logoW != null && logoH != null) {
562         try {
563           myAboutLogoRect =
564             new Rectangle(Integer.parseInt(logoX), Integer.parseInt(logoY), Integer.parseInt(logoW), Integer.parseInt(logoH));
565         }
566         catch (NumberFormatException nfe) {
567           // ignore
568         }
569       }
570     }
571
572     Element iconElement = parentNode.getChild(ELEMENT_ICON);
573     if (iconElement != null) {
574       myIconUrl = iconElement.getAttributeValue(ATTRIBUTE_SIZE32);
575       mySmallIconUrl = iconElement.getAttributeValue(ATTRIBUTE_SIZE16);
576       myOpaqueIconUrl = iconElement.getAttributeValue(ATTRIBUTE_SIZE32OPAQUE);
577       myBigIconUrl = iconElement.getAttributeValue(ATTRIBUTE_SIZE128, (String)null);
578       final String toolWindowIcon = iconElement.getAttributeValue(ATTRIBUTE_SIZE12);
579       if (toolWindowIcon != null) {
580         myToolWindowIconUrl = toolWindowIcon;
581       }
582     }
583
584     Element packageElement = parentNode.getChild(ELEMENT_PACKAGE);
585     if (packageElement != null) {
586       myPackageCode = packageElement.getAttributeValue(ATTRIBUTE_CODE);
587     }
588
589     Element showLicensee = parentNode.getChild(ELEMENT_LICENSEE);
590     if (showLicensee != null) {
591       myShowLicensee = Boolean.valueOf(showLicensee.getAttributeValue(ATTRIBUTE_SHOW)).booleanValue();
592     }
593
594     Element welcomeScreen = parentNode.getChild(WELCOME_SCREEN_ELEMENT_NAME);
595     if (welcomeScreen != null) {
596       myWelcomeScreenLogoUrl = welcomeScreen.getAttributeValue(LOGO_URL_ATTR);
597       myWelcomeScreenCaptionUrl = welcomeScreen.getAttributeValue(CAPTION_URL_ATTR);
598       myWelcomeScreenDeveloperSloganUrl = welcomeScreen.getAttributeValue(SLOGAN_URL_ATTR);
599     }
600
601     Element editor = parentNode.getChild(ELEMENT_EDITOR);
602     if (editor != null) {
603       myEditorBackgroundImageUrl = editor.getAttributeValue(BACKGROUND_URL_ATTR);
604     }
605
606     Element helpElement = parentNode.getChild(HELP_ELEMENT_NAME);
607     if (helpElement != null) {
608       myHelpFileName = helpElement.getAttributeValue(ATTRIBUTE_HELP_FILE);
609       myHelpRootName = helpElement.getAttributeValue(ATTRIBUTE_HELP_ROOT);
610       final String webHelpUrl = helpElement.getAttributeValue(ATTRIBUTE_WEBHELP_URL);
611       if (webHelpUrl != null) {
612         myWebHelpUrl = webHelpUrl;
613       }
614
615       String attValue = helpElement.getAttributeValue(ATTRIBUTE_HAS_HELP);
616       myHasHelp = attValue == null || Boolean.parseBoolean(attValue); // Default is true
617
618       attValue = helpElement.getAttributeValue(ATTRIBUTE_HAS_CONTEXT_HELP);
619       myHasContextHelp = attValue == null || Boolean.parseBoolean(attValue); // Default is true
620     }
621
622     Element updateUrls = parentNode.getChild(UPDATE_URLS_ELEMENT_NAME);
623     myUpdateUrls = new UpdateUrlsImpl(updateUrls);
624
625     Element documentationElement = parentNode.getChild(ELEMENT_DOCUMENTATION);
626     if (documentationElement != null) {
627       myDocumentationUrl = documentationElement.getAttributeValue(ATTRIBUTE_URL);
628     }
629
630     Element supportElement = parentNode.getChild(ELEMENT_SUPPORT);
631     if (supportElement != null) {
632       mySupportUrl = supportElement.getAttributeValue(ATTRIBUTE_URL);
633     }
634
635     Element feedbackElement = parentNode.getChild(ELEMENT_FEEDBACK);
636     if (feedbackElement != null) {
637       myEAPFeedbackUrl = feedbackElement.getAttributeValue(ATTRIBUTE_EAP_URL);
638       myReleaseFeedbackUrl = feedbackElement.getAttributeValue(ATTRIBUTE_RELEASE_URL);
639     }
640
641     Element whatsnewElement = parentNode.getChild(ELEMENT_WHATSNEW);
642     if (whatsnewElement != null) {
643       myWhatsNewUrl = whatsnewElement.getAttributeValue(ATTRIBUTE_URL);
644     }
645
646     myPluginsListUrl = DEFAULT_PLUGINS_HOST + "/plugins/list/";
647     myPluginsDownloadUrl = DEFAULT_PLUGINS_HOST + "/pluginManager/";
648
649     Element pluginsElement = parentNode.getChild(ELEMENT_PLUGINS);
650     if (pluginsElement != null) {
651       myPluginManagerUrl = pluginsElement.getAttributeValue(ATTRIBUTE_URL);
652       final String listUrl = pluginsElement.getAttributeValue(ATTRIBUTE_LIST_URL);
653       if (listUrl != null) {
654         myPluginsListUrl = listUrl;
655       }
656       final String downloadUrl = pluginsElement.getAttributeValue(ATTRIBUTE_DOWNLOAD_URL);
657       if (downloadUrl != null) {
658         myPluginsDownloadUrl = downloadUrl;
659       }
660       if (!getBuild().isSnapshot()) {
661         myBuiltinPluginsUrl = pluginsElement.getAttributeValue(ATTRIBUTE_BUILTIN_URL);
662       }
663     }
664     else {
665       myPluginManagerUrl = DEFAULT_PLUGINS_HOST;
666     }
667
668     final String pluginsHost = System.getProperty("idea.plugins.host");
669     if (pluginsHost != null) {
670       myPluginsListUrl = myPluginsListUrl.replace(DEFAULT_PLUGINS_HOST, pluginsHost);
671       myPluginsDownloadUrl = myPluginsDownloadUrl.replace(DEFAULT_PLUGINS_HOST, pluginsHost);
672     }
673
674     Element keymapElement = parentNode.getChild(ELEMENT_KEYMAP);
675     if (keymapElement != null) {
676       myWinKeymapUrl = keymapElement.getAttributeValue(ATTRIBUTE_WINDOWS_URL);
677       myMacKeymapUrl = keymapElement.getAttributeValue(ATTRIBUTE_MAC_URL);
678     }
679
680     myPluginChooserPages = new ArrayList<PluginChooserPage>();
681     final List children = parentNode.getChildren(PLUGINS_PAGE_ELEMENT_NAME);
682     for(Object child: children) {
683       myPluginChooserPages.add(new PluginChooserPageImpl((Element) child));
684     }
685
686     Element statisticsElement = parentNode.getChild(ELEMENT_STATISTICS);
687     if (statisticsElement != null) {
688       myStatisticsSettingsUrl = statisticsElement.getAttributeValue(ATTRIBUTE_STATISTICS_SETTINGS);
689       myStatisticsServiceUrl  = statisticsElement.getAttributeValue(ATTRIBUTE_STATISTICS_SERVICE);
690       myStatisticsServiceKey  = statisticsElement.getAttributeValue(ATTRIBUTE_STATISTICS_SERVICE_KEY);
691     }
692     else {
693       myStatisticsSettingsUrl = "http://jetbrains.com/idea/statistics/stat-assistant.xml";
694       myStatisticsServiceUrl  = "http://jetbrains.com/idea/statistics/index.jsp";
695       myStatisticsServiceKey  = null;
696     }
697
698     Element thirdPartyElement = parentNode.getChild(ELEMENT_THIRD_PARTY);
699     if (thirdPartyElement != null) {
700       myThirdPartySoftwareUrl = thirdPartyElement.getAttributeValue(ATTRIBUTE_URL);
701     }
702   }
703
704   private static GregorianCalendar parseDate(final String dateString) {
705     @SuppressWarnings("MultipleVariablesInDeclaration")
706     int year = 0, month = 0, day = 0, hour = 0, minute = 0;
707     try {
708       year = Integer.parseInt(dateString.substring(0, 4));
709       month = Integer.parseInt(dateString.substring(4, 6));
710       day = Integer.parseInt(dateString.substring(6, 8));
711       if (dateString.length() > 8) {
712         hour = Integer.parseInt(dateString.substring(8, 10));
713         minute = Integer.parseInt(dateString.substring(10, 12));
714       }
715     }
716     catch (Exception ignore) { }
717     if (month > 0) month--;
718     return new GregorianCalendar(year, month, day, hour, minute);
719   }
720
721   private static Color parseColor(final String colorString) {
722     final long rgb = Long.parseLong(colorString, 16);
723     return new Color((int)rgb, rgb > 0xffffff);
724   }
725
726   public void writeExternal(Element element) throws WriteExternalException {
727     throw new WriteExternalException();
728   }
729
730   public List<PluginChooserPage> getPluginChooserPages() {
731     return myPluginChooserPages;
732   }
733
734   @NotNull
735   public String getComponentName() {
736     return ApplicationNamesInfo.getComponentName();
737   }
738
739   private static class UpdateUrlsImpl implements UpdateUrls {
740     private String myCheckingUrl;
741     private String myPatchesUrl;
742
743     private UpdateUrlsImpl(Element element) {
744       if (element != null) {
745         myCheckingUrl = element.getAttributeValue("check");
746         myPatchesUrl = element.getAttributeValue("patches");
747       }
748     }
749
750     public String getCheckingUrl() {
751       return myCheckingUrl;
752     }
753
754     public String getPatchesUrl() {
755       return myPatchesUrl;
756     }
757   }
758
759   private static class PluginChooserPageImpl implements PluginChooserPage {
760     private final String myTitle;
761     private final String myCategory;
762     private final String myDependentPlugin;
763
764     private PluginChooserPageImpl(Element e) {
765       myTitle = e.getAttributeValue("title");
766       myCategory = e.getAttributeValue("category");
767       myDependentPlugin = e.getAttributeValue("depends");
768     }
769
770     public String getTitle() {
771       return myTitle;
772     }
773
774     public String getCategory() {
775       return myCategory;
776     }
777
778     public String getDependentPlugin() {
779       return myDependentPlugin;
780     }
781   }
782
783   private static volatile boolean myInPerformanceTest;
784   public static boolean isInPerformanceTest() {
785     return myInPerformanceTest;
786   }
787   public static void setInPerformanceTest(boolean inPerformanceTest) {
788     myInPerformanceTest = inPerformanceTest;
789   }
790 }