HTTPSource.java

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
Location : start
Killed by : none
removed call to com/sun/net/httpserver/HttpServer::start → NO_COVERAGE

163

1.1
Location : stop
Killed by : none
removed call to com/sun/net/httpserver/HttpServer::stop → NO_COVERAGE

175

1.1
Location : handle
Killed by : none
removed call to org/graphstream/stream/net/HTTPSource::error → NO_COVERAGE

181

1.1
Location : handle
Killed by : none
removed call to org/graphstream/stream/net/HTTPSource::sendNodeAdded → NO_COVERAGE

187

1.1
Location : handle
Killed by : none
removed call to org/graphstream/stream/net/HTTPSource::sendNodeRemoved → NO_COVERAGE

191

1.1
Location : handle
Killed by : none
removed call to org/graphstream/stream/net/HTTPSource::sendEdgeAdded → NO_COVERAGE

198

1.1
Location : handle
Killed by : none
removed call to org/graphstream/stream/net/HTTPSource::sendEdgeRemoved → NO_COVERAGE

204

1.1
Location : handle
Killed by : none
removed call to org/graphstream/stream/net/HTTPSource::sendStepBegins → NO_COVERAGE

209

1.1
Location : handle
Killed by : none
removed call to com/sun/net/httpserver/HttpExchange::sendResponseHeaders → NO_COVERAGE

210

1.1
Location : handle
Killed by : none
removed call to java/io/OutputStream::close → NO_COVERAGE

218

1.1
Location : error
Killed by : none
removed call to com/sun/net/httpserver/HttpExchange::sendResponseHeaders → NO_COVERAGE

219

1.1
Location : error
Killed by : none
removed call to java/io/OutputStream::write → NO_COVERAGE

220

1.1
Location : error
Killed by : none
removed call to java/io/OutputStream::close → NO_COVERAGE

228

1.1
Location : GET
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : GET
Killed by : none
Changed increment from 1 to -1 → NO_COVERAGE

3.3
Location : GET
Killed by : none
negated conditional → NO_COVERAGE

236

1.1
Location : GET
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : GET
Killed by : none
negated conditional → NO_COVERAGE

240

1.1
Location : GET
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : GET
Killed by : none
negated conditional → NO_COVERAGE

244

1.1
Location : GET
Killed by : none
negated conditional → NO_COVERAGE

247

1.1
Location : GET
Killed by : none
negated conditional → NO_COVERAGE

259

1.1
Location : GET
Killed by : none
removed call to java/io/UnsupportedEncodingException::printStackTrace → NO_COVERAGE

263

1.1
Location : GET
Killed by : none
mutated return of Object value for org/graphstream/stream/net/HTTPSource::GET to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 0.33