diff options
author | Anton Tananaev <anton.tananaev@gmail.com> | 2015-07-17 14:32:55 +1200 |
---|---|---|
committer | Anton Tananaev <anton.tananaev@gmail.com> | 2015-07-17 14:32:55 +1200 |
commit | b6ba5a8ac60e8013e22ed44b15ffdc5ad8097060 (patch) | |
tree | fc06c28d649537226aee29fbeee042f3a023b5f2 /src/org/traccar/web | |
parent | 04afe342615995e773d848be68eef40dc9925197 (diff) | |
download | trackermap-server-b6ba5a8ac60e8013e22ed44b15ffdc5ad8097060.tar.gz trackermap-server-b6ba5a8ac60e8013e22ed44b15ffdc5ad8097060.tar.bz2 trackermap-server-b6ba5a8ac60e8013e22ed44b15ffdc5ad8097060.zip |
Rename package from http to web
Diffstat (limited to 'src/org/traccar/web')
-rw-r--r-- | src/org/traccar/web/AsyncServlet.java | 211 | ||||
-rw-r--r-- | src/org/traccar/web/BaseServlet.java | 91 | ||||
-rw-r--r-- | src/org/traccar/web/CommandsServlet.java | 58 | ||||
-rw-r--r-- | src/org/traccar/web/DeviceServlet.java | 75 | ||||
-rw-r--r-- | src/org/traccar/web/EnumFactory.java | 20 | ||||
-rw-r--r-- | src/org/traccar/web/JsonConverter.java | 155 | ||||
-rw-r--r-- | src/org/traccar/web/JsonIgnore.java | 12 | ||||
-rw-r--r-- | src/org/traccar/web/MainServlet.java | 80 | ||||
-rw-r--r-- | src/org/traccar/web/PositionServlet.java | 47 | ||||
-rw-r--r-- | src/org/traccar/web/ServerServlet.java | 53 | ||||
-rw-r--r-- | src/org/traccar/web/UserServlet.java | 81 | ||||
-rw-r--r-- | src/org/traccar/web/WebServer.java | 116 |
12 files changed, 999 insertions, 0 deletions
diff --git a/src/org/traccar/web/AsyncServlet.java b/src/org/traccar/web/AsyncServlet.java new file mode 100644 index 000000000..20a71ec1c --- /dev/null +++ b/src/org/traccar/web/AsyncServlet.java @@ -0,0 +1,211 @@ +/* + * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.web; + +import java.io.IOException; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import javax.json.Json; +import javax.json.JsonObjectBuilder; +import javax.servlet.AsyncContext; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.jboss.netty.util.Timeout; +import org.jboss.netty.util.TimerTask; +import org.traccar.Context; +import org.traccar.GlobalTimer; +import org.traccar.database.ConnectionManager; +import org.traccar.helper.Log; +import org.traccar.model.Position; + +public class AsyncServlet extends BaseServlet { + + private static final long ASYNC_TIMEOUT = 120000; + + @Override + protected boolean handle(String command, HttpServletRequest req, HttpServletResponse resp) throws Exception { + async(req.startAsync(), getUserId(req)); + return true; + } + + public class AsyncSession { + + private static final boolean DEBUG_ASYNC = false; + + private static final long SESSION_TIMEOUT = 30; + private static final long REQUEST_TIMEOUT = 20; + + private boolean destroyed; + private final long userId; + private final Set<Long> devices = new HashSet<>(); + private Timeout sessionTimeout; + private Timeout requestTimeout; + private final Map<Long, Position> positions = new HashMap<>(); + private AsyncContext activeContext; + + private void logEvent(String message) { + if (DEBUG_ASYNC) { + Log.debug("AsyncSession: " + this.hashCode() + " destroyed: " + destroyed + " " + message); + } + } + + public AsyncSession(long userId, Collection<Long> devices) { + logEvent("create userId: " + userId + " devices: " + devices.size()); + this.userId = userId; + this.devices.addAll(devices); + + Collection<Position> initialPositions = Context.getConnectionManager().getInitialState(devices); + for (Position position : initialPositions) { + positions.put(position.getDeviceId(), position); + } + + Context.getConnectionManager().addListener(devices, dataListener); + } + + public boolean hasDevice(long deviceId) { + return devices.contains(deviceId); + } + + private final ConnectionManager.DataCacheListener dataListener = new ConnectionManager.DataCacheListener() { + @Override + public void onUpdate(Position position) { + synchronized (AsyncSession.this) { + logEvent("onUpdate deviceId: " + position.getDeviceId()); + if (!destroyed) { + if (requestTimeout != null) { + requestTimeout.cancel(); + requestTimeout = null; + } + positions.put(position.getDeviceId(), position); + if (activeContext != null) { + response(); + } + } + } + } + }; + + private final TimerTask sessionTimer = new TimerTask() { + @Override + public void run(Timeout tmt) throws Exception { + synchronized (AsyncSession.this) { + logEvent("sessionTimeout"); + Context.getConnectionManager().removeListener(devices, dataListener); + synchronized (asyncSessions) { + asyncSessions.remove(userId); + } + destroyed = true; + } + } + }; + + private final TimerTask requestTimer = new TimerTask() { + @Override + public void run(Timeout tmt) throws Exception { + synchronized (AsyncSession.this) { + logEvent("requestTimeout"); + if (!destroyed) { + if (activeContext != null) { + response(); + } + } + } + } + }; + + public synchronized void request(AsyncContext context) { + logEvent("request context: " + context.hashCode()); + if (!destroyed) { + activeContext = context; + if (sessionTimeout != null) { + sessionTimeout.cancel(); + sessionTimeout = null; + } + + if (!positions.isEmpty()) { + response(); + } else { + requestTimeout = GlobalTimer.getTimer().newTimeout( + requestTimer, REQUEST_TIMEOUT, TimeUnit.SECONDS); + } + } + } + + private synchronized void response() { + logEvent("response context: " + activeContext.hashCode()); + if (!destroyed) { + ServletResponse response = activeContext.getResponse(); + + JsonObjectBuilder result = Json.createObjectBuilder(); + result.add("success", true); + result.add("data", JsonConverter.arrayToJson(positions.values())); + positions.clear(); + + try { + response.getWriter().println(result.build().toString()); + } catch (IOException error) { + Log.warning(error); + } + + activeContext.complete(); + activeContext = null; + + sessionTimeout = GlobalTimer.getTimer().newTimeout( + sessionTimer, SESSION_TIMEOUT, TimeUnit.SECONDS); + } + } + + } + + private static final Map<Long, AsyncSession> asyncSessions = new HashMap<>(); + + public static void sessionRefreshUser(long userId) { + asyncSessions.remove(userId); + } + + public static void sessionRefreshDevice(long deviceId) { + Iterator<Entry<Long, AsyncSession>> iterator = asyncSessions.entrySet().iterator(); + while (iterator.hasNext()) { + if (iterator.next().getValue().hasDevice(deviceId)) { + iterator.remove(); + } + } + } + + private void async(final AsyncContext context, long userId) { + + context.setTimeout(ASYNC_TIMEOUT); + HttpServletRequest req = (HttpServletRequest) context.getRequest(); + + synchronized (asyncSessions) { + + if (Boolean.valueOf(req.getParameter("first")) || !asyncSessions.containsKey(userId)) { + Collection<Long> devices = Context.getPermissionsManager().allowedDevices(userId); + asyncSessions.put(userId, new AsyncSession(userId, devices)); + } + + asyncSessions.get(userId).request(context); + } + } + +} diff --git a/src/org/traccar/web/BaseServlet.java b/src/org/traccar/web/BaseServlet.java new file mode 100644 index 000000000..28b4b467e --- /dev/null +++ b/src/org/traccar/web/BaseServlet.java @@ -0,0 +1,91 @@ +/* + * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.web; + +import java.io.IOException; +import java.io.Writer; +import java.security.AccessControlException; +import javax.json.Json; +import javax.json.JsonObjectBuilder; +import javax.json.JsonStructure; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.traccar.model.User; + +public abstract class BaseServlet extends HttpServlet { + + public static final String USER_KEY = "user"; + + @Override + protected final void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + String command = req.getPathInfo(); + if (command == null) { + command = ""; + } + try { + resp.setContentType("application/json"); + resp.setCharacterEncoding("UTF-8"); + if (!handle(command, req, resp)) { + resp.sendError(HttpServletResponse.SC_BAD_REQUEST); + } + } catch (Exception error) { + sendResponse(resp.getWriter(), error); + } + } + + protected abstract boolean handle(String command, HttpServletRequest req, HttpServletResponse resp) throws Exception; + + public long getUserId(HttpServletRequest req) { + User user = (User) req.getSession().getAttribute(USER_KEY); + if (user == null) { + throw new AccessControlException("User not logged in"); + } + return user.getId(); + } + + public void securityCheck(boolean check) throws SecurityException { + if (!check) { + throw new SecurityException("Access denied"); + } + } + + public void sendResponse(Writer writer, boolean success) throws IOException { + JsonObjectBuilder result = Json.createObjectBuilder(); + result.add("success", success); + writer.write(result.build().toString()); + } + + public void sendResponse(Writer writer, JsonStructure json) throws IOException { + JsonObjectBuilder result = Json.createObjectBuilder(); + result.add("success", true); + result.add("data", json); + writer.write(result.build().toString()); + } + + public void sendResponse(Writer writer, Exception error) throws IOException { + JsonObjectBuilder result = Json.createObjectBuilder(); + result.add("success", false); + if (error.getMessage() != null) { + result.add("error", error.getMessage()); + } else { + result.add("error", error.getClass().getSimpleName()); + } + writer.write(result.build().toString()); + } + +} diff --git a/src/org/traccar/web/CommandsServlet.java b/src/org/traccar/web/CommandsServlet.java new file mode 100644 index 000000000..b12c0fa53 --- /dev/null +++ b/src/org/traccar/web/CommandsServlet.java @@ -0,0 +1,58 @@ +package org.traccar.web; + +import javax.json.Json; +import javax.json.JsonObject; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.traccar.Context; +import org.traccar.command.CommandType; +import org.traccar.command.GpsCommand; +import org.traccar.database.ActiveDevice; + +public class CommandsServlet extends BaseServlet { + + @Override + protected boolean handle(String command, HttpServletRequest req, HttpServletResponse resp) throws Exception { + + switch (command) { + case "/send": + send(req, resp); + return true; + case "/raw": + sendRawCommand(req, resp); + return true; + default: + return false; + } + } + + private void send(HttpServletRequest req, HttpServletResponse resp) throws Exception { + GpsCommand command = JsonConverter.<GpsCommand>enumObjectFromJson(req.getReader(), new EnumFactory(CommandType.class, "type")); + + String uniqueId = command.getUniqueId(); + + ActiveDevice activeDevice = Context.getConnectionManager().getActiveDevice(uniqueId); + if(activeDevice == null) { + throw new RuntimeException("The device has not yet registered to the server"); + } + + activeDevice.sendCommand(command); + + sendResponse(resp.getWriter(), JsonConverter.objectToJson(new Object())); + } + + private void sendRawCommand(HttpServletRequest req, HttpServletResponse resp) throws Exception { + JsonObject json = Json.createReader(req.getReader()).readObject(); + String uniqueId = json.getString("uniqueId"); + + ActiveDevice activeDevice = Context.getConnectionManager().getActiveDevice(uniqueId); + if(activeDevice == null) { + throw new RuntimeException("The device has not yet registered to the server"); + } + + String command = json.getString("command"); + activeDevice.write(command); + + sendResponse(resp.getWriter(), JsonConverter.objectToJson(new Object())); + } +} diff --git a/src/org/traccar/web/DeviceServlet.java b/src/org/traccar/web/DeviceServlet.java new file mode 100644 index 000000000..6b65efa8b --- /dev/null +++ b/src/org/traccar/web/DeviceServlet.java @@ -0,0 +1,75 @@ +/* + * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.web; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.traccar.Context; +import org.traccar.model.Device; + +public class DeviceServlet extends BaseServlet { + + @Override + protected boolean handle(String command, HttpServletRequest req, HttpServletResponse resp) throws Exception { + + switch (command) { + case "/get": + get(req, resp); + break; + case "/add": + add(req, resp); + break; + case "/update": + update(req, resp); + break; + case "/remove": + remove(req, resp); + break; + default: + return false; + } + return true; + } + + private void get(HttpServletRequest req, HttpServletResponse resp) throws Exception { + sendResponse(resp.getWriter(), JsonConverter.arrayToJson( + Context.getDataManager().getDevices(getUserId(req)))); + } + + private void add(HttpServletRequest req, HttpServletResponse resp) throws Exception { + Device device = JsonConverter.objectFromJson(req.getReader(), new Device()); + Context.getDataManager().addDevice(device); + Context.getDataManager().linkDevice(getUserId(req), device.getId()); + Context.getPermissionsManager().refresh(); + sendResponse(resp.getWriter(), JsonConverter.objectToJson(device)); + } + + private void update(HttpServletRequest req, HttpServletResponse resp) throws Exception { + Device device = JsonConverter.objectFromJson(req.getReader(), new Device()); + Context.getPermissionsManager().checkDevice(getUserId(req), device.getId()); + Context.getDataManager().updateDevice(device); + sendResponse(resp.getWriter(), true); + } + + private void remove(HttpServletRequest req, HttpServletResponse resp) throws Exception { + Device device = JsonConverter.objectFromJson(req.getReader(), new Device()); + Context.getPermissionsManager().checkDevice(getUserId(req), device.getId()); + Context.getDataManager().removeDevice(device); + Context.getPermissionsManager().refresh(); + sendResponse(resp.getWriter(), true); + } + +} diff --git a/src/org/traccar/web/EnumFactory.java b/src/org/traccar/web/EnumFactory.java new file mode 100644 index 000000000..efbfd4b20 --- /dev/null +++ b/src/org/traccar/web/EnumFactory.java @@ -0,0 +1,20 @@ +package org.traccar.web; + +import org.traccar.model.Factory; + +import javax.json.JsonObject; + +public class EnumFactory<T extends Enum<T> & Factory> { + private Class<T> commandTypeClass; + private String jsonKey; + + public EnumFactory(Class<T> commandTypeClass, String type) { + this.commandTypeClass = commandTypeClass; + jsonKey = type; + } + + public <K> K create(JsonObject json) { + Factory factory = Enum.valueOf(commandTypeClass, json.getString(jsonKey)); + return (K) factory.create(); + } +} diff --git a/src/org/traccar/web/JsonConverter.java b/src/org/traccar/web/JsonConverter.java new file mode 100644 index 000000000..7962ac8ab --- /dev/null +++ b/src/org/traccar/web/JsonConverter.java @@ -0,0 +1,155 @@ +/* + * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.web; + +import java.beans.Introspector; +import java.io.Reader; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Collection; +import java.util.Date; +import java.util.Map; +import javax.json.Json; +import javax.json.JsonArray; +import javax.json.JsonArrayBuilder; +import javax.json.JsonObject; +import javax.json.JsonObjectBuilder; +import javax.json.JsonValue; +import org.traccar.model.Factory; +import org.traccar.model.MiscFormatter; + +public class JsonConverter { + + private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + + public static Date parseDate(String value) throws ParseException { + return dateFormat.parse(value); + } + + public static <T extends Factory> T objectFromJson(Reader reader, T prototype) throws ParseException { + return objectFromJson(Json.createReader(reader).readObject(), prototype); + } + + public static <T> T enumObjectFromJson(Reader reader, EnumFactory<? extends Enum<?>> factory) throws ParseException { + JsonObject json = Json.createReader(reader).readObject(); + T object = factory.<T>create(json); + populateObject(json, object); + return object; + } + + public static <T extends Factory> T objectFromJson(JsonObject json, T prototype) throws ParseException { + T object = (T) prototype.create(); + populateObject(json, object); + return object; + } + + private static void populateObject(JsonObject json, Object object) throws ParseException { + Method[] methods = object.getClass().getMethods(); + + for (final Method method : methods) { + if (method.getName().startsWith("set") && method.getParameterTypes().length == 1) { + + final String name = Introspector.decapitalize(method.getName().substring(3)); + Class<?> parameterType = method.getParameterTypes()[0]; + + if (json.containsKey(name)) try { + if (parameterType.equals(boolean.class)) { + method.invoke(object, json.getBoolean(name)); + } else if (parameterType.equals(int.class)) { + method.invoke(object, json.getJsonNumber(name).intValue()); + } else if (parameterType.equals(long.class)) { + if (json.get(name).getValueType() == JsonValue.ValueType.NUMBER) { + method.invoke(object, json.getJsonNumber(name).longValue()); + } + } else if (parameterType.equals(double.class)) { + method.invoke(object, json.getJsonNumber(name).doubleValue()); + } else if (parameterType.equals(String.class)) { + method.invoke(object, json.getString(name)); + } else if (parameterType.equals(Date.class)) { + method.invoke(object, dateFormat.parse(json.getString(name))); + } else if (parameterType.isEnum()) { + method.invoke(object, Enum.valueOf((Class<? extends Enum>) parameterType, json.getString(name))); + } else if (parameterType.equals(Map.class)) { + //method.invoke(object, json.getString(name)); + } else { + Object nestedObject = parameterType.newInstance(); + populateObject(json.getJsonObject(name), nestedObject); + method.invoke(object, nestedObject); + } + } catch (IllegalAccessException | InvocationTargetException | InstantiationException error) { + } + } + } + + } + + public static <T> JsonObject objectToJson(T object) { + + JsonObjectBuilder json = Json.createObjectBuilder(); + + Method[] methods = object.getClass().getMethods(); + + for (Method method : methods) { + if(method.isAnnotationPresent(JsonIgnore.class)) { + continue; + } + if (method.getName().startsWith("get") && method.getParameterTypes().length == 0) { + String name = Introspector.decapitalize(method.getName().substring(3)); + try { + if (method.getReturnType().equals(boolean.class)) { + json.add(name, (Boolean) method.invoke(object)); + } else if (method.getReturnType().equals(int.class)) { + json.add(name, (Integer) method.invoke(object)); + } else if (method.getReturnType().equals(long.class)) { + json.add(name, (Long) method.invoke(object)); + } else if (method.getReturnType().equals(double.class)) { + json.add(name, (Double) method.invoke(object)); + } else if (method.getReturnType().equals(String.class)) { + String value = (String) method.invoke(object); + if (value != null) { + json.add(name, value); + } + } else if (method.getReturnType().equals(Date.class)) { + Date value = (Date) method.invoke(object); + if (value != null) { + json.add(name, dateFormat.format(value)); + } + } else if (method.getReturnType().equals(Map.class)) { + json.add(name, MiscFormatter.toJson((Map) method.invoke(object))); + } + } catch (IllegalAccessException | InvocationTargetException error) { + } + } + } + + return json.build(); + } + + public static JsonArray arrayToJson(Collection<?> array) { + + JsonArrayBuilder json = Json.createArrayBuilder(); + + for (Object object : array) { + json.add(objectToJson(object)); + } + + return json.build(); + } + +} diff --git a/src/org/traccar/web/JsonIgnore.java b/src/org/traccar/web/JsonIgnore.java new file mode 100644 index 000000000..208cdc627 --- /dev/null +++ b/src/org/traccar/web/JsonIgnore.java @@ -0,0 +1,12 @@ +package org.traccar.web; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.METHOD; + +@Retention(RetentionPolicy.RUNTIME) +@Target(value = {METHOD}) +public @interface JsonIgnore { +} diff --git a/src/org/traccar/web/MainServlet.java b/src/org/traccar/web/MainServlet.java new file mode 100644 index 000000000..eaadef245 --- /dev/null +++ b/src/org/traccar/web/MainServlet.java @@ -0,0 +1,80 @@ +/* + * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.web; + +import java.io.IOException; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.traccar.Context; +import org.traccar.model.User; + +public class MainServlet extends BaseServlet { + + @Override + protected boolean handle(String command, HttpServletRequest req, HttpServletResponse resp) throws Exception { + + switch (command) { + case "/session": + session(req, resp); + break; + case "/login": + login(req, resp); + break; + case "/logout": + logout(req, resp); + break; + case "/register": + register(req, resp); + break; + default: + return false; + } + return true; + } + + private void session(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + User user = (User) req.getSession().getAttribute(USER_KEY); + if (user != null) { + sendResponse(resp.getWriter(), JsonConverter.objectToJson(user)); + } else { + sendResponse(resp.getWriter(), false); + } + } + + private void login(HttpServletRequest req, HttpServletResponse resp) throws Exception { + User user = Context.getDataManager().login( + req.getParameter("email"), req.getParameter("password")); + if (user != null) { + req.getSession().setAttribute(USER_KEY, user); + sendResponse(resp.getWriter(), JsonConverter.objectToJson(user)); + } else { + sendResponse(resp.getWriter(), false); + } + } + + private void logout(HttpServletRequest req, HttpServletResponse resp) throws Exception { + req.getSession().removeAttribute(USER_KEY); + sendResponse(resp.getWriter(), true); + } + + private void register(HttpServletRequest req, HttpServletResponse resp) throws Exception { + User user = JsonConverter.objectFromJson(req.getReader(), new User()); + Context.getDataManager().addUser(user); + sendResponse(resp.getWriter(), true); + } + +} diff --git a/src/org/traccar/web/PositionServlet.java b/src/org/traccar/web/PositionServlet.java new file mode 100644 index 000000000..a29b5b274 --- /dev/null +++ b/src/org/traccar/web/PositionServlet.java @@ -0,0 +1,47 @@ +/* + * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.web; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.traccar.Context; + +public class PositionServlet extends BaseServlet { + + @Override + protected boolean handle(String command, HttpServletRequest req, HttpServletResponse resp) throws Exception { + + switch (command) { + case "/get": + get(req, resp); + break; + default: + return false; + } + return true; + } + + private void get(HttpServletRequest req, HttpServletResponse resp) throws Exception { + long deviceId = Long.valueOf(req.getParameter("deviceId")); + Context.getPermissionsManager().checkDevice(getUserId(req), deviceId); + sendResponse(resp.getWriter(), JsonConverter.arrayToJson( + Context.getDataManager().getPositions( + getUserId(req), deviceId, + JsonConverter.parseDate(req.getParameter("from")), + JsonConverter.parseDate(req.getParameter("to"))))); + } + +} diff --git a/src/org/traccar/web/ServerServlet.java b/src/org/traccar/web/ServerServlet.java new file mode 100644 index 000000000..631737eb0 --- /dev/null +++ b/src/org/traccar/web/ServerServlet.java @@ -0,0 +1,53 @@ +/* + * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.web; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.traccar.Context; +import org.traccar.model.Server; + +public class ServerServlet extends BaseServlet { + + @Override + protected boolean handle(String command, HttpServletRequest req, HttpServletResponse resp) throws Exception { + + switch (command) { + case "/get": + get(req, resp); + break; + case "/update": + update(req, resp); + break; + default: + return false; + } + return true; + } + + private void get(HttpServletRequest req, HttpServletResponse resp) throws Exception { + sendResponse(resp.getWriter(), JsonConverter.objectToJson( + Context.getDataManager().getServer())); + } + + private void update(HttpServletRequest req, HttpServletResponse resp) throws Exception { + Server server = JsonConverter.objectFromJson(req.getReader(), new Server()); + Context.getPermissionsManager().checkAdmin(getUserId(req)); + Context.getDataManager().updateServer(server); + sendResponse(resp.getWriter(), true); + } + +} diff --git a/src/org/traccar/web/UserServlet.java b/src/org/traccar/web/UserServlet.java new file mode 100644 index 000000000..eac4b0b13 --- /dev/null +++ b/src/org/traccar/web/UserServlet.java @@ -0,0 +1,81 @@ +/* + * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.web; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.traccar.Context; +import org.traccar.model.User; + +public class UserServlet extends BaseServlet { + + @Override + protected boolean handle(String command, HttpServletRequest req, HttpServletResponse resp) throws Exception { + + switch (command) { + case "/get": + get(req, resp); + break; + case "/add": + add(req, resp); + break; + case "/update": + update(req, resp); + break; + case "/remove": + remove(req, resp); + break; + default: + return false; + } + return true; + } + + private void get(HttpServletRequest req, HttpServletResponse resp) throws Exception { + Context.getPermissionsManager().checkAdmin(getUserId(req)); + sendResponse(resp.getWriter(), JsonConverter.arrayToJson( + Context.getDataManager().getUsers())); + } + + private void add(HttpServletRequest req, HttpServletResponse resp) throws Exception { + User user = JsonConverter.objectFromJson(req.getReader(), new User()); + Context.getPermissionsManager().checkUser(getUserId(req), user.getId()); + Context.getDataManager().addUser(user); + Context.getPermissionsManager().refresh(); + sendResponse(resp.getWriter(), JsonConverter.objectToJson(user)); + } + + private void update(HttpServletRequest req, HttpServletResponse resp) throws Exception { + User user = JsonConverter.objectFromJson(req.getReader(), new User()); + if (user.getAdmin()) { + Context.getPermissionsManager().checkAdmin(getUserId(req)); + } else { + Context.getPermissionsManager().checkUser(getUserId(req), user.getId()); + } + Context.getDataManager().updateUser(user); + Context.getPermissionsManager().refresh(); + sendResponse(resp.getWriter(), true); + } + + private void remove(HttpServletRequest req, HttpServletResponse resp) throws Exception { + User user = JsonConverter.objectFromJson(req.getReader(), new User()); + Context.getPermissionsManager().checkUser(getUserId(req), user.getId()); + Context.getDataManager().removeUser(user); + Context.getPermissionsManager().refresh(); + sendResponse(resp.getWriter(), true); + } + +} diff --git a/src/org/traccar/web/WebServer.java b/src/org/traccar/web/WebServer.java new file mode 100644 index 000000000..698796467 --- /dev/null +++ b/src/org/traccar/web/WebServer.java @@ -0,0 +1,116 @@ +/* + * Copyright 2012 - 2015 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.web; + +import java.net.InetSocketAddress; +import javax.naming.InitialContext; +import javax.sql.DataSource; +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.handler.HandlerList; +import org.eclipse.jetty.server.handler.ResourceHandler; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.webapp.WebAppContext; +import org.traccar.Config; +import org.traccar.helper.Log; + +/** + * Integrated HTTP server + */ +public class WebServer { + + private Server server; + + private void initServer(Config config) { + + String address = config.getString("web.address"); + int port = config.getInteger("web.port", 8082); + if (address == null) { + server = new Server(port); + } else { + server = new Server(new InetSocketAddress(address, port)); + } + } + + public WebServer(Config config, DataSource dataSource) { + + initServer(config); + + try { + javax.naming.Context context = new InitialContext(); + context.bind("java:/DefaultDS", dataSource); + } catch (Exception error) { + Log.warning(error); + } + + WebAppContext webapp = new WebAppContext(); + webapp.setContextPath("/"); + webapp.setWar(config.getString("web.application")); + server.setHandler(webapp); + } + + public WebServer(Config config) { + + initServer(config); + + ServletContextHandler servletHandler = new ServletContextHandler(ServletContextHandler.SESSIONS); + servletHandler.setContextPath("/api"); + servletHandler.addServlet(new ServletHolder(new AsyncServlet()), "/async/*"); + servletHandler.addServlet(new ServletHolder(new ServerServlet()), "/server/*"); + servletHandler.addServlet(new ServletHolder(new UserServlet()), "/user/*"); + servletHandler.addServlet(new ServletHolder(new DeviceServlet()), "/device/*"); + servletHandler.addServlet(new ServletHolder(new PositionServlet()), "/position/*"); + servletHandler.addServlet(new ServletHolder(new CommandsServlet()), "/commands/*"); + servletHandler.addServlet(new ServletHolder(new MainServlet()), "/*"); + + /*ResourceHandler mobileResourceHandler = new ResourceHandler(); + mobileResourceHandler.setResourceBase(properties.getProperty("web.mobile")); + mobileResourceHandler.setWelcomeFiles(new String[] {"index.html"}); + ContextHandler mobileContext = new ContextHandler("/m"); + mobileContext.setHandler(mobileResourceHandler);*/ + + ResourceHandler resourceHandler = new ResourceHandler(); + resourceHandler.setResourceBase(config.getString("web.path")); + if (config.getBoolean("web.debug")) { + resourceHandler.setWelcomeFiles(new String[] { "debug.html" }); + } else { + resourceHandler.setWelcomeFiles(new String[] { "release.html" }); + } + + HandlerList handlerList = new HandlerList(); + handlerList.setHandlers(new Handler[] {servletHandler, resourceHandler}); + + server.setHandler(handlerList); + } + + public void start() { + try { + server.start(); + } catch (Exception error) { + Log.warning(error); + } + } + + public void stop() { + try { + server.stop(); + } catch (Exception error) { + Log.warning(error); + } + } + +} |