Skip to content

Commit 47632ab

Browse files
committed
Avoid downloading gcd if gcloud is installed and gcd version matches v1beta2
1 parent 34d5b7a commit 47632ab

1 file changed

Lines changed: 105 additions & 16 deletions

File tree

gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/LocalGcdHelper.java

Lines changed: 105 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,15 @@
4040
import java.nio.channels.ReadableByteChannel;
4141
import java.nio.file.FileVisitResult;
4242
import java.nio.file.Files;
43+
import java.nio.file.InvalidPathException;
4344
import java.nio.file.Path;
4445
import java.nio.file.Paths;
4546
import java.nio.file.SimpleFileVisitor;
4647
import java.nio.file.attribute.BasicFileAttributes;
4748
import java.security.MessageDigest;
4849
import java.security.NoSuchAlgorithmException;
4950
import java.util.Locale;
51+
import java.util.regex.Pattern;
5052
import java.util.zip.ZipEntry;
5153
import java.util.zip.ZipInputStream;
5254

@@ -62,17 +64,85 @@ public class LocalGcdHelper {
6264
public static final String DEFAULT_PROJECT_ID = "projectid1";
6365
public static final int PORT = 8080;
6466
private static final String GCD = "gcd-v1beta2-rev1-2.1.2b";
67+
private static final String GCD_VERSION = "v1beta2";
6568
private static final String GCD_FILENAME = GCD + ".zip";
6669
private static final String MD5_CHECKSUM = "d84384cdfa8658e1204f4f8be51300e8";
6770
private static final URL GCD_URL;
71+
private static final String GCLOUD = "gcloud";
72+
private static final Path INSTALLED_GCD_PATH;
6873

6974
static {
70-
try {
71-
GCD_URL = new URL("http://storage.googleapis.com/gcd/tools/" + GCD_FILENAME);
72-
} catch (MalformedURLException e) {
73-
throw new RuntimeException(e);
75+
INSTALLED_GCD_PATH = installedGcdPath();
76+
if (INSTALLED_GCD_PATH != null) {
77+
GCD_URL = null;
78+
} else {
79+
try {
80+
GCD_URL = new URL("http://storage.googleapis.com/gcd/tools/" + GCD_FILENAME);
81+
} catch (MalformedURLException e) {
82+
throw new RuntimeException(e);
83+
}
7484
}
7585
}
86+
87+
private static Path installedGcdPath() {
88+
Path gcloudPath = executablePath(GCLOUD);
89+
gcloudPath = (gcloudPath == null) ? null : gcloudPath.getParent();
90+
if (gcloudPath == null) {
91+
return null;
92+
}
93+
Path installedGcdPath = gcloudPath.resolve("platform").resolve("gcd");
94+
if (Files.exists(installedGcdPath)) {
95+
try {
96+
String installedVersion = installedGcdVersion();
97+
if (installedVersion != null && installedVersion.startsWith(GCD_VERSION)) {
98+
return installedGcdPath;
99+
}
100+
} catch (IOException | InterruptedException ignore) {
101+
// ignore
102+
}
103+
}
104+
return null;
105+
}
106+
107+
private static String installedGcdVersion() throws IOException, InterruptedException {
108+
ProcessBuilder processBuilder = new ProcessBuilder()
109+
.redirectErrorStream(true);
110+
if (isWindows()) {
111+
processBuilder.command("cmd", "/C", "gcloud", "version");
112+
} else {
113+
processBuilder.command("bash", "gcloud", "version");
114+
}
115+
Process process = processBuilder.start();
116+
process.waitFor();
117+
try (BufferedReader reader =
118+
new BufferedReader(new InputStreamReader(process.getInputStream()))) {
119+
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
120+
if (line.startsWith("gcd-emulator")) {
121+
String[] lineComponents = line.split(" ");
122+
if (lineComponents.length > 1) {
123+
return lineComponents[1];
124+
}
125+
}
126+
}
127+
return null;
128+
}
129+
130+
}
131+
132+
private static Path executablePath(String cmd) {
133+
String[] paths = System.getenv("PATH").split(Pattern.quote(File.pathSeparator));
134+
for (String pathString : paths) {
135+
try {
136+
Path path = Paths.get(pathString);
137+
if (Files.exists(path.resolve(cmd))) {
138+
return path;
139+
}
140+
} catch (InvalidPathException ignore) {
141+
// ignore
142+
}
143+
}
144+
return null;
145+
}
76146

77147
private static class ProcessStreamReader extends Thread {
78148

@@ -136,6 +206,18 @@ public void start() throws IOException, InterruptedException {
136206
File gcdFolder = gcdPath.toFile();
137207
gcdFolder.deleteOnExit();
138208

209+
Path gcdExecutablePath;
210+
// If cloud is available we use it, otherwise we download and start gcd
211+
if (INSTALLED_GCD_PATH == null) {
212+
downloadGcd();
213+
gcdExecutablePath = gcdPath.resolve(GCD);
214+
} else {
215+
gcdExecutablePath = INSTALLED_GCD_PATH;
216+
}
217+
startGcd(gcdExecutablePath);
218+
}
219+
220+
private void downloadGcd() throws IOException {
139221
// check if we already have a local copy of the gcd utility and download it if not.
140222
File gcdZipFile = new File(System.getProperty("java.io.tmpdir"), GCD_FILENAME);
141223
if (!gcdZipFile.exists() || !MD5_CHECKSUM.equals(md5(gcdZipFile))) {
@@ -148,7 +230,7 @@ public void start() throws IOException, InterruptedException {
148230
try (ZipInputStream zipIn = new ZipInputStream(new FileInputStream(gcdZipFile))) {
149231
ZipEntry entry = zipIn.getNextEntry();
150232
while (entry != null) {
151-
File filePath = new File(gcdFolder, entry.getName());
233+
File filePath = new File(gcdPath.toFile(), entry.getName());
152234
if (!entry.isDirectory()) {
153235
extractFile(zipIn, filePath);
154236
} else {
@@ -157,36 +239,43 @@ public void start() throws IOException, InterruptedException {
157239
zipIn.closeEntry();
158240
entry = zipIn.getNextEntry();
159241
}
160-
}
242+
}
243+
}
244+
245+
private void startGcd(Path executablePath) throws IOException, InterruptedException {
161246
// cleanup any possible data for the same project
162-
File datasetFolder = new File(gcdFolder, GCD + '/' + projectId);
247+
File datasetFolder = new File(gcdPath.toFile(), projectId);
163248
deleteRecurse(datasetFolder.toPath());
164249

165250
// create the datastore for the project
166251
ProcessBuilder processBuilder = new ProcessBuilder()
167252
.redirectError(ProcessBuilder.Redirect.INHERIT)
168-
.directory(new File(gcdFolder, GCD));
253+
.directory(gcdPath.toFile());
169254
if (isWindows()) {
170-
processBuilder.command("cmd", "/C", "gcd.cmd", "create", "-p", projectId, projectId);
171-
processBuilder.redirectOutput(new File("NULL:"));
255+
Path gcdAbsolutePath = executablePath.toAbsolutePath().resolve("gcd.cmd");
256+
processBuilder.command("cmd", "/C", gcdAbsolutePath.toString(), "create",
257+
"-p", projectId, projectId);
172258
} else {
173-
processBuilder.redirectOutput(new File("/dev/null"));
174-
processBuilder.command("bash", "gcd.sh", "create", "-p", projectId, projectId);
259+
Path gcdAbsolutePath = executablePath.toAbsolutePath().resolve("gcd.sh");
260+
processBuilder.command("bash", gcdAbsolutePath.toString(), "create",
261+
"-p", projectId, projectId);
175262
}
176263

177264
Process temp = processBuilder.start();
178265
temp.waitFor();
179266

180267
// start the datastore for the project
181268
processBuilder = new ProcessBuilder()
182-
.directory(new File(gcdFolder, GCD))
269+
.directory(gcdPath.toFile())
183270
.redirectErrorStream(true);
184271
if (isWindows()) {
185-
processBuilder.command("cmd", "/C", "gcd.cmd", "start", "--testing",
272+
Path gcdAbsolutePath = executablePath.toAbsolutePath().resolve("gcd.cmd");
273+
processBuilder.command("cmd", "/C", gcdAbsolutePath.toString(), "start", "--testing",
186274
"--allow_remote_shutdown", projectId);
187275
} else {
188-
processBuilder.command("bash", "gcd.sh", "start", "--testing", "--allow_remote_shutdown",
189-
projectId);
276+
Path gcdAbsolutePath = executablePath.toAbsolutePath().resolve("gcd.sh");
277+
processBuilder.command("bash", gcdAbsolutePath.toString(), "start", "--testing",
278+
"--allow_remote_shutdown", projectId);
190279
}
191280
temp = processBuilder.start();
192281
processReader = ProcessStreamReader.start(temp, "Dev App Server is now running");

0 commit comments

Comments
 (0)