diff --git a/build/scripts/libLicenses.gant b/build/scripts/libLicenses.gant index 853e8e76af1a..542b08d9936e 100644 --- a/build/scripts/libLicenses.gant +++ b/build/scripts/libLicenses.gant @@ -254,6 +254,7 @@ libraryLicense(name: "proxy-vole", libraryName: "proxy-vole", version: "20120920 libraryLicense(name: "Rhino JavaScript Engine", libraryName: "rhino-js-1_7R4", version: "1.7R4", license: "MPL 1.1", url: "http://www.mozilla.org/rhino/", licenseUrl: "http://www.mozilla.org/MPL/MPL-1.1.html") libraryLicense(name: "asm-4.0-all", libraryName: "asm-4.0-all", version: "4.0", attachedTo: "ByteCodeViewer", license: "BSD", url: "http://asm.objectweb.org/", licenseUrl: "http://asm.objectweb.org/license.html") libraryLicense(name: "jsr305", libraryName: "jsr305", version: "snapshot", license: "BSD", url: "http://code.google.com/p/jsr-305/", licenseUrl: "http://code.google.com/p/jsr-305/source/browse/trunk/ri/LICENSE") +libraryLicense(name: "jzlib", libraryName: "jzlib", version: "1.1.1", license: "BSD", url: "http://www.jcraft.com/jzlib/", licenseUrl: "http://www.jcraft.com/jzlib/LICENSE.txt") jetbrainsLibrary("JPS") jetbrainsLibrary("Maven Embedder") jetbrainsLibrary("tcServiceMessages") diff --git a/lib/jzlib-1.1.1.jar b/lib/jzlib-1.1.1.jar new file mode 100644 index 000000000000..5530c9d142c9 Binary files /dev/null and b/lib/jzlib-1.1.1.jar differ diff --git a/lib/src/jzlib-1.1.1.zip b/lib/src/jzlib-1.1.1.zip new file mode 100644 index 000000000000..c0745a092f3e Binary files /dev/null and b/lib/src/jzlib-1.1.1.zip differ diff --git a/platform/lang-api/src/com/intellij/execution/filters/CompositeInputFilter.java b/platform/lang-api/src/com/intellij/execution/filters/CompositeInputFilter.java index 7ba812f9e8d7..1801f74869dc 100644 --- a/platform/lang-api/src/com/intellij/execution/filters/CompositeInputFilter.java +++ b/platform/lang-api/src/com/intellij/execution/filters/CompositeInputFilter.java @@ -39,13 +39,13 @@ public class CompositeInputFilter implements InputFilter { @Override @Nullable - public Pair applyFilter(final String text, final ConsoleViewContentType contentType) { + public List> applyFilter(final String text, final ConsoleViewContentType contentType) { boolean dumb = myDumbService.isDumb(); for (Pair pair : myFilters) { if (!dumb || pair.second == Boolean.TRUE) { long t0 = System.currentTimeMillis(); InputFilter filter = pair.first; - Pair result = filter.applyFilter(text, contentType); + List> result = filter.applyFilter(text, contentType); t0 = System.currentTimeMillis() - t0; if (t0 > 100) { LOG.warn(filter.getClass().getSimpleName() + ".applyFilter() took " + t0 + " ms on '''" + text + "'''"); diff --git a/platform/lang-api/src/com/intellij/execution/filters/InputFilter.java b/platform/lang-api/src/com/intellij/execution/filters/InputFilter.java index 648b1ee037c5..5110ef0a9654 100644 --- a/platform/lang-api/src/com/intellij/execution/filters/InputFilter.java +++ b/platform/lang-api/src/com/intellij/execution/filters/InputFilter.java @@ -19,14 +19,16 @@ import com.intellij.execution.ui.ConsoleViewContentType; import com.intellij.openapi.util.Pair; import org.jetbrains.annotations.Nullable; +import java.util.List; + public interface InputFilter { /** * @param text the text to be filtered. * @param contentType the content type of filtered text - * @return null, if there was no match, otherwise, a pair of ('string to use', 'content type to use') + * @return null, if there was no match, otherwise, a list of pairs like ('string to use', 'content type to use') */ @Nullable - Pair applyFilter(String text, ConsoleViewContentType contentType); + List> applyFilter(String text, ConsoleViewContentType contentType); } diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java index b8f23dedd73b..5ec07f90c479 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java @@ -531,18 +531,20 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo return; } - Pair result = myInputMessageFilter.applyFilter(s, contentType); + List> result = myInputMessageFilter.applyFilter(s, contentType); if (result == null) { printHyperlink(s, contentType, null); } else { - if (result.first != null) { - printHyperlink(result.first, result.second == null ? contentType : result.second, null); + for (Pair pair : result) { + if (pair.first != null) { + printHyperlink(pair.first, pair.second == null ? contentType : pair.second, null); + } } } } - private void printHyperlink(String s, ConsoleViewContentType contentType, HyperlinkInfo info) { + private void printHyperlink(String s, ConsoleViewContentType contentType, @Nullable HyperlinkInfo info) { synchronized (LOCK) { Pair pair = myBuffer.print(s, contentType, info); s = pair.first; diff --git a/platform/platform-api/src/com/intellij/execution/configurations/PathEnvironmentVariableUtil.java b/platform/platform-api/src/com/intellij/execution/configurations/PathEnvironmentVariableUtil.java index f1e7bce7b87c..6bac7c646f88 100644 --- a/platform/platform-api/src/com/intellij/execution/configurations/PathEnvironmentVariableUtil.java +++ b/platform/platform-api/src/com/intellij/execution/configurations/PathEnvironmentVariableUtil.java @@ -5,6 +5,8 @@ import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.EnvironmentUtil; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.text.CaseInsensitiveStringHashingStrategy; +import gnu.trove.THashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -20,10 +22,20 @@ public class PathEnvironmentVariableUtil { public static final String PATH_ENV_VAR_NAME = "PATH"; - private static final String ourFixedMacPathEnvVarValue; + private static final Map ENVIRONMENT_VARIABLES; + private static final String FIXED_MAC_PATH_VALUE; static { - ourFixedMacPathEnvVarValue = calcFixedMacPathEnvVarValue(); + Map envVars = EnvironmentUtil.getEnvironmentProperties(); + if (SystemInfo.isWindows) { + THashMap map = new THashMap(CaseInsensitiveStringHashingStrategy.INSTANCE); + map.putAll(envVars); + ENVIRONMENT_VARIABLES = map; + } + else { + ENVIRONMENT_VARIABLES = envVars; + } + FIXED_MAC_PATH_VALUE = calcFixedMacPathEnvVarValue(); } private PathEnvironmentVariableUtil() { @@ -35,7 +47,7 @@ public class PathEnvironmentVariableUtil { */ @Nullable public static String getFixedPathEnvVarValueOnMac() { - return ourFixedMacPathEnvVarValue; + return FIXED_MAC_PATH_VALUE; } private static String calcFixedMacPathEnvVarValue() { @@ -67,8 +79,7 @@ public class PathEnvironmentVariableUtil { @Nullable private static String getOriginalPathEnvVarValue() { - Map originalEnvVars = EnvironmentUtil.getEnvironmentProperties(); - return originalEnvVars.get(PATH_ENV_VAR_NAME); + return ENVIRONMENT_VARIABLES.get(PATH_ENV_VAR_NAME); } @NotNull diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleDependencyManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleDependencyManager.java index 22c403502f88..3c52c398d16f 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleDependencyManager.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleDependencyManager.java @@ -6,6 +6,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.*; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; +import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.gradle.config.PlatformFacade; import org.jetbrains.plugins.gradle.model.gradle.*; @@ -181,23 +182,55 @@ public class GradleDependencyManager { } } + @SuppressWarnings("MethodMayBeStatic") public void setScope(@NotNull final DependencyScope scope, @NotNull final ExportableOrderEntry dependency, boolean synchronous) { Project project = dependency.getOwnerModule().getProject(); GradleUtil.executeProjectChangeAction(project, dependency, synchronous, new Runnable() { @Override public void run() { - dependency.setScope(scope); + doForDependency(dependency, new Consumer() { + @Override + public void consume(ExportableOrderEntry entry) { + entry.setScope(scope); + } + }); } }); } + @SuppressWarnings("MethodMayBeStatic") public void setExported(final boolean exported, @NotNull final ExportableOrderEntry dependency, boolean synchronous) { Project project = dependency.getOwnerModule().getProject(); GradleUtil.executeProjectChangeAction(project, dependency, synchronous, new Runnable() { @Override public void run() { - dependency.setExported(exported); + doForDependency(dependency, new Consumer() { + @Override + public void consume(ExportableOrderEntry entry) { + entry.setExported(exported); + } + }); } }); } + + private static void doForDependency(@NotNull ExportableOrderEntry entry, @NotNull Consumer consumer) { + // We need to get an up-to-date modifiable model to work with. + ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(entry.getOwnerModule()); + final ModifiableRootModel moduleRootModel = moduleRootManager.getModifiableModel(); + try { + // The thing is that intellij created order entry objects every time new modifiable model is created, + // that's why we can't use target dependency object as is but need to get a reference to the current + // entry object from the model instead. + for (OrderEntry e : moduleRootModel.getOrderEntries()) { + if (e instanceof ExportableOrderEntry && e.getPresentableName().equals(entry.getPresentableName())) { + consumer.consume((ExportableOrderEntry)e); + break; + } + } + } + finally { + moduleRootModel.commit(); + } + } } diff --git a/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java b/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java index 99a90cbd8d78..35982698a670 100644 --- a/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java +++ b/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java @@ -29,29 +29,13 @@ public class HgExecutor extends Executor { private static final String HG_EXECUTABLE_ENV = "IDEA_TEST_HG_EXECUTABLE"; //private static final String TEAMCITY_HG_EXECUTABLE_ENV = "TEAMCITY_HG_PATH"; //todo var for server testing - private static boolean myVersionPrinted; - private static final String HG_EXECUTABLE = findHgExecutable(); - - private static String findHgExecutable() { - return findExecutable("hg", "hg", "hg.exe", Arrays.asList(HG_EXECUTABLE_ENV)); - } + private static final String HG_EXECUTABLE = findExecutable("hg", "hg", "hg.exe", Arrays.asList(HG_EXECUTABLE_ENV)); public static String hg(String command) { - printVersionTheFirstTime(); List split = StringUtil.split(command, " "); split.add(0, HG_EXECUTABLE); log("hg " + command); - for(int attempt = 0; attempt < 3; attempt++) { - return run(split); - } - throw new RuntimeException("fatal error during execution of Hg command: " + command); + return run(split); } - private static void printVersionTheFirstTime() { - if (!myVersionPrinted) { - myVersionPrinted = true; - hg("version"); - } - } } - diff --git a/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java b/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java index b63ba4cde670..60dff15e1a98 100644 --- a/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java +++ b/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java @@ -55,6 +55,9 @@ public abstract class HgPlatformTest extends LightPlatformTestCase { @Override protected void setUp() throws Exception { + cd(FileUtil.getTempDirectory()); + hg("version"); + super.setUp(); myProject = getProject(); @@ -65,11 +68,6 @@ public abstract class HgPlatformTest extends LightPlatformTestCase { setUpHgrc(myRepository); } - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - private static void setUpHgrc(VirtualFile repository) { cd(".hg"); File pluginRoot = new File(PluginPathManager.getPluginHomePath("hg4idea")); diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/context/WorkingContextManager.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/context/WorkingContextManager.java index c411c50eb19d..7e565db65aa2 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/context/WorkingContextManager.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/context/WorkingContextManager.java @@ -16,6 +16,9 @@ package com.intellij.tasks.context; +import com.intellij.notification.Notification; +import com.intellij.notification.NotificationType; +import com.intellij.notification.Notifications; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; @@ -36,6 +39,7 @@ import org.jdom.output.XMLOutputter; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; import java.io.File; import java.io.IOException; @@ -112,7 +116,7 @@ public class WorkingContextManager { saveContext(entryName, CONTEXT_ZIP_POSTFIX, comment); } - private void saveContext(@Nullable String entryName, String zipPostfix, @Nullable String comment) { + private synchronized void saveContext(@Nullable String entryName, String zipPostfix, @Nullable String comment) { try { JBZipFile archive = getTasksArchive(zipPostfix); if (entryName == null) { @@ -128,7 +132,7 @@ public class WorkingContextManager { Element element = new Element("context"); saveContext(element); String s = new XMLOutputter().outputString(element); - entry.setData(s.getBytes()); + entry.setData(s.getBytes("UTF-8")); archive.close(); } catch (IOException e) { @@ -137,6 +141,27 @@ public class WorkingContextManager { } private JBZipFile getTasksArchive(String postfix) throws IOException { + File file = getArchiveFile(postfix); + try { + return new JBZipFile(file); + } + catch (IOException e) { + file.delete(); + JBZipFile zipFile = null; + try { + zipFile = new JBZipFile(file); + Notifications.Bus.notify(new Notification("Tasks", "Context Data Corrupted", + "Context information history for " + myProject.getName() + " was corrupted.\n" + + "The history was replaced with empty one.", NotificationType.ERROR), myProject); + } + catch (IOException e1) { + LOG.error("Can't repair form context data corruption", e1); + } + return zipFile; + } + } + + private File getArchiveFile(String postfix) { String configPath = PathManager.getConfigPath(true); File tasksFolder = new File(configPath, TASKS_FOLDER); if (!tasksFolder.exists()) { @@ -144,39 +169,54 @@ public class WorkingContextManager { tasksFolder.mkdir(); } String projectName = myProject.getName(); - return new JBZipFile(new File(tasksFolder, projectName + postfix)); + return new File(tasksFolder, projectName + postfix); } public void restoreContext(@NotNull Task task) { loadContext(TASKS_ZIP_POSTFIX, task.getId() + TASK_XML_POSTFIX); } - private boolean loadContext(String zipPostfix, String entryName) { + private synchronized boolean loadContext(String zipPostfix, String entryName) { + JBZipFile archive = null; try { - JBZipFile archive = getTasksArchive(zipPostfix); + archive = getTasksArchive(zipPostfix); JBZipEntry entry = archive.getEntry(StringUtil.startsWithChar(entryName, '/') ? entryName : "/" + entryName); if (entry != null) { byte[] bytes = entry.getData(); Document document = JDOMUtil.loadDocument(new String(bytes)); Element rootElement = document.getRootElement(); loadContext(rootElement); - archive.close(); return true; } } catch (Exception e) { LOG.error(e); } + finally { + closeArchive(archive); + } return false; } + private static void closeArchive(JBZipFile archive) { + if (archive != null) { + try { + archive.close(); + } + catch (IOException e) { + LOG.error(e); + } + } + } + public List getContextHistory() { return getContextHistory(CONTEXT_ZIP_POSTFIX); } - private List getContextHistory(String zipPostfix) { + private synchronized List getContextHistory(String zipPostfix) { + JBZipFile archive = null; try { - JBZipFile archive = getTasksArchive(zipPostfix); + archive = getTasksArchive(zipPostfix); List entries = archive.getEntries(); return ContainerUtil.mapNotNull(entries, new NullableFunction() { public ContextInfo fun(JBZipEntry entry) { @@ -188,6 +228,9 @@ public class WorkingContextManager { LOG.error(e); return Collections.emptyList(); } + finally { + closeArchive(archive); + } } public boolean loadContext(String name) { @@ -203,17 +246,20 @@ public class WorkingContextManager { } private void removeContext(String name, String postfix) { + JBZipFile archive = null; try { - JBZipFile archive = getTasksArchive(postfix); + archive = getTasksArchive(postfix); JBZipEntry entry = archive.getEntry(name); if (entry != null) { archive.eraseEntry(entry); } - archive.close(); } catch (IOException e) { LOG.error(e); } + finally { + closeArchive(archive); + } } public void pack(int max, int delta) { @@ -221,9 +267,10 @@ public class WorkingContextManager { pack(max, delta, TASKS_ZIP_POSTFIX); } - private void pack(int max, int delta, String zipPostfix) { + private synchronized void pack(int max, int delta, String zipPostfix) { + JBZipFile archive = null; try { - JBZipFile archive = getTasksArchive(zipPostfix); + archive = getTasksArchive(zipPostfix); List entries = archive.getEntries(); if (entries.size() > max + delta) { JBZipEntry[] array = entries.toArray(new JBZipEntry[entries.size()]); @@ -232,11 +279,17 @@ public class WorkingContextManager { archive.eraseEntry(array[i]); } } - archive.close(); } catch (IOException e) { LOG.error(e); } + finally { + closeArchive(archive); + } + } + @TestOnly + public File getContextFile() throws IOException { + return getArchiveFile(CONTEXT_ZIP_POSTFIX); } } diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/context/ContextTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/context/ContextTest.java index 9a56140acc28..d9471d75c047 100644 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/context/ContextTest.java +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/context/ContextTest.java @@ -16,8 +16,10 @@ package com.intellij.tasks.context; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.tasks.TaskManagerTestCase; +import java.io.File; import java.util.List; /** @@ -55,6 +57,15 @@ public class ContextTest extends TaskManagerTestCase { assertEquals("/context2", history.get(0).name); } + public void testContextFileRepair() throws Exception { + WorkingContextManager manager = getContextManager(); + manager.saveContext("foo", "bar"); + File file = manager.getContextFile(); + assertTrue(file.length() > 0); + FileUtil.writeToFile(file, "123"); // corrupt it + manager.saveContext("foo", "bar"); + } + private WorkingContextManager getContextManager() { return WorkingContextManager.getInstance(getProject()); }