diff --git a/README.md b/README.md index 303a75c..da0a210 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,10 @@ A download manager application written in Java. ##Usage Use eclipse to open the project. +Also it's possible to use intellij idea, just do "import from csv" ##Contact [@luugiathuy](http://twitter.com/luugiathuy) + +me@ali4j.net + diff --git a/src/com/luugiathuy/apps/downloadmanager/DownloadManager.java b/src/com/luugiathuy/apps/downloadmanager/DownloadManager.java index 0f707cd..0c22bd2 100644 --- a/src/com/luugiathuy/apps/downloadmanager/DownloadManager.java +++ b/src/com/luugiathuy/apps/downloadmanager/DownloadManager.java @@ -27,6 +27,7 @@ import java.net.URL; import java.util.ArrayList; +import java.util.logging.Logger; public class DownloadManager { @@ -35,16 +36,21 @@ public class DownloadManager { // Constant variables private static final int DEFAULT_NUM_CONN_PER_DOWNLOAD = 8; - public static final String DEFAULT_OUTPUT_FOLDER = ""; +// public static final String DEFAULT_OUTPUT_FOLDER = ""; + public static final String DEFAULT_OUTPUT_FOLDER = System.getProperty("user.home"); // Member variables private int mNumConnPerDownload; private ArrayList mDownloadList; + + + private static String HTTP_PREFIX = "http://"; + private static Logger logger = Logger.getLogger(DownloadManager.class.getName()); /** Protected constructor */ protected DownloadManager() { mNumConnPerDownload = DEFAULT_NUM_CONN_PER_DOWNLOAD; - mDownloadList = new ArrayList(); + mDownloadList = new ArrayList<>(); } /** @@ -57,7 +63,7 @@ public int getNumConnPerDownload() { /** * Set the max number of connections per download */ - public void SetNumConnPerDownload(int value) { + public void setNumConnPerDownload(int value) { mNumConnPerDownload = value; } @@ -108,14 +114,15 @@ public static DownloadManager getInstance() { */ public static URL verifyURL(String fileURL) { // Only allow HTTP URLs. - if (!fileURL.toLowerCase().startsWith("http://")) + if (!fileURL.toLowerCase().startsWith(HTTP_PREFIX)) return null; // Verify format of URL. - URL verifiedUrl = null; + URL verifiedUrl; try { verifiedUrl = new URL(fileURL); } catch (Exception e) { + logger.finest("url is not valid"); return null; } diff --git a/src/com/luugiathuy/apps/downloadmanager/DownloadManagerGUI.java b/src/com/luugiathuy/apps/downloadmanager/DownloadManagerGUI.java index a53d8c3..61b10d7 100644 --- a/src/com/luugiathuy/apps/downloadmanager/DownloadManagerGUI.java +++ b/src/com/luugiathuy/apps/downloadmanager/DownloadManagerGUI.java @@ -25,16 +25,12 @@ package com.luugiathuy.apps.downloadmanager; +import javax.swing.*; import java.net.URL; import java.util.Observable; import java.util.Observer; +import java.util.logging.*; -import javax.swing.JOptionPane; -import javax.swing.JProgressBar; -import javax.swing.ListSelectionModel; -import javax.swing.UIManager; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; public class DownloadManagerGUI extends javax.swing.JFrame implements Observer{ @@ -45,22 +41,38 @@ public class DownloadManagerGUI extends javax.swing.JFrame implements Observer{ private Downloader mSelectedDownloader; private boolean mIsClearing; - + + private static Logger logger = Logger.getLogger(DownloadManagerGUI.class.getName()); + + static { + Logger log = LogManager.getLogManager().getLogger(""); + for (Handler h : log.getHandlers()) { + h.setLevel(Level.ALL); + h.setFormatter(new SimpleFormatter()); + } + + Logger logger = Logger.getLogger("com.luugiathuy"); + for(Handler handler : logger.getHandlers()) { + handler.setLevel(Level.ALL); + handler.setFormatter(new SimpleFormatter()); + } + logger.setLevel(Level.ALL); + } + /** Creates new form DownloadManagerGUI */ public DownloadManagerGUI() { + logger.finest("DownloadManagerGUI started"); mTableModel = new DownloadTableModel(); initComponents(); initialize(); } private void initialize() { + + logger.finest("default download location: " + System.getProperty("user.home")); + // Set up table - jtbDownload.getSelectionModel().addListSelectionListener(new - ListSelectionListener() { - public void valueChanged(ListSelectionEvent e) { - tableSelectionChanged(); - } - }); + jtbDownload.getSelectionModel().addListSelectionListener(e -> tableSelectionChanged()); // Allow only one row at a time to be selected. jtbDownload.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); @@ -99,53 +111,29 @@ private void initComponents() { setResizable(false); jbnAdd.setText("Add Download"); - jbnAdd.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - jbnAddActionPerformed(evt); - } - }); + jbnAdd.addActionListener(this::jbnAddActionPerformed); jtbDownload.setModel(mTableModel); jScrollPane1.setViewportView(jtbDownload); jbnPause.setText("Pause"); jbnPause.setEnabled(false); - jbnPause.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - jbnPauseActionPerformed(evt); - } - }); + jbnPause.addActionListener(this::jbnPauseActionPerformed); jbnRemove.setText("Remove"); jbnRemove.setEnabled(false); - jbnRemove.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - jbnRemoveActionPerformed(evt); - } - }); + jbnRemove.addActionListener(this::jbnRemoveActionPerformed); jbnCancel.setText("Cancel"); jbnCancel.setEnabled(false); - jbnCancel.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - jbnCancelActionPerformed(evt); - } - }); + jbnCancel.addActionListener(this::jbnCancelActionPerformed); jbnExit.setText("Exit"); - jbnExit.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - jbnExitActionPerformed(evt); - } - }); + jbnExit.addActionListener(this::jbnExitActionPerformed); jbnResume.setText("Resume"); jbnResume.setEnabled(false); - jbnResume.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - jbnResumeActionPerformed(evt); - } - }); + jbnResume.addActionListener(this::jbnResumeActionPerformed); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); @@ -172,7 +160,7 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { .addContainerGap()) ); - layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jbnCancel, jbnExit, jbnPause, jbnRemove, jbnResume}); + layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, jbnCancel, jbnExit, jbnPause, jbnRemove, jbnResume); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -222,7 +210,8 @@ private void jbnRemoveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIR }//GEN-LAST:event_jbnRemoveActionPerformed private void jbnExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jbnExitActionPerformed - setVisible(false); + logger.finest("Exiting"); + System.exit(1); }//GEN-LAST:event_jbnExitActionPerformed private void jbnAddActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jbnAddActionPerformed @@ -313,13 +302,13 @@ public static void main(String args[]) { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) { + e.printStackTrace(); + logger.severe(e.getMessage()); } - - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - new DownloadManagerGUI().setVisible(true); - } - }); + + java.awt.EventQueue.invokeLater( + () -> new DownloadManagerGUI().setVisible(true) + ); } // Variables declaration - do not modify//GEN-BEGIN:variables diff --git a/src/com/luugiathuy/apps/downloadmanager/DownloadTableModel.java b/src/com/luugiathuy/apps/downloadmanager/DownloadTableModel.java index a6089af..0f559a7 100644 --- a/src/com/luugiathuy/apps/downloadmanager/DownloadTableModel.java +++ b/src/com/luugiathuy/apps/downloadmanager/DownloadTableModel.java @@ -41,12 +41,12 @@ public class DownloadTableModel extends AbstractTableModel implements Observer { // These are the names for the table's columns. private static final String[] columnNames = {"URL", "Size (KB)", - "Progress", "Status"}; + "Progress", "Status", "Destination"}; // These are the classes for each column's values. @SuppressWarnings("rawtypes") private static final Class[] columnClasses = {String.class, - String.class, JProgressBar.class, String.class}; + String.class, JProgressBar.class, String.class, String.class}; /** * Add a new download to the table. @@ -114,6 +114,13 @@ public Object getValueAt(int row, int col) { return new Float(download.getProgress()); case 3: // Status return Downloader.STATUSES[download.getState()]; + case 4 : //Destination + { + int state = download.getState(); + if(state == 2 ) return download.getOutputFolder() + download.getFileName(); + else return "-"; + } + } return ""; } diff --git a/src/com/luugiathuy/apps/downloadmanager/Downloader.java b/src/com/luugiathuy/apps/downloadmanager/Downloader.java index 438e0ee..661406a 100644 --- a/src/com/luugiathuy/apps/downloadmanager/Downloader.java +++ b/src/com/luugiathuy/apps/downloadmanager/Downloader.java @@ -25,12 +25,17 @@ package com.luugiathuy.apps.downloadmanager; +import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.Observable; +import java.util.logging.Logger; public abstract class Downloader extends Observable implements Runnable{ - + + private static Logger logger = Logger.getLogger(Downloader.class.getName()); + + // Member variables /** The URL to download the file */ protected URL mURL; @@ -74,7 +79,7 @@ public abstract class Downloader extends Observable implements Runnable{ /** * Constructor - * @param fileURL + * @param url * @param outputFolder * @param numConnections */ @@ -85,13 +90,13 @@ protected Downloader(URL url, String outputFolder, int numConnections) { // Get the file name from url path String fileURL = url.getFile(); - mFileName = fileURL.substring(fileURL.lastIndexOf('/') + 1); - System.out.println("File name: " + mFileName); + mFileName = File.separator + fileURL.substring(fileURL.lastIndexOf('/') + 1); + logger.finest("File name:" + mFileName); mFileSize = -1; mState = DOWNLOADING; mDownloaded = 0; - mListDownloadThread = new ArrayList(); + mListDownloadThread = new ArrayList<>(); } /** @@ -122,7 +127,10 @@ public void cancel() { public String getURL() { return mURL.toString(); } - + + + public String getFileName(){return mFileName;} + /** * Get the downloaded file's size */ @@ -143,6 +151,11 @@ public float getProgress() { public int getState() { return mState; } + + /** + * + */ + public String getOutputFolder(){return mOutputFolder;} /** * Set the state of the downloader diff --git a/src/com/luugiathuy/apps/downloadmanager/HttpDownloader.java b/src/com/luugiathuy/apps/downloadmanager/HttpDownloader.java index 0c81f43..2bf184f 100644 --- a/src/com/luugiathuy/apps/downloadmanager/HttpDownloader.java +++ b/src/com/luugiathuy/apps/downloadmanager/HttpDownloader.java @@ -30,61 +30,75 @@ import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; +import java.util.logging.Logger; public class HttpDownloader extends Downloader{ - - public HttpDownloader(URL url, String outputFolder, int numConnections) { + + private static Logger logger = Logger.getLogger(HttpDownloader.class.getName()); + + public HttpDownloader(URL url, String outputFolder, int numConnections) { super(url, outputFolder, numConnections); download(); } private void error() { - System.out.println("ERROR"); + logger.severe("ERROR"); setState(ERROR); } + + + private HttpURLConnection createAndCheckConnection() throws IOException { + HttpURLConnection conn = (HttpURLConnection)mURL.openConnection(); + conn.setConnectTimeout(10000); + conn.connect(); + + // Make sure the response code is in the 200 range. + if (conn.getResponseCode() / 100 != 2) { + error(); + } + return conn; + } + + private void checkForValidContentLength(HttpURLConnection conn){ + int contentLength = conn.getContentLength(); + if (contentLength < 1) { + error(); + } + + if (mFileSize == -1) { + mFileSize = contentLength; + stateChanged(); + logger.finest("File size:" + mFileName); + } + } @Override public void run() { HttpURLConnection conn = null; try { - // Open connection to URL - conn = (HttpURLConnection)mURL.openConnection(); - conn.setConnectTimeout(10000); - - // Connect to server - conn.connect(); - - // Make sure the response code is in the 200 range. - if (conn.getResponseCode() / 100 != 2) { - error(); - } - + /** + * Opens connection to URL and Connects to the server + * then checks the StatusCode + */ + conn = createAndCheckConnection(); + // Check for valid content length. - int contentLength = conn.getContentLength(); - if (contentLength < 1) { - error(); - } - - if (mFileSize == -1) { - mFileSize = contentLength; - stateChanged(); - System.out.println("File size: " + mFileSize); - } + checkForValidContentLength(conn); // if the state is DOWNLOADING (no error) -> start downloading if (mState == DOWNLOADING) { // check whether we have list of download threads or not, if not -> init download - if (mListDownloadThread.size() == 0) - { + if (mListDownloadThread.size() == 0) { if (mFileSize > MIN_DOWNLOAD_SIZE) { // downloading size for each thread int partSize = Math.round(((float)mFileSize / mNumConnections) / BLOCK_SIZE) * BLOCK_SIZE; - System.out.println("Part size: " + partSize); + logger.finest("Part size: " + partSize); // start/end Byte for each thread int startByte = 0; int endByte = partSize - 1; - HttpDownloadThread aThread = new HttpDownloadThread(1, mURL, mOutputFolder + mFileName, startByte, endByte); + HttpDownloadThread aThread = new HttpDownloadThread(1, mURL, + mOutputFolder + mFileName, startByte, endByte); mListDownloadThread.add(aThread); int i = 2; while (endByte < mFileSize) { @@ -94,8 +108,7 @@ public void run() { mListDownloadThread.add(aThread); ++i; } - } else - { + } else { HttpDownloadThread aThread = new HttpDownloadThread(1, mURL, mOutputFolder + mFileName, 0, mFileSize); mListDownloadThread.add(aThread); } @@ -141,67 +154,47 @@ public HttpDownloadThread(int threadID, URL url, String outputFile, int startByt super(threadID, url, outputFile, startByte, endByte); } + /** + * Downloads that part of the remote resource which is assigned to this thread + * @throws IOException + */ + private void downloadResourcePartially() throws IOException { + HttpURLConnection conn = (HttpURLConnection)mURL.openConnection(); + String byteRange = mStartByte + "-" + mEndByte; + conn.setRequestProperty("Range", "bytes=" + byteRange); + logger.finest("bytes=" + byteRange); + conn.connect(); + if (conn.getResponseCode() / 100 != 2) { + error(); + } + try (BufferedInputStream in = new BufferedInputStream(conn.getInputStream()); + RandomAccessFile raf = new RandomAccessFile(mOutputFile, "rw");) { + raf.seek(mStartByte); + byte data[] = new byte[BUFFER_SIZE]; + int numRead; + while((mState == DOWNLOADING) && ((numRead = in.read(data,0,BUFFER_SIZE)) != -1)) + { + // write to buffer + raf.write(data,0,numRead); + // increase the startByte for resume later + mStartByte += numRead; + // increase the downloaded size + downloaded(numRead); + } + if (mState == DOWNLOADING) { + mIsFinished = true; + } + } + } + @Override public void run() { - BufferedInputStream in = null; - RandomAccessFile raf = null; - - try { - // open Http connection to URL - HttpURLConnection conn = (HttpURLConnection)mURL.openConnection(); - - // set the range of byte to download - String byteRange = mStartByte + "-" + mEndByte; - conn.setRequestProperty("Range", "bytes=" + byteRange); - System.out.println("bytes=" + byteRange); - - // connect to server - conn.connect(); - - // Make sure the response code is in the 200 range. - if (conn.getResponseCode() / 100 != 2) { - error(); - } - - // get the input stream - in = new BufferedInputStream(conn.getInputStream()); - - // open the output file and seek to the start location - raf = new RandomAccessFile(mOutputFile, "rw"); - raf.seek(mStartByte); - - byte data[] = new byte[BUFFER_SIZE]; - int numRead; - while((mState == DOWNLOADING) && ((numRead = in.read(data,0,BUFFER_SIZE)) != -1)) - { - // write to buffer - raf.write(data,0,numRead); - // increase the startByte for resume later - mStartByte += numRead; - // increase the downloaded size - downloaded(numRead); - } - - if (mState == DOWNLOADING) { - mIsFinished = true; - } + try { + downloadResourcePartially(); } catch (IOException e) { error(); - } finally { - if (raf != null) { - try { - raf.close(); - } catch (IOException e) {} - } - - if (in != null) { - try { - in.close(); - } catch (IOException e) {} - } } - - System.out.println("End thread " + mThreadID); + logger.finest("End thread " + mThreadID); } } }