Skip to content

Commit 29ae039

Browse files
committed
Merge pull request #6 from foghina/gradle_start_packager
Start packager from gradle plugin
2 parents 62a5584 + 8a28c54 commit 29ae039

File tree

4 files changed

+102
-16
lines changed

4 files changed

+102
-16
lines changed

react-native-gradle/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ repositories {
1111
dependencies {
1212
compile gradleApi()
1313
compile 'commons-io:commons-io:2.4'
14+
compile 'org.apache.commons:commons-lang3:3.4'
1415

1516
testCompile 'junit:junit:4.12'
1617
testCompile 'com.squareup.okhttp:mockwebserver:2.4.0'

react-native-gradle/src/main/java/com/facebook/react/AbstractPackageJsTask.java

Lines changed: 99 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
import java.io.IOException;
66
import java.io.InputStream;
77
import java.io.OutputStream;
8+
import java.net.HttpURLConnection;
89
import java.net.MalformedURLException;
910
import java.net.URI;
1011
import java.net.URISyntaxException;
1112
import java.net.URL;
1213

1314
import org.apache.commons.io.FilenameUtils;
1415
import org.apache.commons.io.IOUtils;
16+
import org.apache.commons.lang3.SystemUtils;
1517
import org.gradle.api.DefaultTask;
1618

1719
/**
@@ -20,12 +22,35 @@
2022
*/
2123
public abstract class AbstractPackageJsTask extends DefaultTask {
2224

25+
/**
26+
* Describes the status of the JS packager server.
27+
*
28+
* @see #getPackagerStatus
29+
*/
30+
private enum PackagerStatus {
31+
/**
32+
* Packager is up and running
33+
*/
34+
RUNNING,
35+
36+
/**
37+
* Packager is not running, but could be started
38+
*/
39+
NOT_RUNNING,
40+
41+
/**
42+
* Packager is not running and can't be started, something else is listening on the configured
43+
* port
44+
*/
45+
UNKNOWN
46+
}
47+
2348
/**
2449
* Get a bundle from packager and copy it to the appropriate folder.
2550
*
2651
* @param debug whether this is a debug build or not
2752
*/
28-
protected void copyBundle(boolean debug) throws URISyntaxException, IOException {
53+
protected void copyBundle(boolean debug) throws Exception {
2954
ReactGradleExtension config = getConfig();
3055
PackagerParams packagerParams = getPackagerParams(config, debug);
3156

@@ -35,15 +60,81 @@ protected void copyBundle(boolean debug) throws URISyntaxException, IOException
3560
.separatorsToSystem("build/intermediates/assets/" + (debug ? "debug" : "release")));
3661
assets.mkdirs();
3762
File bundle = new File(assets, config.getBundleFileName());
38-
System.out.println("Writing debug=" + debug + " bundle to " + bundle.getAbsolutePath());
3963

40-
URL packageUrl = getPackageUrl(config, packagerParams);
64+
PackagerStatus packagerStatus = getPackagerStatus(config);
65+
if (packagerStatus == PackagerStatus.NOT_RUNNING) {
66+
boolean started = startPackager();
67+
if (started) {
68+
packagerStatus = getPackagerStatus(config);
69+
}
70+
if (!started || packagerStatus != PackagerStatus.RUNNING) {
71+
throw new Exception(
72+
"Could not start packager server. Please start it manually and try again.");
73+
}
74+
}
75+
if (packagerStatus == PackagerStatus.RUNNING) {
76+
URL packageUrl = getPackageUrl(config, packagerParams);
77+
78+
InputStream packageStream = packageUrl.openStream();
79+
OutputStream bundleStream = new FileOutputStream(bundle);
80+
IOUtils.copy(packageStream, bundleStream);
81+
IOUtils.closeQuietly(packageStream);
82+
IOUtils.closeQuietly(bundleStream);
83+
} else if (packagerStatus == PackagerStatus.UNKNOWN) {
84+
throw new Exception("Did not recognize the server at " + config.getPackagerHost() +
85+
". Please stop the service listening at this address and try again.");
86+
}
87+
}
4188

42-
InputStream packageStream = packageUrl.openStream();
43-
OutputStream bundleStream = new FileOutputStream(bundle);
44-
IOUtils.copy(packageStream, bundleStream);
45-
IOUtils.closeQuietly(packageStream);
46-
IOUtils.closeQuietly(bundleStream);
89+
/**
90+
* Tests if there is an HTTP server running at the configured address and if it is our packager.
91+
* See {@link PackagerStatus} for the possible return values and their meaning.
92+
*
93+
* @param config the project config that contains packager address information
94+
*/
95+
private PackagerStatus getPackagerStatus(ReactGradleExtension config) throws URISyntaxException {
96+
try {
97+
URL statusUrl = new URI("http", config.getPackagerHost(), "/status", null, null).toURL();
98+
HttpURLConnection conn = (HttpURLConnection) statusUrl.openConnection();
99+
if (conn.getResponseCode() != 200) {
100+
// something else must be running on this port
101+
return PackagerStatus.UNKNOWN;
102+
}
103+
InputStream is = conn.getInputStream();
104+
String status = IOUtils.toString(is);
105+
IOUtils.closeQuietly(is);
106+
return status.contains("packager-status:running")
107+
? PackagerStatus.RUNNING
108+
: PackagerStatus.UNKNOWN;
109+
} catch (IOException e) {
110+
// connect must have failed
111+
return PackagerStatus.NOT_RUNNING;
112+
}
113+
}
114+
115+
/**
116+
* Tries to spawn a process to run the packager server. Currently support OSX and Linux by running
117+
* {@code open launchPackager.command} and {@code xterm -e bash launchPackager.command}
118+
* respectively. Always waits 5 seconds for the server to finish initializing.
119+
*
120+
* @return {@code true} if the server process was started successfully, {@code false} otherwise.
121+
*/
122+
private boolean startPackager() throws IOException, InterruptedException {
123+
if (SystemUtils.IS_OS_MAC_OSX || SystemUtils.IS_OS_LINUX) {
124+
File jsRoot = new File(getProject().getRootDir(), "..").getCanonicalFile();
125+
String launchPackagerScript =
126+
"node_modules/react-native/packager/launchPackager.command";
127+
if (SystemUtils.IS_OS_MAC_OSX) {
128+
Runtime.getRuntime().exec(new String[]{"open", launchPackagerScript}, null, jsRoot);
129+
} else if (SystemUtils.IS_OS_LINUX) {
130+
Runtime.getRuntime()
131+
.exec(new String[]{"xterm", "-e", "bash", launchPackagerScript}, null, jsRoot);
132+
}
133+
// wait for server to be ready
134+
Thread.sleep(5000);
135+
return true;
136+
}
137+
return false;
47138
}
48139

49140
/**
Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
package com.facebook.react;
22

3-
import java.io.IOException;
4-
import java.net.URISyntaxException;
5-
63
import org.gradle.api.tasks.TaskAction;
74

85
/**
@@ -11,7 +8,7 @@
118
public class PackageDebugJsTask extends AbstractPackageJsTask {
129

1310
@TaskAction
14-
public void packageJS() throws IOException, URISyntaxException {
11+
public void packageJS() throws Exception {
1512
copyBundle(true);
1613
}
1714
}
Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
package com.facebook.react;
22

3-
import java.io.IOException;
4-
import java.net.URISyntaxException;
5-
63
import org.gradle.api.tasks.TaskAction;
74

85
/**
@@ -11,7 +8,7 @@
118
public class PackageReleaseJsTask extends AbstractPackageJsTask {
129

1310
@TaskAction
14-
public void packageJS() throws IOException, URISyntaxException {
11+
public void packageJS() throws Exception {
1512
copyBundle(false);
1613
}
1714
}

0 commit comments

Comments
 (0)