Revision created by MOE tool push_codebase.
[gae.git] / java / src / main / com / google / appengine / tools / admin / AppDownload.java
blob45bcf21738a16b6575d02804cb7472347fb6d97b
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 server, 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 (server != null) {
128 urlArgs.put("server", server);
130 if (appVersion != null) {
131 urlArgs.put("version_match", appVersion);
133 String response;
134 try {
135 response = connection.post("/api/files/list", "", urlArgs);
136 } catch (IOException ioe) {
137 reportFailure("Unable to fetch file list.", ioe.getMessage());
138 return false;
140 String[] lines = response.split("" + NEWLINE);
141 if (lines.length < 1) {
142 reportFailure("Invalid response from server: empty");
143 return false;
145 String fullAppVersion = lines[0];
147 reportProgress("Fetching files...");
148 for (int i = 1; i < lines.length; i++) {
149 String[] parts = lines[i].split("\\|");
150 if (parts.length != 3) {
151 reportFailure("Invalid response from server: expecting \"<id>|<size>|<path>\", "
152 + "found: " + lines[i]);
153 return false;
155 String fileId = parts[0];
156 int fileSize;
157 try {
158 fileSize = Integer.parseInt(parts[1]);
159 } catch (NumberFormatException nfe) {
160 reportFailure("Invalid file list entry from server: invalid size: " + parts[1],
161 nfe.getMessage());
162 return false;
164 String filePath = parts[2];
166 reportProgress("[" + i + "/" + (lines.length - 1) + "] " + filePath);
167 if (!downloadFile(outDir, appId, fullAppVersion, fileId, fileSize, filePath)) {
168 return false;
170 downloadProgress = (100 * i) / (lines.length - 1);
173 reportSuccess("");
174 return true;