blob: f74f1bb91b6db67caea7c3454973c665af7fc498 [file] [log] [blame]
Pierre De Rop6e8f9212016-02-20 21:44:59 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
Pierre De Ropfaca2892016-01-31 23:27:05 +000019package org.apache.felix.dm.lambda.samples.future;
20
21import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
22
23import java.io.IOException;
24import java.net.URL;
25import java.util.ArrayList;
26import java.util.List;
27import java.util.Scanner;
28import java.util.concurrent.CompletableFuture;
29import java.util.regex.Matcher;
30import java.util.regex.Pattern;
31
32import org.apache.felix.dm.Component;
33import org.osgi.service.log.LogService;
34
35/**
36 * Provides all hrefs found from a given web page.
37 */
38public class PageLinksImpl implements PageLinks {
39 private LogService m_log;
40 private final static String HREF_PATTERN = "<a\\s+href\\s*=\\s*(\"[^\"]*\"|[^\\s>]*)\\s*>";
41 private List<String> m_links; // web page hrefs (links).
42 private String m_url;
43
44 PageLinksImpl(String url) {
45 m_url = url;
46 }
47
48 void bind(LogService log) {
49 m_log = log;
50 }
51
52 void init(Component c) {
53 // asynchronously download the content of the URL specified in the constructor.
54 CompletableFuture<List<String>> futureLinks = CompletableFuture.supplyAsync(() -> download(m_url))
55 .thenApply(this::parseLinks);
56
57 // Add the future dependency so we'll be started once the CompletableFuture "futureLinks" has completed.
Pierre De Rop11527502016-02-18 21:07:16 +000058 component(c, comp -> comp.withFuture(futureLinks, future -> future.complete(this::setLinks)));
Pierre De Ropfaca2892016-01-31 23:27:05 +000059 }
60
61 // Called when our future has completed.
62 void setLinks(List<String> links) {
63 m_links = links;
64 }
65
66 // once our future has completed, our component is started.
67 void start() {
Pierre De Rop11527502016-02-18 21:07:16 +000068 m_log.log(LogService.LOG_WARNING, "Service starting: number of links found from Felix web site: " + m_links.size());
Pierre De Ropfaca2892016-01-31 23:27:05 +000069 }
70
71 @Override
72 public List<String> getLinks() {
73 return m_links;
74 }
75
76 private String download(String url) {
77 try (Scanner in = new Scanner(new URL(url).openStream())) {
78 StringBuilder builder = new StringBuilder();
79 while (in.hasNextLine()) {
80 builder.append(in.nextLine());
81 builder.append("\n");
82 }
83 return builder.toString();
84 } catch (IOException ex) {
85 RuntimeException rex = new RuntimeException();
86 rex.initCause(ex);
87 throw rex;
88 }
89 }
90
91 private List<String> parseLinks(String content) {
92 Pattern pattern = Pattern.compile(HREF_PATTERN, Pattern.CASE_INSENSITIVE);
93 Matcher matcher = pattern.matcher(content);
94 List<String> result = new ArrayList<>();
95 while (matcher.find())
96 result.add(matcher.group(1));
97 return result;
98 }
99}