Merge remote-tracking branch 'aosp/upstream-master' into merge

Conflicts:
	platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java
	plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ModuleExtendedModel.java
	plugins/groovy/src/META-INF/plugin.xml

Change-Id: Ib6de04d7226d4eb7f35f66304df68135ad6ff267
diff --git a/.gitignore b/.gitignore
index e1a3e40..6aba63e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,6 @@
 /python/helpers/python-skeletons
 /test-system
 /test-config
+.jps-build-data
+/bin/build-log.xml
+/bin/build.log
diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml
old mode 100644
new mode 100755
index 67bfbb2..33a693a
--- a/.idea/codeStyleSettings.xml
+++ b/.idea/codeStyleSettings.xml
@@ -51,6 +51,7 @@
             <option name="USE_RELATIVE_INDENTS" value="false" />
           </value>
         </option>
+        <option name="LINE_SEPARATOR" value="&#10;" />
         <option name="FIELD_NAME_PREFIX" value="my" />
         <option name="STATIC_FIELD_NAME_PREFIX" value="our" />
         <option name="RIGHT_MARGIN" value="140" />
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index bb073af..3407e7c 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -56,6 +56,7 @@
     <option name="DEPRECATION" value="false" />
   </component>
   <component name="JavacSettings">
+    <option name="DEPRECATION" value="false" />
     <option name="MAXIMUM_HEAP_SIZE" value="400" />
   </component>
 </project>
diff --git a/.idea/copyright/aosp.xml b/.idea/copyright/aosp.xml
new file mode 100644
index 0000000..077aec6
--- /dev/null
+++ b/.idea/copyright/aosp.xml
@@ -0,0 +1,9 @@
+<component name="CopyrightManager">
+  <copyright>
+    <option name="notice" value="Copyright (C) &amp;#36;today.year The Android Open Source Project&#10;&#10;Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#10;you may not use this file except in compliance with the License.&#10;You may obtain a copy of the License at&#10;&#10;     http://www.apache.org/licenses/LICENSE-2.0&#10;&#10;Unless required by applicable law or agreed to in writing, software&#10;distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#10;WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#10;See the License for the specific language governing permissions and&#10;limitations under the License." />
+    <option name="keyword" value="Copyright" />
+    <option name="allowReplaceKeyword" value="" />
+    <option name="myName" value="aosp" />
+    <option name="myLocal" value="true" />
+  </copyright>
+</component>
\ No newline at end of file
diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml
index 19fba77..7d505fe 100644
--- a/.idea/copyright/profiles_settings.xml
+++ b/.idea/copyright/profiles_settings.xml
@@ -1,5 +1,8 @@
 <component name="CopyrightManager">
-  <settings default="apache 2 license">
+  <settings default="aosp">
+    <module2copyright>
+      <element module="aosp-code" copyright="aosp" />
+    </module2copyright>
     <LanguageOptions name="__TEMPLATE__">
       <option name="addBlankAfter" value="false" />
     </LanguageOptions>
diff --git a/.idea/dictionaries/adt.xml b/.idea/dictionaries/adt.xml
new file mode 100644
index 0000000..7be8565
--- /dev/null
+++ b/.idea/dictionaries/adt.xml
@@ -0,0 +1,326 @@
+<component name="ProjectDictionaryState">
+  <dictionary name="adt">
+    <words>
+      <w>&amp;amp</w>
+      <w>aapt</w>
+      <w>aarrggbb</w>
+      <w>accessors</w>
+      <w>actionbar</w>
+      <w>adb's</w>
+      <w>adbhost</w>
+      <w>addon</w>
+      <w>addons</w>
+      <w>addr</w>
+      <w>aidl</w>
+      <w>aload</w>
+      <w>androiddebugkey</w>
+      <w>anim</w>
+      <w>aosp</w>
+      <w>apkbuilder</w>
+      <w>apos</w>
+      <w>appname</w>
+      <w>areturn</w>
+      <w>argb</w>
+      <w>argv</w>
+      <w>armeabi</w>
+      <w>ast's</w>
+      <w>async</w>
+      <w>attrs</w>
+      <w>autofocus</w>
+      <w>automator</w>
+      <w>avd's</w>
+      <w>avdname</w>
+      <w>backfill</w>
+      <w>basename</w>
+      <w>basenames</w>
+      <w>bicubic</w>
+      <w>bilinear</w>
+      <w>bindir</w>
+      <w>bipush</w>
+      <w>bitcodelib</w>
+      <w>bitmask</w>
+      <w>blockquote</w>
+      <w>bluetooth</w>
+      <w>booleans</w>
+      <w>bootloader</w>
+      <w>borderless</w>
+      <w>bytecode</w>
+      <w>calloc</w>
+      <w>charsets</w>
+      <w>checkable</w>
+      <w>chksum</w>
+      <w>classfile</w>
+      <w>classname</w>
+      <w>classpathentry</w>
+      <w>clinit</w>
+      <w>clipart</w>
+      <w>closeables</w>
+      <w>codenames</w>
+      <w>combineaccessrules</w>
+      <w>compat</w>
+      <w>configurables</w>
+      <w>conv</w>
+      <w>crlf</w>
+      <w>crypto</w>
+      <w>cygpath</w>
+      <w>cygwin</w>
+      <w>dalvik</w>
+      <w>darcula</w>
+      <w>ddmlib</w>
+      <w>ddms</w>
+      <w>debuggable</w>
+      <w>densityless</w>
+      <w>designtime</w>
+      <w>dest</w>
+      <w>dexdump</w>
+      <w>digester</w>
+      <w>dimen</w>
+      <w>dirname</w>
+      <w>disp</w>
+      <w>donottranslate</w>
+      <w>dpad</w>
+      <w>drawables</w>
+      <w>dropdown</w>
+      <w>dumpsys</w>
+      <w>eabi</w>
+      <w>easymock</w>
+      <w>emdash</w>
+      <w>endian</w>
+      <w>enqueued</w>
+      <w>errno</w>
+      <w>executables</w>
+      <w>expectedly</w>
+      <w>filenames</w>
+      <w>filepath</w>
+      <w>fixme</w>
+      <w>fqcn</w>
+      <w>framebuffer</w>
+      <w>frameworkdir</w>
+      <w>froyo</w>
+      <w>fwvga</w>
+      <w>gbdserver</w>
+      <w>gdbserver</w>
+      <w>genkey</w>
+      <w>getenv</w>
+      <w>getfield</w>
+      <w>getprop</w>
+      <w>getstatic</w>
+      <w>globbing</w>
+      <w>goto</w>
+      <w>gradle</w>
+      <w>guide's</w>
+      <w>guillemets</w>
+      <w>hardcode</w>
+      <w>hardcoding</w>
+      <w>hashcode</w>
+      <w>hdpi</w>
+      <w>holo</w>
+      <w>horiz</w>
+      <w>httpclient</w>
+      <w>hvga</w>
+      <w>iaload</w>
+      <w>iastore</w>
+      <w>iconst</w>
+      <w>inflater</w>
+      <w>infos</w>
+      <w>inlined</w>
+      <w>innerclass</w>
+      <w>inputfile</w>
+      <w>insn</w>
+      <w>instantiatable</w>
+      <w>instrumentations</w>
+      <w>intelli</w>
+      <w>interpolator</w>
+      <w>ints</w>
+      <w>invokestatic</w>
+      <w>invokevirtual</w>
+      <w>ipsum</w>
+      <w>ireturn</w>
+      <w>iterable</w>
+      <w>jarfile</w>
+      <w>jarlist</w>
+      <w>jarpath</w>
+      <w>javabuilder</w>
+      <w>javanature</w>
+      <w>jdwp</w>
+      <w>jpeg</w>
+      <w>junit</w>
+      <w>keepclasseswithmembernames</w>
+      <w>keepclasseswithmembers</w>
+      <w>keygen</w>
+      <w>keypass</w>
+      <w>keysexposed</w>
+      <w>keyshidden</w>
+      <w>keyssoft</w>
+      <w>keystore</w>
+      <w>keytool</w>
+      <w>kxml</w>
+      <w>landroid</w>
+      <w>layoublib</w>
+      <w>layoutlib</w>
+      <w>layoutlibs</w>
+      <w>layoutopt</w>
+      <w>layoutrules</w>
+      <w>ldltr</w>
+      <w>ldpi</w>
+      <w>ldrtl</w>
+      <w>levenshtein</w>
+      <w>lexing</w>
+      <w>libc</w>
+      <w>licensable</w>
+      <w>licensor</w>
+      <w>linenumber</w>
+      <w>ljava</w>
+      <w>lombok</w>
+      <w>lookups</w>
+      <w>lookupswitch</w>
+      <w>looper</w>
+      <w>lorem</w>
+      <w>lpackage</w>
+      <w>makefile</w>
+      <w>malloc</w>
+      <w>manifestmerger</w>
+      <w>manifmerger</w>
+      <w>mdpi</w>
+      <w>memalign</w>
+      <w>minsdk</w>
+      <w>mipmap</w>
+      <w>mkdirs</w>
+      <w>monospace</w>
+      <w>moreunit</w>
+      <w>multimap</w>
+      <w>multipart</w>
+      <w>multitouch</w>
+      <w>nano</w>
+      <w>nativelib</w>
+      <w>navexposed</w>
+      <w>navhidden</w>
+      <w>ninepatch</w>
+      <w>nodpi</w>
+      <w>nokeys</w>
+      <w>nonav</w>
+      <w>notlong</w>
+      <w>notnight</w>
+      <w>notouch</w>
+      <w>nullable</w>
+      <w>nulling</w>
+      <w>nullness</w>
+      <w>objectweb</w>
+      <w>opcode</w>
+      <w>opcodes</w>
+      <w>pathname</w>
+      <w>picasa</w>
+      <w>plugin's</w>
+      <w>png's</w>
+      <w>prebuilts</w>
+      <w>prefs</w>
+      <w>preload</w>
+      <w>prepending</w>
+      <w>printf</w>
+      <w>println</w>
+      <w>proc</w>
+      <w>prog</w>
+      <w>progdir</w>
+      <w>programmatically</w>
+      <w>proguard</w>
+      <w>prolog</w>
+      <w>qemu</w>
+      <w>quickfix</w>
+      <w>quickstart</w>
+      <w>qvga</w>
+      <w>rasterize</w>
+      <w>rasterizer</w>
+      <w>realloc</w>
+      <w>recurse</w>
+      <w>reflow</w>
+      <w>reformats</w>
+      <w>reimplement</w>
+      <w>renderscript</w>
+      <w>reparse</w>
+      <w>requestor</w>
+      <w>resampling</w>
+      <w>resizability</w>
+      <w>resized</w>
+      <w>revalidate</w>
+      <w>rrggbb</w>
+      <w>sccs</w>
+      <w>screenshot</w>
+      <w>scroller</w>
+      <w>scrollview</w>
+      <w>sdcard</w>
+      <w>sdk's</w>
+      <w>sdkbin</w>
+      <w>sdklib</w>
+      <w>sdkman</w>
+      <w>sdks</w>
+      <w>serialnumber</w>
+      <w>severities</w>
+      <w>sparsearray</w>
+      <w>sqrt</w>
+      <w>stacktrace</w>
+      <w>stderr</w>
+      <w>stdout</w>
+      <w>stopship</w>
+      <w>storepass</w>
+      <w>storetype</w>
+      <w>styleable</w>
+      <w>subclassed</w>
+      <w>subclassing</w>
+      <w>subfolder</w>
+      <w>submenu</w>
+      <w>superset</w>
+      <w>sysdir</w>
+      <w>sysimg</w>
+      <w>targetsdk</w>
+      <w>testcase</w>
+      <w>testroot</w>
+      <w>testsuite</w>
+      <w>tmpdir</w>
+      <w>traceview</w>
+      <w>tuple</w>
+      <w>tvdpi</w>
+      <w>uiautomator</w>
+      <w>uname</w>
+      <w>unarchive</w>
+      <w>unary</w>
+      <w>uncapitalized</w>
+      <w>uncompressing</w>
+      <w>unescape</w>
+      <w>unescaping</w>
+      <w>unformatted</w>
+      <w>unlocalized</w>
+      <w>unmanages</w>
+      <w>unregister</w>
+      <w>unregisters</w>
+      <w>userdata</w>
+      <w>versioncode</w>
+      <w>vert</w>
+      <w>viewport</w>
+      <w>vmsig</w>
+      <w>wakelock</w>
+      <w>wakelocks</w>
+      <w>wakeup</w>
+      <w>webkit</w>
+      <w>wikipedia</w>
+      <w>workdir</w>
+      <w>wqvga</w>
+      <w>writeable</w>
+      <w>wvga</w>
+      <w>xdpi</w>
+      <w>xerces</w>
+      <w>xfermode</w>
+      <w>xhdpi</w>
+      <w>xhigh</w>
+      <w>xlarge</w>
+      <w>xliff</w>
+      <w>xmlns</w>
+      <w>xxhdpi</w>
+      <w>xxhigh</w>
+      <w>xxxhdpi</w>
+      <w>xxxhigh</w>
+      <w>ydpi</w>
+      <w>yyyy</w>
+      <w>zipalign</w>
+    </words>
+  </dictionary>
+</component>
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/idea_default.xml b/.idea/inspectionProfiles/idea_default.xml
index 8924010f..587a48c 100644
--- a/.idea/inspectionProfiles/idea_default.xml
+++ b/.idea/inspectionProfiles/idea_default.xml
@@ -50,7 +50,7 @@
     <inspection_tool class="ConstantConditionalExpressionJS" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="ConstantConditions" enabled="true" level="WARNING" enabled_by_default="true">
       <scope name="runtime.classes" level="WARNING" enabled="false">
-        <option name="SUGGEST_NULLABLE_ANNOTATIONS" value="false" />
+        <option name="SUGGEST_NULLABLE_ANNOTATIONS" value="true" />
         <option name="DONT_REPORT_TRUE_ASSERT_STATEMENTS" value="false" />
       </scope>
       <option name="SUGGEST_NULLABLE_ANNOTATIONS" value="true" />
@@ -318,6 +318,10 @@
     <inspection_tool class="MethodNamesDifferOnlyByCase" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="MethodOverloadsParentMethod" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="MethodOverridesStaticMethod" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MissingOverrideAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
+      <option name="ignoreObjectMethods" value="true" />
+      <option name="ignoreAnonymousClassMethods" value="false" />
+    </inspection_tool>
     <inspection_tool class="MisspelledCompareTo" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="MisspelledEquals" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="MisspelledHashcode" enabled="true" level="WARNING" enabled_by_default="true" />
@@ -569,7 +573,7 @@
     <inspection_tool class="UnnecessaryEnumModifier" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="UnnecessaryFullyQualifiedName" enabled="true" level="WARNING" enabled_by_default="true">
       <scope name="Tests" level="WARNING" enabled="false">
-        <option name="m_ignoreJavadoc" value="false" />
+        <option name="m_ignoreJavadoc" value="true" />
       </scope>
       <option name="m_ignoreJavadoc" value="true" />
     </inspection_tool>
diff --git a/.idea/libraries/asm_tools.xml b/.idea/libraries/asm_tools.xml
new file mode 100644
index 0000000..6009e9f
--- /dev/null
+++ b/.idea/libraries/asm_tools.xml
@@ -0,0 +1,13 @@
+<component name="libraryTable">
+  <library name="asm-tools">
+    <CLASSES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/asm-tools/asm-4.0.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/asm-tools/asm-analysis-4.0.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/asm-tools/asm-tree-4.0.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/asm-tools/src-4.0.zip!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/.idea/libraries/bouncy_castle.xml b/.idea/libraries/bouncy_castle.xml
new file mode 100644
index 0000000..70ec93b
--- /dev/null
+++ b/.idea/libraries/bouncy_castle.xml
@@ -0,0 +1,13 @@
+<component name="libraryTable">
+  <library name="bouncy-castle">
+    <CLASSES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/bouncycastle/bcpkix-jdk15on/1.48/bcpkix-jdk15on-1.48.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/bouncycastle/bcprov-jdk15on/1.48/bcprov-jdk15on-1.48.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/bouncycastle/bcpkix-jdk15on/1.48/bcpkix-jdk15on-1.48-sources.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/bouncycastle/bcprov-jdk15on/1.48/bcprov-jdk15on-1.48-sources.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/.idea/libraries/builder_model.xml b/.idea/libraries/builder_model.xml
new file mode 100644
index 0000000..5eb367b
--- /dev/null
+++ b/.idea/libraries/builder_model.xml
@@ -0,0 +1,11 @@
+<component name="libraryTable">
+  <library name="builder-model">
+    <CLASSES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/builder-model/builder-model-0.11.0.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/builder-model/builder-model-0.11.0-sources.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/.idea/libraries/commons_compress.xml b/.idea/libraries/commons_compress.xml
new file mode 100644
index 0000000..be33df8
--- /dev/null
+++ b/.idea/libraries/commons_compress.xml
@@ -0,0 +1,9 @@
+<component name="libraryTable">
+  <library name="commons-compress">
+    <CLASSES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/commons-compress/commons-compress-1.0.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES />
+  </library>
+</component>
\ No newline at end of file
diff --git a/.idea/libraries/easymock_tools.xml b/.idea/libraries/easymock_tools.xml
new file mode 100644
index 0000000..d01b884
--- /dev/null
+++ b/.idea/libraries/easymock_tools.xml
@@ -0,0 +1,13 @@
+<component name="libraryTable">
+  <library name="easymock-tools">
+    <CLASSES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/easymock-tools/easymock-3.1.jar!/" />
+    </CLASSES>
+    <JAVADOC>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/easymock-tools/easymock-3.1-javadoc.jar!/" />
+    </JAVADOC>
+    <SOURCES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/easymock-tools/easymock-3.1-sources.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/.idea/libraries/freemarker_2_3_20.xml b/.idea/libraries/freemarker_2_3_20.xml
new file mode 100644
index 0000000..b7805a2
--- /dev/null
+++ b/.idea/libraries/freemarker_2_3_20.xml
@@ -0,0 +1,11 @@
+<component name="libraryTable">
+  <library name="freemarker-2.3.20">
+    <CLASSES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/freemarker/freemarker/2.3.20/freemarker-2.3.20.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/freemarker/freemarker/2.3.20/freemarker-2.3.20-sources.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/.idea/libraries/guava_tools.xml b/.idea/libraries/guava_tools.xml
new file mode 100644
index 0000000..ac5f2f6
--- /dev/null
+++ b/.idea/libraries/guava_tools.xml
@@ -0,0 +1,11 @@
+<component name="libraryTable">
+  <library name="guava-tools">
+    <CLASSES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/google/guava/guava/15.0/guava-15.0.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/google/guava/guava/15.0/guava-15.0-sources.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/.idea/libraries/junit3_tools.xml b/.idea/libraries/junit3_tools.xml
new file mode 100644
index 0000000..b3dd3f3
--- /dev/null
+++ b/.idea/libraries/junit3_tools.xml
@@ -0,0 +1,9 @@
+<component name="libraryTable">
+  <library name="junit3-tools">
+    <CLASSES>
+      <root url="jar://$APPLICATION_HOME_DIR$/lib/junit.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES />
+  </library>
+</component>
\ No newline at end of file
diff --git a/.idea/libraries/kxml2.xml b/.idea/libraries/kxml2.xml
new file mode 100644
index 0000000..688c238
--- /dev/null
+++ b/.idea/libraries/kxml2.xml
@@ -0,0 +1,13 @@
+<component name="libraryTable">
+  <library name="kxml2">
+    <CLASSES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/kxml2-tools/kxml2-2.3.0.jar!/" />
+    </CLASSES>
+    <JAVADOC>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/kxml2-tools/kxml2-src-2.3.0.zip!/www/kxml2/javadoc" />
+    </JAVADOC>
+    <SOURCES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/kxml2-tools/kxml2-src-2.3.0.zip!/src" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/.idea/libraries/lombok_ast.xml b/.idea/libraries/lombok_ast.xml
new file mode 100644
index 0000000..ef9fe6d
--- /dev/null
+++ b/.idea/libraries/lombok_ast.xml
@@ -0,0 +1,18 @@
+<component name="libraryTable">
+  <library name="lombok-ast">
+    <CLASSES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2.jar!/" />
+    </CLASSES>
+    <JAVADOC>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2-javadoc.jar!/" />
+    </JAVADOC>
+    <SOURCES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2-sources.jar!/src/main" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2-sources.jar!/src/printer" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2-sources.jar!/src/template" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2-sources.jar!/src/ecjTransformer" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2-sources.jar!/src/javacTransformer" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2-sources.jar!/build/lombok.ast_generatedSource" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/.idea/libraries/mockito.xml b/.idea/libraries/mockito.xml
new file mode 100644
index 0000000..7113f6f
--- /dev/null
+++ b/.idea/libraries/mockito.xml
@@ -0,0 +1,12 @@
+<component name="libraryTable">
+  <library name="mockito">
+    <CLASSES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/mockito/mockito-all/1.9.5/mockito-all-1.9.5.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/mockito/mockito-all/1.9.5/mockito-all-1.9.5-sources.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/mockito/mockito-all/1.9.5/mockito-all-1.9.5.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 941f718..50ad2f0 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -5,6 +5,7 @@
   </component>
   <component name="FrameworkDetectionExcludesConfiguration">
     <file url="file://$PROJECT_DIR$" />
+    <type id="android" />
   </component>
   <component name="IdProvider" IDEtalkID="88DB5D232B345F18EEFB2825E88EC093" />
   <component name="JavadocGenerationManager">
@@ -24,6 +25,30 @@
     <option name="LOCALE" />
     <option name="OPEN_IN_BROWSER" value="true" />
   </component>
+  <component name="NullableNotNullManager">
+    <option name="myDefaultNullable" value="org.jetbrains.annotations.Nullable" />
+    <option name="myDefaultNotNull" value="org.jetbrains.annotations.NotNull" />
+    <option name="myNullables">
+      <value>
+        <list size="4">
+          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
+          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
+          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
+          <item index="3" class="java.lang.String" itemvalue="com.android.annotations.Nullable" />
+        </list>
+      </value>
+    </option>
+    <option name="myNotNulls">
+      <value>
+        <list size="4">
+          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
+          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
+          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
+          <item index="3" class="java.lang.String" itemvalue="com.android.annotations.NonNull" />
+        </list>
+      </value>
+    </option>
+  </component>
   <component name="ProjectDetails">
     <option name="projectName" value="idea-community" />
   </component>
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 971465f..de3de61 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -10,18 +10,26 @@
       <module fileurl="file://$PROJECT_DIR$/plugins/IntelliLang/IntelliLang-tests/IntelliLang-tests.iml" filepath="$PROJECT_DIR$/plugins/IntelliLang/IntelliLang-tests/IntelliLang-tests.iml" group="plugins/IntelliLang" />
       <module fileurl="file://$PROJECT_DIR$/plugins/IntelliLang/IntelliLang-xml.iml" filepath="$PROJECT_DIR$/plugins/IntelliLang/IntelliLang-xml.iml" group="plugins/IntelliLang" />
       <module fileurl="file://$PROJECT_DIR$/RegExpSupport/RegExpSupport.iml" filepath="$PROJECT_DIR$/RegExpSupport/RegExpSupport.iml" group="platform" />
+      <module fileurl="file://$PROJECT_DIR$/../adt/idea/adt-branding/adt-branding.iml" filepath="$PROJECT_DIR$/../adt/idea/adt-branding/adt-branding.iml" group="plugins/Android" />
       <module fileurl="file://$PROJECT_DIR$/platform/analysis-api/analysis-api.iml" filepath="$PROJECT_DIR$/platform/analysis-api/analysis-api.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/platform/analysis-impl/analysis-impl.iml" filepath="$PROJECT_DIR$/platform/analysis-impl/analysis-impl.iml" group="platform" />
+      <module fileurl="file://$PROJECT_DIR$/../adt/idea/android/android.iml" filepath="$PROJECT_DIR$/../adt/idea/android/android.iml" group="plugins/Android" />
+      <module fileurl="file://$PROJECT_DIR$/../adt/idea/android/common/android-common.iml" filepath="$PROJECT_DIR$/../adt/idea/android/common/android-common.iml" group="plugins/Android" />
+      <module fileurl="file://$PROJECT_DIR$/../adt/idea/android-gradle-jps/android-gradle-jps.iml" filepath="$PROJECT_DIR$/../adt/idea/android-gradle-jps/android-gradle-jps.iml" group="plugins/Android" />
+      <module fileurl="file://$PROJECT_DIR$/../adt/idea/android/jps-plugin/android-jps-plugin.iml" filepath="$PROJECT_DIR$/../adt/idea/android/jps-plugin/android-jps-plugin.iml" group="plugins/Android" />
+      <module fileurl="file://$PROJECT_DIR$/../adt/idea/android/rt/android-rt.iml" filepath="$PROJECT_DIR$/../adt/idea/android/rt/android-rt.iml" group="plugins/Android" />
       <module fileurl="file://$PROJECT_DIR$/platform/annotations/annotations.iml" filepath="$PROJECT_DIR$/platform/annotations/annotations.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/plugins/ant/ant.iml" filepath="$PROJECT_DIR$/plugins/ant/ant.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/plugins/ant/jps-plugin/ant-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/ant/jps-plugin/ant-jps-plugin.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/jps/antLayout/antlayout.iml" filepath="$PROJECT_DIR$/jps/antLayout/antlayout.iml" group="jps" />
       <module fileurl="file://$PROJECT_DIR$/plugins/google-app-engine/runtime/appEngine-runtime.iml" filepath="$PROJECT_DIR$/plugins/google-app-engine/runtime/appEngine-runtime.iml" group="plugins/GAE" />
+      <module fileurl="file://$PROJECT_DIR$/../base/asset-studio/assetstudio.iml" filepath="$PROJECT_DIR$/../base/asset-studio/assetstudio.iml" group="plugins/Android/android-sdk" />
       <module fileurl="file://$PROJECT_DIR$/platform/boot/boot.iml" filepath="$PROJECT_DIR$/platform/boot/boot.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/platform/bootstrap/bootstrap.iml" filepath="$PROJECT_DIR$/platform/bootstrap/bootstrap.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/build/build.iml" filepath="$PROJECT_DIR$/build/build.iml" />
       <module fileurl="file://$PROJECT_DIR$/colorSchemes/colorSchemes.iml" filepath="$PROJECT_DIR$/colorSchemes/colorSchemes.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/plugins/commander/commander.iml" filepath="$PROJECT_DIR$/plugins/commander/commander.iml" group="plugins" />
+      <module fileurl="file://$PROJECT_DIR$/../base/common/common.iml" filepath="$PROJECT_DIR$/../base/common/common.iml" group="plugins/Android/android-sdk" />
       <module fileurl="file://$PROJECT_DIR$/plugins/eclipse/common-eclipse-util/common-eclipse-util.iml" filepath="$PROJECT_DIR$/plugins/eclipse/common-eclipse-util/common-eclipse-util.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/plugins/javaFX/common-javaFX-plugin/common-javaFX-plugin.iml" filepath="$PROJECT_DIR$/plugins/javaFX/common-javaFX-plugin/common-javaFX-plugin.iml" group="plugins/JavaFX" />
       <module fileurl="file://$PROJECT_DIR$/community-main.iml" filepath="$PROJECT_DIR$/community-main.iml" />
@@ -36,6 +44,7 @@
       <module fileurl="file://$PROJECT_DIR$/build/cucumber-test-runner/cucumber-test-runner.iml" filepath="$PROJECT_DIR$/build/cucumber-test-runner/cucumber-test-runner.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/plugins/cvs/cvs-core/cvs-core.iml" filepath="$PROJECT_DIR$/plugins/cvs/cvs-core/cvs-core.iml" group="plugins/VCS/cvs" />
       <module fileurl="file://$PROJECT_DIR$/plugins/cvs/cvs-plugin/cvs-plugin.iml" filepath="$PROJECT_DIR$/plugins/cvs/cvs-plugin/cvs-plugin.iml" group="plugins/VCS/cvs" />
+      <module fileurl="file://$PROJECT_DIR$/../base/ddmlib/ddmlib.iml" filepath="$PROJECT_DIR$/../base/ddmlib/ddmlib.iml" group="plugins/Android/android-sdk" />
       <module fileurl="file://$PROJECT_DIR$/java/debugger/impl/debugger-impl.iml" filepath="$PROJECT_DIR$/java/debugger/impl/debugger-impl.iml" group="java" />
       <module fileurl="file://$PROJECT_DIR$/java/debugger/openapi/debugger-openapi.iml" filepath="$PROJECT_DIR$/java/debugger/openapi/debugger-openapi.iml" group="java" />
       <module fileurl="file://$PROJECT_DIR$/plugins/devkit/devkit.iml" filepath="$PROJECT_DIR$/plugins/devkit/devkit.iml" group="plugins" />
@@ -43,7 +52,9 @@
       <module fileurl="file://$PROJECT_DIR$/xml/dom-impl/dom-impl.iml" filepath="$PROJECT_DIR$/xml/dom-impl/dom-impl.iml" group="xml" />
       <module fileurl="file://$PROJECT_DIR$/xml/dom-openapi/dom-openapi.iml" filepath="$PROJECT_DIR$/xml/dom-openapi/dom-openapi.iml" group="xml" />
       <module fileurl="file://$PROJECT_DIR$/xml/dom-tests/dom-tests.iml" filepath="$PROJECT_DIR$/xml/dom-tests/dom-tests.iml" group="xml" />
+      <module fileurl="file://$PROJECT_DIR$/../base/draw9patch/draw9patch.iml" filepath="$PROJECT_DIR$/../base/draw9patch/draw9patch.iml" group="plugins/Android/android-sdk" />
       <module fileurl="file://$PROJECT_DIR$/platform/dvcs/dvcs.iml" filepath="$PROJECT_DIR$/platform/dvcs/dvcs.iml" group="platform" />
+      <module fileurl="file://$PROJECT_DIR$/../base/device_validator/dvlib/dvlib.iml" filepath="$PROJECT_DIR$/../base/device_validator/dvlib/dvlib.iml" group="plugins/Android/android-sdk" />
       <module fileurl="file://$PROJECT_DIR$/plugins/eclipse/eclipse.iml" filepath="$PROJECT_DIR$/plugins/eclipse/eclipse.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/plugins/eclipse/jps-plugin/eclipse-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/eclipse/jps-plugin/eclipse-jps-plugin.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/platform/editor-ui-api/editor-ui-api.iml" filepath="$PROJECT_DIR$/platform/editor-ui-api/editor-ui-api.iml" group="platform" />
@@ -60,10 +71,13 @@
       <module fileurl="file://$PROJECT_DIR$/plugins/github/github.iml" filepath="$PROJECT_DIR$/plugins/github/github.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/plugins/google-app-engine/google-app-engine.iml" filepath="$PROJECT_DIR$/plugins/google-app-engine/google-app-engine.iml" group="plugins/GAE" />
       <module fileurl="file://$PROJECT_DIR$/plugins/google-app-engine/jps-plugin/google-app-engine-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/google-app-engine/jps-plugin/google-app-engine-jps-plugin.iml" group="plugins/GAE" />
+      <module fileurl="file://$PROJECT_DIR$/../studio/cloud/google-cloud-tools.iml" filepath="$PROJECT_DIR$/../studio/cloud/google-cloud-tools.iml" group="plugins/Google" />
       <module fileurl="file://$PROJECT_DIR$/plugins/gradle/gradle.iml" filepath="$PROJECT_DIR$/plugins/gradle/gradle.iml" group="community/plugins/gradle" />
+      <module fileurl="file://$PROJECT_DIR$/../base/gradle-import/gradle-import.iml" filepath="$PROJECT_DIR$/../base/gradle-import/gradle-import.iml" group="plugins/Android/android-sdk" />
       <module fileurl="file://$PROJECT_DIR$/plugins/gradle/tooling-extension-api/gradle-tooling-extension-api.iml" filepath="$PROJECT_DIR$/plugins/gradle/tooling-extension-api/gradle-tooling-extension-api.iml" group="community/plugins/gradle" />
       <module fileurl="file://$PROJECT_DIR$/plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml" filepath="$PROJECT_DIR$/plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml" group="community/plugins/gradle" />
       <module fileurl="file://$PROJECT_DIR$/plugins/groovy/jps-plugin/groovy-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/groovy/jps-plugin/groovy-jps-plugin.iml" group="plugins/Groovy" />
+      <module fileurl="file://$PROJECT_DIR$/plugins/groovy/groovy-psi/groovy-psi.iml" filepath="$PROJECT_DIR$/plugins/groovy/groovy-psi/groovy-psi.iml" group="plugins/Groovy" />
       <module fileurl="file://$PROJECT_DIR$/plugins/groovy/rt-constants/groovy-rt-constants.iml" filepath="$PROJECT_DIR$/plugins/groovy/rt-constants/groovy-rt-constants.iml" group="plugins/Groovy" />
       <module fileurl="file://$PROJECT_DIR$/plugins/groovy/rt/groovy_rt.iml" filepath="$PROJECT_DIR$/plugins/groovy/rt/groovy_rt.iml" group="plugins/Groovy" />
       <module fileurl="file://$PROJECT_DIR$/plugins/hg4idea/hg4idea.iml" filepath="$PROJECT_DIR$/plugins/hg4idea/hg4idea.iml" group="plugins/VCS" />
@@ -90,7 +104,6 @@
       <module fileurl="file://$PROJECT_DIR$/plugins/javaFX/javaFX-jps-plugin/javaFX-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/javaFX/javaFX-jps-plugin/javaFX-jps-plugin.iml" group="plugins/JavaFX" />
       <module fileurl="file://$PROJECT_DIR$/java/compiler/javac2/javac2.iml" filepath="$PROJECT_DIR$/java/compiler/javac2/javac2.iml" group="java/compiler" />
       <module fileurl="file://$PROJECT_DIR$/plugins/cvs/javacvs-src/javacvs-src.iml" filepath="$PROJECT_DIR$/plugins/cvs/javacvs-src/javacvs-src.iml" group="plugins/VCS/cvs" />
-      <module fileurl="file://$PROJECT_DIR$/plugins/groovy/groovy-psi/groovy-psi.iml" filepath="$PROJECT_DIR$/plugins/groovy/groovy-psi/groovy-psi.iml" group="plugins/Groovy" />
       <module fileurl="file://$PROJECT_DIR$/plugins/groovy/jetgroovy.iml" filepath="$PROJECT_DIR$/plugins/groovy/jetgroovy.iml" group="plugins/Groovy" />
       <module fileurl="file://$PROJECT_DIR$/plugins/tasks/tasks-core/jira/jira.iml" filepath="$PROJECT_DIR$/plugins/tasks/tasks-core/jira/jira.iml" group="plugins/tasks" />
       <module fileurl="file://$PROJECT_DIR$/jps/jps-builders/jps-builders.iml" filepath="$PROJECT_DIR$/jps/jps-builders/jps-builders.iml" group="jps" />
@@ -109,11 +122,15 @@
       <module fileurl="file://$PROJECT_DIR$/plugins/junit_rt/junit_rt.iml" filepath="$PROJECT_DIR$/plugins/junit_rt/junit_rt.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/platform/lang-api/lang-api.iml" filepath="$PROJECT_DIR$/platform/lang-api/lang-api.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/platform/lang-impl/lang-impl.iml" filepath="$PROJECT_DIR$/platform/lang-impl/lang-impl.iml" group="platform" />
+      <module fileurl="file://$PROJECT_DIR$/../base/layoutlib-api/layoutlib-api.iml" filepath="$PROJECT_DIR$/../base/layoutlib-api/layoutlib-api.iml" group="plugins/Android/android-sdk" />
+      <module fileurl="file://$PROJECT_DIR$/../base/lint/libs/lint-api/lint-api.iml" filepath="$PROJECT_DIR$/../base/lint/libs/lint-api/lint-api.iml" group="plugins/Android/android-sdk/lint" />
+      <module fileurl="file://$PROJECT_DIR$/../base/lint/libs/lint-checks/lint-checks.iml" filepath="$PROJECT_DIR$/../base/lint/libs/lint-checks/lint-checks.iml" group="plugins/Android/android-sdk/lint" />
       <module fileurl="file://$PROJECT_DIR$/platform/lvcs-api/lvcs-api.iml" filepath="$PROJECT_DIR$/platform/lvcs-api/lvcs-api.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/platform/lvcs-impl/lvcs-impl.iml" filepath="$PROJECT_DIR$/platform/lvcs-impl/lvcs-impl.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/python/main_idea_python_plugin.iml" filepath="$PROJECT_DIR$/python/main_idea_python_plugin.iml" group="python" />
       <module fileurl="file://$PROJECT_DIR$/python/main_pycharm_ce.iml" filepath="$PROJECT_DIR$/python/main_pycharm_ce.iml" group="python" />
       <module fileurl="file://$PROJECT_DIR$/java/manifest/manifest.iml" filepath="$PROJECT_DIR$/java/manifest/manifest.iml" group="java" />
+      <module fileurl="file://$PROJECT_DIR$/../base/build-system/manifest-merger/manifest-merger.iml" filepath="$PROJECT_DIR$/../base/build-system/manifest-merger/manifest-merger.iml" group="plugins/Android/android-sdk" />
       <module fileurl="file://$PROJECT_DIR$/plugins/maven/maven.iml" filepath="$PROJECT_DIR$/plugins/maven/maven.iml" group="plugins/maven" />
       <module fileurl="file://$PROJECT_DIR$/plugins/maven/artifact-resolver-m2/maven-artifact-resolver-m2.iml" filepath="$PROJECT_DIR$/plugins/maven/artifact-resolver-m2/maven-artifact-resolver-m2.iml" group="plugins/maven" />
       <module fileurl="file://$PROJECT_DIR$/plugins/maven/artifact-resolver-m3/maven-artifact-resolver-m3.iml" filepath="$PROJECT_DIR$/plugins/maven/artifact-resolver-m3/maven-artifact-resolver-m3.iml" group="plugins/maven" />
@@ -122,7 +139,9 @@
       <module fileurl="file://$PROJECT_DIR$/plugins/maven/maven-server-api/maven-server-api.iml" filepath="$PROJECT_DIR$/plugins/maven/maven-server-api/maven-server-api.iml" group="plugins/maven" />
       <module fileurl="file://$PROJECT_DIR$/plugins/maven/maven2-server-impl/maven2-server-impl.iml" filepath="$PROJECT_DIR$/plugins/maven/maven2-server-impl/maven2-server-impl.iml" group="plugins/maven" />
       <module fileurl="file://$PROJECT_DIR$/plugins/maven/maven3-server-impl/maven3-server-impl.iml" filepath="$PROJECT_DIR$/plugins/maven/maven3-server-impl/maven3-server-impl.iml" group="plugins/maven" />
+      <module fileurl="file://$PROJECT_DIR$/../base/ninepatch/ninepatch.iml" filepath="$PROJECT_DIR$/../base/ninepatch/ninepatch.iml" group="plugins/Android/android-sdk" />
       <module fileurl="file://$PROJECT_DIR$/java/openapi/openapi.iml" filepath="$PROJECT_DIR$/java/openapi/openapi.iml" group="java" />
+      <module fileurl="file://$PROJECT_DIR$/../base/perflib/perflib.iml" filepath="$PROJECT_DIR$/../base/perflib/perflib.iml" group="plugins/Android/android-sdk" />
       <module fileurl="file://$PROJECT_DIR$/platform/platform-api/platform-api.iml" filepath="$PROJECT_DIR$/platform/platform-api/platform-api.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/platform/platform-impl/platform-impl.iml" filepath="$PROJECT_DIR$/platform/platform-impl/platform-impl.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/platform/platform-main/platform-main.iml" filepath="$PROJECT_DIR$/platform/platform-main/platform-main.iml" group="platform" />
@@ -158,6 +177,8 @@
       <module fileurl="file://$PROJECT_DIR$/python/rest/rest.iml" filepath="$PROJECT_DIR$/python/rest/rest.iml" group="python" />
       <module fileurl="file://$PROJECT_DIR$/platform/script-debugger/backend/script-debugger-backend.iml" filepath="$PROJECT_DIR$/platform/script-debugger/backend/script-debugger-backend.iml" group="platform/script-debugger" />
       <module fileurl="file://$PROJECT_DIR$/platform/script-debugger/debugger-ui/script-debugger-ui.iml" filepath="$PROJECT_DIR$/platform/script-debugger/debugger-ui/script-debugger-ui.iml" group="platform/script-debugger" />
+      <module fileurl="file://$PROJECT_DIR$/../base/sdk-common/sdk-common.iml" filepath="$PROJECT_DIR$/../base/sdk-common/sdk-common.iml" group="plugins/Android/android-sdk" />
+      <module fileurl="file://$PROJECT_DIR$/../base/sdklib/sdklib.iml" filepath="$PROJECT_DIR$/../base/sdklib/sdklib.iml" group="plugins/Android/android-sdk" />
       <module fileurl="file://$PROJECT_DIR$/platform/smRunner/smRunner.iml" filepath="$PROJECT_DIR$/platform/smRunner/smRunner.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/plugins/cvs/smartcvs-src/smartcvs-src.iml" filepath="$PROJECT_DIR$/plugins/cvs/smartcvs-src/smartcvs-src.iml" group="plugins/VCS/cvs" />
       <module fileurl="file://$PROJECT_DIR$/spellchecker/spellchecker.iml" filepath="$PROJECT_DIR$/spellchecker/spellchecker.iml" group="plugins" />
@@ -176,9 +197,11 @@
       <module fileurl="file://$PROJECT_DIR$/plugins/testng/testng.iml" filepath="$PROJECT_DIR$/plugins/testng/testng.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/plugins/testng_rt/testng_rt.iml" filepath="$PROJECT_DIR$/plugins/testng_rt/testng_rt.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/platform/testFramework/bootstrap/tests_bootstrap.iml" filepath="$PROJECT_DIR$/platform/testFramework/bootstrap/tests_bootstrap.iml" group="platform" />
+      <module fileurl="file://$PROJECT_DIR$/../base/testutils/testutils.iml" filepath="$PROJECT_DIR$/../base/testutils/testutils.iml" group="plugins/Android/android-sdk" />
       <module fileurl="file://$PROJECT_DIR$/plugins/ui-designer/ui-designer.iml" filepath="$PROJECT_DIR$/plugins/ui-designer/ui-designer.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/plugins/ui-designer-core/ui-designer-core.iml" filepath="$PROJECT_DIR$/plugins/ui-designer-core/ui-designer-core.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/plugins/ui-designer/jps-plugin/ui-designer-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/ui-designer/jps-plugin/ui-designer-jps-plugin.iml" group="plugins" />
+      <module fileurl="file://$PROJECT_DIR$/updater/updater.iml" filepath="$PROJECT_DIR$/updater/updater.iml" />
       <module fileurl="file://$PROJECT_DIR$/platform/usageView/usageView.iml" filepath="$PROJECT_DIR$/platform/usageView/usageView.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/platform/util/util.iml" filepath="$PROJECT_DIR$/platform/util/util.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/platform/util-rt/util-rt.iml" filepath="$PROJECT_DIR$/platform/util-rt/util-rt.iml" group="platform" />
diff --git a/.idea/runConfigurations/AndroidStudio.xml b/.idea/runConfigurations/AndroidStudio.xml
new file mode 100644
index 0000000..c62432d
--- /dev/null
+++ b/.idea/runConfigurations/AndroidStudio.xml
@@ -0,0 +1,25 @@
+<component name="ProjectRunConfigurationManager">
+  <configuration default="false" name="AndroidStudio" type="Application" factoryName="Application" singleton="true">
+    <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+    <option name="MAIN_CLASS_NAME" value="com.intellij.idea.Main" />
+    <option name="VM_PARAMETERS" value="-ea -Xbootclasspath/p:../out/classes/production/boot -Xms384m -Xmx768m -Didea.is.internal=true -XX:MaxPermSize=384m -Dapple.awt.graphics.UseQuartz=true -Didea.platform.prefix=AndroidStudio -Dandroid.extra_templates.path=../../../sdk/templates -Dapple.laf.useScreenMenuBar=true -Dcom.apple.mrj.application.apple.menu.about.name=AndroidStudio -Dsun.awt.disablegrab=true" />
+    <option name="PROGRAM_PARAMETERS" value="" />
+    <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bin" />
+    <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+    <option name="ALTERNATIVE_JRE_PATH" value="" />
+    <option name="ENABLE_SWING_INSPECTOR" value="false" />
+    <option name="ENV_VARIABLES" />
+    <option name="PASS_PARENT_ENVS" value="true" />
+    <module name="community-main" />
+    <envs />
+    <RunnerSettings RunnerId="Debug">
+      <option name="DEBUG_PORT" value="" />
+      <option name="TRANSPORT" value="0" />
+      <option name="LOCAL" value="true" />
+    </RunnerSettings>
+    <RunnerSettings RunnerId="Run" />
+    <ConfigurationWrapper RunnerId="Debug" />
+    <ConfigurationWrapper RunnerId="Run" />
+    <method />
+  </configuration>
+</component>
\ No newline at end of file
diff --git a/.idea/scopes/androidplugin.xml b/.idea/scopes/androidplugin.xml
new file mode 100644
index 0000000..dcc1341
--- /dev/null
+++ b/.idea/scopes/androidplugin.xml
@@ -0,0 +1,3 @@
+<component name="DependencyValidationManager">
+  <scope name="androidplugin" pattern="file[group:Android]:*//*&amp;&amp;!file[group:android-sdk]:*//*" />
+</component>
\ No newline at end of file
diff --git a/.idea/scopes/aosp_code.xml b/.idea/scopes/aosp_code.xml
new file mode 100644
index 0000000..abf77af
--- /dev/null
+++ b/.idea/scopes/aosp_code.xml
@@ -0,0 +1,3 @@
+<component name="DependencyValidationManager">
+  <scope name="aosp-code" pattern="test[group:android-sdk]:*..*||src[group:android-sdk]:*..*" />
+</component>
\ No newline at end of file
diff --git a/.idea/scopes/obsoleteplugin.xml b/.idea/scopes/obsoleteplugin.xml
new file mode 100644
index 0000000..0537436
--- /dev/null
+++ b/.idea/scopes/obsoleteplugin.xml
@@ -0,0 +1,3 @@
+<component name="DependencyValidationManager">
+  <scope name="obsoleteplugin" pattern="file[community-main]:plugins/android//*||file[community-main]:plugins/android-designer//*" />
+</component>
\ No newline at end of file
diff --git a/.idea/scopes/platform.xml b/.idea/scopes/platform.xml
new file mode 100644
index 0000000..a0bafd1
--- /dev/null
+++ b/.idea/scopes/platform.xml
@@ -0,0 +1,3 @@
+<component name="DependencyValidationManager">
+  <scope name="platform" pattern="src:*..*&amp;&amp;!src[group:Android]:*..*" />
+</component>
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 275077f..d10a1db 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -2,6 +2,9 @@
 <project version="4">
   <component name="VcsDirectoryMappings">
     <mapping directory="" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$/../adt/idea" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$/../base" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$/../studio/cloud" vcs="Git" />
   </component>
 </project>
 
diff --git a/build.xml b/build.xml
index 8e6bdbc..3df0948 100644
--- a/build.xml
+++ b/build.xml
@@ -1,7 +1,23 @@
 <project name="IntelliJ IDEA Community Edition" default="all">
   <property name="project.home" value="${basedir}"/>
-  <property name="out.dir" value="${project.home}/out"/>
-  <property name="tmp.dir" value="${project.home}/out/tmp"/>
+
+  <!--
+    Sets the out folder. Defaults to ${basedir}/out.
+    To override, use command line arg "out": e.g. -Dout=/path/
+  -->
+  <condition property="out.dir" value="${out}" else="${project.home}/out">
+    <isset property="out" />
+  </condition>
+
+  <property name="tmp.dir" value="${out.dir}/tmp"/>
+
+  <!--
+    Sets the build number. Defaults to SNAPSHOT.
+    To override, use command line arg "buildNumber": e.g. -DbuildNumber=777
+  -->
+  <condition property="buildId" value="${buildNumber}" else="SNAPSHOT">
+    <isset property="buildNumber" />
+  </condition>
 
   <target name="cleanup">
     <delete dir="${out.dir}" failonerror="false"/>
@@ -14,12 +30,17 @@
 
   <macrodef name="call_gant">
     <attribute name="script" />
+    <attribute name="test.patterns" default="" />
     <sequential>
       <java failonerror="true" jar="${project.home}/lib/ant/lib/ant-launcher.jar" fork="true">
+        <jvmarg line="-Xmx1424m -XX:MaxPermSize=352m"/>
+        <jvmarg value="-Dout=${out.dir}" />
+        <jvmarg value="-DbuildNumber=${buildId}" />
         <jvmarg line="-Xmx612m -XX:MaxPermSize=152m"/>
         <sysproperty key="java.awt.headless" value="true"/>
         <arg line="&quot;-Dgant.script=@{script}&quot;"/>
         <arg line="&quot;-Dteamcity.build.tempDir=${tmp.dir}&quot;"/>
+        <arg line="&quot;-Didea.test.patterns=@{test.patterns}&quot;"/>
         <arg line="&quot;-Didea.test.group=ALL_EXCLUDE_DEFINED&quot;"/>
         <arg value="-f"/>
         <arg value="${project.home}/build/gant.xml"/>
@@ -32,8 +53,17 @@
   </target>
 
   <target name="test" depends="init">
-    <call_gant script="${project.home}/build/scripts/tests.gant"/>
+    <call_gant script="${project.home}/build/scripts/tests.gant" test.patterns="org.jetbrains.android.*;com.android.tools.idea.*;com.google.gct.*"/>
   </target>
 
-  <target name="all" depends="cleanup,build"/>
+  <!-- The build task creates an updater.jar in ${out.dir}. This task bundles log4j & the updater into a single jar -->
+  <taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpath="${project.home}/build/lib/jarjar-1.0.jar"/>
+  <target name="fullupdater" depends="build">
+    <jarjar jarfile="${out.dir}/updater-full.jar">
+        <zipfileset src="${out.dir}/updater.jar" />
+        <zipfileset src="lib/log4j.jar" />
+    </jarjar>
+  </target>
+
+  <target name="all" depends="cleanup,build,fullupdater"/>
 </project>
diff --git a/build/Install-Linux-tar.txt b/build/Install-Linux-tar.txt
index 8c9f048..2faac26 100644
--- a/build/Install-Linux-tar.txt
+++ b/build/Install-Linux-tar.txt
@@ -11,7 +11,7 @@
 
   2. Open a console and cd into "{installation home}/bin" and type:
 
-       ./@@product@@.sh
+       ./@@script_name@@
 
      to start the application.
 
diff --git a/build/conf/mac/Contents/Info.plist b/build/conf/mac/Contents/Info.plist
index 0345101..eb5a131 100644
--- a/build/conf/mac/Contents/Info.plist
+++ b/build/conf/mac/Contents/Info.plist
@@ -39,11 +39,11 @@
     <key>CFBundleSignature</key>
     <string>????</string>
     <key>CFBundleGetInfoString</key>
-    <string>@@bundle_name@@ @@version@@, build @@build@@. Copyright JetBrains s.r.o., (c) 2000-@@year@@</string>
+    <string>@@bundle_name@@ EAP, build EAP. Copyright @@company_name@@, (c) @@min_year@@-@@max_year@@</string>
     <key>CFBundleShortVersionString</key>
-    <string>@@version@@</string>
+    <string>EAP</string>
     <key>CFBundleVersion</key>
-    <string>@@build@@</string>
+    <string>EAP</string>
     <key>LSApplicationCategoryType</key>
     <string>public.app-category.developer-tools</string>
     <key>CFBundleHelpBookName</key>
diff --git a/build/gant.xml b/build/gant.xml
index f332c9a..190ddb6 100644
--- a/build/gant.xml
+++ b/build/gant.xml
@@ -37,6 +37,9 @@
   </taskdef>
 
   <target name="doGant">
-    <gant file="${gant.script}" target="${gant.target}"/>
+    <gant file="${gant.script}" target="${gant.target}">
+      <definition name="teamcity.build.tempDir" value="${teamcity.build.tempDir}"/>
+      <definition name="idea.test.patterns" value="${idea.test.patterns}"/>
+    </gant>
   </target>
 </project>
diff --git a/build/scripts/common_tests.gant b/build/scripts/common_tests.gant
index 1af3d7a..f13c342 100644
--- a/build/scripts/common_tests.gant
+++ b/build/scripts/common_tests.gant
@@ -20,6 +20,10 @@
 
 requireProperty("out", "$home/out")
 
+target(check: "Ensure the environment is configured") {
+  tempDir = p("teamcity.build.tempDir")
+}
+
 target(compile: "Compile project") {
   ant.delete(failonerror: false) {
     fileset(dir: "$home/reports")
@@ -39,9 +43,9 @@
 }
 
 target('run_tests': 'Run java tests') {
-  depends([compile])
+  depends([check, compile])
 
-  ant.junit(fork: "yes", showoutput: "true", logfailedtests:false) {
+  ant.junit(fork: "yes", showoutput: "true", logfailedtests:false, printsummary: "true") {
     pass("idea.test.group")
     pass("idea.test.patterns")
     pass("idea.fast.only")
@@ -59,6 +63,7 @@
 
     commonJvmArgs().each { jvmarg(value: it) }
 
+
     if (isDefined("jvm_args")) {
       jvm_args.each { jvmarg(value: it) }
     }
@@ -70,6 +75,9 @@
       pathelement(location: "${jdkHome}/lib/tools.jar")
     }
 
+    formatter(type: "plain")
+    formatter(type: "xml")
+
     testcases.each {
       test (name: it)
     }
@@ -77,5 +85,5 @@
 }
 
 target('default' : "Run all tests") {
-  depends([compile, run_tests, run_cucumber_tests])
-}
\ No newline at end of file
+  depends([compile, run_tests])
+}
diff --git a/build/scripts/dist.gant b/build/scripts/dist.gant
index fef5203..17b20d7 100644
--- a/build/scripts/dist.gant
+++ b/build/scripts/dist.gant
@@ -19,6 +19,12 @@
 includeTargets << new File("${guessHome(this)}/build/scripts/utils.gant")
 
 requireProperty("out", "$home/out")
+requireProperty("buildNumber", "SNAPSHOT")
+
+// "out" has to be canonical, otherwise the ant build fails
+// with mysterious errors
+out = new File(out).getCanonicalPath()
+setProperty("out", out)
 
 class Paths {
   final sandbox
@@ -62,7 +68,7 @@
 }
 
 private String appInfoFile() {
-  return "${projectBuilder.moduleOutput(findModule("community-resources"))}/idea/IdeaApplicationInfo.xml"
+  return "${projectBuilder.moduleOutput(findModule("adt-branding"))}/idea/AndroidStudioApplicationInfo.xml"
 }
 
 target('default': 'The default target') {
@@ -73,10 +79,17 @@
 
   zipSources(home, paths.artifacts)
 
-  layoutAll([buildNumber: "IC-$snapshot",
-             system_selector: "IdeaIC${p("component.version.major")}",
+  layoutAll([buildNumber: "AI-$snapshot".replaceAll("SNAPSHOT", p("buildNumber")),
+             system_selector: "AndroidStudioPreview",
+             platform_prefix: "AndroidStudio",
+             icns: "${projectBuilder.moduleOutput(findModule("adt-branding"))}/artwork/AndroidStudio.icns",
+             ide_jvm_args: "-Didea.platform.prefix=AndroidStudio",
              tools_jar: true],
             home, null, paths, true)
+
+  // Generate updater.jar from the updater module (patch updater)
+  projectBuilder.stage("Generating updater in $out")
+  layoutUpdater(out)
 }
 
 target('build-dist-jars' : 'Target to build jars from locally compiled classes') {
@@ -84,7 +97,7 @@
   // load ApplicationInfo.xml properties
   ant.xmlproperty(file: appInfoFile(), collapseAttributes: "true")
 
-  layoutAll([buildNumber: "IC-$snapshot",
+  layoutAll([buildNumber: "AI-$snapshot".replaceAll("SNAPSHOT", p("buildNumber")),
              system_selector: "IdeaIC${p("component.version.major")}",
              tools_jar: true],
              home, null, paths)
@@ -93,6 +106,8 @@
 def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps = false) {
   Paths paths = _paths != null ? _paths : new Paths(out)
 
+  args.companyName = p("component.company.name")
+
   wireBuildDate(args.buildNumber, appInfoFile())
   ant.echo(message: args.buildNumber, file: "$paths.distAll/build.txt")
 
@@ -123,44 +138,63 @@
   layoutMac(args, home, paths)
   layoutUnix(args, home, paths)
 
-  buildWinZip("$paths.artifacts/idea${args.buildNumber}.win.zip", [paths.distAll, paths.distWin])
+  def winAppRoot = "android-studio"
+  def macAppRoot = "Android Studio.app"
+  def linTarRoot = "android-studio"
 
-  def macAppRoot = isEap() ?
-                   "IntelliJ IDEA ${p("component.version.major")} CE EAP.app" :
-                   "IntelliJ IDEA ${p("component.version.major")} CE.app"
+  androidBuildNumber = p("buildNumber")
+  //def macAppRoot = isEap() ?
+  //                 "IntelliJ IDEA ${p("component.version.major")} CE EAP.app" :
+  //                 "IntelliJ IDEA ${p("component.version.major")} CE.app"
 
-  String macZip = "$paths.artifacts/idea${args.buildNumber}.mac.zip"
+  def winZip = "$paths.artifacts/android-studio-${androidBuildNumber}.win.zip"
+  def macZip = "$paths.artifacts/android-studio-${androidBuildNumber}.mac.zip"
+  def linTar = "$paths.artifacts/android-studio-${androidBuildNumber}.tar"
+
+  buildWinZip(winAppRoot, winZip, [paths.distAll, paths.distWin])
+  buildTarGz(linTarRoot, linTar, [paths.distAll, paths.distUnix])
   buildMacZip(macAppRoot, macZip, [paths.distAll], paths.distMac)
-  notifyArtifactBuilt(macZip)
-
-  buildTarGz("idea-${args.buildNumber}", "$paths.artifacts/idea${args.buildNumber}.tar", [paths.distAll, paths.distUnix])
 }
 
-private layoutWin(Map args, String home, Paths paths) {
+private layoutWin(Map _args, String home, Paths paths) {
   String target = paths.distWin
 
+  Map args = new HashMap(_args)
+  args.product_uc = "ANDROID_STUDIO"
+  args.vm_options = "studio.exe"
+
   layout(target) {
     dir("bin") {
       fileset(dir: "$home/bin/win")
     }
   }
 
-  ant.copy(file: "$home/platform/icons/src/idea_CE.ico", tofile: "$target/bin/idea.ico")
+  ant.copy(file: "$home/../adt/idea/adt-branding/src/artwork/androidstudio.ico", tofile: "$target/bin/idea.ico")
 
-  winScripts(target, home, "idea.bat", args)
-  winVMOptions(target, null, "idea.exe", "idea64.exe")
-  List resourcePaths = ["$home/community-resources/src", "$home/platform/icons/src"]
-  buildWinLauncher(home, "$home/bin/WinLauncher/WinLauncher.exe", "$target/bin/idea.exe", appInfoFile(),
-                   "$home/build/conf/ideaCE-launcher.properties", args.ce_exe_selector, resourcePaths)
-  buildWinLauncher(home, "$home/bin/WinLauncher/WinLauncher64.exe", "$target/bin/idea64.exe", appInfoFile(),
-                   "$home/build/conf/ideaCE64-launcher.properties", args.ce_exe_selector, resourcePaths)
+  // The 0.1.1 win launcher.
+  ant.copy(  file: "$home/../adt/idea/native/WinLauncher/out/Release-Win32/studio.exe",
+           tofile: "$target/bin/studio.exe")
+  ant.copy(  file: "$home/../adt/idea/native/WinLauncher/out/Release-Win32/studio.exe.manifest",
+           tofile: "$target/bin/studio.exe.manifest")
+  ant.copy(  file: "$home/../adt/idea/native/WinLauncher/out/Release-x64/studio64.exe",
+           tofile: "$target/bin/studio64.exe")
+  ant.copy(  file: "$home/../adt/idea/native/WinLauncher/out/Release-x64/studio64.exe.manifest",
+           tofile: "$target/bin/studio64.exe.manifest")
+  // Manual updater script
+  ant.copy(  file: "$home/../adt/idea/native/update_studio.bat",
+           tofile: "$target/bin/update_studio.bat")
+
+  winScripts(target, home, "studio.bat", args)
+  winVMOptions(target, args, "studio.exe", "studio64.exe")
 }
 
 private layoutMac(Map _args, String home, Paths paths) {
   String target = paths.distMac
 
   Map args = new HashMap(_args)
-  args.bundleIdentifier = "com.jetbrains.intellij.ce"
+  args.bundleIdentifier = "com.google.android.studio"
+  args.executable = "studio"
+  args.help_id = "AI"
   args.doc_types = """
       <dict>
         <key>CFBundleTypeExtensions</key>
@@ -178,21 +212,34 @@
   args."idea.properties.path" = "${paths.distAll}/bin/idea.properties"
   args.urlSchemes = ["idea"]
   args.mac_no_yjp = true
+
+  // Manual updater script
+  ant.copy(file: "$home/../adt/idea/native/update_studio.sh", tofile: "$target/bin/update_studio.sh")
+
   layoutMacApp(target, home, args)
 }
 
-private layoutUnix(Map args, String home, Paths paths) {
+private layoutUnix(Map _args, String home, Paths paths) {
   String target = paths.distUnix
 
+  Map args = new HashMap(_args)
+  args.product_uc = "STUDIO"
+  args.vm_options = "studio"
+  args.script_name = "studio.sh"
+
   layout(target) {
     dir("bin") {
       fileset(dir: "$home/bin/linux")
     }
   }
 
-  ant.copy(file: "$home/platform/icons/src/icon_CE_128.png", tofile: "$target/bin/idea.png")
+  ant.copy(file: "$home/../adt/idea/adt-branding/src/artwork/icon_AS_128.png", tofile: "$target/bin/idea.png")
+  ant.copy(file: "$home/../adt/idea/adt-branding/src/artwork/androidstudio.ico", tofile: "$target/bin/androidstudio.ico")
 
-  unixScripts(target, home, "idea.sh", args)
-  unixVMOptions(target, "idea")
+  // Manual updater script
+  ant.copy(file: "$home/../adt/idea/native/update_studio.sh", tofile: "$target/bin/update_studio.sh")
+
+  unixScripts(target, home, args.script_name, args)
+  unixVMOptions(target, "studio")
   unixReadme(target, home, args)
 }
diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant
index 317ea36..8bbd139 100644
--- a/build/scripts/layouts.gant
+++ b/build/scripts/layouts.gant
@@ -13,6 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
+import org.jetbrains.jps.model.java.JpsJavaClasspathKind
+import org.jetbrains.jps.model.module.JpsLibraryDependency
+import org.jetbrains.jps.model.library.JpsOrderRootType
+import org.jetbrains.jps.util.JpsPathUtil
+
 import static org.jetbrains.jps.idea.IdeaProjectLoader.guessHome
 
 includeTargets << new File("${guessHome(this)}/build/scripts/utils.gant")
@@ -24,7 +30,7 @@
 }
 
 String appInfoFileName() {
-  return "idea/IdeaApplicationInfo.xml"
+  return "idea/AndroidStudioApplicationInfo.xml"
 }
 
 String patchAppDescriptor(String targetDirectory) {
@@ -33,12 +39,12 @@
   ant.delete(dir: patchedDirectory)
 
   layout(patchedDirectory) {
-    module("community-resources") {
+    module("adt-branding") {
       include(name: appInfoFileName())
     }
   }
 
-  ant.replace(file: "$patchedDirectory/${appInfoFileName()}", token: "__BUILD_NUMBER__", value: "IC-$snapshot")
+  ant.replace(file: "$patchedDirectory/${appInfoFileName()}", token: "__BUILD_NUMBER__", value: "AI-$snapshot")
   ant.replace(file: "$patchedDirectory/${appInfoFileName()}", token: "__BUILD_DATE__", value: new Date().format("yyyyMMddHHmm"))
 
   return patchedDirectory
@@ -148,7 +154,8 @@
         module("colorSchemes")
         module("resources")
         module("platform-resources")
-        module("community-resources") {
+        module("community-resources")
+        module("adt-branding") {
           if (patchedDescriptorDir != null) {
             exclude(name: appInfoFileName())
           }
@@ -251,9 +258,8 @@
 }
 
 public def layoutCommunityPlugins(String home) {
-  if (isDefined("androidPluginHome")) {
-    layoutAndroid(p("androidPluginHome"))
-  }
+  layoutAndroid()
+  layoutCloud()
 
   dir("plugins") {
     def simplePlugins = ["commander", "copyright", "java-i18n", "hg4idea", "github"] //, "tasks-time-tracking"]
@@ -262,18 +268,21 @@
       layoutPlugin it
     }
 
-    layoutPlugin("ant", "ant", "antIntegration") {
-      jar("ant-jps-plugin.jar") {
-        module("ant-jps-plugin")
-      }
-    }
-    layoutPlugin("uiDesigner", "ui-designer", "uiDesigner") {
-      dir("jps") {
-        jar("ui-designer-jps-plugin.jar") {
-          module("ui-designer-jps-plugin")
-        }
-      }
-    }
+    // ant not needed in AS
+    // layoutPlugin("ant", "ant", "antIntegration") {
+    //   jar("ant-jps-plugin.jar") {
+    //     module("ant-jps-plugin")
+    //   }
+    // }
+
+    // uiDesigner not needed in AS
+    // layoutPlugin("uiDesigner", "ui-designer", "uiDesigner") {
+    //   dir("jps") {
+    //     jar("ui-designer-jps-plugin.jar") {
+    //       module("ui-designer-jps-plugin")
+    //     }
+    //   }
+    // }
 
     pluginDir("properties") {
       dir("lib") {
@@ -377,13 +386,14 @@
       }
     }
 
-    pluginDir("ByteCodeViewer") {
-      dir("lib") {
-        jar("byteCodeViewer.jar") {
-          noResources("ByteCodeViewer")
-        }
-      }
-    }
+    // ByteCodeViewer not needed in AS
+    // pluginDir("ByteCodeViewer") {
+    //   dir("lib") {
+    //     jar("byteCodeViewer.jar") {
+    //       noResources("ByteCodeViewer")
+    //     }
+    //   }
+    // }
 
     pluginDir("cvsIntegration") {
       dir("lib") {
@@ -413,36 +423,38 @@
       }
     }
 
-    layoutPlugin("xpath") {
-      dir("rt") {
-        jar("xslt-rt.jar") {module("xslt-rt")}
-      }
-    }
+    // xpath not needed in AS
+    // layoutPlugin("xpath") {
+    //   dir("rt") {
+    //     jar("xslt-rt.jar") {module("xslt-rt")}
+    //   }
+    // }
 
-    layoutPlugin("xslt-debugger") {
-      jar("xslt-debugger-engine.jar") {
-        module("xslt-debugger-engine") {
-          excludes: "lib"
-        }
-      }
-      fileset(dir: "$home/plugins/xslt-debugger/engine/lib") {
-        include(name: "**/rmi-stubs.jar")
-      }
-      dir("rt") {
-        jar("xslt-debugger-engine-impl.jar") {
-          module("xslt-debugger-engine-impl") {
-            exclude(name: "lib")
-            exclude(name: "**/*.jar")
-            exclude(name: "**/*.html")
-          }
-        }
-        fileset(dir: "$home/plugins/xslt-debugger/engine/impl/lib") {
-          include(name: "**/*.jar")
-          exclude(name: "**/rmi-stubs.jar")
-          include(name: "**/*.html")
-        }
-      }
-    }
+    // xslt-debugger not needed in AS
+    // layoutPlugin("xslt-debugger") {
+    //   jar("xslt-debugger-engine.jar") {
+    //     module("xslt-debugger-engine") {
+    //       excludes: "lib"
+    //     }
+    //   }
+    //   fileset(dir: "$home/plugins/xslt-debugger/engine/lib") {
+    //     include(name: "**/rmi-stubs.jar")
+    //   }
+    //   dir("rt") {
+    //     jar("xslt-debugger-engine-impl.jar") {
+    //       module("xslt-debugger-engine-impl") {
+    //         exclude(name: "lib")
+    //         exclude(name: "**/*.jar")
+    //         exclude(name: "**/*.html")
+    //       }
+    //     }
+    //     fileset(dir: "$home/plugins/xslt-debugger/engine/impl/lib") {
+    //       include(name: "**/*.jar")
+    //       exclude(name: "**/rmi-stubs.jar")
+    //       include(name: "**/*.html")
+    //     }
+    //   }
+    // }
 
     pluginDir("Groovy") {
       dir("lib") {
@@ -488,24 +500,27 @@
       }
     }
 
-    layoutPlugin("devkit") {
-      dir("jps") {
-        jar("devkit-jps-plugin.jar") {
-          module("devkit-jps-plugin")
-        }
-      }
-      fileset(dir: "${home}/plugins/devkit/lib") {
-        include(name: "**/*.jar")
-      }
-    }
-    layoutPlugin("eclipse") {
-      jar("eclipse-jps-plugin.jar") {
-        module("eclipse-jps-plugin")
-      }
-      jar("common-eclipse-util.jar") {
-        module("common-eclipse-util")
-      }
-    }
+    // devkit not needed in AS
+    // layoutPlugin("devkit") {
+    //   dir("jps") {
+    //     jar("devkit-jps-plugin.jar") {
+    //       module("devkit-jps-plugin")
+    //     }
+    //   }
+    //   fileset(dir: "${home}/plugins/devkit/lib") {
+    //     include(name: "**/*.jar")
+    //   }
+    // }
+
+    // eclipse not needed in AS
+    // layoutPlugin("eclipse") {
+    //   jar("eclipse-jps-plugin.jar") {
+    //     module("eclipse-jps-plugin")
+    //   }
+    //   jar("common-eclipse-util.jar") {
+    //     module("common-eclipse-util")
+    //   }
+    // }
 
     layoutPlugin("terminal") {
       jar("terminal.jar") {
@@ -519,6 +534,39 @@
   }
 }
 
+def layoutCloud() {
+  dir("plugins") {
+    layoutPlugin("google-cloud-tools") {
+      jar("google-cloud-tools.jar") {
+        module("google-cloud-tools")
+      }
+      dir("templates") {
+        fileset(dir: "$home/../studio/cloud/resources/templates")
+      }
+    }
+  }
+}
+
+private Set<String> findModuleDependencies(List<String> modules) {
+  Set<String> paths = new HashSet<String>();
+  modules.each {
+    m = findModule(it)
+    m.getDependenciesList().getDependencies().each {
+      projectBuilder.stage("looking at dependency " + it);
+
+      if (it instanceof JpsLibraryDependency) {  // only want library dependencies (and not other modules)
+        lib = it.getLibrary()
+        if (lib != null) {
+          libroots = lib.getRoots(JpsOrderRootType.COMPILED) // only want compile (and not test)
+          libroots.each {
+            paths.addAll(JpsPathUtil.urlToFile(it.getUrl()).getAbsolutePath());
+          }
+        }
+      }
+    }
+  }
+  return paths;
+}
 
 def layoutPlugin(String moduleName) {
   layoutPlugin(moduleName, moduleName, {})
@@ -624,68 +672,94 @@
   }
 }
 
-def layoutAndroid(String androidHome) {
+def layoutAndroid() {
   dir("plugins") {
-    layoutPlugin("android") {
-      fileset(dir: "${androidHome}/android/lib") {
-        include(name: "**/*.jar")
-        exclude(name: "**/ddmlib_1.jar")
-        exclude(name: "src/*.jar")
-      }
-
-      jar("android-common.jar") {
-        module("android-common")
-      }
-
-      jar("android-rt.jar") {
-        module("android-rt")
-      }
-
-      jar("common.jar") {
-        module("common")
-      }
-      jar("sdklib.jar") {
-        module("sdklib")
-      }
-      jar("layoutlib-api.jar") {
-        module("layoutlib-api")
-      }
-      jar("manifest-merger.jar") {
-        module("manifest-merger")
-      }
-      jar("sdk-tools.jar") {
-        module("assetstudio")
-        module("ddmlib")
-        module("dvlib")
-        module("draw9patch")
-        module("lint-api")
-        module("lint-checks")
-        module("ninepatch")
-        module("sdk-common")
-        module("perflib")
-      }
-      jar("androidAnnotations.jar") {
-        fileset(dir: "$androidHome/android/annotations")
-      }
-      dir("jps") {
-        jar("android-gradle-jps.jar") { module("android-gradle-jps") }
-      }
-      dir("device-art-resources") {
-        fileset(dir: "$androidHome/android/device-art-resources")
-      }
-
-      dir("jps") {
-        jar("android-jps-plugin.jar") { module("android-jps-plugin") }
-      }
-      dir("templates") {
-        fileset(dir: "$androidHome/tools-base/templates")
-      }
-    }
-
-    dir("android-designer") {
+    def androidModule = "android"
+    dir(androidModule) {
       dir("lib") {
-        jar("android-designer.jar") {
-          module("android-designer")
+        jar("android.jar") {
+          module("ui-designer-core") {
+            patternset(refid: "resources.excluded")
+          }
+          noResources(androidModule)
+        }
+
+        jar("resources_en.jar") {
+          module(androidModule) {
+            patternset(refid: "resources.included")
+          }
+          module("ui-designer-core") {
+            patternset(refid: "resources.included")
+          }
+        }
+
+        fileset(dir: "${home}/../adt/idea/android/lib") {
+          include(name: "**/*.jar")
+        }
+
+        // Add Additional libraries that the Android plugin depends on that come from TOOLS_PREBUILTS.
+        // Note: This is a HACK: rather than encoding the full path, we should really query
+        // the project model for the classpath just like we do for the androidModules' dependencies
+        // below
+        fileset(file: "${home}/../../prebuilts/tools/common/m2/repository/org/freemarker/freemarker/2.3.20/freemarker-2.3.20.jar")
+
+        androidModules = [
+                "assetstudio",
+                "common",
+                "ddmlib",
+                "draw9patch",
+                "dvlib",
+                "gradle-import",
+                "layoutlib-api",
+                "lint-api",
+                "lint-checks",
+                "manifest-merger",
+                "ninepatch",
+                "perflib",
+                "sdk-common",
+                "sdklib"
+        ]
+
+        androidModules.each { moduleName ->
+          jar("${moduleName}.jar") {
+            module(moduleName)
+          }
+        }
+
+        jar("androidAnnotations.jar") {
+          fileset(dir: "${home}/../adt/idea/android/annotations")
+        }
+
+        // copy over dependencies of all android modules
+        androidModuleDeps = findModuleDependencies(androidModules)
+        androidModuleDeps.each {
+          fileset(file: it)
+        }
+
+        jar("android-common.jar") {
+          module("android-common")
+        }
+
+        jar("android-rt.jar") {
+          module("android-rt")
+        }
+
+        dir("jps") {
+          jar("android-jps-plugin.jar") { module("android-jps-plugin") }
+          jar("android-gradle-jps.jar") { module("android-gradle-jps") }
+        }
+
+        dir("device-art-resources") {
+          fileset(dir: "${home}/../adt/idea/android/device-art-resources")
+        }
+
+        dir("templates") {
+          fileset(dir: "${home}/../base/templates") {
+            include(name: "activities/**")
+            include(name: "gradle/**")
+            include(name: "other/**")
+            include(name: "gradle-projects/**")
+          }
         }
       }
     }
diff --git a/build/scripts/tests.gant b/build/scripts/tests.gant
index 14bd38a5..d10d72b 100644
--- a/build/scripts/tests.gant
+++ b/build/scripts/tests.gant
@@ -7,8 +7,8 @@
 
 def isMac = System.getProperty("os.name").toLowerCase().startsWith("mac")
 def args = [
-        "-Xmx450m",
-        "-XX:MaxPermSize=430m",
+        "-Xmx1024m",
+        "-XX:MaxPermSize=630m",
 ]
 if (isMac) args << "-d32";
 
diff --git a/build/scripts/utils.gant b/build/scripts/utils.gant
index e1f0571..5853eae 100644
--- a/build/scripts/utils.gant
+++ b/build/scripts/utils.gant
@@ -56,6 +56,7 @@
 binding.setVariable("mem32", "-server -Xms128m -Xmx512m -XX:MaxPermSize=250m -XX:ReservedCodeCacheSize=64m")
 binding.setVariable("mem64", "-Xms128m -Xmx750m -XX:MaxPermSize=350m -XX:ReservedCodeCacheSize=96m")
 binding.setVariable("common_vmoptions", "-ea -Dsun.io.useCanonCaches=false -Djava.net.preferIPv4Stack=true " +
+                                        "-Didea.project.structure.max.errors.to.show=0 " +
                                         "-Djsse.enableSNIExtension=false " +
                                         "-XX:+UseCodeCacheFlushing -XX:+UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB=50")
 
@@ -166,7 +167,10 @@
 
 binding.setVariable("notifyArtifactBuilt", { String artifactPath ->
   if (!artifactPath.startsWith(home)) {
-    projectBuilder.error("Artifact path $artifactPath should start with $home")
+    // AndroidStudio: make this to be just an info as the out folder is typically
+    // not in the home folder
+    projectBuilder.info("Artifact path $artifactPath should start with $home")
+    return
   }
   def relativePath = artifactPath.substring(home.length())
   if (relativePath.startsWith("/")) {
@@ -220,7 +224,8 @@
 
 binding.setVariable("wireBuildDate", { String buildNumber, String appInfoFile ->
   ant.tstamp()
-  patchFiles([appInfoFile], ["BUILD_NUMBER": buildNumber, "BUILD_DATE": DSTAMP])
+  patchFiles([appInfoFile], ["BUILD_NUMBER": buildNumber, "BUILD_DATE": DSTAMP,
+          "PACKAGE_CODE": buildNumber.substring(0, buildNumber.indexOf('-'))])
 })
 
 binding.setVariable("commonJvmArgs", {
@@ -230,9 +235,10 @@
    "-Xbootclasspath/p:${projectBuilder.moduleOutput(findModule("boot"))}",
    "-XX:+HeapDumpOnOutOfMemoryError",
    "-Didea.system.path=${p("teamcity.build.tempDir")}/system",
-   "-Didea.config.path=${p("teamcity.build.tempDir")}/config",
-   "-Xdebug",
-   "-Xrunjdwp:transport=dt_socket,server=y,suspend=$suspendUntilDebuggerConnect,address=$debugPort"]
+   "-Didea.config.path=${p("teamcity.build.tempDir")}/config"]
+   // We don't want this on the Jenkins build server
+   // "-Xdebug",
+   // "-Xrunjdwp:transport=dt_socket,server=y,suspend=$suspendUntilDebuggerConnect,address=$debugPort"]
 })
 
 binding.setVariable("classPathLibs", [
@@ -397,6 +403,9 @@
     replacefilter(token: "@@bundle_name@@", value: fullName)
     replacefilter(token: "@@bundle_identifier@@", value: args.bundleIdentifier)
     replacefilter(token: "@@year@@", value: "$todayYear")
+    replacefilter(token: "@@company_name@@", value: args.companyName)
+    replacefilter(token: "@@min_year@@", value: "2013")
+    replacefilter(token: "@@max_year@@", value: "$todayYear")
     replacefilter(token: "@@version@@", value: version)
     replacefilter(token: "@@vmoptions@@", value: vmOptions)
     replacefilter(token: "@@idea_properties@@", value: coreProperties)
@@ -424,8 +433,8 @@
 
 binding.setVariable("winScripts", { String target, String home, String name, Map args ->
   String fullName = args.fullName != null ? args.fullName : p("component.names.fullname")
-  String product_uc = args.product_uc != null ? args.product_uc : p("component.names.product").toUpperCase()
-  String vm_options = args.vm_options != null ? args.vm_options : "${p("component.names.product").toLowerCase()}.exe"
+  String product_uc = args.product_uc != null ? args.product_uc : p("component.names.product").toUpperCase().replace(" ", "_")
+  String vm_options = args.vm_options != null ? args.vm_options : "${p("component.names.product").toLowerCase().replace(" ", "-")}.exe"
   if (vm_options.endsWith(".exe")) {
     vm_options = vm_options.replace(".exe", "%BITS%.exe")
   }
@@ -498,14 +507,19 @@
   ant.fixcrlf(srcdir: "$target/bin", includes: "*.sh", eol: "unix")
 })
 
-binding.setVariable("winVMOptions", { String target, String system_selector, String name, String name64 = null ->
+binding.setVariable("winVMOptions", { String target, Map args, String name, String name64 = null ->
   if (name != null) {
-    def options = isEap() && system_selector != null ? vmOptions32yjp(system_selector) : vmOptions32()
+    def options = vmOptions32()
+    options = options.replace(" -XX:+UseCodeCacheFlushing", "")
+    options += " -Didea.platform.prefix=" + args.platform_prefix
+    options += " -Didea.paths.selector="  + args.system_selector
     ant.echo(file: "$target/bin/${name}.vmoptions", message: options.replace(' ', '\n'))
   }
 
   if (name64 != null) {
-    def options = isEap() && system_selector != null ? vmOptions64yjp(system_selector) : vmOptions64()
+    def options = vmOptions64()
+    options += " -Didea.platform.prefix=" + args.platform_prefix
+    options += " -Didea.paths.selector="  + args.system_selector
     ant.echo(file: "$target/bin/${name64}.vmoptions", message: options.replace(' ', '\n'))
   }
 
@@ -529,6 +543,7 @@
                    ["product_full": fullName,
                     "product": p("component.names.product").toLowerCase(),
                     "system_selector": args.system_selector,
+                    "script_name" : args.script_name,
                     "settings_dir": settings_dir], "@@")
   ant.fixcrlf(file: "$target/bin/Install-Linux-tar.txt", eol: "unix")
 })
@@ -685,14 +700,14 @@
   return buff.toString()
 }
 
-binding.setVariable("buildWinZip", { String zipPath, List paths ->
+binding.setVariable("buildWinZip", { String zipRoot, String zipPath, List paths ->
   projectBuilder.stage(".win.zip")
 
   fixIdeaPropertiesEol(paths, "dos")
 
   ant.zip(zipfile: zipPath) {
     paths.each {
-      fileset(dir: it)
+      zipfileset(dir: it, prefix: zipRoot)
     }
   }
 
@@ -811,6 +826,14 @@
   }
 })
 
+binding.setVariable("layoutUpdater", { String target, String jarName = "updater.jar" ->
+  layout(target) {
+    jar(jarName) {
+      module("updater")
+    }
+  }
+})
+
 binding.setVariable("collectUsedJars", { List modules, List approvedJars, List forbiddenJars, List modulesToBuild ->
   def usedJars = new HashSet();
 
@@ -890,4 +913,4 @@
                                                       "<mouse-shortcut keystroke=\"alt button1\"/>")
   patchedKeymapFile = new File("${paths.sandbox}/classes/production/platform-resources/idea/Keymap_Default.xml")
   patchedKeymapFile.write(defaultKeymapContent)
-})
\ No newline at end of file
+})
diff --git a/build_ide_ext.sh b/build_ide_ext.sh
new file mode 100755
index 0000000..bc8109a
--- /dev/null
+++ b/build_ide_ext.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+# Expected arguments:
+# $1 = out_dir
+# $2 = qualifier (ignored, optional)
+# $3 = build_number or preview-<build_number>
+# $4 = --target ...
+
+PROG_DIR=$(dirname "$0")
+
+DEST=""
+QUAL=""
+BNUM=""
+TARGET=""
+
+function die() {
+  echo "$*" > /dev/stderr
+  echo "Usage: $0 [--keep] dest_dir [date] build_number [--target build]" > /dev/stderr
+  exit 1
+}
+
+while [[ -n "$1" ]]; do
+  if [[ "$1" == "--target" ]]; then
+    shift
+    TARGET="$1"
+  elif [[ "${1:0:2}" == "--" ]]; then
+    die "[$0] Unknown parameter: $1"
+  elif [[ -z "$DEST" ]]; then
+    DEST="$1"
+  elif [[ -z "$QUAL" ]]; then
+    QUAL="$1"
+  elif [[ -z "$BNUM" ]]; then
+    BNUM="$1"
+  else
+    die "[$0] Unknown parameter: $1"
+  fi
+  shift
+done
+
+if [[ -z $BNUM && -n $QUAL ]]; then
+  BNUM="$QUAL"
+  QUAL=""
+fi
+BNUM="${BNUM/preview-/}"
+
+if [[ -z "$DEST" ]]; then die "## Error: Missing dest_dir"; fi
+if [[ -z "$BNUM" ]]; then die "## Error: Missing build_number"; fi
+
+cd $PROG_DIR
+
+OUT="../../out/host/android-studio"
+mkdir -p "$OUT"
+
+ANT="java -jar lib/ant/lib/ant-launcher.jar -f build.xml"
+
+echo "## Building android-studio ##"
+echo "## Dest dir : $DEST"
+echo "## Qualifier: $QUAL"
+echo "## Build Num: $BNUM"
+echo "## Target   : $TARGET"
+echo
+
+$ANT "-Dout=$OUT" "-DbuildNumber=$BNUM" $TARGET
+
+echo "## Copying android-studio destination files"
+cp -rfv $OUT/artifacts/android-studio* $DEST/
+cp -rfv $OUT/updater-full.jar $DEST/android-studio-updater.jar
diff --git a/build_studio.sh b/build_studio.sh
new file mode 100755
index 0000000..d7bed52
--- /dev/null
+++ b/build_studio.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# Expected arguments:
+# $1 = out_dir
+# $2 = dist_dir
+# $3 = build_number
+
+PROG_DIR=$(dirname "$0")
+
+function die() {
+  echo "$*" > /dev/stderr
+  echo "Usage: $0 <out_dir> <dest_dir> <build_number>" > /dev/stderr
+  exit 1
+}
+
+while [[ -n "$1" ]]; do
+  if [[ -z "$OUT" ]]; then
+    OUT="$1"
+  elif [[ -z "$DIST" ]]; then
+    DIST="$1"
+  elif [[ -z "$BNUM" ]]; then
+    BNUM="$1"
+  else
+    die "[$0] Unknown parameter: $1"
+  fi
+  shift
+done
+
+if [[ -z "$OUT" ]]; then die "## Error: Missing out folder"; fi
+if [[ -z "$DIST" ]]; then die "## Error: Missing destination folder"; fi
+if [[ -z "$BNUM" ]]; then die "## Error: Missing build number"; fi
+
+cd "$PROG_DIR"
+
+mkdir -p "$OUT"
+
+ANT="java -jar lib/ant/lib/ant-launcher.jar -f build.xml"
+
+echo "## Building android-studio ##"
+echo "## Dest dir : $DIST"
+echo "## Qualifier: $QUAL"
+echo "## Build Num: $BNUM"
+echo
+
+$ANT "-Dout=$OUT" "-DbuildNumber=$BNUM"
+
+echo "## Copying android-studio destination files"
+cp -rfv "$OUT"/artifacts/android-studio* "$DIST"/
+cp -rfv "$OUT"/updater-full.jar "$DIST"/android-studio-updater.jar
diff --git a/community-main.iml b/community-main.iml
index 474b93d..a56cb30 100644
--- a/community-main.iml
+++ b/community-main.iml
@@ -82,6 +82,9 @@
     <orderEntry type="module" module-name="tasks-tests" />
     <orderEntry type="module" module-name="github" />
     <orderEntry type="module" module-name="hg4idea" />
+    <orderEntry type="module" module-name="android" />
+    <orderEntry type="module" module-name="android-designer" />
+    <orderEntry type="module" module-name="adt-branding" />
     <orderEntry type="module" module-name="relaxng" />
     <orderEntry type="module" module-name="gradle" />
     <orderEntry type="module" module-name="remote-servers-impl" />
@@ -99,6 +102,7 @@
     <orderEntry type="module" module-name="ui-designer-jps-plugin" scope="TEST" />
     <orderEntry type="module" module-name="java-tests" scope="TEST" />
     <orderEntry type="module" module-name="community-tests" scope="TEST" />
+    <orderEntry type="module" module-name="google-cloud-tools" />
     <orderEntry type="module" module-name="jira" />
   </component>
 </module>
diff --git a/platform/bootstrap/src/com/intellij/idea/Main.java b/platform/bootstrap/src/com/intellij/idea/Main.java
old mode 100644
new mode 100755
index 7c32853..05cbe63
--- a/platform/bootstrap/src/com/intellij/idea/Main.java
+++ b/platform/bootstrap/src/com/intellij/idea/Main.java
@@ -17,6 +17,7 @@
 
 import com.intellij.ide.Bootstrap;
 import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.SystemInfoRt;
 import com.intellij.openapi.util.io.FileUtilRt;
@@ -26,10 +27,12 @@
 import javax.swing.*;
 import java.awt.*;
 import java.io.*;
-import java.util.ArrayList;
-import java.util.Collections;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
 import java.util.List;
 
+
 @SuppressWarnings({"UseOfSystemOutOrSystemErr", "MethodNamesDifferingOnlyByCase"})
 public class Main {
   public static final int UPDATE_FAILED = 1;
@@ -42,6 +45,8 @@
   private static final String PLATFORM_PREFIX_PROPERTY = "idea.platform.prefix";
   private static final String[] NO_ARGS = {};
 
+  private static final String MAIN_LOG_PROPERTY = "com.intellij.idea.Main.DelayedLog";
+
   private static boolean isHeadless;
   private static boolean isCommandLine;
 
@@ -67,8 +72,9 @@
           installPatch();
         }
         catch (Throwable t) {
+          appendLog("Exception: " + t.toString() + '\n');
           showMessage("Update Failed", t);
-          System.exit(UPDATE_FAILED);
+          exit(UPDATE_FAILED);
         }
       }
     }
@@ -78,10 +84,15 @@
     }
     catch (Throwable t) {
       showMessage("Start Failed", t);
-      System.exit(STARTUP_EXCEPTION);
+      exit(STARTUP_EXCEPTION);
     }
   }
 
+  private static void exit(int code) {
+    dumpDelayedLogging();
+    System.exit(code);
+  }
+
   public static boolean isHeadless() {
     return isHeadless;
   }
@@ -129,13 +140,19 @@
     File patchCopy = new File(tempDir, patchFileName + "_copy");
     File log4jCopy = new File(tempDir, "log4j.jar." + platform + "_copy");
     if (!FileUtilRt.delete(patchCopy) || !FileUtilRt.delete(log4jCopy)) {
+      appendLog("Cannot delete temporary files in " + tempDir);
       throw new IOException("Cannot delete temporary files in " + tempDir);
     }
 
     File patch = new File(tempDir, patchFileName);
+    appendLog("[Patch] Original patch %s: %s\n", patch.exists() ? "exists" : "does not exist",
+              patch.getAbsolutePath());
     if (!patch.exists()) return;
     File log4j = new File(PathManager.getLibPath(), "log4j.jar");
-    if (!log4j.exists()) throw new IOException("Log4J missing: " + log4j);
+    if (!log4j.exists()) {
+      appendLog("Log4J missing: " + log4j);
+      throw new IOException("Log4J missing: " + log4j);
+    }
     copyFile(patch, patchCopy, true);
     copyFile(log4j, log4jCopy, false);
 
@@ -149,7 +166,7 @@
       }
 
       Collections.addAll(args,
-                         System.getProperty("java.home") + "/bin/java",
+                         System.getProperty("java.home") + "/bin/java".replace('/', File.separatorChar),
                          "-Xmx500m",
                          "-classpath",
                          patchCopy.getPath() + File.pathSeparator + log4jCopy.getPath(),
@@ -160,14 +177,19 @@
                          "install",
                          PathManager.getHomePath());
 
+      appendLog("[Patch] Restarted cmd: %s\n", args.toString());
+
       status = Restarter.scheduleRestart(ArrayUtilRt.toStringArray(args));
+
+      appendLog("[Patch] Restarted status: %d\n", status);
     }
     else {
+      appendLog("[Patch] Restart is not supported\n");
       String message = "Patch update is not supported - please do it manually";
       showMessage("Update Error", message, true);
     }
 
-    System.exit(status);
+    exit(status);
   }
 
   private static void copyFile(File original, File copy, boolean move) throws IOException {
@@ -191,6 +213,12 @@
     message.append(studio ? "code.google.com/p/android/issues" : "youtrack.jetbrains.com");
     message.append("\n\n");
     t.printStackTrace(new PrintWriter(message));
+
+    String p = System.getProperty(MAIN_LOG_PROPERTY);
+    if (p != null) {
+      message.append('\n').append(p);
+    }
+
     showMessage(title, message.toString(), true);
   }
 
@@ -224,4 +252,60 @@
       JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), scrollPane, title, type);
     }
   }
+
+
+  /**
+   * Appends the non-null string to an internal log property because at
+   * this point when the updater runs the main logger hasn't been setup yet.
+   *
+   * We use a system property rather than a global static variable because
+   * both codes do not run in the same ClassLoader and don't have the same
+   * globals.
+   */
+  private static void appendLog(String message, Object...params) {
+    String p = System.getProperty(MAIN_LOG_PROPERTY);
+    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ");
+    String s = dateFormat.format(new Date()) + String.format(message, params);
+    if (p == null) {
+      p = s;
+    } else {
+      p += s;
+    }
+    System.setProperty(MAIN_LOG_PROPERTY, p);
+  }
+
+  /** Invoked by Main to dump the log when the Main is exiting right away.
+   * The normal IDE log will not be used. */
+  public static void dumpDelayedLogging() {
+    String p = System.getProperty(MAIN_LOG_PROPERTY);
+    if (p != null) {
+      System.clearProperty(MAIN_LOG_PROPERTY);
+      File log = new File(PathManager.getLogPath());
+      //noinspection ResultOfMethodCallIgnored
+      log.mkdirs();
+      log = new File(log, "idea_patch.log");
+      FileOutputStream fos = null;
+      try {
+        //noinspection IOResourceOpenedButNotSafelyClosed
+        fos = new FileOutputStream(log, true /*append*/);
+        fos.write(p.getBytes("UTF-8"));
+      } catch (IOException ignore) {
+      } finally {
+        if (fos != null) {
+          try { fos.close(); } catch (IOException ignored) {}
+        }
+      }
+    }
+  }
+
+  /** Invoked by StartupUtil once the main logger is setup. */
+  public static void dumpDelayedLogging(Logger log) {
+    if (log != null) {
+      String p = System.getProperty(MAIN_LOG_PROPERTY);
+      if (p != null) {
+        log.info(p);
+        System.clearProperty(MAIN_LOG_PROPERTY);
+      }
+    }
+  }
 }
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemSettings.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemSettings.java
index 6e1740c..f240681 100644
--- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemSettings.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemSettings.java
@@ -18,6 +18,7 @@
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.util.containers.ContainerUtilRt;
 import com.intellij.util.messages.Topic;
 import org.jetbrains.annotations.NotNull;
@@ -107,6 +108,9 @@
         }
       }
     }
+    if (ps == null) {
+      ps = myLinkedProjectsSettings.get(FileUtil.toSystemIndependentName(linkedProjectPath));
+    }
     return ps;
   }
 
diff --git a/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java b/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java
index d9ef2be..8cdcbc4d 100644
--- a/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java
+++ b/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java
@@ -1008,6 +1008,11 @@
       return getCorePluginSubmitter(reporters);
     }
     for (ErrorReportSubmitter reporter : reporters) {
+      /** Android Studio: Always use the android error reporter */
+      String canonicalName = reporter.getClass().getCanonicalName();
+      if (canonicalName != null && canonicalName.contains("android")) {
+        return reporter;
+      }
       final PluginDescriptor descriptor = reporter.getPluginDescriptor();
       if (descriptor != null && Comparing.equal(pluginId, descriptor.getPluginId())) {
         return reporter;
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/CreateDesktopEntryAction.java b/platform/platform-impl/src/com/intellij/ide/actions/CreateDesktopEntryAction.java
index 7728781..f1032fe 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/CreateDesktopEntryAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/CreateDesktopEntryAction.java
@@ -169,6 +169,10 @@
     execPath = binPath + '/' + productName.toLowerCase() + ".sh";
     if (new File(execPath).canExecute()) return execPath;
 
+    final String scriptName = ApplicationNamesInfo.getInstance().getScriptName();
+    String scriptPath = binPath + '/' + scriptName + ".sh";
+    if (new File(scriptPath).canExecute()) return scriptPath;
+
     return null;
   }
 
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java b/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java
index c700091..9140d0a 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java
@@ -44,6 +44,7 @@
     urlTemplate = urlTemplate
       .replace("$BUILD", eap ? appInfo.getBuild().asStringWithoutProductCode() : appInfo.getBuild().asString())
       .replace("$TIMEZONE", System.getProperty("user.timezone"))
+      .replace("$VERSION", appInfo.getFullVersion())
       .replace("$EVAL", isEvaluationLicense() ? "true" : "false")
       .replace("$DESCR", getDescription());
     BrowserUtil.browse(urlTemplate);
diff --git a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java
old mode 100644
new mode 100755
index 611e1a6..54e81ab
--- a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java
+++ b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java
@@ -130,6 +130,7 @@
     Logger log = Logger.getInstance(Main.class);
     startLogging(log);
     loadSystemLibraries(log);
+    Main.dumpDelayedLogging(log);
     fixProcessEnvironment(log);
 
     if (!Main.isHeadless()) {
diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/updater/SendStatisticsProjectComponent.java b/platform/platform-impl/src/com/intellij/internal/statistic/updater/SendStatisticsProjectComponent.java
index 0e5ac83..28a17e2 100644
--- a/platform/platform-impl/src/com/intellij/internal/statistic/updater/SendStatisticsProjectComponent.java
+++ b/platform/platform-impl/src/com/intellij/internal/statistic/updater/SendStatisticsProjectComponent.java
@@ -71,18 +71,7 @@
       StatisticsNotificationManager.showNotification(statisticsService, myProject);
     }
     else if (StatisticsUploadAssistant.isSendAllowed() && StatisticsUploadAssistant.isTimeToSend()) {
-      StatisticsService serviceToUse = null;
-      StatisticsServiceEP[] extensions = StatisticsService.EP_NAME.getExtensions();
-      if (extensions.length > 1) {
-        LOG.warn(String.format("More than one stats service detected (%s). Falling back to the built-in one", Arrays.toString(extensions)));
-      }
-      else if (extensions.length == 1) {
-        serviceToUse = extensions[0].getInstance();
-      }
-      if (serviceToUse == null) {
-        serviceToUse = statisticsService;
-      }
-      runWithDelay(serviceToUse);
+      runWithDelay(statisticsService);
     }
   }
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/ChannelStatus.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/ChannelStatus.java
old mode 100644
new mode 100755
index b7c133f..b4adf37
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/ChannelStatus.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/ChannelStatus.java
@@ -28,10 +28,25 @@
   @NonNls public static final String EAP_CODE = "eap";
   @NonNls public static final String RELEASE_CODE = "release";
 
-  public static final ChannelStatus EAP = new ChannelStatus(0, EAP_CODE, "Early Access Program");
-  public static final ChannelStatus MILESTONE = new ChannelStatus(1, "milestone", "Milestone Releases");
-  public static final ChannelStatus BETA = new ChannelStatus(2, "beta", "Beta Releases or Public Previews");
-  public static final ChannelStatus RELEASE = new ChannelStatus(3, RELEASE_CODE, "New Major Version Releases");
+  /**
+   * EAP is our Canary Channel.
+   * <p/>
+   * From the updates.xml description: <br/>
+   * Canary builds are the bleeding edge, released about weekly. While these builds do get tested,
+   * they are still subject to bugs, as we want people to see what's new as soon as possible.
+   * This is not recommended for production.
+   */
+  public static final ChannelStatus EAP = new ChannelStatus(0, EAP_CODE, "Canary Channel");
+  /**
+   * Milestone is our Dev Channel.
+   * <p/>
+   * From the updates.xml description: <br/>
+   * Dev channel builds are hand-picked older canary builds that survived the test of time.
+   * It's updated roughly every month.
+   */
+  public static final ChannelStatus MILESTONE = new ChannelStatus(1, "milestone", "Dev Channel");
+  public static final ChannelStatus BETA = new ChannelStatus(2, "beta", "Beta Channel");
+  public static final ChannelStatus RELEASE = new ChannelStatus(3, RELEASE_CODE, "Stable Channel");
 
   private static final List<ChannelStatus> ALL_TYPES = ContainerUtil.immutableList(RELEASE, BETA, MILESTONE, EAP);
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
old mode 100644
new mode 100755
index 8a27864..828bff5
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
@@ -15,6 +15,7 @@
  */
 package com.intellij.openapi.updateSettings.impl;
 
+import com.google.common.net.HttpHeaders;
 import com.intellij.ide.IdeBundle;
 import com.intellij.ide.plugins.*;
 import com.intellij.ide.reporter.ConnectionException;
@@ -761,10 +762,31 @@
     String platform = PlatformUtils.getPlatformPrefix();
 
     File tempFile = FileUtil.createTempFile(platform, "patch", true);
+    LOG.info(String.format("[Patch] Download %s to %s", fileName, tempFile.getAbsolutePath()));
 
     OutputStream out = new BufferedOutputStream(new FileOutputStream(tempFile));
     try {
-      URLConnection connection = HttpConfigurable.getInstance().openConnection(new URL(new URL(getPatchesUrl()), fileName).toString());
+      String requestUrl = new URL(new URL(getPatchesUrl()), fileName).toString();
+      URLConnection connection;
+
+      int followCount = 2;
+      while(true) {
+        connection = HttpConfigurable.getInstance().openConnection(requestUrl);
+
+        if (connection instanceof HttpURLConnection) {
+          HttpURLConnection hcnx = (HttpURLConnection)connection;
+          int code = hcnx.getResponseCode();
+          if (code >= 301 && code <= 307 && --followCount >= 0) {
+            String loc = hcnx.getHeaderField(HttpHeaders.LOCATION);
+            if (loc != null) {
+              requestUrl = loc;
+              continue;
+            }
+          }
+        }
+        break;
+      }
+
       try {
         InputStream in = UrlConnectionUtil.getConnectionInputStreamWithException(connection, i);
         try {
@@ -806,6 +828,7 @@
     File patchFile = new File(FileUtil.getTempDirectory(), patchFileName);
     FileUtil.copy(tempFile, patchFile);
     FileUtil.delete(tempFile);
+    LOG.info(String.format("[Patch] moved to %s", patchFile.getAbsolutePath()));
   }
 
   public static Set<String> getDisabledToUpdatePlugins() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java
index d1010f5..94e287e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java
@@ -16,6 +16,7 @@
 package com.intellij.openapi.updateSettings.impl;
 
 
+import com.google.common.net.HttpHeaders;
 import com.intellij.ide.IdeBundle;
 import com.intellij.ide.reporter.ConnectionException;
 import com.intellij.openapi.application.ApplicationManager;
@@ -31,7 +32,9 @@
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.net.HttpURLConnection;
 import java.net.URL;
+import java.net.URLConnection;
 import java.util.concurrent.Callable;
 import java.util.concurrent.FutureTask;
 import java.util.concurrent.TimeUnit;
@@ -67,7 +70,27 @@
 
           URL requestUrl = prepareRequestUrl(updateUrl);
 
-          final InputStream inputStream = requestUrl.openStream();
+          URLConnection cnx;
+          int followCount = 2;
+          while(true) {
+            cnx = requestUrl.openConnection();
+
+            if (cnx instanceof HttpURLConnection) {
+              HttpURLConnection hcnx = (HttpURLConnection)cnx;
+              int code = hcnx.getResponseCode();
+              if (code >= 301 && code <= 307 && --followCount >= 0) {
+                String loc = hcnx.getHeaderField(HttpHeaders.LOCATION);
+                if (loc != null) {
+                  prepareUrl(loc);
+                  requestUrl = prepareRequestUrl(loc);
+                  continue;
+                }
+              }
+            }
+            break;
+          }
+
+          final InputStream inputStream = cnx.getInputStream();
           Reader reader = new InputStreamReader(inputStream);
           try {
             return new UpdatesInfo(JDOMUtil.loadDocument(inputStream).getRootElement());
diff --git a/plugins/android/lib/guava-15.0.jar b/plugins/android/lib/guava-15.0.jar
new file mode 100644
index 0000000..eb9ef8a
--- /dev/null
+++ b/plugins/android/lib/guava-15.0.jar
Binary files differ
diff --git a/plugins/android/lib/jarutils.jar b/plugins/android/lib/jarutils.jar
new file mode 100644
index 0000000..1259ccf
--- /dev/null
+++ b/plugins/android/lib/jarutils.jar
Binary files differ
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java
index 126f0db..8219ec0 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java
@@ -324,6 +324,10 @@
         }
       }
 
+      if (result == GlobalSearchScope.EMPTY_SCOPE) {
+        result = baseScope;
+      }
+
       String modulePath = module.getOptionValue(ExternalSystemConstants.LINKED_PROJECT_PATH_KEY);
       if(modulePath == null) return result;
 
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java
index 465d6b2..c7018aa 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java
@@ -218,23 +218,40 @@
   public void populateModuleCompileOutputSettings(@NotNull IdeaModule gradleModule,
                                                   @NotNull DataNode<ModuleData> ideModule) {
     IdeaCompilerOutput moduleCompilerOutput = gradleModule.getCompilerOutput();
-    if (moduleCompilerOutput == null) {
-      return;
+
+    File sourceCompileOutputPath = null;
+    File testCompileOutputPath = null;
+    boolean inheritOutputDirs = false;
+
+    ModuleData moduleData = ideModule.getData();
+    if (moduleCompilerOutput != null) {
+      sourceCompileOutputPath = moduleCompilerOutput.getOutputDir();
+      testCompileOutputPath = moduleCompilerOutput.getTestOutputDir();
+      inheritOutputDirs = moduleCompilerOutput.getInheritOutputDirs();
     }
 
-    File sourceCompileOutputPath = moduleCompilerOutput.getOutputDir();
-    ModuleData moduleData = ideModule.getData();
+    if (!inheritOutputDirs && (sourceCompileOutputPath == null || testCompileOutputPath == null)) {
+      ModuleExtendedModel moduleExtendedModel = resolverCtx.getExtraProject(gradleModule, ModuleExtendedModel.class);
+      if (moduleExtendedModel != null) {
+        ExtIdeaCompilerOutput output = moduleExtendedModel.getCompilerOutput();
+        if (output != null) {
+          if (sourceCompileOutputPath == null) {
+            sourceCompileOutputPath = output.getMainClassesDir();
+          }
+          if (testCompileOutputPath == null) {
+            testCompileOutputPath = output.getTestClassesDir();
+          }
+        }
+      }
+    }
+
     if (sourceCompileOutputPath != null) {
       moduleData.setCompileOutputPath(ExternalSystemSourceType.SOURCE, sourceCompileOutputPath.getAbsolutePath());
     }
-
-    File testCompileOutputPath = moduleCompilerOutput.getTestOutputDir();
     if (testCompileOutputPath != null) {
       moduleData.setCompileOutputPath(ExternalSystemSourceType.TEST, testCompileOutputPath.getAbsolutePath());
     }
-    moduleData.setInheritProjectCompileOutputPath(
-      moduleCompilerOutput.getInheritOutputDirs() || sourceCompileOutputPath == null || testCompileOutputPath == null
-    );
+    moduleData.setInheritProjectCompileOutputPath(inheritOutputDirs || sourceCompileOutputPath == null);
   }
 
   @Override
diff --git a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ExtIdeaCompilerOutput.java b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ExtIdeaCompilerOutput.java
new file mode 100644
index 0000000..9ec6882
--- /dev/null
+++ b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ExtIdeaCompilerOutput.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * 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 org.jetbrains.plugins.gradle.model;
+
+import org.gradle.api.Nullable;
+
+import java.io.File;
+import java.io.Serializable;
+
+public interface ExtIdeaCompilerOutput extends Serializable {
+  /**
+   * @return the directory to generate the classes of the "main" source set into.
+   */
+  @Nullable
+  File getMainClassesDir();
+
+  /**
+   * @return the directory to generate the resources of the "main" source set into.
+   */
+  @Nullable
+  File getMainResourcesDir();
+
+  /**
+   * @return the directory to generate the classes of the "test" source set into.
+   */
+  @Nullable
+  File getTestClassesDir();
+
+  /**
+   * @return the directory to generate the resources of the "test" source set into.
+   */
+  @Nullable
+  File getTestResourcesDir();
+}
diff --git a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ModuleExtendedModel.java b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ModuleExtendedModel.java
index e9a99b9..97dfd25 100644
--- a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ModuleExtendedModel.java
+++ b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ModuleExtendedModel.java
@@ -67,4 +67,11 @@
    * @return the build directory.
    */
   File getBuildDir();
+
+  /**
+   * The compiler output directories.
+   *
+   * @return the compiler output directories.
+   */
+  ExtIdeaCompilerOutput getCompilerOutput();
 }
diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ModuleExtendedModelBuilderImpl.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ModuleExtendedModelBuilderImpl.java
index ee9b256..616016d 100644
--- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ModuleExtendedModelBuilderImpl.java
+++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ModuleExtendedModelBuilderImpl.java
@@ -20,6 +20,7 @@
 import org.gradle.api.Task;
 import org.gradle.api.tasks.SourceSet;
 import org.gradle.api.tasks.SourceSetContainer;
+import org.gradle.api.tasks.SourceSetOutput;
 import org.gradle.api.tasks.bundling.Jar;
 import org.gradle.api.tasks.testing.Test;
 import org.gradle.plugins.ide.idea.IdeaPlugin;
@@ -30,6 +31,7 @@
 import org.jetbrains.plugins.gradle.model.ModuleExtendedModel;
 import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder;
 import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
+import org.jetbrains.plugins.gradle.tooling.internal.IdeaCompilerOutputImpl;
 import org.jetbrains.plugins.gradle.tooling.internal.IdeaContentRootImpl;
 import org.jetbrains.plugins.gradle.tooling.internal.IdeaSourceDirectoryImpl;
 import org.jetbrains.plugins.gradle.tooling.internal.ModuleExtendedModelImpl;
@@ -95,11 +97,24 @@
       }
     }
 
+    IdeaCompilerOutputImpl compilerOutput = new IdeaCompilerOutputImpl();
+
     if (project.hasProperty(SOURCE_SETS_PROPERTY)) {
       Object sourceSets = project.property(SOURCE_SETS_PROPERTY);
       if (sourceSets instanceof SourceSetContainer) {
         SourceSetContainer sourceSetContainer = (SourceSetContainer)sourceSets;
         for (SourceSet sourceSet : sourceSetContainer) {
+
+          SourceSetOutput output = sourceSet.getOutput();
+          if (SourceSet.TEST_SOURCE_SET_NAME.equals(sourceSet.getName())) {
+            compilerOutput.setTestClassesDir(output.getClassesDir());
+            compilerOutput.setTestResourcesDir(output.getResourcesDir());
+          }
+          if (SourceSet.MAIN_SOURCE_SET_NAME.equals(sourceSet.getName())) {
+            compilerOutput.setMainClassesDir(output.getClassesDir());
+            compilerOutput.setMainResourcesDir(output.getResourcesDir());
+          }
+
           for (File javaSrcDir : sourceSet.getAllJava().getSrcDirs()) {
             boolean isTestDir = isTestDir(sourceSet, testClassesDirs);
             addFilePath(isTestDir ? testDirectories : sourceDirectories, javaSrcDir);
@@ -166,6 +181,7 @@
     }
 
     moduleVersionModel.setContentRoots(Collections.<ExtIdeaContentRoot>singleton(contentRoot));
+    moduleVersionModel.setCompilerOutput(compilerOutput);
     return moduleVersionModel;
   }
 
diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/internal/IdeaCompilerOutputImpl.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/internal/IdeaCompilerOutputImpl.java
new file mode 100644
index 0000000..214e999
--- /dev/null
+++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/internal/IdeaCompilerOutputImpl.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * 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 org.jetbrains.plugins.gradle.tooling.internal;
+
+import org.jetbrains.plugins.gradle.model.ExtIdeaCompilerOutput;
+
+import java.io.File;
+
+public class IdeaCompilerOutputImpl implements ExtIdeaCompilerOutput {
+  private File myMainClassesDir;
+  private File myMainResourcesDir;
+  private File myTestClassesDir;
+  private File myTestResourcesDir;
+
+  @Override
+  public File getMainClassesDir() {
+    return myMainClassesDir;
+  }
+
+  @Override
+  public File getMainResourcesDir() {
+    return myMainResourcesDir;
+  }
+
+  @Override
+  public File getTestClassesDir() {
+    return myTestClassesDir;
+  }
+
+  @Override
+  public File getTestResourcesDir() {
+    return myTestResourcesDir;
+  }
+
+  public void setMainClassesDir(File mainClassesDir) {
+    myMainClassesDir = mainClassesDir;
+  }
+
+  public void setMainResourcesDir(File mainResourcesDir) {
+    myMainResourcesDir = mainResourcesDir;
+  }
+
+  public void setTestClassesDir(File testClassesDir) {
+    myTestClassesDir = testClassesDir;
+  }
+
+  public void setTestResourcesDir(File testResourcesDir) {
+    myTestResourcesDir = testResourcesDir;
+  }
+}
diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/internal/ModuleExtendedModelImpl.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/internal/ModuleExtendedModelImpl.java
index 4eea475..547029c 100644
--- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/internal/ModuleExtendedModelImpl.java
+++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/internal/ModuleExtendedModelImpl.java
@@ -17,6 +17,7 @@
 
 import org.gradle.tooling.model.DomainObjectSet;
 import org.gradle.tooling.model.internal.ImmutableDomainObjectSet;
+import org.jetbrains.plugins.gradle.model.ExtIdeaCompilerOutput;
 import org.jetbrains.plugins.gradle.model.ExtIdeaContentRoot;
 import org.jetbrains.plugins.gradle.model.ModuleExtendedModel;
 
@@ -36,6 +37,7 @@
   private final File myBuildDir;
   private List<File> myArtifacts;
   private Set<ExtIdeaContentRoot> myContentRoots;
+  private ExtIdeaCompilerOutput myCompilerOutput;
 
   public ModuleExtendedModelImpl(String name, String group, String version, File buildDir) {
     myName = name;
@@ -83,4 +85,13 @@
   public void setContentRoots(Set<ExtIdeaContentRoot> contentRoots) {
     myContentRoots = contentRoots == null ? Collections.<ExtIdeaContentRoot>emptySet() : contentRoots;
   }
+
+  @Override
+  public ExtIdeaCompilerOutput getCompilerOutput() {
+    return myCompilerOutput;
+  }
+
+  public void setCompilerOutput(ExtIdeaCompilerOutput compilerOutput) {
+    myCompilerOutput = compilerOutput;
+  }
 }
diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexerImpl.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexerImpl.java
index 199db3a..bfe3d14 100644
--- a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexerImpl.java
+++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexerImpl.java
@@ -207,7 +207,8 @@
       throw new MavenServerProcessCanceledException();
     }
     catch (Exception e) {
-      throw new MavenServerIndexerException(wrapException(e));
+      // Disabled in Android Studio, no need to know about this exception
+      // throw new MavenServerIndexerException(wrapException(e));
     }
   }
 
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/CreationTool.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/CreationTool.java
index 83ed504..5f301ac7 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/CreationTool.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/CreationTool.java
@@ -16,8 +16,10 @@
 package com.intellij.designer.designSurface.tools;
 
 import com.intellij.designer.designSurface.OperationContext;
+import com.intellij.designer.model.RadComponent;
 
 import java.util.Collections;
+import java.util.List;
 
 /**
  * @author Alexander Lobas
@@ -49,6 +51,11 @@
 
   @Override
   protected void updateTarget() {
-    myTargetOperation.setComponent(myContext.getComponents().get(0));
+    if (myTargetOperation != null && myContext != null) {
+      List<RadComponent> components = myContext.getComponents();
+      if (components != null && !components.isEmpty()) {
+        myTargetOperation.setComponent(components.get(0));
+      }
+    }
   }
 }
\ No newline at end of file
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/PropertyTablePanel.java b/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/PropertyTablePanel.java
index a44a3439..5ad9e44 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/PropertyTablePanel.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/PropertyTablePanel.java
@@ -23,6 +23,7 @@
 import com.intellij.openapi.actionSystem.impl.ActionButton;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.wm.IdeFocusManager;
 import com.intellij.ui.IdeBorderFactory;
 import com.intellij.ui.PopupHandler;
@@ -85,7 +86,11 @@
     actionGroup.addSeparator();
 
     RestoreDefault restoreDefault = new RestoreDefault(myPropertyTable);
-    restoreDefault.registerCustomShortcutSet(actionManager.getAction(IdeActions.ACTION_DELETE).getShortcutSet(), myPropertyTable);
+    // Don't register ACTION_DELETE on Mac; on Mac, the default delete key is VK_DELETE rather than VK_BACK_SPACE
+    // which means users end up accidentally restoring to default when trying to edit inside property editors.
+    if (!SystemInfo.isMac) {
+      restoreDefault.registerCustomShortcutSet(actionManager.getAction(IdeActions.ACTION_DELETE).getShortcutSet(), myPropertyTable);
+    }
     actionGroup.add(restoreDefault);
 
     actionGroup.add(new ShowExpert(myPropertyTable));
diff --git a/resources-en/src/tips/Welcome.html b/resources-en/src/tips/Welcome.html
index 7301e94..6d8381a 100644
--- a/resources-en/src/tips/Welcome.html
+++ b/resources-en/src/tips/Welcome.html
@@ -4,7 +4,7 @@
 </head>
 <body>
     <h1>
-        Welcome to <span class="product">&productName;</span> <span class="version">&majorVersion;</span></h1>
+        Welcome to <span class="product">&productName;</span> <span class="version">&majorVersion;.&minorVersion;<</span></h1>
     <p>
         You can quickly get familiar with the main features of the IDE by reading these tips. You may try out
         the features described in the tips while this dialog stays open on the screen. If you close the dialog,
diff --git a/updater/src/com/intellij/updater/BaseUpdateAction.java b/updater/src/com/intellij/updater/BaseUpdateAction.java
old mode 100644
new mode 100755
index 1d5e5a1..67a16f8e
--- a/updater/src/com/intellij/updater/BaseUpdateAction.java
+++ b/updater/src/com/intellij/updater/BaseUpdateAction.java
@@ -35,7 +35,13 @@
 
   protected void replaceUpdated(File from, File dest) throws IOException {
     // on OS X code signing caches seem to be associated with specific file ids, so we need to remove the original file.
-    if (!dest.delete()) throw new IOException("Cannot delete file " + dest);
+    if (!dest.delete()) {
+      if (Utils.isWindows()) {
+        throw new RetryException("Cannot delete file " + dest);
+      } else {
+        throw new IOException("Cannot delete file " + dest);
+      }
+    }
     Utils.copy(from, dest);
   }
 
diff --git a/updater/src/com/intellij/updater/CreateAction.java b/updater/src/com/intellij/updater/CreateAction.java
old mode 100644
new mode 100755
index e1a3fa1..5b0f8df
--- a/updater/src/com/intellij/updater/CreateAction.java
+++ b/updater/src/com/intellij/updater/CreateAction.java
@@ -59,7 +59,15 @@
 
   private static void prepareToWriteFile(File file) throws IOException {
     if (file.exists()) {
-      Utils.delete(file);
+      try {
+        Utils.delete(file);
+      } catch (IOException e) {
+        if (Utils.isWindows() && file.exists()) {
+          throw new RetryException(e);
+        } else {
+          throw e;
+        }
+      }
       return;
     }
 
diff --git a/updater/src/com/intellij/updater/DeleteAction.java b/updater/src/com/intellij/updater/DeleteAction.java
old mode 100644
new mode 100755
index 3dd1b85..286e471
--- a/updater/src/com/intellij/updater/DeleteAction.java
+++ b/updater/src/com/intellij/updater/DeleteAction.java
@@ -43,13 +43,23 @@
 
   @Override
   protected void doApply(ZipFile patchFile, File toFile) throws IOException {
-    Utils.delete(toFile);
+    try {
+      Utils.delete(toFile);
+    } catch (IOException e) {
+      if (Utils.isWindows() && toFile.exists()) {
+        throw new RetryException(e);
+      } else {
+        throw e;
+      }
+    }
   }
 
+  @Override
   protected void doBackup(File toFile, File backupFile) throws IOException {
     Utils.copy(toFile, backupFile);
   }
 
+  @Override
   protected void doRevert(File toFile, File backupFile) throws IOException {
     Utils.delete(toFile); // make sure there is no directory remained on this path (may remain from previous 'create' actions
     Utils.copy(backupFile, toFile);
diff --git a/updater/src/com/intellij/updater/Digester.java b/updater/src/com/intellij/updater/Digester.java
old mode 100644
new mode 100755
index 00792ce..ba6a470
--- a/updater/src/com/intellij/updater/Digester.java
+++ b/updater/src/com/intellij/updater/Digester.java
@@ -28,7 +28,8 @@
         zipFile = new ZipFile(file);
       }
       catch (IOException e) {
-        Runner.printStackTrace(e);
+        // If this isn't a zip file, this isn't really an error, merely an info.
+        Runner.infoStackTrace("Can't open file as zip file: " + file.getPath() + "\n", e);
         return doDigestRegularFile(file);
       }
 
diff --git a/updater/src/com/intellij/updater/RetryException.java b/updater/src/com/intellij/updater/RetryException.java
new file mode 100755
index 0000000..e13c4eb
--- /dev/null
+++ b/updater/src/com/intellij/updater/RetryException.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * 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.updater;
+
+import java.io.IOException;
+
+/**
+ * Exception thrown when an IOException arises when performing a patch
+ * action and it's likely that retrying will be successful.
+ */
+public class RetryException extends IOException {
+  public RetryException() {
+  }
+
+  public RetryException(String message) {
+    super(message);
+  }
+
+  public RetryException(String message, Throwable cause) {
+    super(message, cause);
+  }
+
+  public RetryException(Throwable cause) {
+    super(cause);
+  }
+}
diff --git a/updater/src/com/intellij/updater/Runner.java b/updater/src/com/intellij/updater/Runner.java
old mode 100644
new mode 100755
index 1e57010..d0143a9
--- a/updater/src/com/intellij/updater/Runner.java
+++ b/updater/src/com/intellij/updater/Runner.java
@@ -38,11 +38,22 @@
       create(oldVersionDesc, newVersionDesc, oldFolder, newFolder, patchFile, ignoredFiles, criticalFiles, optionalFiles);
     }
     else if (args.length >= 2 && "install".equals(args[0])) {
-      String destFolder = args[1];
+      // install [--exit0] <destination_folder>
+      int nextArg = 1;
+
+      // Default install exit code is SwingUpdaterUI.RESULT_REQUIRES_RESTART (42) unless overridden to be 0.
+      // This is used by testUI/build.gradle as gradle expects a javaexec to exit with code 0.
+      boolean useExitCode0 = false;
+      if (args[nextArg].equals("--exit0")) {
+        useExitCode0 = true;
+        nextArg++;
+      }
+
+      String destFolder = args[nextArg++];
       initLogger();
       logger.info("destFolder: " + destFolder);
 
-      install(destFolder);
+      install(useExitCode0, destFolder);
     }
     else {
       printUsage();
@@ -93,6 +104,10 @@
     }
   }
 
+  public static void infoStackTrace(String msg, Throwable e){
+    logger.info(msg, e);
+  }
+
   public static void printStackTrace(Throwable e){
     logger.error(e.getMessage(), e);
   }
@@ -115,8 +130,8 @@
   private static void printUsage() {
     System.err.println("Usage:\n" +
                        "create <old_version_description> <new_version_description> <old_version_folder> <new_version_folder>" +
-                       " <patch_file_name> [ignored=file1;file2;...] [critical=file1;file2;...] [optional=file1;file2;...]\n" +
-                       "install <destination_folder> [log_directory]\n");
+                       " <patch_file_name> <log_directory> [ignored=file1;file2;...] [critical=file1;file2;...] [optional=file1;file2;...]\n" +
+                       "install [--exit0] <destination_folder> [log_directory]\n");
   }
 
   private static void create(String oldBuildDesc,
@@ -127,9 +142,31 @@
                              List<String> ignoredFiles,
                              List<String> criticalFiles,
                              List<String> optionalFiles) throws IOException, OperationCancelledException {
-    UpdaterUI ui = new ConsoleUpdaterUI();
+    File tempPatchFile = Utils.createTempFile();
+    createImpl(oldBuildDesc,
+               newBuildDesc,
+               oldFolder,
+               newFolder,
+               patchFile,
+               tempPatchFile,
+               ignoredFiles,
+               criticalFiles,
+               optionalFiles,
+               new ConsoleUpdaterUI(), resolveJarFile());
+  }
+
+  static void createImpl(String oldBuildDesc,
+                         String newBuildDesc,
+                         String oldFolder,
+                         String newFolder,
+                         String outPatchJar,
+                         File   tempPatchFile,
+                         List<String> ignoredFiles,
+                         List<String> criticalFiles,
+                         List<String> optionalFiles,
+                         UpdaterUI ui,
+                         File resolvedJar) throws IOException, OperationCancelledException {
     try {
-      File tempPatchFile = Utils.createTempFile();
       PatchFileCreator.create(new File(oldFolder),
                               new File(newFolder),
                               tempPatchFile,
@@ -138,13 +175,13 @@
                               optionalFiles,
                               ui);
 
-      logger.info("Packing jar file: " + patchFile );
-      ui.startProcess("Packing jar file '" + patchFile + "'...");
+      logger.info("Packing jar file: " + outPatchJar );
+      ui.startProcess("Packing jar file '" + outPatchJar + "'...");
 
-      FileOutputStream fileOut = new FileOutputStream(patchFile);
+      FileOutputStream fileOut = new FileOutputStream(outPatchJar);
       try {
         ZipOutputWrapper out = new ZipOutputWrapper(fileOut);
-        ZipInputStream in = new ZipInputStream(new FileInputStream(resolveJarFile()));
+        ZipInputStream in = new ZipInputStream(new FileInputStream(resolvedJar));
         try {
           ZipEntry e;
           while ((e = in.getNextEntry()) != null) {
@@ -186,7 +223,7 @@
     Utils.cleanup();
   }
 
-  private static void install(final String destFolder) throws Exception {
+  private static void install(final boolean useExitCode0, final String destFolder) throws Exception {
     InputStream in = Runner.class.getResourceAsStream("/" + PATCH_PROPERTIES_ENTRY);
     Properties props = new Properties();
     try {
@@ -213,7 +250,9 @@
 
     new SwingUpdaterUI(props.getProperty(OLD_BUILD_DESCRIPTION),
                   props.getProperty(NEW_BUILD_DESCRIPTION),
+                  useExitCode0 ? 0 : SwingUpdaterUI.RESULT_REQUIRES_RESTART,
                   new SwingUpdaterUI.InstallOperation() {
+                    @Override
                     public boolean execute(UpdaterUI ui) throws OperationCancelledException {
                       logger.info("installing patch to the " + destFolder);
                       return doInstall(ui, destFolder);
@@ -221,11 +260,26 @@
                   });
   }
 
+  interface IJarResolver {
+    File resolveJar() throws IOException;
+  }
+
   private static boolean doInstall(UpdaterUI ui, String destFolder) throws OperationCancelledException {
+    return doInstallImpl(ui, destFolder, new IJarResolver() {
+      @Override
+      public File resolveJar() throws IOException {
+        return resolveJarFile();
+      }
+    });
+  }
+
+  static boolean doInstallImpl(UpdaterUI ui,
+                               String destFolder,
+                               IJarResolver jarResolver) throws OperationCancelledException {
     try {
       try {
         File patchFile = Utils.createTempFile();
-        ZipFile jarFile = new ZipFile(resolveJarFile());
+        ZipFile jarFile = new ZipFile(jarResolver.resolveJar());
 
         logger.info("Extracting patch file...");
         ui.startProcess("Extracting patch file...");
diff --git a/updater/src/com/intellij/updater/SwingUpdaterUI.java b/updater/src/com/intellij/updater/SwingUpdaterUI.java
old mode 100644
new mode 100755
index d44fc2e..749dcc2
--- a/updater/src/com/intellij/updater/SwingUpdaterUI.java
+++ b/updater/src/com/intellij/updater/SwingUpdaterUI.java
@@ -10,6 +10,7 @@
 import java.awt.event.ActionListener;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.lang.reflect.InvocationTargetException;
@@ -19,7 +20,7 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 
 public class SwingUpdaterUI implements UpdaterUI {
-  private static final int RESULT_REQUIRES_RESTART = 42;
+  static final int RESULT_REQUIRES_RESTART = 42;
 
   private static final EmptyBorder FRAME_BORDER = new EmptyBorder(8, 8, 8, 8);
   private static final EmptyBorder LABEL_BORDER = new EmptyBorder(0, 0, 5, 0);
@@ -32,6 +33,7 @@
 
   private static final String PROCEED_BUTTON_TITLE = "Proceed";
 
+  private final int mySuccessExitCode;
   private final InstallOperation myOperation;
 
   private final JLabel myProcessTitle;
@@ -40,16 +42,30 @@
   private final JTextArea myConsole;
   private final JPanel myConsolePane;
 
+  private final JButton myRetryButton;
   private final JButton myCancelButton;
 
   private final ConcurrentLinkedQueue<UpdateRequest> myQueue = new ConcurrentLinkedQueue<UpdateRequest>();
   private final AtomicBoolean isCancelled = new AtomicBoolean(false);
   private final AtomicBoolean isRunning = new AtomicBoolean(false);
   private final AtomicBoolean hasError = new AtomicBoolean(false);
+  private final AtomicBoolean hasRetry = new AtomicBoolean(false);
   private final JFrame myFrame;
   private boolean myApplied;
 
-  public SwingUpdaterUI(String oldBuildDesc, String newBuildDesc, InstallOperation operation) {
+  /**
+   * Displays the updater UI and asynchronously runs the operation list.
+   *
+   * @param oldBuildDesc The old build description, for display purposes.
+   * @param newBuildDesc The new build description, for display purposes.
+   * @param successExitCode The desired exit code on success. Default is {@link #RESULT_REQUIRES_RESTART}.
+   * @param operation The install operations to perform.
+   */
+  public SwingUpdaterUI(String oldBuildDesc,
+                        String newBuildDesc,
+                        int successExitCode,
+                        InstallOperation operation) {
+    mySuccessExitCode = successExitCode;
     myOperation = operation;
 
     myProcessTitle = new JLabel(" ");
@@ -58,6 +74,10 @@
 
     myCancelButton = new JButton(CANCEL_BUTTON_TITLE);
 
+    myRetryButton = new JButton("Retry");
+    myRetryButton.setEnabled(false);
+    myRetryButton.setVisible(false);
+
     myConsole = new JTextArea();
     myConsole.setLineWrap(true);
     myConsole.setWrapStyleWord(true);
@@ -70,11 +90,19 @@
     myConsolePane.setVisible(false);
 
     myCancelButton.addActionListener(new ActionListener() {
+      @Override
       public void actionPerformed(ActionEvent e) {
         doCancel();
       }
     });
 
+    myRetryButton.addActionListener(new ActionListener() {
+      @Override
+      public void actionPerformed(ActionEvent e) {
+        doRetry();
+      }
+    });
+
     myFrame = new JFrame();
     myFrame.setTitle(TITLE);
 
@@ -104,6 +132,7 @@
     buttonsPanel.setBorder(BUTTONS_BORDER);
     buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.X_AXIS));
     buttonsPanel.add(Box.createHorizontalGlue());
+    buttonsPanel.add(myRetryButton);
     buttonsPanel.add(myCancelButton);
 
     myProcessTitle.setText("<html>Updating " + oldBuildDesc + " to " + newBuildDesc + "...");
@@ -129,6 +158,7 @@
 
   private void startRequestDispatching() {
     new Thread(new Runnable() {
+      @Override
       public void run() {
         while (true) {
           try {
@@ -146,6 +176,7 @@
           }
 
           SwingUtilities.invokeLater(new Runnable() {
+            @Override
             public void run() {
               for (UpdateRequest each : pendingRequests) {
                 each.perform();
@@ -172,10 +203,28 @@
     }
   }
 
+  private void doRetry() {
+    hasError.set(false);
+    hasRetry.set(false);
+    isCancelled.set(false);
+    myQueue.add(new UpdateRequest() {
+      @Override
+      public void perform() {
+        myConsole.setText("");
+        myConsolePane.setVisible(false);
+        myConsolePane.setPreferredSize(new Dimension(10, 200));
+        myRetryButton.setEnabled(false);
+        myCancelButton.setEnabled(true);
+      }
+    });
+    doPerform();
+  }
+
   private void doPerform() {
     isRunning.set(true);
 
     new Thread(new Runnable() {
+      @Override
       public void run() {
         try {
           myApplied = myOperation.execute(SwingUpdaterUI.this);
@@ -190,6 +239,10 @@
         finally {
           isRunning.set(false);
 
+          if (hasRetry.get()) {
+            myRetryButton.setVisible(true);
+            myRetryButton.setEnabled(true);
+          }
           if (hasError.get()) {
             startProcess("Failed to apply patch");
             setProgress(100);
@@ -204,15 +257,17 @@
   }
 
   private void exit() {
-    System.exit(myApplied ? RESULT_REQUIRES_RESTART : 0);
+    System.exit(myApplied ? mySuccessExitCode : 0);
   }
 
+  @Override
   public Map<String, ValidationResult.Option> askUser(final List<ValidationResult> validationResults) throws OperationCancelledException {
     if (validationResults.isEmpty()) return Collections.emptyMap();
 
     final Map<String, ValidationResult.Option> result = new HashMap<String, ValidationResult.Option>();
     try {
       SwingUtilities.invokeAndWait(new Runnable() {
+        @Override
         public void run() {
           final JDialog dialog = new JDialog(myFrame, TITLE, true);
           dialog.setLayout(new BorderLayout());
@@ -224,6 +279,7 @@
           buttonsPanel.add(Box.createHorizontalGlue());
           JButton proceedButton = new JButton(PROCEED_BUTTON_TITLE);
           proceedButton.addActionListener(new ActionListener() {
+            @Override
             public void actionPerformed(ActionEvent e) {
               dialog.setVisible(false);
             }
@@ -231,6 +287,7 @@
 
           JButton cancelButton = new JButton(CANCEL_BUTTON_TITLE);
           cancelButton.addActionListener(new ActionListener() {
+            @Override
             public void actionPerformed(ActionEvent e) {
               isCancelled.set(true);
               myCancelButton.setEnabled(false);
@@ -287,8 +344,10 @@
     return result;
   }
 
+  @Override
   public void startProcess(final String title) {
     myQueue.add(new UpdateRequest() {
+      @Override
       public void perform() {
         myProcessStatus.setText(title);
         myProcessProgress.setIndeterminate(false);
@@ -297,8 +356,10 @@
     });
   }
 
+  @Override
   public void setProgress(final int percentage) {
     myQueue.add(new UpdateRequest() {
+      @Override
       public void perform() {
         myProcessProgress.setIndeterminate(false);
         myProcessProgress.setValue(percentage);
@@ -306,21 +367,43 @@
     });
   }
 
+  @Override
   public void setProgressIndeterminate() {
     myQueue.add(new UpdateRequest() {
+      @Override
       public void perform() {
         myProcessProgress.setIndeterminate(true);
       }
     });
   }
 
+  @Override
   public void setStatus(final String status) {
   }
 
+  @Override
   public void showError(final Throwable e) {
     hasError.set(true);
+    StringWriter w = new StringWriter();
+
+    if (e instanceof RetryException) {
+      hasRetry.set(true);
+
+      w.write("+----------------\n");
+      w.write("| A file operation failed.\n");
+      w.write("| This might be due to a file being locked by another\n");
+      w.write("| application. Please try closing any application\n");
+      w.write("| that uses the files being updated then press 'Retry'.\n");
+      w.write("+----------------\n");
+      w.write("\n\n");
+    }
+
+    e.printStackTrace(new PrintWriter(w));
+
+    final String content = w.getBuffer().toString();
 
     myQueue.add(new UpdateRequest() {
+      @Override
       public void perform() {
         StringWriter w = new StringWriter();
         if (!myConsolePane.isVisible()) {
@@ -328,9 +411,8 @@
           w.write(System.getProperty("java.io.tmpdir"));
           w.write("\n\n");
         }
-        e.printStackTrace(new PrintWriter(w));
-        w.append("\n");
         myConsole.append(w.getBuffer().toString());
+        myConsole.append(content);
         if (!myConsolePane.isVisible()) {
           myConsole.setCaretPosition(0);
           myConsolePane.setVisible(true);
@@ -341,6 +423,7 @@
     });
   }
 
+  @Override
   public void checkCancelled() throws OperationCancelledException {
     if (isCancelled.get()) throw new OperationCancelledException();
   }
@@ -354,7 +437,8 @@
   }
 
   public static void main(String[] args) {
-    new SwingUpdaterUI("xxx", "yyy", new InstallOperation() {
+    new SwingUpdaterUI("xxx", "yyy", RESULT_REQUIRES_RESTART, new InstallOperation() {
+      @Override
       public boolean execute(UpdaterUI ui) throws OperationCancelledException {
         ui.startProcess("Process1");
         ui.checkCancelled();
@@ -438,6 +522,7 @@
       }
     }
 
+    @Override
     public int getColumnCount() {
       return COLUMNS.length;
     }
@@ -464,6 +549,7 @@
       return super.getColumnClass(columnIndex);
     }
 
+    @Override
     public int getRowCount() {
       return myItems.size();
     }
@@ -480,6 +566,7 @@
       }
     }
 
+    @Override
     public Object getValueAt(int rowIndex, int columnIndex) {
       Item item = myItems.get(rowIndex);
       switch (columnIndex) {
diff --git a/updater/src/com/intellij/updater/Utils.java b/updater/src/com/intellij/updater/Utils.java
old mode 100644
new mode 100755
index 959a93c..b5ad212
--- a/updater/src/com/intellij/updater/Utils.java
+++ b/updater/src/com/intellij/updater/Utils.java
@@ -10,10 +10,19 @@
   private static final byte[] BUFFER = new byte[64 * 1024];
   private static File myTempDir;
 
+  public static boolean isWindows() {
+    return System.getProperty("os.name").startsWith("Windows");
+  }
+
   public static boolean isZipFile(String fileName) {
     return fileName.endsWith(".zip") || fileName.endsWith(".jar");
   }
 
+  /**
+   * Creates a new temp file. <br/>
+   * All the temp files created here are located in a unique root temp directory
+   * that is automatically deleted by {@link #cleanup()}.
+   */
   @SuppressWarnings({"SSBasedInspection"})
   public static File createTempFile() throws IOException {
     if (myTempDir == null) {
@@ -26,6 +35,12 @@
     return File.createTempFile("temp.", ".tmp", myTempDir);
   }
 
+
+  /**
+   * Creates a new temp directory. <br/>
+   * All the temp directories created here are located in a unique root temp directory
+   * that is automatically deleted by {@link #cleanup()}.
+   */
   public static File createTempDir() throws IOException {
     File result = createTempFile();
     delete(result);
@@ -42,6 +57,15 @@
     myTempDir = null;
   }
 
+  /**
+   * Deletes a file or directory with a default timeout of 100 milliseconds.
+   * Directories are deleted recursively. The timeout occurs on each file.
+   * If one of the files fails to be deleted, the recursive directory deletion
+   * is aborted and not retried.
+   *
+   * @param file The file or directory to delete.
+   * @throws IOException
+   */
   public static void delete(File file) throws IOException {
     if (file.isDirectory()) {
       File[] files = file.listFiles();
@@ -52,16 +76,20 @@
         }
       }
     }
+
     for (int i = 0; i < 10; i++) {
-      if (file.delete() || !file.exists()) return;
+      if (file.delete() || !file.exists()) {
+        return;
+      }
       try {
         Thread.sleep(10);
-      }
-      catch (InterruptedException ignore) {
+      } catch (InterruptedException ignore) {
         Runner.printStackTrace(ignore);
       }
     }
-    if (file.exists()) throw new IOException("Cannot delete file " + file);
+    if (file.exists()) {
+      throw new IOException("Cannot delete file " + file);
+    }
   }
 
   public static void setExecutable(File file, boolean executable) throws IOException {
diff --git a/updater/testSrc/com/intellij/updater/RunnerAdditionalTest.java b/updater/testSrc/com/intellij/updater/RunnerAdditionalTest.java
new file mode 100644
index 0000000..577c2bc
--- /dev/null
+++ b/updater/testSrc/com/intellij/updater/RunnerAdditionalTest.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * 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.updater;
+
+import junit.framework.TestCase;
+
+import java.io.*;
+import java.nio.charset.Charset;
+import java.util.*;
+
+public class RunnerAdditionalTest extends TestCase {
+  private final LinkedList<File> myFiles = new LinkedList<File>();
+  private final ArrayList<NamePair> myFileNames = new ArrayList<NamePair>();
+
+  @Override
+  public void setUp() throws Exception {
+    super.setUp();
+    myFiles.clear();
+    myFileNames.clear();
+  }
+
+  @Override
+  public void tearDown() throws Exception {
+    super.tearDown();
+
+    while (!myFiles.isEmpty()) {
+      remove(myFiles.removeLast());
+    }
+  }
+
+  public void testUpdater1() throws Exception {
+    File dir1 = add(createTempDir("old", ".dir"));
+    File dir2 = add(createTempDir("new", ".dir"));
+    File f3 = add(createFileContent(dir1, "something.txt", "Content version 1"));
+    File f4 = add(createFileContent(dir2, "something.txt", "Content version 2"));
+    File inputJar5 = add(File.createTempFile("input", ".jar"));
+    File tmpPatch6 = add(File.createTempFile("temp", ".patch"));
+    final File patch7 = add(File.createTempFile("output", ".jar"));
+
+    createEmptyJar(inputJar5);
+
+    //noinspection ResultOfMethodCallIgnored
+    patch7.delete();
+    assertFalse(patch7.exists());
+
+    MockUpdaterUI ui1 = new MockUpdaterUI();
+    Runner.createImpl("1.2",                    //oldBuildDesc
+                      "1.3",                    //newBuildDesc
+                      dir1.getAbsolutePath(),   //oldFolder
+                      dir2.getAbsolutePath(),   //newFolder
+                      patch7.getAbsolutePath(), //outPatchJar
+                      tmpPatch6,                //tempPatchFile
+                      new ArrayList<String>(),  //ignoredFiles
+                      new ArrayList<String>(),  //criticalFiles
+                      new ArrayList<String>(),  //optionalFiles
+                      ui1,                      //ui
+                      inputJar5);               //resolvedJar
+
+    assertEquals(
+      "[Start   ] Calculating difference...\n" +
+      "[Status  ] something.txt\n" +
+      "[Status  ] something.txt\n" +
+      "[Start   ] Preparing actions...\n" +
+      "[Status  ] something.txt\n" +
+      "[Start   ] Creating the patch file 'file-6_temp.patch'...\n" +
+      "[Status  ] Packing something.txt\n" +
+      "[Start   ] Packing jar file 'file-7_output.jar'...\n" +
+      "[Start   ] Cleaning up...\n" +
+      "[Indeterminate Progress]\n",
+      ui1.toString());
+    assertTrue(patch7.exists());
+
+    File dir8 = add(createTempDir("extracted", ".dir"));
+    File f9 = add(createFileContent(dir8, "something.txt", "Content version 1"));
+    assertTrue(f9.exists());
+
+    MockUpdaterUI ui2 = new MockUpdaterUI();
+    Runner.doInstallImpl(ui2,
+                         dir8.getAbsolutePath(),
+                         new Runner.IJarResolver() {
+                           @Override
+                           public File resolveJar() throws IOException {
+                             return patch7;
+                           }
+                         });
+    assertEquals(
+      "[Start   ] Extracting patch file...\n" +
+      "[Indeterminate Progress]\n" +
+      "[Start   ] Validating installation...\n" +
+      "[Status  ] something.txt\n" +
+      "[Progress] 100\n" +
+      "[Start   ] Backing up files...\n" +
+      "[Status  ] something.txt\n" +
+      "[Progress] 100\n" +
+      "[Start   ] Applying patch...\n" +
+      "[Status  ] something.txt\n" +
+      "[Progress] 100\n" +
+      "[Start   ] Cleaning up...\n" +
+      "[Indeterminate Progress]\n",
+      ui2.toString());
+    assertEquals("Content version 2", getFileContent(f9));
+  }
+
+  //---- utilities -----
+
+  private File createTempDir(String prefix, String suffix) throws IOException {
+    File d = File.createTempFile(prefix, suffix);
+    if (!d.delete()) throw new IOException("Failed to delete directory " + d.getAbsolutePath());
+    if (!d.mkdirs()) throw new IOException("Failed to mkdirs " + d.getAbsolutePath());
+    return d;
+  }
+
+  private static void createEmptyJar(File jar) throws IOException {
+    FileOutputStream outStream = new FileOutputStream(jar);
+    try {
+      ZipOutputWrapper out = new ZipOutputWrapper(outStream);
+
+      // zip file can't be empty, add one dummy entry
+      ByteArrayOutputStream baos = new ByteArrayOutputStream();
+      baos.write("dummy entry".getBytes("UTF-8"));
+      out.zipBytes("dummy.txt", baos);
+
+      out.finish();
+    } finally {
+      outStream.close();
+    }
+  }
+
+  private File add(File f) {
+    myFiles.add(f);
+
+    String unique = f.getName().replaceAll("[^a-zA-Z.]", "");
+    NamePair fromTo = new NamePair(f.getAbsolutePath(),
+                                   (f.isDirectory() ? "dir-" : "file-") + (myFileNames.size() + 1) + '_' + unique);
+    myFileNames.add(fromTo);
+    Collections.sort(myFileNames);
+    return f;
+  }
+
+  private String getFileContent(File file) throws IOException {
+    if (!file.exists()) throw new IOException("File not found, expected file: " + replaceFileNames(file.getAbsolutePath()));
+    BufferedReader br = new BufferedReader(new FileReader(file));
+    try {
+      return br.readLine();
+    } finally {
+      br.close();
+    }
+  }
+
+  private static File createFileContent(File parentDir, String fileName, String fileContent) throws IOException {
+    File f = new File(parentDir, fileName);
+    OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(f), Charset.forName("UTF-8"));
+    try {
+      fw.write(fileContent);
+    } finally {
+      fw.close();
+    }
+    return f;
+  }
+
+  private static void remove(File... files) {
+    for (File f : files) {
+      if (f != null && f.exists()) {
+        if (!f.delete()) {
+          f.deleteOnExit();
+        }
+      }
+    }
+  }
+
+  private String replaceFileNames(String str) {
+    for (NamePair name : myFileNames) {
+      str = str.replace(name.getFrom(), name.getTo());
+    }
+    return str;
+  }
+
+  /**
+   * A list of from->to name pairs, ordered by descending from
+   * (to get the longer ones first.)
+   */
+  private static class NamePair implements Comparable<NamePair> {
+    private final String myFrom;
+    private final String myTo;
+
+    public NamePair(String from, String to) {
+      myFrom = from;
+      myTo = to;
+    }
+
+    public String getFrom() {
+      return myFrom;
+    }
+
+    public String getTo() {
+      return myTo;
+    }
+
+    @Override
+    public int compareTo(NamePair n2) {
+      return -1 * this.getFrom().compareTo(n2.getFrom());
+    }
+  }
+
+  /**
+   * Mock UpdaterUI that dumps all the text to a string buffer, which can be
+   * grabbed using toString(). It also replaces all the filenames using the
+   * provided name pair list.
+   */
+  private class MockUpdaterUI implements UpdaterUI {
+    private final StringBuilder myOutput = new StringBuilder();
+
+    private MockUpdaterUI() {
+    }
+
+    @Override
+    public void startProcess(String title) {
+      title = replaceFileNames(title);
+      myOutput.append("[Start   ] ").append(title).append('\n');
+    }
+
+    @Override
+    public void setProgress(int percentage) {
+      myOutput.append("[Progress] ").append(percentage).append('\n');
+    }
+
+    @Override
+    public void setProgressIndeterminate() {
+      myOutput.append("[Indeterminate Progress]\n");
+    }
+
+    @Override
+    public void setStatus(String status) {
+      status = replaceFileNames(status);
+      myOutput.append("[Status  ] ").append(status).append('\n');
+    }
+
+    @Override
+    public void showError(Throwable e) {
+      myOutput.append("[Error   ] ").append(e.toString()).append('\n');
+    }
+
+    @Override
+    public void checkCancelled() throws OperationCancelledException {
+      // no-op
+    }
+
+    @Override
+    public Map<String, ValidationResult.Option> askUser(List<ValidationResult> validationResults) throws OperationCancelledException {
+      return Collections.emptyMap();
+    }
+
+    @Override
+    public String toString() {
+      return myOutput.toString();
+    }
+  }
+}
diff --git a/updater/testSrc/com/intellij/updater/UtilsTest.java b/updater/testSrc/com/intellij/updater/UtilsTest.java
new file mode 100755
index 0000000..6e9e4eb
--- /dev/null
+++ b/updater/testSrc/com/intellij/updater/UtilsTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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.updater;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+public class UtilsTest extends TestCase {
+
+  private boolean mIsWindows;
+
+  @Override
+  public void setUp() throws Exception {
+    super.setUp();
+    mIsWindows = Utils.isWindows();
+  }
+
+  public void testDelete() throws Exception {
+    File f = File.createTempFile("test", "tmp");
+    assertTrue(f.exists());
+
+    try {
+      Utils.delete(f);
+      assertFalse(f.exists());
+    } finally {
+      f.deleteOnExit();
+    }
+  }
+
+  public void testDelete_LockedFile() throws Exception {
+    File f = File.createTempFile("test", "tmp");
+    assertTrue(f.exists());
+
+    long millis = 0;
+    FileWriter fw = new FileWriter(f);
+    try {
+      // This locks the file on Windows, preventing it from being deleted.
+      // Utils.delete() will retry for about 100 ms.
+      fw.write("test");
+      millis = System.currentTimeMillis();
+
+      Utils.delete(f);
+
+    } catch (IOException e) {
+      millis = System.currentTimeMillis() - millis;
+      assertEquals("Cannot delete file " + f.getAbsolutePath(), e.getMessage());
+      assertTrue("Utils.delete took " + millis + " ms, which is less than the expected 100 ms.", millis > 100);
+      return;
+
+    } finally {
+      f.deleteOnExit();
+      fw.close();
+    }
+
+    assertFalse("Utils.delete did not fail with the expected IOException on Windows.", mIsWindows);
+  }
+}
diff --git a/updater/testUI/.gitignore b/updater/testUI/.gitignore
new file mode 100644
index 0000000..378eac2
--- /dev/null
+++ b/updater/testUI/.gitignore
@@ -0,0 +1 @@
+build
diff --git a/updater/testUI/build.gradle b/updater/testUI/build.gradle
new file mode 100755
index 0000000..2c86712
--- /dev/null
+++ b/updater/testUI/build.gradle
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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.
+ */
+import java.nio.charset.Charset
+
+apply plugin: "application"
+
+project.mainClassName = "com.intellij.updater.Runner"
+
+defaultTasks "testSuite"
+
+repositories {
+  mavenCentral()
+}
+
+dependencies {
+  compile files("../../lib/log4j.jar")
+  testCompile group: "junit", name: "junit", version: "3.+"
+}
+
+sourceSets {
+  main {
+    java      { srcDir "../src" }
+    resources { srcDir "../src" }
+  }
+  test {
+    java      { srcDir "../tests" }
+    resources { srcDir "../tests" }
+  }
+}
+
+
+test {
+  testLogging {
+    showStandardStreams = true
+    showStackTraces = true
+    exceptionFormat = "full"
+  }
+}
+
+//---
+
+// Task : Tests updater create + install in the default normal case.
+// Scope: large test.
+// Running this will display the install patcher UI.
+task testUI1(dependsOn: jar) << {
+  println "## Running UI test 1"
+  println "## Jar file: " + jar.archivePath.getAbsolutePath()
+
+  // Create a temp dir inside the gradle build/tmp dir
+  //noinspection GroovyAssignabilityCheck
+  def buildTmpDir = new File(project.buildDir, "tmp");
+  def tmpDir = _createTempDir(buildTmpDir)
+  def logDir = _createTempDir(buildTmpDir)
+
+  try {
+    // create a "from version 1" and "to version 2" directories
+    def dataDir1 = _createTestData(tmpDir, "1")
+    assert  _mkFile(dataDir1, "plugins", "v1", "myplugin.jar").exists()
+    assert !_mkFile(dataDir1, "plugins", "v2", "myplugin.jar").exists()
+    assert _getFileContent(_mkFile(dataDir1, "build.txt")).equals("AI-123.45678-1")
+
+    def dataDir2 = _createTestData(tmpDir, "2")
+    assert !_mkFile(dataDir2, "plugins", "v1", "myplugin.jar").exists()
+    assert  _mkFile(dataDir2, "plugins", "v2", "myplugin.jar").exists()
+    assert _getFileContent(_mkFile(dataDir2, "build.txt")).equals("AI-123.45678-2")
+
+    def patch    = _createFileContent(tmpDir, "patch.jar", "patch jar placeholder");
+    patch.delete()
+    assert !patch.exists()
+
+    def logFullFile  = _mkFile(logDir, "idea_updater.log")
+    def logErrorFile = _mkFile(logDir, "idea_updater_error.log")
+    assert !logFullFile .exists()
+    assert !logErrorFile.exists()
+
+    // call updater jar to create a diff, resulting in a patch jar.
+    println "## Invoking updater <create>"
+    javaexec {
+      classpath jar.archivePath
+      classpath "../../lib/log4j.jar"
+      main = "com.intellij.updater.Runner"
+      args "create"
+      args "AI-123.45678-1"
+      args "AI-123.45678-2"
+      args dataDir1.getAbsolutePath()
+      args dataDir2.getAbsolutePath()
+      args patch.getAbsolutePath()
+      args logDir.getAbsolutePath()
+    }
+    assert patch.exists()
+
+    assert logFullFile .exists()
+    assert logErrorFile.exists()    // should exist and be empty
+    assert _getFileContent(logErrorFile).equals(null)
+
+
+    // that patch jar is self-executable. use it to update dir1 into dir2 in-place.
+    println "## Invoking updater <install>"
+    javaexec {
+      classpath patch
+      classpath "../../lib/log4j.jar"
+      main = "com.intellij.updater.Runner"
+      args "install"
+      args "--exit0"
+      args dataDir1.getAbsolutePath()
+      args logDir.getAbsolutePath()
+    }
+    // build.txt should have changed to v2
+    assert _getFileContent(_mkFile(dataDir1, "build.txt")).equals("AI-123.45678-2")
+    // plugin v1 should have been replaced by pluging v2 in the dataDir1 directory.
+    assert !_mkFile(dataDir1, "plugins", "v1", "myplugin.jar").exists()
+    assert  _mkFile(dataDir1, "plugins", "v2", "myplugin.jar").exists()
+
+    assert logFullFile .exists()
+    assert logErrorFile.exists()    // should exist and be empty
+    assert _getFileContent(logErrorFile).equals(null)
+
+  } finally {
+    // Cleanup on exit
+    tmpDir.deleteDir()
+    logDir.deleteDir()
+  }
+}
+
+// Task : Tests updater create + install with 2 open files.
+// Scope: large *interactive* test.
+// On Windows, the opened files are locked and can't be deleted/overwritten.
+// On Linux/Mac, they should be writable & deletable.
+//
+// Running this will display the install patcher UI, which will fail at
+// first on Windows. After 5 seconds the open files will be closed.
+// Hitting "retry" in the UI after this point should perform the whole
+// install operation again.
+task testUI2(dependsOn: jar) << {
+  println "## Running UI test 2"
+  println "## Jar file: " + jar.archivePath.getAbsolutePath()
+
+  // Create a temp dir inside the gradle build/tmp dir
+  //noinspection GroovyAssignabilityCheck
+  def buildTmpDir = new File(project.buildDir, "tmp");
+  def tmpDir = _createTempDir(buildTmpDir)
+  def logDir = _createTempDir(buildTmpDir)
+  def closeableFiles = []
+
+  try {
+    // create a "from version 1" and "to version 2" directories
+    def dataDir1 = _createTestData(tmpDir, "1")
+    assert  _mkFile(dataDir1, "plugins", "v1", "myplugin.jar").exists()
+    assert !_mkFile(dataDir1, "plugins", "v2", "myplugin.jar").exists()
+    assert _getFileContent(_mkFile(dataDir1, "build.txt")).equals("AI-123.45678-1")
+
+    def dataDir2 = _createTestData(tmpDir, "2")
+    assert !_mkFile(dataDir2, "plugins", "v1", "myplugin.jar").exists()
+    assert  _mkFile(dataDir2, "plugins", "v2", "myplugin.jar").exists()
+    assert _getFileContent(_mkFile(dataDir2, "build.txt")).equals("AI-123.45678-2")
+
+    def patch    = _createFileContent(tmpDir, "patch.jar", "patch jar placeholder");
+    patch.delete()
+    assert !patch.exists()
+
+    def logFullFile  = _mkFile(logDir, "idea_updater.log")
+    def logErrorFile = _mkFile(logDir, "idea_updater_error.log")
+    assert !logFullFile .exists()
+    assert !logErrorFile.exists()
+
+    // keep a couple files open, preventing them from being deleted or replaced on Windows
+    closeableFiles << _openFile(_mkFile(dataDir1, "build.txt"))
+    closeableFiles << _openFile(_mkFile(dataDir1, "plugins", "v1", "myplugin.jar"))
+
+    // call updater jar to create a diff, resulting in a patch jar.
+    println "## Invoking updater <create>"
+    javaexec {
+      classpath jar.archivePath
+      classpath "../../lib/log4j.jar"
+      main = "com.intellij.updater.Runner"
+      args "create"
+      args "AI-123.45678-1"
+      args "AI-123.45678-2"
+      args dataDir1.getAbsolutePath()
+      args dataDir2.getAbsolutePath()
+      args patch.getAbsolutePath()
+      args logDir.getAbsolutePath()
+    }
+    assert patch.exists()
+
+    assert logFullFile .exists()
+    assert logErrorFile.exists()    // should exist and be empty
+    assert _getFileContent(logErrorFile).equals(null)
+
+    Thread.start {
+      sleep(5 * 1000) // 5 seconds
+      synchronized(closeableFiles) {
+        println "##"
+        println "## Closing pending open files --> now click 'Retry' in Updater UI."
+        println "##"
+        closeableFiles.each { it.close() }
+        closeableFiles.clear()
+      }
+    }
+
+    // that patch jar is self-executable. use it to update dir1 into dir2 in-place.
+    println "## Invoking updater <install>"
+    println "##"
+    println "## Note: on Windows some files will be locked for 5 seconds and the installer"
+    println "##       window should display a 'Retry' button. This code will wait 5 seconds"
+    println "##       then unlock the files, at which point you would click that 'Retry'"
+    println "##       button and the install should continue correctly."
+    println "##"
+
+    javaexec {
+      classpath patch
+      classpath "../../lib/log4j.jar"
+      main = "com.intellij.updater.Runner"
+      args "install"
+      args "--exit0"
+      args dataDir1.getAbsolutePath()
+      args logDir.getAbsolutePath()
+    }
+    // build.txt should have changed to v2
+    assert _getFileContent(_mkFile(dataDir1, "build.txt")).equals("AI-123.45678-2")
+    // plugin v1 should have been replaced by pluging v2 in the dataDir1 directory.
+    assert !_mkFile(dataDir1, "plugins", "v1", "myplugin.jar").exists()
+    assert  _mkFile(dataDir1, "plugins", "v2", "myplugin.jar").exists()
+
+    assert logFullFile .exists()
+    // the log error file should exist and should not be empty on Windows.
+    assert logErrorFile.exists()
+    if (System.getProperty("os.name").startsWith("Windows")) {
+      assert _getFileContent(logErrorFile) != null
+    } else {
+      assert _getFileContent(logErrorFile).equals(null)
+    }
+
+  } finally {
+    // Cleanup on exit
+    synchronized(closeableFiles) {
+      closeableFiles.each { it.close() }
+      closeableFiles.clear()
+    }
+    tmpDir.deleteDir()
+    logDir.deleteDir()
+  }
+}
+
+// Task: Test suite to run both tests above.
+task testSuite(dependsOn: [testUI1, testUI2]) << {
+}
+
+// ---- Helper methods
+
+// Convention: all local helper methods start with an underscore to clearly
+// differentiate them from groovy/gradle methods.
+
+
+// Creates a temp dir with a random name in the build/tmp directory.
+File _createTempDir(File parent) {
+  def d = File.createTempFile("test", "", parent)
+  d.delete()
+  d.mkdirs()
+  return d
+}
+
+// Creates a new directory with the specific name in the specified parent directory.
+File _createDir(File parent, String name) {
+  def d = new File(parent, name)
+  d.mkdirs()
+  return d
+}
+
+// Creates a new file with the specified name, in the specified parent directory with the given UTF-8 content.
+File _createFileContent(File parentDir, String fileName, String fileContent) throws IOException {
+  File f = new File(parentDir, fileName)
+  OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(f), Charset.forName("UTF-8"))
+  try {
+    fw.write(fileContent)
+  } finally {
+    fw.close()
+  }
+  return f
+}
+
+// Opens a file for writing (thus locking it on Windows) but does not close it.
+// Caller should call Closeable.close() on the returned Closeable object.
+Closeable _openFile(File file) throws IOException {
+  if (!file.exists()) throw new IOException("File not found, expected file: " + file.getName())
+  // We need to actually write to the file but not change its content so just read it
+  // then write the same thing back to it, without closing it.
+  String content = _getFileContent(file)
+  FileWriter fw = new FileWriter(file, false /*append*/)
+  fw.append(content)
+  fw.flush()
+  println("## Open file " + file.getName());
+  return fw   // file is not closed
+}
+
+// Returns the first line of the file.
+// Returns null if the file exists and is empty.
+// Throws IOException if file does not exist.
+String _getFileContent(File file) throws IOException {
+  if (!file.exists()) throw new IOException("File not found, expected file: " + file.getName())
+  BufferedReader br = new BufferedReader(new FileReader(file))
+  try {
+    return br.readLine()
+  } finally {
+    br.close()
+  }
+}
+
+// Creates a new File() object with the concatenated name segments.
+File _mkFile(File base, String...segments) {
+  for(String segment : segments) {
+    base = new File(base, segment)
+  }
+  return base
+}
+
+// Creates a mock test data for an idea-based IDE.
+File _createTestData(File tmpDir, String value) {
+  File root     = _createDir(tmpDir,  "idea-ide-" + value)
+  File bin      = _createDir(root,    "bin")
+  File lib      = _createDir(root,    "lib")
+  File plugins  = _createDir(root,    "plugins")
+  File myplugin = _createDir(plugins, "v" + value)
+
+  _createFileContent(root,     "build.txt",    "AI-123.45678-"  + value);
+  _createFileContent(bin,      "idea.exe",     "binary file "   + value);
+  _createFileContent(lib,      "idea.jar",     "some jar file " + value);
+  _createFileContent(myplugin, "myplugin.jar", "some jar file " + value);
+
+  return root
+}
diff --git a/updater/testUI/gradle/wrapper/gradle-wrapper.jar b/updater/testUI/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..7b359d7
--- /dev/null
+++ b/updater/testUI/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/updater/testUI/gradle/wrapper/gradle-wrapper.properties b/updater/testUI/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..97f4761
--- /dev/null
+++ b/updater/testUI/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Dec 12 15:16:42 PST 2012
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=../../../../../external/gradle/gradle-1.9-bin.zip
diff --git a/updater/testUI/gradlew b/updater/testUI/gradlew
new file mode 100755
index 0000000..779e68d
--- /dev/null
+++ b/updater/testUI/gradlew
@@ -0,0 +1,179 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+    [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/"
+APP_HOME="`pwd -P`"
+cd "$SAVED"
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+    JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+# Change the project's .gradle to the android out dir.
+ANDROID_GRADLE_ROOT="$APP_HOME/../../../../out/host/gradle/tools/updater"
+if [[ -z "$ANDROID_CACHE_DIR" ]]; then
+  ANDROID_CACHE_DIR="$ANDROID_GRADLE_ROOT/.gradle"
+fi
+
+# Change the local user directories to be under the android out dir
+export GRADLE_USER_HOME="$ANDROID_GRADLE_ROOT/.gradle"
+export M2_HOME="$ANDROID_GRADLE_ROOT/.m2"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" \
+    -classpath "$CLASSPATH" \
+    org.gradle.wrapper.GradleWrapperMain \
+    --project-cache-dir=$ANDROID_CACHE_DIR \
+    "$@"
+
diff --git a/updater/testUI/gradlew.bat b/updater/testUI/gradlew.bat
new file mode 100755
index 0000000..3569a7b
--- /dev/null
+++ b/updater/testUI/gradlew.bat
@@ -0,0 +1,96 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Change the project's .gradle to the android out dir.
+set ANDROID_GRADLE_ROOT=%APP_HOME%\..\..\..\..\out\host\gradle\tools\updater
+set ANDROID_CACHE_DIR=%ANDROID_GRADLE_ROOT%\.gradle
+set GRADLE_USER_HOME=%ANDROID_GRADLE_ROOT%\.gradle
+set M2_HOME=%ANDROID_GRADLE_ROOT%\.m2
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% --project-cache-dir=%ANDROID_CACHE_DIR%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/updater/updater.iml b/updater/updater.iml
old mode 100644
new mode 100755