1 | /* | |
2 | * Copyright 2006 - 2013 | |
3 | * Stefan Balev <stefan.balev@graphstream-project.org> | |
4 | * Julien Baudry <julien.baudry@graphstream-project.org> | |
5 | * Antoine Dutot <antoine.dutot@graphstream-project.org> | |
6 | * Yoann Pign�� <yoann.pigne@graphstream-project.org> | |
7 | * Guilhelm Savin <guilhelm.savin@graphstream-project.org> | |
8 | * | |
9 | * This file is part of GraphStream <http://graphstream-project.org>. | |
10 | * | |
11 | * GraphStream is a library whose purpose is to handle static or dynamic | |
12 | * graph, create them from scratch, file or any source and display them. | |
13 | * | |
14 | * This program is free software distributed under the terms of two licenses, the | |
15 | * CeCILL-C license that fits European law, and the GNU Lesser General Public | |
16 | * License. You can use, modify and/ or redistribute the software under the terms | |
17 | * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following | |
18 | * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by | |
19 | * the Free Software Foundation, either version 3 of the License, or (at your | |
20 | * option) any later version. | |
21 | * | |
22 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY | |
23 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A | |
24 | * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. | |
25 | * | |
26 | * You should have received a copy of the GNU Lesser General Public License | |
27 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
28 | * | |
29 | * The fact that you are presently reading this means that you have had | |
30 | * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms. | |
31 | */ | |
32 | package org.graphstream.stream.net; | |
33 | ||
34 | import java.io.IOException; | |
35 | import java.io.UnsupportedEncodingException; | |
36 | import java.net.InetSocketAddress; | |
37 | import java.net.URLDecoder; | |
38 | import java.util.HashMap; | |
39 | import java.util.LinkedList; | |
40 | ||
41 | import org.graphstream.stream.SourceBase; | |
42 | ||
43 | import com.sun.net.httpserver.HttpExchange; | |
44 | import com.sun.net.httpserver.HttpHandler; | |
45 | import com.sun.net.httpserver.HttpServer; | |
46 | ||
47 | /** | |
48 | * This source allows to control a graph from a web browser. Control is done | |
49 | * calling the following url : | |
50 | * <code>http://host/graphId/edit?q=ACTION&...</code>. ACTION is one of the | |
51 | * following action : | |
52 | * <ul> | |
53 | * <li>an : add node</li> | |
54 | * <li>cn : change node</li> | |
55 | * <li>dn : delete node</li> | |
56 | * <li>ae : add edge</li> | |
57 | * <li>ce : change edge</li> | |
58 | * <li>de : delete edge</li> | |
59 | * <li>cg : change graph</li> | |
60 | * <li>st : step begins</li> | |
61 | * <li>clear : clear the whole graph</li> | |
62 | * </ul> | |
63 | * | |
64 | * Each of these actions needs some argument. | |
65 | * <dl> | |
66 | * <dt>an</dt> | |
67 | * <dd> | |
68 | * <ul> | |
69 | * <li>id</li> | |
70 | * </ul> | |
71 | * </dd> | |
72 | * <dt>cn</dt> | |
73 | * <dd> | |
74 | * <ul> | |
75 | * <li>id</li> | |
76 | * <li>key</li> | |
77 | * <li>value</li> | |
78 | * </ul> | |
79 | * </dd> | |
80 | * <dt>dn</dt> | |
81 | * <dd> | |
82 | * <ul> | |
83 | * <li>id</li> | |
84 | * </ul> | |
85 | * </dd> | |
86 | * <dt>ae</dt> | |
87 | * <dd> | |
88 | * <ul> | |
89 | * <li>id</li> | |
90 | * <li>from</li> | |
91 | * <li>to</li> | |
92 | * <li>[directed]</li> | |
93 | * </ul> | |
94 | * </dd> | |
95 | * <dt>ce</dt> | |
96 | * <dd> | |
97 | * <ul> | |
98 | * <li>id</li> | |
99 | * <li>key</li> | |
100 | * <li>value</li> | |
101 | * </ul> | |
102 | * </dd> | |
103 | * <dt>de</dt> | |
104 | * <dd> | |
105 | * <ul> | |
106 | * <li>id</li> | |
107 | * </ul> | |
108 | * </dd> | |
109 | * <dt>cg</dt> | |
110 | * <dd> | |
111 | * <ul> | |
112 | * <li>key</li> | |
113 | * <li>value</li> | |
114 | * </ul> | |
115 | * </dd> | |
116 | * <dt>st</dt> | |
117 | * <dd> | |
118 | * <ul> | |
119 | * <li>step</li> | |
120 | * </ul> | |
121 | * </dd> | |
122 | * </dl> | |
123 | */ | |
124 | public class HTTPSource extends SourceBase { | |
125 | ||
126 | /** | |
127 | * Http server. | |
128 | */ | |
129 | protected final HttpServer server; | |
130 | ||
131 | /** | |
132 | * Create a new http source. The source will be available on | |
133 | * 'http://localhost/graphId' where graphId is passed as parameter of this | |
134 | * constructor. | |
135 | * | |
136 | * @param graphId | |
137 | * id of the graph | |
138 | * @param port | |
139 | * port on which server will be bound | |
140 | * @throws IOException | |
141 | * if server creation failed. | |
142 | */ | |
143 | public HTTPSource(String graphId, int port) throws IOException { | |
144 | super(String.format("http://%s", graphId)); | |
145 | ||
146 | server = HttpServer.create(new InetSocketAddress(port), 4); | |
147 | server.createContext(String.format("/%s/edit", graphId), | |
148 | new EditHandler()); | |
149 | ||
150 | } | |
151 | ||
152 | /** | |
153 | * Start the http server. | |
154 | */ | |
155 | public void start() { | |
156 |
1
1. start : removed call to com/sun/net/httpserver/HttpServer::start → NO_COVERAGE |
server.start(); |
157 | } | |
158 | ||
159 | /** | |
160 | * Stop the http server. | |
161 | */ | |
162 | public void stop() { | |
163 |
1
1. stop : removed call to com/sun/net/httpserver/HttpServer::stop → NO_COVERAGE |
server.stop(0); |
164 | } | |
165 | ||
166 | private class EditHandler implements HttpHandler { | |
167 | ||
168 | public void handle(HttpExchange ex) throws IOException { | |
169 | HashMap<String, Object> get = GET(ex); | |
170 | Action a; | |
171 | ||
172 | try { | |
173 | a = Action.valueOf(get.get("q").toString().toUpperCase()); | |
174 | } catch (Exception e) { | |
175 |
1
1. handle : removed call to org/graphstream/stream/net/HTTPSource::error → NO_COVERAGE |
error(ex, "invalid action"); |
176 | return; | |
177 | } | |
178 | ||
179 | switch (a) { | |
180 | case AN: | |
181 |
1
1. handle : removed call to org/graphstream/stream/net/HTTPSource::sendNodeAdded → NO_COVERAGE |
HTTPSource.this.sendNodeAdded(sourceId, get.get("id") |
182 | .toString()); | |
183 | break; | |
184 | case CN: | |
185 | break; | |
186 | case DN: | |
187 |
1
1. handle : removed call to org/graphstream/stream/net/HTTPSource::sendNodeRemoved → NO_COVERAGE |
HTTPSource.this.sendNodeRemoved(sourceId, get.get("id") |
188 | .toString()); | |
189 | break; | |
190 | case AE: | |
191 |
1
1. handle : removed call to org/graphstream/stream/net/HTTPSource::sendEdgeAdded → NO_COVERAGE |
HTTPSource.this.sendEdgeAdded(sourceId, get.get("id") |
192 | .toString(), get.get("from").toString(), get.get("to") | |
193 | .toString(), get.containsKey("directed")); | |
194 | break; | |
195 | case CE: | |
196 | break; | |
197 | case DE: | |
198 |
1
1. handle : removed call to org/graphstream/stream/net/HTTPSource::sendEdgeRemoved → NO_COVERAGE |
HTTPSource.this.sendEdgeRemoved(sourceId, get.get("id") |
199 | .toString()); | |
200 | break; | |
201 | case CG: | |
202 | break; | |
203 | case ST: | |
204 |
1
1. handle : removed call to org/graphstream/stream/net/HTTPSource::sendStepBegins → NO_COVERAGE |
HTTPSource.this.sendStepBegins(sourceId, Double.valueOf(get |
205 | .get("step").toString())); | |
206 | break; | |
207 | } | |
208 | ||
209 |
1
1. handle : removed call to com/sun/net/httpserver/HttpExchange::sendResponseHeaders → NO_COVERAGE |
ex.sendResponseHeaders(200, 0); |
210 |
1
1. handle : removed call to java/io/OutputStream::close → NO_COVERAGE |
ex.getResponseBody().close(); |
211 | } | |
212 | } | |
213 | ||
214 | protected static void error(HttpExchange ex, String message) | |
215 | throws IOException { | |
216 | byte[] data = message.getBytes(); | |
217 | ||
218 |
1
1. error : removed call to com/sun/net/httpserver/HttpExchange::sendResponseHeaders → NO_COVERAGE |
ex.sendResponseHeaders(400, data.length); |
219 |
1
1. error : removed call to java/io/OutputStream::write → NO_COVERAGE |
ex.getResponseBody().write(data); |
220 |
1
1. error : removed call to java/io/OutputStream::close → NO_COVERAGE |
ex.getResponseBody().close(); |
221 | } | |
222 | ||
223 | @SuppressWarnings("unchecked") | |
224 | protected static HashMap<String, Object> GET(HttpExchange ex) { | |
225 | HashMap<String, Object> get = new HashMap<String, Object>(); | |
226 | String[] args = ex.getRequestURI().getRawQuery().split("[&]"); | |
227 | ||
228 |
3
1. GET : changed conditional boundary → NO_COVERAGE 2. GET : Changed increment from 1 to -1 → NO_COVERAGE 3. GET : negated conditional → NO_COVERAGE |
for (String arg : args) { |
229 | String[] kv = arg.split("[=]"); | |
230 | String k, v; | |
231 | ||
232 | k = null; | |
233 | v = null; | |
234 | ||
235 | try { | |
236 |
2
1. GET : changed conditional boundary → NO_COVERAGE 2. GET : negated conditional → NO_COVERAGE |
if (kv.length > 0) |
237 | k = URLDecoder.decode(kv[0], System | |
238 | .getProperty("file.encoding")); | |
239 | ||
240 |
2
1. GET : changed conditional boundary → NO_COVERAGE 2. GET : negated conditional → NO_COVERAGE |
if (kv.length > 1) |
241 | v = URLDecoder.decode(kv[1], System | |
242 | .getProperty("file.encoding")); | |
243 | ||
244 |
1
1. GET : negated conditional → NO_COVERAGE |
if (get.containsKey(k)) { |
245 | Object o = get.get(k); | |
246 | ||
247 |
1
1. GET : negated conditional → NO_COVERAGE |
if (o instanceof LinkedList<?>) |
248 | ((LinkedList<Object>) o).add(v); | |
249 | else { | |
250 | LinkedList<Object> l = new LinkedList<Object>(); | |
251 | l.add(o); | |
252 | l.add(v); | |
253 | get.put(k, l); | |
254 | } | |
255 | } else { | |
256 | get.put(k, v); | |
257 | } | |
258 | } catch (UnsupportedEncodingException e) { | |
259 |
1
1. GET : removed call to java/io/UnsupportedEncodingException::printStackTrace → NO_COVERAGE |
e.printStackTrace(); |
260 | } | |
261 | } | |
262 | ||
263 |
1
1. GET : mutated return of Object value for org/graphstream/stream/net/HTTPSource::GET to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return get; |
264 | } | |
265 | ||
266 | static enum Action { | |
267 | AN, CN, DN, AE, CE, DE, CG, ST, CLEAR | |
268 | } | |
269 | } | |
Mutations | ||
156 |
1.1 |
|
163 |
1.1 |
|
175 |
1.1 |
|
181 |
1.1 |
|
187 |
1.1 |
|
191 |
1.1 |
|
198 |
1.1 |
|
204 |
1.1 |
|
209 |
1.1 |
|
210 |
1.1 |
|
218 |
1.1 |
|
219 |
1.1 |
|
220 |
1.1 |
|
228 |
1.1 2.2 3.3 |
|
236 |
1.1 2.2 |
|
240 |
1.1 2.2 |
|
244 |
1.1 |
|
247 |
1.1 |
|
259 |
1.1 |
|
263 |
1.1 |