App Engine Java SDK version 1.7.0
[gae.git] / java / src / main / com / google / appengine / tools / admin / AppDownload.java
bloba39a0f4921e041d110a1d62cd0a0d8e5ab6c7944
1 // Copyright 2011 Google Inc. All Rights Reserved.
3 package com.google.appengine.tools.admin;
5 import com.google.appengine.tools.admin.ServerConnection;
6 import com.google.appengine.tools.admin.UpdateFailureEvent;
7 import com.google.appengine.tools.admin.UpdateListener;
8 import com.google.appengine.tools.admin.UpdateProgressEvent;
9 import com.google.appengine.tools.admin.UpdateSuccessEvent;
11 import java.io.BufferedInputStream;
12 import java.io.File;
13 import java.io.FileNotFoundException;
14 import java.io.FileOutputStream;
15 import java.io.IOException;
16 import java.util.HashMap;
17 import java.util.Map;
19 /**
20 * Class to download application code.
23 public class AppDownload {
25 private ServerConnection connection;
26 private UpdateListener listener;
27 private int downloadProgress;
28 private static final char NEWLINE = '\n';
30 public AppDownload(ServerConnection connection, UpdateListener listener) {
31 this.connection = connection;
32 this.listener = listener;
35 private void reportProgress(String message) {
36 if (listener != null) {
37 listener.onProgress(new UpdateProgressEvent(
38 Thread.currentThread(), message, downloadProgress));
42 private void reportSuccess(String message) {
43 if (listener != null) {
44 listener.onSuccess(new UpdateSuccessEvent(message));
48 private void reportFailure(String message) {
49 reportFailure(message, "");
52 private void reportFailure(String message, String details) {
53 if (listener != null) {
54 listener.onFailure(new UpdateFailureEvent(null, message, details));
58 private boolean downloadFile(File outDir, String appId, String appVersion, String fileId,
59 int fileSize, String filePath) {
60 BufferedInputStream fileStream;
61 try {
62 fileStream = new BufferedInputStream(
63 connection.postAndGetInputStream("/api/files/get", "", "app_id", appId,
64 "version", appVersion, "id", fileId));
65 } catch (IOException ioe) {
66 reportFailure("Unable to download file " + filePath, ioe.getMessage());
67 return false;
70 File outFile = new File(outDir, filePath);
71 File parentDir = outFile.getParentFile();
72 if (parentDir != null) {
73 try {
74 parentDir.mkdirs();
75 } catch (SecurityException se) {
76 reportFailure("Could not create directory " + parentDir.getPath(), se.getMessage());
77 return false;
81 int downloadedFileSize = 0;
82 try {
83 byte[] b = new byte[4096];
84 FileOutputStream outStream = new FileOutputStream(outFile);
85 int len;
86 while ((len = fileStream.read(b)) != -1) {
87 outStream.write(b, 0, len);
88 downloadedFileSize += len;
90 outStream.close();
91 } catch (FileNotFoundException fnfe) {
92 reportFailure("Could not create file " + outFile.getPath(), fnfe.getMessage());
93 return false;
94 } catch (IOException ioe) {
95 reportFailure("Could not write to file " + outFile.getPath(), ioe.getMessage());
96 return false;
99 if (downloadedFileSize != fileSize) {
100 reportFailure("File " + filePath + ": server listed as " + fileSize
101 + " bytes but served " + downloadedFileSize + " bytes.");
102 return false;
105 return true;
108 public boolean download(String appId, String appVersion, File outDir) {
109 downloadProgress = 0;
111 if (outDir.exists()) {
112 if (outDir.isFile()) {
113 reportFailure("Cannot download to path \"" + outDir.getPath()
114 + "\": there's a file in the way.");
115 return false;
117 if (outDir.list().length > 0) {
118 reportFailure("Cannot download to path \"" + outDir.getPath()
119 + "\": directory already exists and it isn't empty.");
120 return false;
124 reportProgress("Fetching file list...");
125 Map<String, String> urlArgs = new HashMap<String, String>();
126 urlArgs.put("app_id", appId);
127 if (appVersion != null) {
128 urlArgs.put("version_match", appVersion);
130 String response;
131 try {
132 response = connection.post("/api/files/list", "", urlArgs);
133 } catch (IOException ioe) {
134 reportFailure("Unable to fetch file list.", ioe.getMessage());
135 return false;
137 String[] lines = response.split("" + NEWLINE);
138 if (lines.length < 1) {
139 reportFailure("Invalid response from server: empty");
140 return false;
142 String fullAppVersion = lines[0];
144 reportProgress("Fetching files...");
145 for (int i = 1; i < lines.length; i++) {
146 String[] parts = lines[i].split("\\|");
147 if (parts.length != 3) {
148 reportFailure("Invalid response from server: expecting \"<id>|<size>|<path>\", "
149 + "found: " + lines[i]);
150 return false;
152 String fileId = parts[0];
153 int fileSize;
154 try {
155 fileSize = Integer.parseInt(parts[1]);
156 } catch (NumberFormatException nfe) {
157 reportFailure("Invalid file list entry from server: invalid size: " + parts[1],
158 nfe.getMessage());
159 return false;
161 String filePath = parts[2];
163 reportProgress("[" + i + "/" + (lines.length - 1) + "] " + filePath);
164 if (!downloadFile(outDir, appId, fullAppVersion, fileId, fileSize, filePath)) {
165 return false;
167 downloadProgress = (100 * i) / (lines.length - 1);
170 reportSuccess("");
171 return true;