diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/EncodingTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/EncodingTests.java index c9368c8..ff05591 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/EncodingTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/EncodingTests.java @@ -28,6 +28,7 @@ import org.eclipse.core.runtime.content.IContentDescription; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.jdt.core.IClasspathAttribute; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaProject; @@ -62,7 +63,7 @@ // Use this static initializer to specify subset for tests // All specified tests which do not belong to the class are skipped... static { -// TESTS_NAMES = new String[] { "testBug110576" }; +// TESTS_NAMES = new String[] { "testBug361356" }; // TESTS_NUMBERS = new int[] { 2, 12 }; // TESTS_RANGE = new int[] { 16, -1 }; } @@ -1217,7 +1218,156 @@ getWorkspaceRoot().setDefaultCharset(wkspEncoding, null); } } - + public void testBug361356() throws Exception { + String oldEncoding = this.encodingProject.getDefaultCharset(); + try{ + String encoding = "Shift-JIS"; + if (wkspEncoding.equals(encoding)) + getWorkspaceRoot().setDefaultCharset("UTF-8", null); + this.encodingProject.setDefaultCharset("UTF-8", null); + IJavaProject project = this.createJavaProject("Encoding2", new String[] {""}, ""); + IFile zipFile = (IFile) this.encodingProject.findMember("testShiftJIS.zip"); //$NON-NLS-1$ + IFile sourceFile = (IFile) this.encodingProject.findMember("src/testShiftJIS/A.java"); + + IClasspathEntry[] entries = this.encodingJavaProject.getRawClasspath(); + IClasspathEntry newEntry = null; + for (int index = 0; index < entries.length; index++) { + IClasspathEntry entry = entries[index]; + if (entry.getPath().toOSString().endsWith("testShiftJIS.jar")) { + newEntry = entries[index]; + } + } + + IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.SOURCE_ATTACHMENT_ENCODING, encoding); + project.setRawClasspath(new IClasspathEntry[]{JavaCore.newLibraryEntry(newEntry.getPath(), new Path("/Encoding/src"), null, null, new IClasspathAttribute[]{attribute}, false)}, null); + sourceFile.setCharset(null, null); + + IPackageFragmentRoot root = getPackageFragmentRoot("Encoding2", "testShiftJIS.jar"); + ISourceReference sourceRef = root.getPackageFragment("testShiftJIS").getClassFile("A.class"); + assertNotNull(sourceRef); + String source = sourceRef.getSource(); + assertNotNull(source); + String encodedContents = new String (Util.getResourceContentsAsCharArray(sourceFile, encoding)); + char[] charArray = encodedContents.toCharArray(); + encodedContents = new String(CharOperation.remove(charArray, '\r')); + charArray = source.toCharArray(); + source = new String(CharOperation.remove(charArray, '\r')); + assertTrue("Sources should be decoded the same way", encodedContents.equals(source)); + + attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.SOURCE_ATTACHMENT_ENCODING, "UTF-8"); + project.setRawClasspath(new IClasspathEntry[]{JavaCore.newLibraryEntry(newEntry.getPath(), new Path("/Encoding/src"), null, null, new IClasspathAttribute[]{attribute}, false)}, null); + sourceFile.setCharset(encoding, null); + + root = getPackageFragmentRoot("Encoding2", "testShiftJIS.jar"); + sourceRef = root.getPackageFragment("testShiftJIS").getClassFile("A.class"); + assertNotNull(sourceRef); + source = sourceRef.getSource(); + assertNotNull(source); + encodedContents = new String (Util.getResourceContentsAsCharArray(sourceFile, encoding)); + charArray = encodedContents.toCharArray(); + encodedContents = new String(CharOperation.remove(charArray, '\r')); + charArray = source.toCharArray(); + source = new String(CharOperation.remove(charArray, '\r')); + assertTrue("Sources should be decoded the same way", encodedContents.equals(source)); + + attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.SOURCE_ATTACHMENT_ENCODING, encoding); + project.setRawClasspath(new IClasspathEntry[]{JavaCore.newLibraryEntry(newEntry.getPath(), new Path("/Encoding/testShiftJIS.zip"), null, null, new IClasspathAttribute[]{attribute}, false)}, null); + zipFile.setCharset(null, null); + + root = getPackageFragmentRoot("Encoding2", "testShiftJIS.jar"); + sourceRef = root.getPackageFragment("testShiftJIS").getClassFile("A.class"); + assertNotNull(sourceRef); + source = sourceRef.getSource(); + assertNotNull(source); + encodedContents = new String (Util.getResourceContentsAsCharArray(sourceFile, encoding)); + charArray = encodedContents.toCharArray(); + encodedContents = new String(CharOperation.remove(charArray, '\r')); + charArray = source.toCharArray(); + source = new String(CharOperation.remove(charArray, '\r')); + assertTrue("Sources should be decoded the same way", encodedContents.equals(source)); + + attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.SOURCE_ATTACHMENT_ENCODING, "UTF-8"); + project.setRawClasspath(new IClasspathEntry[]{JavaCore.newLibraryEntry(newEntry.getPath(), new Path("/Encoding/testShiftJIS.zip"), null, null, new IClasspathAttribute[]{attribute}, false)}, null); + zipFile.setCharset(encoding, null); + + root = getPackageFragmentRoot("Encoding2", "testShiftJIS.jar"); + sourceRef = root.getPackageFragment("testShiftJIS").getClassFile("A.class"); + assertNotNull(sourceRef); + source = sourceRef.getSource(); + assertNotNull(source); + encodedContents = new String (Util.getResourceContentsAsCharArray(sourceFile, encoding)); + charArray = encodedContents.toCharArray(); + encodedContents = new String(CharOperation.remove(charArray, '\r')); + charArray = source.toCharArray(); + source = new String(CharOperation.remove(charArray, '\r')); + assertTrue("Sources should be decoded the same way", encodedContents.equals(source)); + + } + finally { + this.encodingProject.setDefaultCharset(oldEncoding, null); + deleteProject("Encoding2"); + getWorkspaceRoot().setDefaultCharset(wkspEncoding, null); + } + } + public void testBug361356a() throws Exception { + String oldEncoding = this.encodingProject.getDefaultCharset(); + try{ + String encoding = "Shift-JIS"; + if (wkspEncoding.equals(encoding)) + getWorkspaceRoot().setDefaultCharset("UTF-8", null); + this.encodingProject.setDefaultCharset("UTF-8", null); + IJavaProject project = this.createJavaProject("Encoding2", new String[] {""}, ""); + IFile zipFile = (IFile) this.encodingProject.findMember("testShiftJIS.zip"); //$NON-NLS-1$ + IFile sourceFile = (IFile) this.encodingProject.findMember("src/testShiftJIS/A.java"); + + IClasspathEntry[] entries = this.encodingJavaProject.getRawClasspath(); + IClasspathEntry newEntry = null; + for (int index = 0; index < entries.length; index++) { + IClasspathEntry entry = entries[index]; + if (entry.getPath().toOSString().endsWith("testShiftJIS.jar")) { + newEntry = entries[index]; + } + } + + IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.SOURCE_ATTACHMENT_ENCODING, encoding); + attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.SOURCE_ATTACHMENT_ENCODING, encoding); + project.setRawClasspath(new IClasspathEntry[]{JavaCore.newLibraryEntry(newEntry.getPath(), new Path("/Encoding/testShiftJIS.zip"), null, null, new IClasspathAttribute[]{attribute}, false)}, null); + zipFile.setCharset(null, null); + + IPackageFragmentRoot root = getPackageFragmentRoot("Encoding2", "testShiftJIS.jar"); + ISourceReference sourceRef = root.getPackageFragment("testShiftJIS").getClassFile("A.class"); + assertNotNull(sourceRef); + String source = sourceRef.getSource(); + assertNotNull(source); + String encodedContents = new String (Util.getResourceContentsAsCharArray(sourceFile, encoding)); + char[] charArray = encodedContents.toCharArray(); + encodedContents = new String(CharOperation.remove(charArray, '\r')); + charArray = source.toCharArray(); + source = new String(CharOperation.remove(charArray, '\r')); + assertTrue("Sources should be decoded the same way", encodedContents.equals(source)); + + attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.SOURCE_ATTACHMENT_ENCODING, "UTF-8"); + project.setRawClasspath(new IClasspathEntry[]{JavaCore.newLibraryEntry(newEntry.getPath(), new Path("/Encoding/testShiftJIS.zip"), null, null, new IClasspathAttribute[]{attribute}, false)}, null); + zipFile.setCharset(encoding, null); + + root = getPackageFragmentRoot("Encoding2", "testShiftJIS.jar"); + sourceRef = root.getPackageFragment("testShiftJIS").getClassFile("A.class"); + assertNotNull(sourceRef); + source = sourceRef.getSource(); + assertNotNull(source); + encodedContents = new String (Util.getResourceContentsAsCharArray(sourceFile, encoding)); + charArray = encodedContents.toCharArray(); + encodedContents = new String(CharOperation.remove(charArray, '\r')); + charArray = source.toCharArray(); + source = new String(CharOperation.remove(charArray, '\r')); + assertTrue("Sources should be decoded the same way", encodedContents.equals(source)); + } + finally { + this.encodingProject.setDefaultCharset(oldEncoding, null); + deleteProject("Encoding2"); + getWorkspaceRoot().setDefaultCharset(wkspEncoding, null); + } + } private void verifyUtf8BOM(IFile file) throws CoreException { assertNull("File should not have any explicit charset", file.getCharset(false)); IContentDescription contentDescription = file.getContentDescription(); diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java index 685c1a3..e48d449 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java @@ -70,6 +70,14 @@ String INDEX_LOCATION_ATTRIBUTE_NAME = "index_location"; //$NON-NLS-1$ /** + * Constant for the name of the encoding to be used for source attachments. + * + *

The value of this attribute has to be a string representation of a valid encoding

+ * @since 3.8 + */ + String SOURCE_ATTACHMENT_ENCODING = "source_encoding"; //$NON-NLS-1$ + + /** * Constant for the name of the optional attribute. The possible values * for this attribute are "true" or "false". * When not present, "false" is assumed. diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java index 810a6b2..3b80fa7 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java @@ -1270,6 +1270,14 @@ } return false; } + public String getSourceAttachmentEncoding() { + for (int i = 0, length = this.extraAttributes.length; i < length; i++) { + IClasspathAttribute attribute = this.extraAttributes[i]; + if (IClasspathAttribute.SOURCE_ATTACHMENT_ENCODING.equals(attribute.getName())) + return attribute.getValue(); + } + return null; + } /** * Returns the kind of a PackageFragmentRoot from its String form. diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java index 9fb59c6..c1e54a0 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java @@ -154,11 +154,15 @@ return computeChildren(info, underlyingResource); } -SourceMapper createSourceMapper(IPath sourcePath, IPath rootPath) { +SourceMapper createSourceMapper(IPath sourcePath, IPath rootPath) throws JavaModelException { + IClasspathEntry entry = ((JavaProject) getParent()).getClasspathEntryFor(getPath()); + String encoding = (entry== null) ? null : ((ClasspathEntry) entry).getSourceAttachmentEncoding(); SourceMapper mapper = new SourceMapper( sourcePath, rootPath == null ? null : rootPath.toOSString(), - getJavaProject().getOptions(true)); // cannot use workspace options if external jar is 1.5 jar and workspace options are 1.4 options + getJavaProject().getOptions(true),// cannot use workspace options if external jar is 1.5 jar and workspace options are 1.4 options + encoding); + return mapper; } /* diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java index b2302d6..c1c3e86 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java @@ -250,6 +250,7 @@ *Options to be used */ String encoding; + String defaultEncoding; Map options; /** @@ -261,15 +262,19 @@ this.areRootPathsComputed = false; } + public SourceMapper(IPath sourcePath, String rootPath, Map options) { + this(sourcePath, rootPath, options, null); + } /** * Creates a SourceMapper that locates source in the zip file * at the given location in the specified package fragment root. */ - public SourceMapper(IPath sourcePath, String rootPath, Map options) { + public SourceMapper(IPath sourcePath, String rootPath, Map options, String encoding) { this.areRootPathsComputed = false; this.options = options; + this.encoding = encoding; try { - this.encoding = ResourcesPlugin.getWorkspace().getRoot().getDefaultCharset(); + this.defaultEncoding = ResourcesPlugin.getWorkspace().getRoot().getDefaultCharset(); } catch (CoreException e) { // use no encoding } @@ -1020,9 +1025,16 @@ IResource res = ((IContainer)target).findMember(fullName); if (res instanceof IFile) { try { - source = org.eclipse.jdt.internal.core.util.Util.getResourceContentsAsCharArray((IFile)res); + // Order of preference: charSet supplied, this.encoding or this.defaultEncoding in that order + try { + charSet = ((IFile) res).getCharset(this.encoding == null); + } catch (CoreException e) { + // Ignore + } + source = org.eclipse.jdt.internal.core.util.Util.getResourceContentsAsCharArray((IFile) res, + charSet == null ? (this.encoding == null ? this.defaultEncoding : this.encoding) : charSet); } catch (JavaModelException e) { - // ignore + // Ignore } } } else { @@ -1030,7 +1042,7 @@ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=303511 // For a resource inside the workspace, use the encoding set on the resource if (target instanceof IFile) - charSet = ((IFile)target).getCharset(); + charSet = ((IFile)target).getCharset(this.encoding == null); } catch (CoreException e) { // Ignore } @@ -1414,7 +1426,8 @@ try { byte[] bytes = Util.getZipEntryByteContent(entry, zip); if (bytes != null) { - return Util.bytesToChar(bytes, charSet == null ? this.encoding : charSet); + // Order of preference: charSet supplied, this.encoding or this.defaultEncoding in that order + return Util.bytesToChar(bytes, charSet == null ? (this.encoding == null ? this.defaultEncoding : this.encoding) : charSet); } } catch (IOException e) { // ignore