JAR File isn't being written correctly

I was bored today and decided to make a jar updater/launcher. It all was working well, until I checked the contents of the output file, and it didn’t have the class files or packages when I opened it in a java decompiler.

My questions:

  • Am I writing the download properly?
  • Is the input stream closed properly?
    [li]What could be causing the file to not act like a normal jar file in the decompiler?[icode]
while (running) {
					if (state == 0) {
						// fetch the update
						try {
							URL url = new URL(updateServerUrl + "version.html");
							URLConnection conn = url.openConnection();
							BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
							latest = bufferedReader.readLine();
							if (!latest.equalsIgnoreCase(properties.getProperty("version"))) {
								state = 1;
								progress = 0;
							} else {
								// updated!
								state = 2;
							}
							bufferedReader.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
						progress = 1;
					}
					else if (state == 1) {
						// download the application
						if (!startedDownload) {
							// prepare the download
							String fileUrl = updateServerUrl + "version-" + latest + ".jar";
							try {
@@								bufferedInput = new BufferedInputStream(new URL(fileUrl).openStream());
@@								fileOutput = new BufferedOutputStream(new FileOutputStream("game.jar")); // overwrite
@@								blocks = (int) Math.ceil(bufferedInput.available() / 1024);
								startedDownload = true;
							} catch (IOException e) {
								e.printStackTrace();
							}
						} else {
							if (block == blocks || inputState == -1) {
								// launch the application
								try {
@@									bufferedInput.close();
@@									fileOutput.close();
								} catch (IOException e) {
									e.printStackTrace();
								}
								progress = 1;
								state++;
							} else {
								try {
@@									inputState = bufferedInput.read(scratch, 0, 1024);
									System.out.println("Reading block " + block + " / " + blocks + ": " + Arrays.toString(scratch));
@@									if (inputState > 0)
@@										fileOutput.write(scratch, 0, inputState);
									block++;
								} catch (IOException e) {
									e.printStackTrace();
								}
							}
						}
					}
					else if (state == 2) {
						// launch the application
						properties.setProperty("version", latest);
						try {
							properties.store(new FileOutputStream("version.properties", false), "");
						} catch (IOException e1) {
							e1.printStackTrace();
						}
						Thread thread = new Thread() {
							public void run() {
								try {
									Runtime.getRuntime().exec("java -jar game.jar");
								} catch (IOException e) {
									e.printStackTrace();
								}
							}
						};
						thread.setDaemon(true);
						thread.start();
						Platform.runLater(new Runnable() {
							public void run() {
								stage.close();
							}
						});
					}
					Platform.runLater(new Runnable() {
						public void run() {
							progressBar.setProgress(progress);
							text.setText(prompts[state].replaceAll("PERCENT", String.valueOf(progress)));
						}
					});
				}

For reading and writing *.jar files I would take a look at JarInputStream and JarOutputStream.
Did you have already tried that? :slight_smile:

fileOutput is a BufferedOutputStream, which will need to be flushed to get it to write to disk. Try this on line 50:


if (inputState > 0) {
  fileOutput.write(scratch, 0, inputState);
  fileOutput.flush();
  fileOutput.close();
}

Simply closing the stream should do the trick, but flush is useful if you have more to write to it a later stage.

  1. BufferedInputStream.available() returns an estimate. Never rely on it. In fact I believe it only returns the amount of bytes that can be read without blocking to wait for more.
  2. BufferedInputStream.read(buffer, offset, len) does not guarantee the whole buffer will be filled.
  3. With the previous two problems along with your method of reading in ‘blocks’ (don’t do this, just read and write normally), you’re losing a lot of data.

That’s 3 problems off the top of my head.