Skip to content

Commit cd87ada

Browse files
committed
Use unchecked exceptions instead of checked exceptions
1 parent 8d5c21b commit cd87ada

File tree

9 files changed

+279
-57
lines changed

9 files changed

+279
-57
lines changed

cdtp-java-client/src/main/java/com/github/kklisura/cdtp/App.java

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,47 +20,51 @@
2020
* #L%
2121
*/
2222

23+
import static com.github.kklisura.cdtp.utils.ChromeDevToolsUtils.waitForEvent;
24+
2325
import com.github.kklisura.cdtp.launch.ChromeLauncher;
2426
import com.github.kklisura.cdtp.protocol.commands.Network;
2527
import com.github.kklisura.cdtp.protocol.commands.Page;
2628
import com.github.kklisura.cdtp.services.ChromeDevToolsService;
2729
import com.github.kklisura.cdtp.services.ChromeService;
2830
import com.github.kklisura.cdtp.services.types.ChromeTab;
29-
import java.util.concurrent.CountDownLatch;
31+
import java.util.Arrays;
3032

3133
/** Hello world! */
3234
public class App {
33-
public static void main(String[] args) throws Exception {
35+
public static void main(String[] args) throws InterruptedException {
3436
// Create chrome launcher
35-
try (final ChromeLauncher chromeLauncher = new ChromeLauncher()) {
36-
37-
// Launch chrome either as headless (true) or no.
38-
final ChromeService chromeService = chromeLauncher.launch(true);
37+
try (final ChromeLauncher launcher = new ChromeLauncher()) {
38+
// Launch chrome either as headless (true) or regular (false).
39+
final ChromeService chromeService = launcher.launch(false);
3940

40-
// Create empty tab (about:blank)
41+
// Create empty tab ie about:blank.
4142
final ChromeTab tab = chromeService.createTab();
4243

43-
// Get dev tools service to this tab
44-
try (ChromeDevToolsService devToolsService = chromeService.createDevToolsService(tab)) {
44+
// Get DevTools service to this tab
45+
try (final ChromeDevToolsService devToolsService = chromeService.createDevToolsService(tab)) {
46+
// Get individual commands
4547
final Network network = devToolsService.getNetwork();
4648
final Page page = devToolsService.getPage();
4749

50+
// Log requests that will be sent.
4851
network.onRequestWillBeSent(event -> System.out.println(event.getRequest().getUrl()));
49-
network.enable();
5052

51-
page.navigate("http://klix.ba");
53+
network.setBlockedURLs(Arrays.asList("**/*.png", "**/*.css"));
54+
55+
// Enable network events.
56+
network.enable();
5257

53-
CountDownLatch countDownLatch = new CountDownLatch(1);
58+
// Navigate to github.com
59+
page.navigate("http://github.com");
5460

55-
network.onLoadingFinished(
56-
event -> {
57-
System.out.println("Finished");
58-
countDownLatch.countDown();
59-
});
61+
// Wait until loading is finished.
62+
waitForEvent(network::onLoadingFinished);
6063

61-
countDownLatch.await();
64+
Thread.sleep(10000);
6265
}
6366

67+
// Close the tab.
6468
chromeService.closeTab(tab);
6569
}
6670
}

cdtp-java-client/src/main/java/com/github/kklisura/cdtp/launch/ChromeArguments.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ public static Builder builder() {
313313
*
314314
* @param headless Headless.
315315
* @return Builder. builder
316+
* @throws RuntimeException If it fails to create temp directory for user-data-dir.
316317
*/
317318
public static Builder defaults(boolean headless) {
318319
Builder builder =

cdtp-java-client/src/main/java/com/github/kklisura/cdtp/launch/ChromeLauncher.java

Lines changed: 69 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,17 @@
2020
* #L%
2121
*/
2222

23+
import static com.github.kklisura.cdtp.utils.ChromeDevToolsUtils.closeQuietly;
24+
2325
import com.github.kklisura.cdtp.launch.config.ChromeLauncherConfiguration;
26+
import com.github.kklisura.cdtp.launch.exceptions.ChromeProcessException;
27+
import com.github.kklisura.cdtp.launch.exceptions.ChromeProcessTimeoutException;
2428
import com.github.kklisura.cdtp.launch.support.ProcessLauncher;
2529
import com.github.kklisura.cdtp.launch.support.annotations.ChromeArgument;
2630
import com.github.kklisura.cdtp.launch.support.impl.ProcessLauncherImpl;
2731
import com.github.kklisura.cdtp.services.ChromeService;
2832
import com.github.kklisura.cdtp.services.impl.ChromeServiceImpl;
2933
import java.io.BufferedReader;
30-
import java.io.Closeable;
3134
import java.io.IOException;
3235
import java.io.InputStreamReader;
3336
import java.lang.reflect.Field;
@@ -40,6 +43,7 @@
4043
import java.util.concurrent.TimeUnit;
4144
import java.util.concurrent.atomic.AtomicBoolean;
4245
import java.util.concurrent.atomic.AtomicInteger;
46+
import java.util.concurrent.atomic.AtomicReference;
4347
import java.util.regex.Matcher;
4448
import java.util.regex.Pattern;
4549
import org.slf4j.Logger;
@@ -56,7 +60,7 @@ public class ChromeLauncher implements AutoCloseable {
5660

5761
private static final Logger LOGGER = LoggerFactory.getLogger(ChromeLauncher.class);
5862

59-
private static final Pattern DEVTOOLS_LISTENING_LINE_MATCH =
63+
private static final Pattern DEVTOOLS_LISTENING_LINE_PATTERN =
6064
Pattern.compile("^DevTools listening on ws:\\/\\/.+?:(\\d+)\\/");
6165

6266
private static final String[] CHROME_BINARIES =
@@ -124,10 +128,12 @@ public ChromeLauncher(
124128
* @param chromeBinaryPath the chrome binary path
125129
* @param chromeArguments the chrome arguments
126130
* @return Chrome service.
127-
* @throws IOException the io exception
131+
* @throws IllegalStateException If chrome process has already been started.
132+
* @throws ChromeProcessException If an I/O error occurs during chrome process start.
133+
* @throws ChromeProcessTimeoutException If timeout expired while waiting for chrome to start.
128134
*/
129135
public ChromeService launch(Path chromeBinaryPath, ChromeArguments chromeArguments)
130-
throws IOException {
136+
throws ChromeProcessException {
131137
int port = launchChromeProcess(chromeBinaryPath, chromeArguments);
132138
return new ChromeServiceImpl(port);
133139
}
@@ -137,9 +143,11 @@ public ChromeService launch(Path chromeBinaryPath, ChromeArguments chromeArgumen
137143
*
138144
* @param chromeArguments the chrome arguments
139145
* @return Chrome service.
140-
* @throws IOException the io exception
146+
* @throws IllegalStateException If chrome process has already been started.
147+
* @throws ChromeProcessException If an I/O error occurs during chrome process start.
148+
* @throws ChromeProcessTimeoutException If timeout expired while waiting for chrome to start.
141149
*/
142-
public ChromeService launch(ChromeArguments chromeArguments) throws IOException {
150+
public ChromeService launch(ChromeArguments chromeArguments) throws ChromeProcessException {
143151
return launch(getChromeBinaryPath(), chromeArguments);
144152
}
145153

@@ -148,19 +156,23 @@ public ChromeService launch(ChromeArguments chromeArguments) throws IOException
148156
*
149157
* @param headless Headless flag.
150158
* @return Chrome service.
151-
* @throws IOException the io exception
159+
* @throws IllegalStateException If chrome process has already been started.
160+
* @throws ChromeProcessException If an I/O error occurs during chrome process start.
161+
* @throws ChromeProcessTimeoutException If timeout expired while waiting for chrome to start.
152162
*/
153-
public ChromeService launch(boolean headless) throws IOException {
163+
public ChromeService launch(boolean headless) throws ChromeProcessException {
154164
return launch(getChromeBinaryPath(), ChromeArguments.defaults(headless).build());
155165
}
156166

157167
/**
158168
* Launches a headless chrome with default arguments.
159169
*
160170
* @return Chrome service.
161-
* @throws IOException the io exception
171+
* @throws IllegalStateException If chrome process has already been started.
172+
* @throws ChromeProcessException If an I/O error occurs during chrome process start.
173+
* @throws ChromeProcessTimeoutException If timeout expired while waiting for chrome to start.
162174
*/
163-
public ChromeService launch() throws IOException {
175+
public ChromeService launch() throws ChromeProcessException {
164176
return launch(true);
165177
}
166178

@@ -177,6 +189,8 @@ public Path getChromeBinaryPath() {
177189
if (isExecutable) {
178190
return Paths.get(envChrome).toAbsolutePath();
179191
}
192+
193+
throw new RuntimeException("CHROME_PATH environment value is not an executable file.");
180194
}
181195

182196
for (String binary : CHROME_BINARIES) {
@@ -220,8 +234,18 @@ public void close() {
220234
}
221235
}
222236

237+
/**
238+
* Launches a chrome process given a chrome binary and its arguments.
239+
*
240+
* @param chromeBinary Chrome binary path.
241+
* @param chromeArguments Chrome arguments.
242+
* @return Port on which devtools is listening.
243+
* @throws IllegalStateException If chrome process has already been started.
244+
* @throws ChromeProcessException If an I/O error occurs during chrome process start.
245+
* @throws ChromeProcessTimeoutException If timeout expired while waiting for chrome to start.
246+
*/
223247
private int launchChromeProcess(Path chromeBinary, ChromeArguments chromeArguments)
224-
throws IOException {
248+
throws ChromeProcessException {
225249
if (chromeProcess != null) {
226250
throw new IllegalStateException("Chrome process has already been started started.");
227251
}
@@ -235,34 +259,59 @@ private int launchChromeProcess(Path chromeBinary, ChromeArguments chromeArgumen
235259
LOGGER.info(
236260
"Launching chrome process {} with arguments {}", chromeBinary.toString(), argumentsMap);
237261

238-
chromeProcess = processLauncher.launch(chromeBinary.toString(), arguments);
239-
return waitForDevToolsServer(chromeProcess);
262+
try {
263+
chromeProcess = processLauncher.launch(chromeBinary.toString(), arguments);
264+
return waitForDevToolsServer(chromeProcess);
265+
} catch (IOException e) {
266+
// Unsubscribe from registry on exceptions.
267+
shutdownHookRegistry.remove(shutdownHookThread);
268+
269+
throw new ChromeProcessException("Failed starting chrome process.", e);
270+
} catch (Exception e) {
271+
close();
272+
throw e;
273+
}
240274
}
241275

242-
private int waitForDevToolsServer(final Process process) {
276+
/**
277+
* Waits for DevTools server is up on chrome process.
278+
*
279+
* @param process Chrome process.
280+
* @return DevTools listening port.
281+
* @throws ChromeProcessTimeoutException If timeout expired while waiting for chrome process.
282+
*/
283+
private int waitForDevToolsServer(final Process process) throws ChromeProcessTimeoutException {
243284
final AtomicInteger port = new AtomicInteger();
244285
final AtomicBoolean success = new AtomicBoolean(false);
286+
final AtomicReference<String> chromeOutput = new AtomicReference<>("");
245287

246288
Thread readLineThread =
247289
new Thread(
248290
() -> {
291+
StringBuilder chromeOutputBuilder = new StringBuilder();
249292
BufferedReader reader = null;
250293
try {
251294
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
252295

253296
// Wait for DevTools listening line and extract port number.
254297
String line;
255298
while ((line = reader.readLine()) != null) {
256-
Matcher matcher = DEVTOOLS_LISTENING_LINE_MATCH.matcher(line);
299+
Matcher matcher = DEVTOOLS_LISTENING_LINE_PATTERN.matcher(line);
257300
if (matcher.find()) {
258301
port.set(Integer.parseInt(matcher.group(1)));
259302
success.set(true);
260303
break;
261304
}
305+
306+
if (chromeOutputBuilder.length() != 0) {
307+
chromeOutputBuilder.append(System.lineSeparator());
308+
}
309+
chromeOutputBuilder.append(line);
262310
}
263311
} catch (Exception e) {
264312
LOGGER.error("Failed while waiting for dev tools server.", e);
265313
} finally {
314+
chromeOutput.set(chromeOutputBuilder.toString());
266315
closeQuietly(reader);
267316
}
268317
});
@@ -274,7 +323,11 @@ private int waitForDevToolsServer(final Process process) {
274323

275324
if (!success.get()) {
276325
close(readLineThread);
277-
throw new RuntimeException("Failed while waiting for chrome to start. Timeout expired!");
326+
327+
throw new ChromeProcessTimeoutException(
328+
"Failed while waiting for chrome to start: "
329+
+ "Timeout expired! Chrome output: "
330+
+ chromeOutput.get());
278331
}
279332
} catch (InterruptedException e) {
280333
close(readLineThread);
@@ -287,7 +340,6 @@ private int waitForDevToolsServer(final Process process) {
287340
}
288341

289342
private void close(Thread thread) {
290-
close();
291343
try {
292344
thread.join(TimeUnit.SECONDS.toMillis(configuration.getThreadWaitTime()));
293345
} catch (InterruptedException e) {
@@ -332,16 +384,6 @@ private Map<String, Object> getArguments(ChromeArguments arguments) {
332384
return args;
333385
}
334386

335-
private static void closeQuietly(Closeable closeable) {
336-
if (closeable != null) {
337-
try {
338-
closeable.close();
339-
} catch (IOException e) {
340-
// Ignore this exception.
341-
}
342-
}
343-
}
344-
345387
/** Environment interface. */
346388
@FunctionalInterface
347389
public interface Environment {
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.github.kklisura.cdtp.launch.exceptions;
2+
3+
/*-
4+
* #%L
5+
* cdpt-java-client
6+
* %%
7+
* Copyright (C) 2018 Kenan Klisura
8+
* %%
9+
* Licensed under the Apache License, Version 2.0 (the "License");
10+
* you may not use this file except in compliance with the License.
11+
* You may obtain a copy of the License at
12+
*
13+
* http://www.apache.org/licenses/LICENSE-2.0
14+
*
15+
* Unless required by applicable law or agreed to in writing, software
16+
* distributed under the License is distributed on an "AS IS" BASIS,
17+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
* See the License for the specific language governing permissions and
19+
* limitations under the License.
20+
* #L%
21+
*/
22+
23+
/**
24+
* Chrome process exception raised when error occurs during chrome startup.
25+
*
26+
* @author Kenan Klisura
27+
*/
28+
public class ChromeProcessException extends RuntimeException {
29+
/**
30+
* Instantiates a new Chrome process exception.
31+
*
32+
* @param message Message.
33+
*/
34+
public ChromeProcessException(String message) {
35+
super(message);
36+
}
37+
38+
/**
39+
* Instantiates a new Chrome process exception.
40+
*
41+
* @param message Message.
42+
* @param cause Root exception cause.
43+
*/
44+
public ChromeProcessException(String message, Throwable cause) {
45+
super(message, cause);
46+
}
47+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.github.kklisura.cdtp.launch.exceptions;
2+
3+
/*-
4+
* #%L
5+
* cdpt-java-client
6+
* %%
7+
* Copyright (C) 2018 Kenan Klisura
8+
* %%
9+
* Licensed under the Apache License, Version 2.0 (the "License");
10+
* you may not use this file except in compliance with the License.
11+
* You may obtain a copy of the License at
12+
*
13+
* http://www.apache.org/licenses/LICENSE-2.0
14+
*
15+
* Unless required by applicable law or agreed to in writing, software
16+
* distributed under the License is distributed on an "AS IS" BASIS,
17+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
* See the License for the specific language governing permissions and
19+
* limitations under the License.
20+
* #L%
21+
*/
22+
23+
/**
24+
* Exception thrown when timeout expired when waiting for chrome process.
25+
*
26+
* @author Kenan Klisura
27+
*/
28+
public class ChromeProcessTimeoutException extends ChromeProcessException {
29+
/**
30+
* Instantiates a new Chrome process timeout exception.
31+
*
32+
* @param message Message.
33+
*/
34+
public ChromeProcessTimeoutException(String message) {
35+
super(message);
36+
}
37+
38+
/**
39+
* Instantiates a new Chrome process timeout exception.
40+
*
41+
* @param message Message.
42+
* @param cause Exception cause
43+
*/
44+
public ChromeProcessTimeoutException(String message, Throwable cause) {
45+
super(message, cause);
46+
}
47+
}

0 commit comments

Comments
 (0)