Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug 516583 - Use UTF-8 as default encoding for *new* workspaces #51

Merged
merged 1 commit into from
Apr 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,10 @@ public boolean hasSavedWorkspace() {
return metaAreaLocation.toFile().exists() || getBackupLocationFor(metaAreaLocation).toFile().exists();
}

public boolean hasSavedProjects() {
return projectMetaLocation.toFile().exists();
}

/**
* Returns the local file system location in which the meta data for the
* resource with the given path is stored.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import java.io.IOException;
import java.io.InputStream;
import java.lang.management.ManagementFactory;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
Expand All @@ -43,6 +44,8 @@
import org.eclipse.core.resources.team.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.*;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Bundle;
import org.xml.sax.InputSource;
Expand Down Expand Up @@ -2231,6 +2234,11 @@ public IStatus open(IProgressMonitor monitor) throws CoreException {
ResourcesPlugin.getPlugin().savePluginPreferences();
}

// Set explicit workspace encoding if no projects exist in the workspace
if (!localMetaArea.hasSavedProjects()) {
setExplicitWorkspaceEncoding();
}

// create root location
localMetaArea.locationFor(getRoot()).toFile().mkdirs();

Expand All @@ -2253,6 +2261,52 @@ public IStatus open(IProgressMonitor monitor) throws CoreException {
return Status.OK_STATUS;
}

/**
* Writes explicit workspace encoding to workspace preferences
* ("org.eclipse.core.resources/encoding"). If the user started Eclipse with
* explicit encoding set (-Dfile.encoding=XYZ), this encoding used, otherwise
* UTF-8.
* <p>
* With that, if user did not specified any encoding, all projects created in
* this workspace will get explicit UTF-8 encoding set.
*/
private void setExplicitWorkspaceEncoding() {
// ResourcesPlugin.getEncoding() defaults to JVM "file.encoding" value
// which is *always* set in the JVM, so it can't be used.
// Therefore check preferences directly (encoding could be set even in a new
// workspace via product customization file, like
// org.eclipse.core.resources/encoding=ISO-8859-1)
String defaultEncoding = Platform.getPreferencesService().getString(ResourcesPlugin.PI_RESOURCES,
ResourcesPlugin.PREF_ENCODING, /* default */null, /* all scopes */null);

if (defaultEncoding == null || defaultEncoding.isBlank()) {
// Check if -Dfile.encoding= startup argument was given to Eclipse's JVM
List<String> commandLineArgs = ManagementFactory.getRuntimeMXBean().getInputArguments();
for (String arg : commandLineArgs) {
if (arg.startsWith("-Dfile.encoding=")) { //$NON-NLS-1$
defaultEncoding = arg.substring("-Dfile.encoding=".length()); //$NON-NLS-1$
// continue, it can be specified multiple times, last one wins.
}
}
// Now we are sure user didn't specified encoding, so we can set
// default encoding for the workspace
if (defaultEncoding == null || defaultEncoding.isBlank()) {
defaultEncoding = "UTF-8"; //$NON-NLS-1$
}

// Persist encoding to the workspace preferences - if same workspace is started
// later by other Eclipse instance without product customization or system
// property or with differently set properties, we want keep same encoding as on
// the first startup. Otherwise users may end up with projects in same workspace
// created with different encodings. This is surely supported but would surprise
// users sooner or later. So better to set it first time, users can always
// change it later if needed.
IEclipsePreferences workspacePrefs = InstanceScope.INSTANCE.getNode(ResourcesPlugin.PI_RESOURCES);
workspacePrefs.put(ResourcesPlugin.PREF_ENCODING, defaultEncoding);
Assert.isTrue(defaultEncoding.equals(ResourcesPlugin.getEncoding()));
}
}

/**
* Called before checking the pre-conditions of an operation. Optionally supply
* a scheduling rule to determine when the operation is safe to run. If a scheduling
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,9 @@ public void testBug94279() throws CoreException {
try {
root.setDefaultCharset(null);
assertNull("1.0", root.getDefaultCharset(false));

root.setDefaultCharset(null, new NullProgressMonitor());
assertNull("1.0", root.getDefaultCharset(false));
} finally {
if (originalUserCharset != null) {
root.setDefaultCharset(originalUserCharset);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
Bug_266907.class, TestBug297635.class, TestBug323833.class,
org.eclipse.core.tests.resources.regression.TestMultipleBuildersOfSameType.class,
org.eclipse.core.tests.resources.usecase.SnapshotTest.class, ProjectDescriptionDynamicTest.class,
TestBug202384.class, TestBug369177.class, TestBug316182.class, TestBug294854.class, TestBug426263.class })
TestBug202384.class, TestBug369177.class, TestBug316182.class, TestBug294854.class, TestBug426263.class,
TestWorkspaceEncodingExistingWorkspace.class, TestWorkspaceEncodingNewWorkspace.class,
TestWorkspaceEncodingWithJvmArgs.class, TestWorkspaceEncodingWithPluginCustomization.class, })
public class AllTests {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*******************************************************************************
* Copyright (c) 2022 Andrey Loskutov <loskutov@gmx.de> and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Andrey Loskutov <loskutov@gmx.de> - initial API and implementation
*******************************************************************************/
package org.eclipse.core.tests.resources.session;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import junit.framework.Test;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.tests.resources.AutomatedTests;
import org.eclipse.core.tests.resources.WorkspaceSessionTest;
import org.eclipse.core.tests.session.WorkspaceSessionTestSuite;

/**
* Tests that explicit workspace encoding not set if there are projects defined
*/
public class TestWorkspaceEncodingExistingWorkspace extends WorkspaceSessionTest {

public static Test suite() {
WorkspaceSessionTestSuite suite = new WorkspaceSessionTestSuite(AutomatedTests.PI_RESOURCES_TESTS,
TestWorkspaceEncodingExistingWorkspace.class);
Path wspRoot = suite.getInstanceLocation().toFile().toPath();
Path projectsTree = wspRoot.resolve(".metadata/.plugins/org.eclipse.core.resources/.projects");
try {
Files.createDirectories(projectsTree);
} catch (IOException e) {
fail("Unable to create directories: " + projectsTree, e);
}
return suite;
}

public TestWorkspaceEncodingExistingWorkspace() {
super();
}

public void testExpectedEncoding1() throws Exception {
String defaultValue = System.getProperty("file.encoding");
IWorkspace workspace = ResourcesPlugin.getWorkspace();

// Should be system default
assertEquals(defaultValue, ResourcesPlugin.getEncoding());
assertEquals(defaultValue, workspace.getRoot().getDefaultCharset(true));

// and not defined in workspace
String charset = workspace.getRoot().getDefaultCharset(false);
assertEquals(null, charset);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*******************************************************************************
* Copyright (c) 2022 Andrey Loskutov <loskutov@gmx.de> and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Andrey Loskutov <loskutov@gmx.de> - initial API and implementation
*******************************************************************************/
package org.eclipse.core.tests.resources.session;

import junit.framework.Test;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.tests.resources.AutomatedTests;
import org.eclipse.core.tests.resources.WorkspaceSessionTest;
import org.eclipse.core.tests.session.WorkspaceSessionTestSuite;

/**
* Tests that encoding is set to UTF-8 in an empty workspace and only if no
* preference set already
*/
public class TestWorkspaceEncodingNewWorkspace extends WorkspaceSessionTest {

private static final String CHARSET = "UTF-16";

public static Test suite() {
WorkspaceSessionTestSuite suite = new WorkspaceSessionTestSuite(AutomatedTests.PI_RESOURCES_TESTS,
TestWorkspaceEncodingNewWorkspace.class);
// no special setup
return suite;
}

public TestWorkspaceEncodingNewWorkspace() {
super();
}

public void testExpectedEncoding1() throws Exception {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
String charset = workspace.getRoot().getDefaultCharset(false);
// Should be default
assertEquals("UTF-8", charset);
// Set something else
workspace.getRoot().setDefaultCharset(CHARSET, getMonitor());
workspace.save(true, getMonitor());
}

public void testExpectedEncoding2() throws Exception {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
String charset = workspace.getRoot().getDefaultCharset(false);
// Shouldn't be changed anymore
assertEquals(CHARSET, charset);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*******************************************************************************
* Copyright (c) 2022 Andrey Loskutov <loskutov@gmx.de> and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Andrey Loskutov <loskutov@gmx.de> - initial API and implementation
*******************************************************************************/
package org.eclipse.core.tests.resources.session;

import junit.framework.Test;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.tests.resources.AutomatedTests;
import org.eclipse.core.tests.resources.WorkspaceSessionTest;
import org.eclipse.core.tests.session.Setup;
import org.eclipse.core.tests.session.SetupManager.SetupException;
import org.eclipse.core.tests.session.WorkspaceSessionTestSuite;

/**
* Tests that encoding is set according to jvm arguments
*/
public class TestWorkspaceEncodingWithJvmArgs extends WorkspaceSessionTest {

private static final String CHARSET = "UTF-16";

public static Test suite() {
WorkspaceSessionTestSuite suite = new WorkspaceSessionTestSuite(AutomatedTests.PI_RESOURCES_TESTS,
TestWorkspaceEncodingWithJvmArgs.class);
try {

// add pluginCustomization argument
Setup setup = suite.getSetup();
setup.setSystemProperty("file.encoding", CHARSET);
} catch (SetupException e) {
// ignore, the test will fail for us
}
return suite;
}

public TestWorkspaceEncodingWithJvmArgs() {
super();
}

public void testExpectedEncoding() throws Exception {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
// Should be system default
assertEquals(CHARSET, ResourcesPlugin.getEncoding());
assertEquals(CHARSET, workspace.getRoot().getDefaultCharset(true));

// and also defined in workspace
String charset = workspace.getRoot().getDefaultCharset(false);
assertEquals(CHARSET, charset);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*******************************************************************************
* Copyright (c) 2022 Andrey Loskutov <loskutov@gmx.de> and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Andrey Loskutov <loskutov@gmx.de> - initial API and implementation
*******************************************************************************/
package org.eclipse.core.tests.resources.session;

import java.io.*;
import junit.framework.Test;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.tests.harness.FileSystemHelper;
import org.eclipse.core.tests.resources.AutomatedTests;
import org.eclipse.core.tests.resources.WorkspaceSessionTest;
import org.eclipse.core.tests.session.Setup;
import org.eclipse.core.tests.session.SetupManager.SetupException;
import org.eclipse.core.tests.session.WorkspaceSessionTestSuite;

/**
* Tests that encoding is set according to plugin customization
*/
public class TestWorkspaceEncodingWithPluginCustomization extends WorkspaceSessionTest {

private static final String CHARSET = "UTF-16";
private static final String FILE_NAME = FileSystemHelper.getTempDir().append("plugin_customization_encoding.ini").toOSString();

public static Test suite() {
WorkspaceSessionTestSuite suite = new WorkspaceSessionTestSuite(AutomatedTests.PI_RESOURCES_TESTS,
TestWorkspaceEncodingWithPluginCustomization.class);
try {
// create plugin_customization.ini file
File file = new File(FILE_NAME);
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
writer.write("org.eclipse.core.resources/encoding=" + CHARSET);
}

// add pluginCustomization argument
Setup setup = suite.getSetup();
setup.setEclipseArgument("pluginCustomization", file.toString());
} catch (IOException | SetupException e) {
// ignore, the test will fail for us
}
return suite;
}

public TestWorkspaceEncodingWithPluginCustomization() {
super();
}

public void testExpectedEncoding() throws Exception {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
// Should be system default
assertEquals(CHARSET, ResourcesPlugin.getEncoding());
assertEquals(CHARSET, workspace.getRoot().getDefaultCharset(true));

// and defined in workspace because it is the custom product preference
String charset = workspace.getRoot().getDefaultCharset(false);
assertEquals(CHARSET, charset);
}
}