[jira] [Updated] (NET-499) FTP transfer to mainframe extremely slow
[ https://issues.apache.org/jira/browse/NET-499?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Sebb updated NET-499: - Description: FTPClient.storeFile() is incredibly slow. I have two example files, one FB (4MB) and one in ravel VB (94K) format. Under 3.1 both files transfer in less than a second (FB:328ms, VB:112ms). Under 3.2 the VB transfer takes 30,000ms, and the FB transfer takes too long to find out ( 15 minutes). I have checked the FB file on the mainframe after cancelling the transfer and it is always partly there. But the length varies, suggesting that it hasn't hit the same error each time. I have built two jar files, one with 3.1 and the other with 3.2. These jars are available. The code is as follows: {code} public class FTPTransfer { public static void transfer (String name, FTPClient ftp, File file) throws IOException { FileInputStream fis = new FileInputStream (file); long start = System.currentTimeMillis (); if (ftp.storeFile (name, fis)) System.out.print (File transferred); else System.out.print (Transfer failed); System.out.printf ( in %d ms%n, (System.currentTimeMillis () - start)); fis.close (); } public static void main (String[] args) { File file1 = null; File file2 = null; if (System.getProperty (os.name).toLowerCase ().startsWith (mac)) { file1 = new File (/Users/Denis/comtest/DENIS-018.SRC); // ravel file format file2 = new File (/Users/Denis/comtest/MOLONYD.NCD); // FB252 format } else { file1 = new File (D:/comtest/DENIS-018.SRC); // ravel file format file2 = new File (D:/comtest/MOLONYD.NCD); // FB252 format } FTPClient ftp = new FTPClient (); ftp.addProtocolCommandListener (new PrintCommandListener (new PrintWriter (System.out), true)); try { ftp.connect (server); int reply = ftp.getReplyCode (); if (!FTPReply.isPositiveCompletion (reply)) { ftp.disconnect (); System.err.println (FTP server refused connection.); System.exit (1); } ftp.login (user, pw); FTPFile[] files = ftp.listFiles (); System.out.printf (%nListing contains %d files%n%n, files.length); ftp.setFileType (FTP.BINARY_FILE_TYPE); ftp.setFileStructure (FTP.RECORD_STRUCTURE); transfer (TEST.VB, ftp, file1); ftp.setFileStructure (FTP.FILE_STRUCTURE); transfer (TEST.FB, ftp, file2); ftp.logout (); } catch (IOException e) { e.printStackTrace (); } finally { if (ftp.isConnected ()) { try { ftp.disconnect (); } catch (IOException ioe) { } } } } } {code} was: FTPClient.storeFile() is incredibly slow. I have two example files, one FB (4MB) and one in ravel VB (94K) format. Under 3.1 both files transfer in less than a second (FB:328ms, VB:112ms). Under 3.2 the VB transfer takes 30,000ms, and the FB transfer takes too long to find out ( 15 minutes). I have checked the FB file on the mainframe after cancelling the transfer and it is always partly there. But the length varies, suggesting that it hasn't hit the same error each time. I have built two jar files, one with 3.1 and the other with 3.2. These jars are available. The code is as follows: code public class FTPTransfer { public static void transfer (String name, FTPClient ftp, File file) throws IOException { FileInputStream fis = new FileInputStream (file); long start = System.currentTimeMillis (); if (ftp.storeFile (name, fis)) System.out.print (File transferred); else System.out.print (Transfer failed); System.out.printf ( in %d ms%n, (System.currentTimeMillis () - start)); fis.close (); } public static void main (String[] args) { File file1 = null; File file2 = null; if (System.getProperty (os.name).toLowerCase ().startsWith (mac)) { file1 = new File (/Users/Denis/comtest/DENIS-018.SRC); // ravel file format file2 = new File (/Users/Denis/comtest/MOLONYD.NCD); // FB252 format } else { file1 = new File (D:/comtest/DENIS-018.SRC); // ravel file format file2 = new File (D:/comtest/MOLONYD.NCD); // FB252 format } FTPClient ftp = new FTPClient (); ftp.addProtocolCommandListener (new PrintCommandListener (new PrintWriter (System.out), true)); try { ftp.connect (server); int reply = ftp.getReplyCode (); if (!FTPReply.isPositiveCompletion (reply)) { ftp.disconnect (); System.err.println (FTP server refused connection.); System.exit (1); } ftp.login (user, pw); FTPFile[] files = ftp.listFiles (); System.out.printf (%nListing contains %d files%n%n, files.length); ftp.setFileType (FTP.BINARY_FILE_TYPE);
[jira] [Commented] (NET-499) FTP transfer to mainframe extremely slow
[ https://issues.apache.org/jira/browse/NET-499?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13569488#comment-13569488 ] Denis Molony commented on NET-499: -- I tried this, but it didn't help. {code} FTPClient ftp = new FTPClient (); ftp.addProtocolCommandListener (new PrintCommandListener (new PrintWriter (System.out), true)); ftp.setBufferSize (0); {code} Is that what you meant? I'm happy to try a snapshot if you can point me to one. FTP transfer to mainframe extremely slow Key: NET-499 URL: https://issues.apache.org/jira/browse/NET-499 Project: Commons Net Issue Type: Bug Components: FTP Affects Versions: 3.2 Environment: Windows and OSX Reporter: Denis Molony FTPClient.storeFile() is incredibly slow. I have two example files, one FB (4MB) and one in ravel VB (94K) format. Under 3.1 both files transfer in less than a second (FB:328ms, VB:112ms). Under 3.2 the VB transfer takes 30,000ms, and the FB transfer takes too long to find out ( 15 minutes). I have checked the FB file on the mainframe after cancelling the transfer and it is always partly there. But the length varies, suggesting that it hasn't hit the same error each time. I have built two jar files, one with 3.1 and the other with 3.2. These jars are available. The code is as follows: {code} public class FTPTransfer { public static void transfer (String name, FTPClient ftp, File file) throws IOException { FileInputStream fis = new FileInputStream (file); long start = System.currentTimeMillis (); if (ftp.storeFile (name, fis)) System.out.print (File transferred); else System.out.print (Transfer failed); System.out.printf ( in %d ms%n, (System.currentTimeMillis () - start)); fis.close (); } public static void main (String[] args) { File file1 = null; File file2 = null; if (System.getProperty (os.name).toLowerCase ().startsWith (mac)) { file1 = new File (/Users/Denis/comtest/DENIS-018.SRC); // ravel file format file2 = new File (/Users/Denis/comtest/MOLONYD.NCD); // FB252 format } else { file1 = new File (D:/comtest/DENIS-018.SRC); // ravel file format file2 = new File (D:/comtest/MOLONYD.NCD); // FB252 format } FTPClient ftp = new FTPClient (); ftp.addProtocolCommandListener (new PrintCommandListener (new PrintWriter (System.out), true)); try { ftp.connect (server); int reply = ftp.getReplyCode (); if (!FTPReply.isPositiveCompletion (reply)) { ftp.disconnect (); System.err.println (FTP server refused connection.); System.exit (1); } ftp.login (user, pw); FTPFile[] files = ftp.listFiles (); System.out.printf (%nListing contains %d files%n%n, files.length); ftp.setFileType (FTP.BINARY_FILE_TYPE); ftp.setFileStructure (FTP.RECORD_STRUCTURE); transfer (TEST.VB, ftp, file1); ftp.setFileStructure (FTP.FILE_STRUCTURE); transfer (TEST.FB, ftp, file2); ftp.logout (); } catch (IOException e) { e.printStackTrace (); } finally { if (ftp.isConnected ()) { try { ftp.disconnect (); } catch (IOException ioe) { } } } } } {code} -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators For more information on JIRA, see: http://www.atlassian.com/software/jira
[jira] [Commented] (NET-499) FTP transfer to mainframe extremely slow
[ https://issues.apache.org/jira/browse/NET-499?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13569491#comment-13569491 ] Sebb commented on NET-499: -- I meant setSendBufferSize(int) setReceiveBufferSize(int) The ASF snapshot repo is at http://repository.apache.org/snapshots/ FTP transfer to mainframe extremely slow Key: NET-499 URL: https://issues.apache.org/jira/browse/NET-499 Project: Commons Net Issue Type: Bug Components: FTP Affects Versions: 3.2 Environment: Windows and OSX Reporter: Denis Molony FTPClient.storeFile() is incredibly slow. I have two example files, one FB (4MB) and one in ravel VB (94K) format. Under 3.1 both files transfer in less than a second (FB:328ms, VB:112ms). Under 3.2 the VB transfer takes 30,000ms, and the FB transfer takes too long to find out ( 15 minutes). I have checked the FB file on the mainframe after cancelling the transfer and it is always partly there. But the length varies, suggesting that it hasn't hit the same error each time. I have built two jar files, one with 3.1 and the other with 3.2. These jars are available. The code is as follows: {code} public class FTPTransfer { public static void transfer (String name, FTPClient ftp, File file) throws IOException { FileInputStream fis = new FileInputStream (file); long start = System.currentTimeMillis (); if (ftp.storeFile (name, fis)) System.out.print (File transferred); else System.out.print (Transfer failed); System.out.printf ( in %d ms%n, (System.currentTimeMillis () - start)); fis.close (); } public static void main (String[] args) { File file1 = null; File file2 = null; if (System.getProperty (os.name).toLowerCase ().startsWith (mac)) { file1 = new File (/Users/Denis/comtest/DENIS-018.SRC); // ravel file format file2 = new File (/Users/Denis/comtest/MOLONYD.NCD); // FB252 format } else { file1 = new File (D:/comtest/DENIS-018.SRC); // ravel file format file2 = new File (D:/comtest/MOLONYD.NCD); // FB252 format } FTPClient ftp = new FTPClient (); ftp.addProtocolCommandListener (new PrintCommandListener (new PrintWriter (System.out), true)); try { ftp.connect (server); int reply = ftp.getReplyCode (); if (!FTPReply.isPositiveCompletion (reply)) { ftp.disconnect (); System.err.println (FTP server refused connection.); System.exit (1); } ftp.login (user, pw); FTPFile[] files = ftp.listFiles (); System.out.printf (%nListing contains %d files%n%n, files.length); ftp.setFileType (FTP.BINARY_FILE_TYPE); ftp.setFileStructure (FTP.RECORD_STRUCTURE); transfer (TEST.VB, ftp, file1); ftp.setFileStructure (FTP.FILE_STRUCTURE); transfer (TEST.FB, ftp, file2); ftp.logout (); } catch (IOException e) { e.printStackTrace (); } finally { if (ftp.isConnected ()) { try { ftp.disconnect (); } catch (IOException ioe) { } } } } } {code} -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators For more information on JIRA, see: http://www.atlassian.com/software/jira
[jira] [Commented] (NET-499) FTP transfer to mainframe extremely slow
[ https://issues.apache.org/jira/browse/NET-499?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13569495#comment-13569495 ] Denis Molony commented on NET-499: -- I tried those two calls, but I get an IllegalArgumentException - invalid receive size. But the 30/1 snapshot works fine, thanks. FTP transfer to mainframe extremely slow Key: NET-499 URL: https://issues.apache.org/jira/browse/NET-499 Project: Commons Net Issue Type: Bug Components: FTP Affects Versions: 3.2 Environment: Windows and OSX Reporter: Denis Molony FTPClient.storeFile() is incredibly slow. I have two example files, one FB (4MB) and one in ravel VB (94K) format. Under 3.1 both files transfer in less than a second (FB:328ms, VB:112ms). Under 3.2 the VB transfer takes 30,000ms, and the FB transfer takes too long to find out ( 15 minutes). I have checked the FB file on the mainframe after cancelling the transfer and it is always partly there. But the length varies, suggesting that it hasn't hit the same error each time. I have built two jar files, one with 3.1 and the other with 3.2. These jars are available. The code is as follows: {code} public class FTPTransfer { public static void transfer (String name, FTPClient ftp, File file) throws IOException { FileInputStream fis = new FileInputStream (file); long start = System.currentTimeMillis (); if (ftp.storeFile (name, fis)) System.out.print (File transferred); else System.out.print (Transfer failed); System.out.printf ( in %d ms%n, (System.currentTimeMillis () - start)); fis.close (); } public static void main (String[] args) { File file1 = null; File file2 = null; if (System.getProperty (os.name).toLowerCase ().startsWith (mac)) { file1 = new File (/Users/Denis/comtest/DENIS-018.SRC); // ravel file format file2 = new File (/Users/Denis/comtest/MOLONYD.NCD); // FB252 format } else { file1 = new File (D:/comtest/DENIS-018.SRC); // ravel file format file2 = new File (D:/comtest/MOLONYD.NCD); // FB252 format } FTPClient ftp = new FTPClient (); ftp.addProtocolCommandListener (new PrintCommandListener (new PrintWriter (System.out), true)); try { ftp.connect (server); int reply = ftp.getReplyCode (); if (!FTPReply.isPositiveCompletion (reply)) { ftp.disconnect (); System.err.println (FTP server refused connection.); System.exit (1); } ftp.login (user, pw); FTPFile[] files = ftp.listFiles (); System.out.printf (%nListing contains %d files%n%n, files.length); ftp.setFileType (FTP.BINARY_FILE_TYPE); ftp.setFileStructure (FTP.RECORD_STRUCTURE); transfer (TEST.VB, ftp, file1); ftp.setFileStructure (FTP.FILE_STRUCTURE); transfer (TEST.FB, ftp, file2); ftp.logout (); } catch (IOException e) { e.printStackTrace (); } finally { if (ftp.isConnected ()) { try { ftp.disconnect (); } catch (IOException ioe) { } } } } } {code} -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators For more information on JIRA, see: http://www.atlassian.com/software/jira
[jira] [Commented] (NET-499) FTP transfer to mainframe extremely slow
[ https://issues.apache.org/jira/browse/NET-499?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13569497#comment-13569497 ] Sebb commented on NET-499: -- Just curious - what sizes did you use? FTP transfer to mainframe extremely slow Key: NET-499 URL: https://issues.apache.org/jira/browse/NET-499 Project: Commons Net Issue Type: Bug Components: FTP Affects Versions: 3.2 Environment: Windows and OSX Reporter: Denis Molony FTPClient.storeFile() is incredibly slow. I have two example files, one FB (4MB) and one in ravel VB (94K) format. Under 3.1 both files transfer in less than a second (FB:328ms, VB:112ms). Under 3.2 the VB transfer takes 30,000ms, and the FB transfer takes too long to find out ( 15 minutes). I have checked the FB file on the mainframe after cancelling the transfer and it is always partly there. But the length varies, suggesting that it hasn't hit the same error each time. I have built two jar files, one with 3.1 and the other with 3.2. These jars are available. The code is as follows: {code} public class FTPTransfer { public static void transfer (String name, FTPClient ftp, File file) throws IOException { FileInputStream fis = new FileInputStream (file); long start = System.currentTimeMillis (); if (ftp.storeFile (name, fis)) System.out.print (File transferred); else System.out.print (Transfer failed); System.out.printf ( in %d ms%n, (System.currentTimeMillis () - start)); fis.close (); } public static void main (String[] args) { File file1 = null; File file2 = null; if (System.getProperty (os.name).toLowerCase ().startsWith (mac)) { file1 = new File (/Users/Denis/comtest/DENIS-018.SRC); // ravel file format file2 = new File (/Users/Denis/comtest/MOLONYD.NCD); // FB252 format } else { file1 = new File (D:/comtest/DENIS-018.SRC); // ravel file format file2 = new File (D:/comtest/MOLONYD.NCD); // FB252 format } FTPClient ftp = new FTPClient (); ftp.addProtocolCommandListener (new PrintCommandListener (new PrintWriter (System.out), true)); try { ftp.connect (server); int reply = ftp.getReplyCode (); if (!FTPReply.isPositiveCompletion (reply)) { ftp.disconnect (); System.err.println (FTP server refused connection.); System.exit (1); } ftp.login (user, pw); FTPFile[] files = ftp.listFiles (); System.out.printf (%nListing contains %d files%n%n, files.length); ftp.setFileType (FTP.BINARY_FILE_TYPE); ftp.setFileStructure (FTP.RECORD_STRUCTURE); transfer (TEST.VB, ftp, file1); ftp.setFileStructure (FTP.FILE_STRUCTURE); transfer (TEST.FB, ftp, file2); ftp.logout (); } catch (IOException e) { e.printStackTrace (); } finally { if (ftp.isConnected ()) { try { ftp.disconnect (); } catch (IOException ioe) { } } } } } {code} -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators For more information on JIRA, see: http://www.atlassian.com/software/jira
[jira] [Commented] (NET-499) FTP transfer to mainframe extremely slow
[ https://issues.apache.org/jira/browse/NET-499?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13569507#comment-13569507 ] Denis Molony commented on NET-499: -- Zero. Isn't that what you asked me to do? FTP transfer to mainframe extremely slow Key: NET-499 URL: https://issues.apache.org/jira/browse/NET-499 Project: Commons Net Issue Type: Bug Components: FTP Affects Versions: 3.2 Environment: Windows and OSX Reporter: Denis Molony FTPClient.storeFile() is incredibly slow. I have two example files, one FB (4MB) and one in ravel VB (94K) format. Under 3.1 both files transfer in less than a second (FB:328ms, VB:112ms). Under 3.2 the VB transfer takes 30,000ms, and the FB transfer takes too long to find out ( 15 minutes). I have checked the FB file on the mainframe after cancelling the transfer and it is always partly there. But the length varies, suggesting that it hasn't hit the same error each time. I have built two jar files, one with 3.1 and the other with 3.2. These jars are available. The code is as follows: {code} public class FTPTransfer { public static void transfer (String name, FTPClient ftp, File file) throws IOException { FileInputStream fis = new FileInputStream (file); long start = System.currentTimeMillis (); if (ftp.storeFile (name, fis)) System.out.print (File transferred); else System.out.print (Transfer failed); System.out.printf ( in %d ms%n, (System.currentTimeMillis () - start)); fis.close (); } public static void main (String[] args) { File file1 = null; File file2 = null; if (System.getProperty (os.name).toLowerCase ().startsWith (mac)) { file1 = new File (/Users/Denis/comtest/DENIS-018.SRC); // ravel file format file2 = new File (/Users/Denis/comtest/MOLONYD.NCD); // FB252 format } else { file1 = new File (D:/comtest/DENIS-018.SRC); // ravel file format file2 = new File (D:/comtest/MOLONYD.NCD); // FB252 format } FTPClient ftp = new FTPClient (); ftp.addProtocolCommandListener (new PrintCommandListener (new PrintWriter (System.out), true)); try { ftp.connect (server); int reply = ftp.getReplyCode (); if (!FTPReply.isPositiveCompletion (reply)) { ftp.disconnect (); System.err.println (FTP server refused connection.); System.exit (1); } ftp.login (user, pw); FTPFile[] files = ftp.listFiles (); System.out.printf (%nListing contains %d files%n%n, files.length); ftp.setFileType (FTP.BINARY_FILE_TYPE); ftp.setFileStructure (FTP.RECORD_STRUCTURE); transfer (TEST.VB, ftp, file1); ftp.setFileStructure (FTP.FILE_STRUCTURE); transfer (TEST.FB, ftp, file2); ftp.logout (); } catch (IOException e) { e.printStackTrace (); } finally { if (ftp.isConnected ()) { try { ftp.disconnect (); } catch (IOException ioe) { } } } } } {code} -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators For more information on JIRA, see: http://www.atlassian.com/software/jira
[jira] [Commented] (NET-499) FTP transfer to mainframe extremely slow
[ https://issues.apache.org/jira/browse/NET-499?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13569510#comment-13569510 ] Sebb commented on NET-499: -- Yes. But that was wrong, sorry. setSendBufferSize(int) and setReceiveBufferSize(int) aren't the problem in 3.2. The problem was that ftp.setBufferSize() was overriding the socket buffer sizes if 0. The fix was supposed to be as you originally had it, i.e. ftp.setBufferSize(0); I don't understand why that did not fix it for you. Anyway, glad the snapshot works. FTP transfer to mainframe extremely slow Key: NET-499 URL: https://issues.apache.org/jira/browse/NET-499 Project: Commons Net Issue Type: Bug Components: FTP Affects Versions: 3.2 Environment: Windows and OSX Reporter: Denis Molony FTPClient.storeFile() is incredibly slow. I have two example files, one FB (4MB) and one in ravel VB (94K) format. Under 3.1 both files transfer in less than a second (FB:328ms, VB:112ms). Under 3.2 the VB transfer takes 30,000ms, and the FB transfer takes too long to find out ( 15 minutes). I have checked the FB file on the mainframe after cancelling the transfer and it is always partly there. But the length varies, suggesting that it hasn't hit the same error each time. I have built two jar files, one with 3.1 and the other with 3.2. These jars are available. The code is as follows: {code} public class FTPTransfer { public static void transfer (String name, FTPClient ftp, File file) throws IOException { FileInputStream fis = new FileInputStream (file); long start = System.currentTimeMillis (); if (ftp.storeFile (name, fis)) System.out.print (File transferred); else System.out.print (Transfer failed); System.out.printf ( in %d ms%n, (System.currentTimeMillis () - start)); fis.close (); } public static void main (String[] args) { File file1 = null; File file2 = null; if (System.getProperty (os.name).toLowerCase ().startsWith (mac)) { file1 = new File (/Users/Denis/comtest/DENIS-018.SRC); // ravel file format file2 = new File (/Users/Denis/comtest/MOLONYD.NCD); // FB252 format } else { file1 = new File (D:/comtest/DENIS-018.SRC); // ravel file format file2 = new File (D:/comtest/MOLONYD.NCD); // FB252 format } FTPClient ftp = new FTPClient (); ftp.addProtocolCommandListener (new PrintCommandListener (new PrintWriter (System.out), true)); try { ftp.connect (server); int reply = ftp.getReplyCode (); if (!FTPReply.isPositiveCompletion (reply)) { ftp.disconnect (); System.err.println (FTP server refused connection.); System.exit (1); } ftp.login (user, pw); FTPFile[] files = ftp.listFiles (); System.out.printf (%nListing contains %d files%n%n, files.length); ftp.setFileType (FTP.BINARY_FILE_TYPE); ftp.setFileStructure (FTP.RECORD_STRUCTURE); transfer (TEST.VB, ftp, file1); ftp.setFileStructure (FTP.FILE_STRUCTURE); transfer (TEST.FB, ftp, file2); ftp.logout (); } catch (IOException e) { e.printStackTrace (); } finally { if (ftp.isConnected ()) { try { ftp.disconnect (); } catch (IOException ioe) { } } } } } {code} -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators For more information on JIRA, see: http://www.atlassian.com/software/jira
[jira] [Commented] (COLLECTIONS-310) Modifications of a SetUniqueList.subList() invalidate the parent list
[ https://issues.apache.org/jira/browse/COLLECTIONS-310?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13569532#comment-13569532 ] Thomas Vahrst commented on COLLECTIONS-310: --- I took a deeper look on this issue and the suggested behavior/junit tests and tried to understand the problem(s). It seems, there a two issues with the current implementation regarding modifications of sublists: # Modifications of sublist items are delegated to the underlying backing list (which is the default sublist implementation) but *not* to the internal set of the parent SetUniqueList. So a new entry is added to the list, but the contains() method of the parent SetUniqueList returns false # Modifications of the sublist may result in changes outside the range of the sublist. For example adding an element which is not in the sublist but somewhere in the backing list should result in *moving* the item from its current position to the new position defined by the subset. This move may corrupt the internal range offsets of the sublist. To solve Modifications of a SetUniqueList.subList() invalidate the parent list - Key: COLLECTIONS-310 URL: https://issues.apache.org/jira/browse/COLLECTIONS-310 Project: Commons Collections Issue Type: Bug Components: List Affects Versions: 3.2, Nightly Builds Reporter: Christian Semrau Priority: Minor Fix For: 4.0 The List returned by SetUniqueList.subList() is again a SetUniqueList. The contract for List.subList() says that the returned list supports all the operations of the parent list, and it is backed by the parent list. We have a SetUniqueList uniqueList equal to {Hello, World}. We get a subList containing the last element. Now we add the element Hello, contained in the uniqueList but not in the subList, to the subList. What should happen? Should the subList behave like a SetUniqueList and add the element - meaning that it changes position in the uniqueList because at the old place it gets removed, so now uniqueList equals {World, Hello} (which fails)? Or should the element not be added, because it is already contained in the parent list, thereby violating the SetUniqueList-ness of the subList (which fails)? I prefer the former behaviour, because modifications should only be made through the subList and not through the parent list (as explained in List.subList()). What should happen if we replace (using set) the subList element World with Hello instead of adding an element? The subList should contain only Hello, and for the parent list, the old element 0 (now a duplicate of the just set element 1) should be removed (which fails). And of course the parent list should know what happens to it (specifically, its uniqueness Set) (which fails in the current snapshot). public void testSubListAddNew() { List uniqueList = SetUniqueList.decorate(new ArrayList()); uniqueList.add(Hello); uniqueList.add(World); List subList = uniqueList.subList(1, 2); subList.add(Goodbye); List expectedSubList = Arrays.asList(new Object[] { World, Goodbye }); List expectedParentList = Arrays.asList(new Object[] { Hello, World, Goodbye }); assertEquals(expectedSubList, subList); assertEquals(expectedParentList, uniqueList); assertTrue(uniqueList.contains(Goodbye)); // fails } public void testSubListAddDuplicate() { List uniqueList = SetUniqueList.decorate(new ArrayList()); uniqueList.add(Hello); uniqueList.add(World); List subList = uniqueList.subList(1, 2); subList.add(Hello); List expectedSubList = Arrays.asList(new Object[] { World, Hello }); List expectedParentList = Arrays.asList(new Object[] { World, Hello }); assertEquals(expectedSubList, subList); assertEquals(expectedParentList, uniqueList); // fails } public void testSubListSetDuplicate() { List uniqueList = SetUniqueList.decorate(new ArrayList()); uniqueList.add(Hello); uniqueList.add(World); List subList = uniqueList.subList(1, 2); subList.set(0, Hello); List expectedSubList = Arrays.asList(new Object[] { Hello }); List expectedParentList = Arrays.asList(new Object[] { Hello }); assertEquals(expectedSubList, subList); assertEquals(expectedParentList, uniqueList); // fails } -- This message is automatically generated by JIRA. If you think it was sent incorrectly,
[jira] [Comment Edited] (COLLECTIONS-310) Modifications of a SetUniqueList.subList() invalidate the parent list
[ https://issues.apache.org/jira/browse/COLLECTIONS-310?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13569532#comment-13569532 ] Thomas Vahrst edited comment on COLLECTIONS-310 at 2/2/13 1:01 PM: --- I took a deeper look on this issue and the suggested behavior/junit tests and tried to understand the problem(s). It seems, there a two issues with the current implementation regarding modifications of sublists: # Modifications of sublist items are delegated to the underlying backing list (which is the default sublist implementation) but *not* to the internal set of the parent SetUniqueList. So a new entry is added to the list, but the contains() method of the parent SetUniqueList returns false # Modifications of the sublist may result in changes outside the range of the sublist. For example adding an element which is not in the sublist but somewhere in the backing list should result in *moving* the item from its current position to the new position defined by the subset. This move may corrupt the internal range offsets of the sublist. The first issue seems easy to solve, for example by holding a reference of the parent set in the subset. But if another subset is created based on the first subset, we have to maintain a collections of parent sets. The second issue is similar to a direct modification of a backing list - which is not supported. The javadoc of sublist states {quote} The semantics of the list returned by this method become undefined if the backing list (i.e., this list) is structurally modified in any way other than via the returned list. (Structural modifications are those that change the size of this list, or otherwise perturb it in such a fashion that iterations in progress may yield incorrect results.) {quote} To solve this problem, the subList implementation has to track all modifications of the backing list and adjust it's internal range offsets accordingly. For example adding a duplicate item to a sublist, which exists 'in front' of the sublist will result - moving the item to the new sublist position - decrement the range offsets of the sublist. So first of all I wrote a short javadoc comment for the sublist method: {code} /** * Returns a view of the portion of this list between the specified * fromIndex, inclusive, and toIndex, exclusive. * p * i(Violation)/i According to the codeList/code interface the returned * sublist has to be backed by the original list. Because a codeSetUniqueList/code * requires both a defined ordering of the list items iand/i uniqueness of * all list items, modifications cannot garantee consistant behavior of both * the backing list and the sub list. It is strongly recommended not to modify * the sublist. * p * * @param fromIndex * @param toIndex * @return */ {code} Should we perhaps return the sublist as a UnmodifiableList? was (Author: t.vahrst): I took a deeper look on this issue and the suggested behavior/junit tests and tried to understand the problem(s). It seems, there a two issues with the current implementation regarding modifications of sublists: # Modifications of sublist items are delegated to the underlying backing list (which is the default sublist implementation) but *not* to the internal set of the parent SetUniqueList. So a new entry is added to the list, but the contains() method of the parent SetUniqueList returns false # Modifications of the sublist may result in changes outside the range of the sublist. For example adding an element which is not in the sublist but somewhere in the backing list should result in *moving* the item from its current position to the new position defined by the subset. This move may corrupt the internal range offsets of the sublist. To solve Modifications of a SetUniqueList.subList() invalidate the parent list - Key: COLLECTIONS-310 URL: https://issues.apache.org/jira/browse/COLLECTIONS-310 Project: Commons Collections Issue Type: Bug Components: List Affects Versions: 3.2, Nightly Builds Reporter: Christian Semrau Priority: Minor Fix For: 4.0 The List returned by SetUniqueList.subList() is again a SetUniqueList. The contract for List.subList() says that the returned list supports all the operations of the parent list, and it is backed by the parent list. We have a SetUniqueList uniqueList equal to {Hello, World}. We get a subList containing the last element. Now we add the element Hello, contained in the uniqueList but not in the subList, to the subList. What should happen? Should the subList behave like a SetUniqueList and add the
[jira] [Comment Edited] (COLLECTIONS-310) Modifications of a SetUniqueList.subList() invalidate the parent list
[ https://issues.apache.org/jira/browse/COLLECTIONS-310?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13569532#comment-13569532 ] Thomas Vahrst edited comment on COLLECTIONS-310 at 2/2/13 1:02 PM: --- I took a deeper look on this issue and the suggested behavior/junit tests and tried to understand the problem(s). It seems, there a two issues with the current implementation regarding modifications of sublists: # Modifications of sublist items are delegated to the underlying backing list (which is the default sublist implementation) but *not* to the internal set of the parent SetUniqueList. So a new entry is added to the list, but the contains() method of the parent SetUniqueList returns false # Modifications of the sublist may result in changes *outside* the range of the sublist. For example adding an element which is not in the sublist but somewhere in the backing list should result in *moving* the item from its current position to the new position defined by the subset. This move may corrupt the internal range offsets of the sublist. The first issue seems easy to solve, for example by holding a reference of the parent set in the subset. But if another subset is created based on the first subset, we have to maintain a collections of parent sets. The second issue is similar to a direct modification of a backing list - which is not supported. The javadoc of sublist states {quote} The semantics of the list returned by this method become undefined if the backing list (i.e., this list) is structurally modified in any way other than via the returned list. (Structural modifications are those that change the size of this list, or otherwise perturb it in such a fashion that iterations in progress may yield incorrect results.) {quote} To solve this problem, the subList implementation has to track all modifications of the backing list and adjust it's internal range offsets accordingly. For example adding a duplicate item to a sublist, which exists 'in front' of the sublist will result - moving the item to the new sublist position - decrement the range offsets of the sublist. So first of all I wrote a short javadoc comment for the sublist method: {code} /** * Returns a view of the portion of this list between the specified * fromIndex, inclusive, and toIndex, exclusive. * p * i(Violation)/i According to the codeList/code interface the returned * sublist has to be backed by the original list. Because a codeSetUniqueList/code * requires both a defined ordering of the list items iand/i uniqueness of * all list items, modifications cannot garantee consistant behavior of both * the backing list and the sub list. It is strongly recommended not to modify * the sublist. * p * * @param fromIndex * @param toIndex * @return */ {code} Should we perhaps return the sublist as a UnmodifiableList? was (Author: t.vahrst): I took a deeper look on this issue and the suggested behavior/junit tests and tried to understand the problem(s). It seems, there a two issues with the current implementation regarding modifications of sublists: # Modifications of sublist items are delegated to the underlying backing list (which is the default sublist implementation) but *not* to the internal set of the parent SetUniqueList. So a new entry is added to the list, but the contains() method of the parent SetUniqueList returns false # Modifications of the sublist may result in changes outside the range of the sublist. For example adding an element which is not in the sublist but somewhere in the backing list should result in *moving* the item from its current position to the new position defined by the subset. This move may corrupt the internal range offsets of the sublist. The first issue seems easy to solve, for example by holding a reference of the parent set in the subset. But if another subset is created based on the first subset, we have to maintain a collections of parent sets. The second issue is similar to a direct modification of a backing list - which is not supported. The javadoc of sublist states {quote} The semantics of the list returned by this method become undefined if the backing list (i.e., this list) is structurally modified in any way other than via the returned list. (Structural modifications are those that change the size of this list, or otherwise perturb it in such a fashion that iterations in progress may yield incorrect results.) {quote} To solve this problem, the subList implementation has to track all modifications of the backing list and adjust it's internal range offsets accordingly. For example adding a duplicate item to a sublist, which exists 'in front' of the sublist will result - moving the item to the new sublist position - decrement
[jira] [Commented] (SANDBOX-419) [BeanUtils2] Implement setIndexed(String propertyName) on DefaultBeanAccessor
[ https://issues.apache.org/jira/browse/SANDBOX-419?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13569588#comment-13569588 ] Benedikt Ritter commented on SANDBOX-419: - Assigning this one to me, as I'm now able to commit changes myself ;) [BeanUtils2] Implement setIndexed(String propertyName) on DefaultBeanAccessor - Key: SANDBOX-419 URL: https://issues.apache.org/jira/browse/SANDBOX-419 Project: Commons Sandbox Issue Type: Improvement Components: BeanUtils2 Affects Versions: Nightly Builds Reporter: Benedikt Ritter Assignee: Benedikt Ritter Attachments: SANDBOX-419.patch Implement {{DefaultBeanAccessor.setIndexed(String propertyName)}} -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators For more information on JIRA, see: http://www.atlassian.com/software/jira
[jira] [Resolved] (SANDBOX-419) [BeanUtils2] Implement setIndexed(String propertyName) on DefaultBeanAccessor
[ https://issues.apache.org/jira/browse/SANDBOX-419?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Benedikt Ritter resolved SANDBOX-419. - Resolution: Fixed Assignee: Simone Tripodi (was: Benedikt Ritter) Patch has already been committed to trunk a long while ago. Closing this one an reassigning it to Simo. [BeanUtils2] Implement setIndexed(String propertyName) on DefaultBeanAccessor - Key: SANDBOX-419 URL: https://issues.apache.org/jira/browse/SANDBOX-419 Project: Commons Sandbox Issue Type: Improvement Components: BeanUtils2 Affects Versions: Nightly Builds Reporter: Benedikt Ritter Assignee: Simone Tripodi Attachments: SANDBOX-419.patch Implement {{DefaultBeanAccessor.setIndexed(String propertyName)}} -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators For more information on JIRA, see: http://www.atlassian.com/software/jira
[jira] [Resolved] (SANDBOX-433) [BeanUtils2] Setting properties or calling methods very often results in a NullPointerException
[ https://issues.apache.org/jira/browse/SANDBOX-433?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Benedikt Ritter resolved SANDBOX-433. - Resolution: Fixed Assignee: Benedikt Ritter Patch applied in r1441774 [BeanUtils2] Setting properties or calling methods very often results in a NullPointerException --- Key: SANDBOX-433 URL: https://issues.apache.org/jira/browse/SANDBOX-433 Project: Commons Sandbox Issue Type: Bug Components: BeanUtils2 Reporter: Benedikt Ritter Assignee: Benedikt Ritter Attachments: SANDBOX-433.patch, SANDBOX-433-TestCase.patch If a property get accessed too often, a NullPointerException will be thrown. The same is true for calling methods several times. In my configuration I'm seeing a NPE after about 27.000 calls. Calling constructors very often does seem to work. -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators For more information on JIRA, see: http://www.atlassian.com/software/jira
[jira] [Resolved] (SANDBOX-436) [BeanUtils2] Implement BeanAccessor.getMapped
[ https://issues.apache.org/jira/browse/SANDBOX-436?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Benedikt Ritter resolved SANDBOX-436. - Resolution: Fixed Assignee: Benedikt Ritter Patch applied in r1441781 [BeanUtils2] Implement BeanAccessor.getMapped - Key: SANDBOX-436 URL: https://issues.apache.org/jira/browse/SANDBOX-436 Project: Commons Sandbox Issue Type: Improvement Components: BeanUtils2 Affects Versions: Nightly Builds Reporter: Benedikt Ritter Assignee: Benedikt Ritter Attachments: SANDBOX-436.patch The method getMapped() has to be implemented on DefaultBeanAccessor. -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators For more information on JIRA, see: http://www.atlassian.com/software/jira
[jira] [Updated] (CONFIGURATION-524) AbstractConfiguration does not interpolate correctly after cloning
[ https://issues.apache.org/jira/browse/CONFIGURATION-524?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Oliver Heger updated CONFIGURATION-524: --- Description: If you clone a Configuration, does not clone the StrSubstitutor when it has been instanced, so the cloned copy has the same StrSubstituor than the original composite. If you change a property in the original compoiste it is changed in the cloned copy. Way to reproduce it : {code} public class SampleConfiguration { public static void main(final String[] args) { final String sentence = SELECT * FORM TABLE WHERE YEAR=${year} and QUARTER=${quarter}; final CompositeConfiguration cp = new CompositeConfiguration(); cp.addProperty(year, 2000); cp.addProperty(quarter, 2); final AbstractConfiguration clonedConfig = (AbstractConfiguration) ConfigurationUtils.cloneConfiguration(cp); cp.setProperty(year, 2001); clonedConfig.setProperty(year, 2002); System.out.println(Original sentence + PropertyConverter.interpolate(sentence, cp)); System.out.println(Cloned sentence + PropertyConverter.interpolate(sentence, clonedConfig)); final AbstractConfiguration clonedConfig2 = (AbstractConfiguration) ConfigurationUtils.cloneConfiguration(cp); cp.setProperty(year, 2003); clonedConfig2.setProperty(year, 2004); System.out.println(Original sentence + PropertyConverter.interpolate(sentence, cp)); System.out.println(Cloned (after interpolate with same strSubstitutor )sentence + PropertyConverter.interpolate(sentence, clonedConfig2)); } } {code} The solution can be to make in the following ways: Make the clone of the strSubstitutor in the AbstractConfigutration class. Create a clone method inside the StrSubtitutor and invoke it from the AbstractConfiguration class. Set null the strSubstituror when the clone method is invoked in the Abstract Configuration class. The next invocation to interpolate methos instances the strSubstitutor. was: If you clone a Configuration, does not clone the StrSubstitutor when it has been instanced, so the cloned copy has the same StrSubstituor than the original composite. If you change a property in the original compoiste it is changed in the cloned copy. Way to reproduce it : public class SampleConfiguration { public static void main(final String[] args) { final String sentence = SELECT * FORM TABLE WHERE YEAR=${year} and QUARTER=${quarter}; final CompositeConfiguration cp = new CompositeConfiguration(); cp.addProperty(year, 2000); cp.addProperty(quarter, 2); final AbstractConfiguration clonedConfig = (AbstractConfiguration) ConfigurationUtils.cloneConfiguration(cp); cp.setProperty(year, 2001); clonedConfig.setProperty(year, 2002); System.out.println(Original sentence + PropertyConverter.interpolate(sentence, cp)); System.out.println(Cloned sentence + PropertyConverter.interpolate(sentence, clonedConfig)); final AbstractConfiguration clonedConfig2 = (AbstractConfiguration) ConfigurationUtils.cloneConfiguration(cp); cp.setProperty(year, 2003); clonedConfig2.setProperty(year, 2004); System.out.println(Original sentence + PropertyConverter.interpolate(sentence, cp)); System.out.println(Cloned (after interpolate with same strSubstitutor )sentence + PropertyConverter.interpolate(sentence, clonedConfig2)); } } The solution can be to make in the following ways: Make the clone of the strSubstitutor in the AbstractConfigutration class. Create a clone method inside the StrSubtitutor and invoke it from the AbstractConfiguration class. Set null the strSubstituror when the clone method is invoked in the Abstract Configuration class. The next invocation to interpolate methos instances the strSubstitutor. Summary: AbstractConfiguration does not interpolate correctly after cloning (was: AbstractConfiguration does not clone correctly after interpolation) AbstractConfiguration does not interpolate correctly after cloning -- Key: CONFIGURATION-524 URL: https://issues.apache.org/jira/browse/CONFIGURATION-524 Project: Commons Configuration Issue Type: Bug Components: Build Reporter: Juan Diego Gago Perez Original Estimate: 24h Remaining Estimate: 24h If you clone a Configuration, does not clone the StrSubstitutor when it has been instanced, so the cloned copy has the same StrSubstituor than the original composite. If you change a property in the original compoiste it is changed in the cloned copy. Way to reproduce it : {code} public class SampleConfiguration { public static void main(final
[jira] [Commented] (CONFIGURATION-524) AbstractConfiguration does not interpolate correctly after cloning
[ https://issues.apache.org/jira/browse/CONFIGURATION-524?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13569612#comment-13569612 ] Oliver Heger commented on CONFIGURATION-524: Thank you for the report. There have been some changes recently in the current development version in the field of interpolation. However, I am pretty sure that the problem still exists. AbstractConfiguration does not interpolate correctly after cloning -- Key: CONFIGURATION-524 URL: https://issues.apache.org/jira/browse/CONFIGURATION-524 Project: Commons Configuration Issue Type: Bug Components: Build Reporter: Juan Diego Gago Perez Original Estimate: 24h Remaining Estimate: 24h If you clone a Configuration, does not clone the StrSubstitutor when it has been instanced, so the cloned copy has the same StrSubstituor than the original composite. If you change a property in the original compoiste it is changed in the cloned copy. Way to reproduce it : {code} public class SampleConfiguration { public static void main(final String[] args) { final String sentence = SELECT * FORM TABLE WHERE YEAR=${year} and QUARTER=${quarter}; final CompositeConfiguration cp = new CompositeConfiguration(); cp.addProperty(year, 2000); cp.addProperty(quarter, 2); final AbstractConfiguration clonedConfig = (AbstractConfiguration) ConfigurationUtils.cloneConfiguration(cp); cp.setProperty(year, 2001); clonedConfig.setProperty(year, 2002); System.out.println(Original sentence + PropertyConverter.interpolate(sentence, cp)); System.out.println(Cloned sentence + PropertyConverter.interpolate(sentence, clonedConfig)); final AbstractConfiguration clonedConfig2 = (AbstractConfiguration) ConfigurationUtils.cloneConfiguration(cp); cp.setProperty(year, 2003); clonedConfig2.setProperty(year, 2004); System.out.println(Original sentence + PropertyConverter.interpolate(sentence, cp)); System.out.println(Cloned (after interpolate with same strSubstitutor )sentence + PropertyConverter.interpolate(sentence, clonedConfig2)); } } {code} The solution can be to make in the following ways: Make the clone of the strSubstitutor in the AbstractConfigutration class. Create a clone method inside the StrSubtitutor and invoke it from the AbstractConfiguration class. Set null the strSubstituror when the clone method is invoked in the Abstract Configuration class. The next invocation to interpolate methos instances the strSubstitutor. -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators For more information on JIRA, see: http://www.atlassian.com/software/jira
[jira] [Created] (COLLECTIONS-441) MultiKeyMap.clone() should call super.clone()
Thomas Vahrst created COLLECTIONS-441: - Summary: MultiKeyMap.clone() should call super.clone() Key: COLLECTIONS-441 URL: https://issues.apache.org/jira/browse/COLLECTIONS-441 Project: Commons Collections Issue Type: Improvement Components: Map Affects Versions: 4.0-beta-1 Reporter: Thomas Vahrst Priority: Minor This issue addresses a findbugs issue: {quote} org.apache.commons.collections.map.MultiKeyMap.clone() does not call super.clone() {quote} The current clone() implementation creates a new MultiKeyMap instance. This will lead to problems when clone() is invoked on subclasses of MultiKeyMap. This is a corresponding junit test which fails: {code} class MultiKeyMapTest // Subclass to test clone() method private static class MultiKeyMapSubclass extends MultiKeyMapString, String{ } public void testCloneSubclass(){ MultiKeyMapSubclass m = new MultiKeyMapSubclass(); m.put(A, B, C); MultiKeyMapSubclass m2 = (MultiKeyMapSubclass) m.clone(); assertEquals(C, m.get(A, B)); } {code} Instead of creating a new MultiKeyMap instance, the clone() method should invoke super.clone() which leads in Object.clone(). This always returns an object of the correct type. {code} class MultiKeyMap{ /** * Clones the map without cloning the keys or values. * * @return a shallow clone */ @Override public MultiKeyMapK, V clone() { try { MultiKeyMapK,V m = (MultiKeyMapK, V) super.clone(); AbstractHashedMapMultiKey? extends K, V del = (AbstractHashedMapMultiKey? extends K, V)decorated().clone(); m.map = del; ((AbstractMapDecoratorK,V)m).map = (Map) del; return m; } catch (CloneNotSupportedException ex) { throw new RuntimeException (ex); // this should never happen... } } {code} *Note* For serialisation compatibilty reasons to commons collections V.3.2, MultiKeyMap contains a map reference (the decorated map) which hides the same field in the super class AbstractMapDecorator. This is quite 'ugly' to understand and maintain. Should we consider to break the compatibility to the 3.2 version? -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators For more information on JIRA, see: http://www.atlassian.com/software/jira
[jira] [Updated] (COLLECTIONS-441) MultiKeyMap.clone() should call super.clone()
[ https://issues.apache.org/jira/browse/COLLECTIONS-441?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Thomas Vahrst updated COLLECTIONS-441: -- Description: This issue addresses a findbugs issue: {quote} org.apache.commons.collections.map.MultiKeyMap.clone() does not call super.clone() {quote} The current clone() implementation creates a new MultiKeyMap instance. This will lead to problems when clone() is invoked on subclasses of MultiKeyMap. This is a corresponding junit test which fails: {code} class MultiKeyMapTest // Subclass to test clone() method private static class MultiKeyMapSubclass extends MultiKeyMapString, String{ } public void testCloneSubclass(){ MultiKeyMapSubclass m = new MultiKeyMapSubclass(); MultiKeyMapSubclass m2 = (MultiKeyMapSubclass) m.clone(); } {code} Instead of creating a new MultiKeyMap instance, the clone() method should invoke super.clone() which leads in Object.clone(). This always returns an object of the correct type. {code} class MultiKeyMap{ /** * Clones the map without cloning the keys or values. * * @return a shallow clone */ @Override public MultiKeyMapK, V clone() { try { MultiKeyMapK,V m = (MultiKeyMapK, V) super.clone(); AbstractHashedMapMultiKey? extends K, V del = (AbstractHashedMapMultiKey? extends K, V)decorated().clone(); m.map = del; ((AbstractMapDecoratorK,V)m).map = (Map) del; return m; } catch (CloneNotSupportedException ex) { throw new RuntimeException (ex); // this should never happen... } } {code} *Note* For serialisation compatibilty reasons to commons collections V.3.2, MultiKeyMap contains a map reference (the decorated map) which hides the same field in the super class AbstractMapDecorator. This is quite 'ugly' to understand and maintain. Should we consider to break the compatibility to the 3.2 version? was: This issue addresses a findbugs issue: {quote} org.apache.commons.collections.map.MultiKeyMap.clone() does not call super.clone() {quote} The current clone() implementation creates a new MultiKeyMap instance. This will lead to problems when clone() is invoked on subclasses of MultiKeyMap. This is a corresponding junit test which fails: {code} class MultiKeyMapTest // Subclass to test clone() method private static class MultiKeyMapSubclass extends MultiKeyMapString, String{ } public void testCloneSubclass(){ MultiKeyMapSubclass m = new MultiKeyMapSubclass(); m.put(A, B, C); MultiKeyMapSubclass m2 = (MultiKeyMapSubclass) m.clone(); assertEquals(C, m.get(A, B)); } {code} Instead of creating a new MultiKeyMap instance, the clone() method should invoke super.clone() which leads in Object.clone(). This always returns an object of the correct type. {code} class MultiKeyMap{ /** * Clones the map without cloning the keys or values. * * @return a shallow clone */ @Override public MultiKeyMapK, V clone() { try { MultiKeyMapK,V m = (MultiKeyMapK, V) super.clone(); AbstractHashedMapMultiKey? extends K, V del = (AbstractHashedMapMultiKey? extends K, V)decorated().clone(); m.map = del; ((AbstractMapDecoratorK,V)m).map = (Map) del; return m; } catch (CloneNotSupportedException ex) { throw new RuntimeException (ex); // this should never happen... } } {code} *Note* For serialisation compatibilty reasons to commons collections V.3.2, MultiKeyMap contains a map reference (the decorated map) which hides the same field in the super class AbstractMapDecorator. This is quite 'ugly' to understand and maintain. Should we consider to break the compatibility to the 3.2 version? MultiKeyMap.clone() should call super.clone() - Key: COLLECTIONS-441 URL: https://issues.apache.org/jira/browse/COLLECTIONS-441 Project: Commons Collections Issue Type: Improvement Components: Map Affects Versions: 4.0-beta-1 Reporter: Thomas Vahrst Priority: Minor This issue addresses a findbugs issue: {quote} org.apache.commons.collections.map.MultiKeyMap.clone() does not call super.clone() {quote} The current clone() implementation creates a new MultiKeyMap instance. This will lead to problems when clone() is invoked on subclasses of MultiKeyMap. This is a corresponding junit test which fails: {code} class MultiKeyMapTest // Subclass to test clone() method private static class MultiKeyMapSubclass extends MultiKeyMapString, String{ } public void
[jira] [Commented] (COLLECTIONS-441) MultiKeyMap.clone() should call super.clone()
[ https://issues.apache.org/jira/browse/COLLECTIONS-441?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13569649#comment-13569649 ] Thomas Vahrst commented on COLLECTIONS-441: --- In the suggested solution, the decorated map itself (an AbstractHashedMap instance) is cloned and then filled into the new MultiKeyMap instance. The clone() method of AbstractHashedMap contains another findbugs issue: it returns null in the case of a CloneNotSupportedException: {quote} org.apache.commons.collections.map.AbstractHashedMap.clone() may return null {quote} Instead of returning null, throwing a RuntimeException makes findbugs happy ;-) {code} /** * Clones the map without cloning the keys or values. * p * To implement codeclone()/code, a subclass must implement the * codeCloneable/code interface and make this method public. * * @return a shallow clone */ @Override @SuppressWarnings(unchecked) protected AbstractHashedMapK, V clone() { try { final AbstractHashedMapK, V cloned = (AbstractHashedMapK, V) super.clone(); cloned.data = new HashEntry[data.length]; cloned.entrySet = null; cloned.keySet = null; cloned.values = null; cloned.modCount = 0; cloned.size = 0; cloned.init(); cloned.putAll(this); return cloned; } catch (final CloneNotSupportedException ex) { // return null; // should never happen. throw new RuntimeException(ex); // should never happen. } } {code} MultiKeyMap.clone() should call super.clone() - Key: COLLECTIONS-441 URL: https://issues.apache.org/jira/browse/COLLECTIONS-441 Project: Commons Collections Issue Type: Improvement Components: Map Affects Versions: 4.0-beta-1 Reporter: Thomas Vahrst Priority: Minor This issue addresses a findbugs issue: {quote} org.apache.commons.collections.map.MultiKeyMap.clone() does not call super.clone() {quote} The current clone() implementation creates a new MultiKeyMap instance. This will lead to problems when clone() is invoked on subclasses of MultiKeyMap. This is a corresponding junit test which fails: {code} class MultiKeyMapTest // Subclass to test clone() method private static class MultiKeyMapSubclass extends MultiKeyMapString, String{ } public void testCloneSubclass(){ MultiKeyMapSubclass m = new MultiKeyMapSubclass(); MultiKeyMapSubclass m2 = (MultiKeyMapSubclass) m.clone(); } {code} Instead of creating a new MultiKeyMap instance, the clone() method should invoke super.clone() which leads in Object.clone(). This always returns an object of the correct type. {code} class MultiKeyMap{ /** * Clones the map without cloning the keys or values. * * @return a shallow clone */ @Override public MultiKeyMapK, V clone() { try { MultiKeyMapK,V m = (MultiKeyMapK, V) super.clone(); AbstractHashedMapMultiKey? extends K, V del = (AbstractHashedMapMultiKey? extends K, V)decorated().clone(); m.map = del; ((AbstractMapDecoratorK,V)m).map = (Map) del; return m; } catch (CloneNotSupportedException ex) { throw new RuntimeException (ex); // this should never happen... } } {code} *Note* For serialisation compatibilty reasons to commons collections V.3.2, MultiKeyMap contains a map reference (the decorated map) which hides the same field in the super class AbstractMapDecorator. This is quite 'ugly' to understand and maintain. Should we consider to break the compatibility to the 3.2 version? -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators For more information on JIRA, see: http://www.atlassian.com/software/jira