Reputation: 1571
I'm writting a small file browser. I have a small problem with downloading files implementation. When I try to cancel the download and delete from the list, i get this error:
Exception in thread "Timer-2" java.lang.ArrayIndexOutOfBoundsException: 2 >= 2
at java.util.Vector.elementAt(Unknown Source)
at javax.swing.table.DefaultTableModel.setValueAt(Unknown Source)
at pkg_main.CLS_Downloader$1.run(CLS_Downloader.java:151)
at java.util.TimerThread.mainLoop(Unknown Source)
at java.util.TimerThread.run(Unknown Source)
And this my code:
Download class:
public class CLS_Downloader extends Thread {
private final String sDOWNLOAD_FOLDER = "descargas/";
private Socket tSock;
private ObjectInputStream tObjInStream;
private ObjectOutputStream tObjOutStream;
private JTable tTable;
private int iIndex;
private CLS_TransferTableModel tTransferModel;
private Boolean bDownloaded;
private Boolean bFailed;
private long iReadCount = 0;
private long iReadTotal = 0;
private long lTotalSize = 0;
private long lRemainSize = 0;
private String sFileName;
private JProgressBar tProgressBar;
public CLS_Downloader(Socket tSock, JTable tTable, int iIndex) {
this.tTable = tTable;
this.iIndex = iIndex;
this.tSock = tSock;
this.bDownloaded = false;
this.bFailed = false;
this.tTransferModel = (CLS_TransferTableModel) tTable.getModel();
try {
this.tObjOutStream = new ObjectOutputStream(
this.tSock.getOutputStream());
this.tObjOutStream.flush();
this.tObjInStream = new ObjectInputStream(
this.tSock.getInputStream());
this.start();
} catch (IOException e) {
this.bFailed = true;
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public JTable getTable() {
return tTable;
}
public void setTable(JTable tTable) {
this.tTable = tTable;
}
public int getiIndex() {
return iIndex;
}
public void setiIndex(int iIndex) {
this.iIndex = iIndex;
}
public Socket getSock() {
return tSock;
}
public void setSock(Socket tSock) {
this.tSock = tSock;
}
public String getFileName() {
return sFileName;
}
public void setFileName(String sFileName) {
this.sFileName = sFileName;
}
public long getTotalSize() {
return lTotalSize;
}
public void setTotalSize(long lTotalSize) {
this.lTotalSize = lTotalSize;
}
public Boolean isDownloaded() {
return bDownloaded;
}
public void setDownloaded(Boolean bDownloaded) {
this.bDownloaded = bDownloaded;
}
public Boolean isFailed() {
return bFailed;
}
public void setFailed(Boolean bFailed) {
this.bFailed = bFailed;
}
private void setTableValues() {
this.tTransferModel.setValueAt(this.tSock.getInetAddress()
.getHostAddress(), iIndex, 0);
this.tTransferModel.setValueAt(this.sFileName, iIndex, 1);
this.tTransferModel.setValueAt("Descargando", iIndex, 2);
this.tProgressBar = (JProgressBar) tTable.getModel().getValueAt(
this.iIndex, 3);
this.tProgressBar.setStringPainted(true);
this.tTransferModel.setValueAt(
CLS_Functions.convertSize(this.lRemainSize), iIndex, 6);
}
private void downloadComplete() {
this.tProgressBar.setValue(100);
this.tTable.repaint();
this.tTransferModel.setValueAt("Completado", iIndex, 2);
this.tTransferModel.setValueAt(CLS_Functions.convertSize(iReadTotal),
iIndex, 4);
this.tTransferModel.setValueAt(CLS_Functions.convertSize(lRemainSize),
iIndex, 5);
this.bDownloaded = true;
}
TimerTask tUpdateTable = new TimerTask() {
public void run() {
tProgressBar.setValue((int) ((iReadTotal * 100) / lTotalSize));
tTable.repaint();
tTransferModel.setValueAt(CLS_Functions.convertSize(iReadTotal),
iIndex, 4); //ERROR LINE
tTransferModel.setValueAt(CLS_Functions.convertSize(lRemainSize),
iIndex, 5);
}
};
public void run() {
String sData = null;
FileOutputStream tFileInStream = null;
byte[] bArrRet = new byte[2048];
try {
sData = this.tObjInStream.readUTF();
this.sFileName = new File(sData.split("#")[0]).getName();
this.lTotalSize = Long.parseLong(sData.split("#")[1]);
this.lRemainSize = this.lTotalSize;
this.setTableValues();
new Timer().scheduleAtFixedRate(tUpdateTable, 0, 1000);
tFileInStream = new FileOutputStream(sDOWNLOAD_FOLDER + this.sFileName);
while (this.lRemainSize > 0) {
this.iReadCount = tObjInStream.read(bArrRet);
tFileInStream.write(bArrRet, 0, (int) this.iReadCount);
tFileInStream.flush();
this.lRemainSize -= this.iReadCount;
this.iReadTotal += this.iReadCount;
Thread.sleep(5);
}
this.tUpdateTable.cancel();
this.downloadComplete();
tFileInStream.close();
this.close();
System.out.println("listo");
} catch (Exception e) {
// TODO Auto-generated catch block
try {
tFileInStream.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
this.close();
this.bFailed = true;
this.tTransferModel.setValueAt("Fallado", iIndex, 2);
this.tUpdateTable.cancel();
}
}
public void close() {
try {
this.tUpdateTable.cancel();
this.tObjOutStream.close();
this.tObjInStream.close();
this.tSock.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Downloads Manager class:
public class CLS_DownloadManager {
private static CLS_DownloadManager tDownloadManager;
private ArrayList<CLS_Downloader> tDownloadList = new ArrayList<CLS_Downloader>();
public static CLS_DownloadManager getInstance() {
if (tDownloadManager == null)
tDownloadManager = new CLS_DownloadManager();
return tDownloadManager;
}
public ArrayList<CLS_Downloader> getDownloadList() {
return tDownloadList;
}
public void setDownloadList(ArrayList<CLS_Downloader> tDownloadList) {
this.tDownloadList = tDownloadList;
}
public void addDownload(CLS_Downloader tDownload) {
this.tDownloadList.add(tDownload);
}
public CLS_Downloader getDownload(int iIndex) {
return this.tDownloadList.get(iIndex);
}
public void deleteDownload(int iIndex) {
this.tDownloadList.remove(iIndex);
}
public void deleteDownload(CLS_Downloader tDownload) {
this.tDownloadList.remove(tDownload);
}
public void cancelDownload(int iIndex) {
this.tDownloadList.get(iIndex).close();
}
public void cleanDownloads() {
for (int i = this.tDownloadList.size() - 1; i >= 0; i--)
if (this.tDownloadList.get(i).isDownloaded()
|| this.tDownloadList.get(i).isFailed())
this.tDownloadList.remove(i);
}
public int getListCount() {
return this.tDownloadList.size();
}
}
Download cancel function:
if (TBL_Downloads.getSelectedRow() > -1) {
CLS_DownloadManager.getInstance().cancelDownload(TBL_Downloads.getSelectedRow());
}
Thanks in advance!
Upvotes: 0
Views: 159
Reputation: 14671
Your design is mixing the business objects (the CLS_Downloader) with the view (the JTable and its table model).
The problem I see here is that your CLS_Downloader has a reference to the table model and, more importantly to it's index in it. On top of that you also keep track of your downloads in a list inside the CLS_DownloadManager.
When you update the data (by cancelling a download) it becomes complicated to keep everything in sync (the table model, the CLS_DownloadManager, the indices in all the CLS_Downloader).
Look up the model view controller architecture for a better way to organize your code. In yor case, the model should be the CLS_Downloader, the view should be the JTable and the controller should be the CLS_DownloadManager
Upvotes: 2