### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: model/org/eclipse/jdt/internal/core/SourceMapper.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java,v retrieving revision 1.150 diff -u -r1.150 SourceMapper.java --- model/org/eclipse/jdt/internal/core/SourceMapper.java 28 Jul 2010 16:17:01 -0000 1.150 +++ model/org/eclipse/jdt/internal/core/SourceMapper.java 21 Oct 2010 07:36:09 -0000 @@ -27,6 +27,7 @@ import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; @@ -868,12 +869,13 @@ char[] source = null; + IProject project = pkgFrag.getPackageFragmentRoot().getJavaProject().getProject(); JavaModelManager javaModelManager = JavaModelManager.getJavaModelManager(); try { javaModelManager.cacheZipFiles(this); // Cache any zip files we open during this operation if (this.rootPath != null) { - source = getSourceForRootPath(this.rootPath, name); + source = getSourceForRootPath(this.rootPath, name, project); } if (source == null) { @@ -882,7 +884,7 @@ loop: for (Iterator iterator = this.rootPaths.iterator(); iterator.hasNext(); ) { String currentRootPath = (String) iterator.next(); if (!currentRootPath.equals(this.rootPath)) { - source = getSourceForRootPath(currentRootPath, name); + source = getSourceForRootPath(currentRootPath, name, project); if (source != null) { // remember right root path this.rootPath = currentRootPath; @@ -901,7 +903,7 @@ return source; } - private char[] getSourceForRootPath(String currentRootPath, String name) { + private char[] getSourceForRootPath(String currentRootPath, String name, IProject project) { String newFullName; if (!currentRootPath.equals(IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH)) { if (currentRootPath.endsWith("/")) { //$NON-NLS-1$ @@ -912,22 +914,47 @@ } else { newFullName = name; } - return this.findSource(newFullName); + return this.findSource(newFullName, project); } - public char[] findSource(String fullName) { + public char[] findSource(String fullName, IProject project) { char[] source = null; Object target = JavaModel.getTarget(this.sourcePath, true); + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=303511 + // Use the character encoding set by the user than the default one + String charSet = null; if (target instanceof IContainer) { + // For external folders, get use the project's encoding + if (project != null && ExternalFoldersManager.isInternalPathForExternalFolder(((IContainer)target).getFullPath())) { + try { + charSet = project.getDefaultCharset(); + } catch (CoreException e) { + // Proceed with null encoding + } + } IResource res = ((IContainer)target).findMember(fullName); if (res instanceof IFile) { try { - source = org.eclipse.jdt.internal.core.util.Util.getResourceContentsAsCharArray((IFile)res); + if (charSet == null) + source = org.eclipse.jdt.internal.core.util.Util.getResourceContentsAsCharArray((IFile)res); + else + source = org.eclipse.jdt.internal.core.util.Util.getResourceContentsAsCharArray((IFile)res, charSet); } catch (JavaModelException e) { // ignore } } } else { + try { + // If the archive (IResource) is available from the workspace, use it's encoding + // Else take it from the project + if (target instanceof IFile) + charSet = ((IFile)target).getCharset(); + else if (project != null) + charSet = project.getDefaultCharset(); + } catch (CoreException e) { + // Ignore + } + // try to get the entry ZipEntry entry = null; ZipFile zip = null; @@ -937,7 +964,7 @@ entry = zip.getEntry(fullName); if (entry != null) { // now read the source code - source = readSource(entry, zip); + source = readSource(entry, zip, charSet); } } catch (CoreException e) { return null; @@ -948,7 +975,9 @@ return source; } - + public char[] findSource(String fullName) { + return findSource(fullName, null); + } /** * Returns the SourceRange for the name of the given element, or @@ -1275,11 +1304,11 @@ this.typeDepth = -1; } } - private char[] readSource(ZipEntry entry, ZipFile zip) { + private char[] readSource(ZipEntry entry, ZipFile zip, String charSet) { try { byte[] bytes = Util.getZipEntryByteContent(entry, zip); if (bytes != null) { - return Util.bytesToChar(bytes, this.encoding); + return Util.bytesToChar(bytes, charSet == null ? this.encoding : charSet); } } catch (IOException e) { // ignore #P org.eclipse.jdt.core.tests.model Index: src/org/eclipse/jdt/core/tests/model/EncodingTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/EncodingTests.java,v retrieving revision 1.53 diff -u -r1.53 EncodingTests.java --- src/org/eclipse/jdt/core/tests/model/EncodingTests.java 28 Apr 2009 17:46:10 -0000 1.53 +++ src/org/eclipse/jdt/core/tests/model/EncodingTests.java 21 Oct 2010 07:36:11 -0000 @@ -24,9 +24,11 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Path; 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.IClasspathEntry; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IOpenable; @@ -929,6 +931,113 @@ preferences.flush(); } } + + /** + * Bug 303511: Allow to specify encoding for source attachments + * Test whether the source mapper picks the right encoding for the source attachment as a ZIP in workspace. + * The encoding could be explicitly set or inherited from the project. + * + * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=303511" + */ + public void testBug303511() throws JavaModelException, CoreException { + + // Set file encoding + String encoding = "Shift-JIS"; + IFile zipFile = (IFile) this.encodingProject.findMember("testShiftJIS.zip"); //$NON-NLS-1$ + IFile sourceFile = (IFile) this.encodingProject.findMember("src/testShiftJIS/A.java"); + + assertNotNull("Cannot find class file!", zipFile); + zipFile.setCharset(encoding, null); + + // Get class file and compare source (should not be the same as modify charset on zip file has no effect...) + IPackageFragmentRoot root = getPackageFragmentRoot("Encoding", "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)); + assertTrue("Sources should be decoded the same way", encodedContents.equals(source)); + + // Reset zip file encoding + zipFile.setCharset(null, null); + String oldEncoding = this.encodingProject.getDefaultCharset(); + this.encodingProject.setDefaultCharset(encoding, null); + + root = getPackageFragmentRoot("Encoding", "testShiftJIS.jar"); + sourceRef = root.getPackageFragment("testShiftJIS").getClassFile("A.class"); + assertNotNull(sourceRef); + source = sourceRef.getSource(); + assertNotNull(source); + encodedContents = new String (Util.getResourceContentsAsCharArray(sourceFile, encoding)); + assertTrue("Sources should be decoded the same way", encodedContents.equals(source)); + + // Reset zip file encoding + zipFile.setCharset(null, null); + this.encodingProject.setDefaultCharset(oldEncoding, null); + } + + /** + * Bug 303511: Allow to specify encoding for source attachments + * Test whether the source mapper picks the right encoding for an external source attachment + * The attachment could be an external folder or external archive and have the encoding + * explicitly set or inherit from the project. + * + * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=303511" + */ + public void testBug303511a() throws JavaModelException, CoreException { + // Set file encoding + String encoding = "Shift-JIS"; + String oldEncoding = this.encodingProject.getDefaultCharset(); + String externalPath = this.encodingProject.getLocation().toOSString() + File.separator + "testShiftJIS.zip"; + IFile sourceFile = (IFile) this.encodingProject.findMember("src/testShiftJIS/A.java"); + + this.encodingProject.setDefaultCharset(encoding, null); + IClasspathEntry[] entries = this.encodingJavaProject.getRawClasspath(); + IClasspathEntry oldEntry = null; + for (int index = 0; index < entries.length; index++) { + IClasspathEntry entry = entries[index]; + if (entry.getPath().toOSString().endsWith("testShiftJIS.jar")) { + oldEntry = entry; + IClasspathEntry newEntry = JavaCore.newLibraryEntry(entry.getPath(), new Path(externalPath), null); + entries[index] = newEntry; + } + } + this.encodingJavaProject.setRawClasspath(entries, null); + this.encodingJavaProject.getResolvedClasspath(true); + + // Get class file and compare source (should not be the same as modify charset on zip file has no effect...) + IPackageFragmentRoot root = getPackageFragmentRoot("Encoding", "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)); + assertTrue("Sources should be decoded the same way", encodedContents.equals(source)); + + entries = this.encodingJavaProject.getRawClasspath(); + String sourcePath = this.encodingProject.getLocation().toOSString() + File.separator + "src"; + for (int index = 0; index < entries.length; index++) { + IClasspathEntry entry = entries[index]; + if (entry.getPath().toOSString().endsWith("testShiftJIS.jar")) { + IClasspathEntry newEntry = JavaCore.newLibraryEntry(entry.getPath(), new Path(sourcePath), null); + entries[index] = newEntry; + } + } + this.encodingJavaProject.setRawClasspath(entries, null); + this.encodingJavaProject.getResolvedClasspath(true); + + entries = this.encodingJavaProject.getRawClasspath(); + for (int index = 0; index < entries.length; index++) { + IClasspathEntry entry = entries[index]; + if (entry.getPath().toOSString().endsWith("testShiftJIS.jar")) { + entries[index] = oldEntry; + } + } + this.encodingJavaProject.setRawClasspath(entries, null); + this.encodingJavaProject.getResolvedClasspath(true); + refreshExternalArchives(this.encodingJavaProject); + this.encodingProject.setDefaultCharset(oldEncoding, null); + } private void verifyUtf8BOM(IFile file) throws CoreException { assertNull("File should not have any explicit charset", file.getCharset(false));