/* * Copyright 2012 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; import java.io.FileInputStream; import java.io.IOException; import java.sql.SQLException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.Properties; import java.util.logging.FileHandler; import java.util.logging.Formatter; import java.util.logging.Level; import java.util.logging.LogRecord; import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder; import org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder; import org.jboss.netty.handler.codec.string.StringDecoder; import org.jboss.netty.handler.codec.string.StringEncoder; import org.traccar.geocode.GoogleReverseGeocoder; import org.traccar.geocode.ReverseGeocoder; import org.traccar.helper.Log; import org.traccar.http.WebServer; import org.traccar.model.DataManager; import org.traccar.model.DatabaseDataManager; import org.traccar.protocol.*; /** * Server */ public class Server { /** * Server list */ private List<TrackerServer> serverList; private boolean loggerEnabled; public Server() { serverList = new LinkedList<TrackerServer>(); loggerEnabled = false; } public boolean isLoggerEnabled() { return loggerEnabled; } private DataManager dataManager; private WebServer webServer; private ReverseGeocoder geocoder; /** * Initialize */ public void init(String[] arguments) throws IOException, ClassNotFoundException, SQLException { // Load properties Properties properties = new Properties(); if (arguments.length > 0) { properties.loadFromXML(new FileInputStream(arguments[0])); } dataManager = new DatabaseDataManager(properties); initLogger(properties); initGeocoder(properties); initXexunServer(properties); initGps103Server(properties); initTk103Server(properties); initGl100Server(properties); initGl200Server(properties); initT55Server(properties); initXexun2Server(properties); initAvl08Server(properties); initEnforaServer(properties); initMeiligaoServer(properties); initMaxonServer(properties); initST210Server(properties); initProgressServer(properties); initH02Server(properties); initJt600Server(properties); // Initialize web server if (Boolean.valueOf(properties.getProperty("http.enable"))) { Integer port = Integer.valueOf(properties.getProperty("http.port", "8082")); String address = properties.getProperty("http.address"); if (address != null) { webServer = new WebServer(address, port, dataManager); } else { webServer = new WebServer(port, dataManager); } } } /** * Start */ public void start() { if (webServer != null) { webServer.start(); } for (Object server: serverList) { ((TrackerServer) server).start(); } } /** * Stop */ public void stop() { for (Object server: serverList) { ((TrackerServer) server).stop(); } if (webServer != null) { webServer.stop(); } } /** * Destroy */ public void destroy() { serverList.clear(); } /** * Initialize logger */ private void initLogger(Properties properties) throws IOException { loggerEnabled = Boolean.valueOf(properties.getProperty("logger.enable")); if (loggerEnabled) { String fileName = properties.getProperty("logger.file"); if (fileName != null) { FileHandler file = new FileHandler(fileName, true); // Simple formatter file.setFormatter(new Formatter() { private final String LINE_SEPARATOR = System.getProperty("line.separator", "\n"); private final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); public String format(LogRecord record) { String line = dateFormat.format(new Date(record.getMillis())); line += " " + record.getLevel().getName() + ": "; line += formatMessage(record); line += LINE_SEPARATOR; return line; } }); // NOTE: Console logger level will remain INFO Log.getLogger().setLevel(Level.ALL); Log.getLogger().addHandler(file); } } } private void initGeocoder(Properties properties) throws IOException { if (Boolean.parseBoolean(properties.getProperty("geocoder.enable"))) { geocoder = new GoogleReverseGeocoder(); } } private boolean isProtocolEnabled(Properties properties, String protocol) { String enabled = properties.getProperty(protocol + ".enable"); if (enabled != null) { return Boolean.valueOf(enabled); } return false; } private Integer getProtocolPort(Properties properties, String protocol) { String port = properties.getProperty(protocol + ".port"); if (port != null) { return Integer.valueOf(port); } return 5000; // Magic number } private Integer getProtocolResetDelay(Properties properties, String protocol) { String resetDelay = properties.getProperty(protocol + ".resetDelay"); if (resetDelay != null) { return Integer.valueOf(resetDelay); } return 0; } /** * Init Xexun server */ private void initXexunServer(Properties properties) throws SQLException { String protocol = "xexun"; if (isProtocolEnabled(properties, protocol)) { TrackerServer server = new TrackerServer(getProtocolPort(properties, protocol)); final Integer resetDelay = getProtocolResetDelay(properties, protocol); server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), geocoder) { protected void addSpecificHandlers(ChannelPipeline pipeline) { pipeline.addLast("frameDecoder", new XexunFrameDecoder()); pipeline.addLast("stringDecoder", new StringDecoder()); pipeline.addLast("objectDecoder", new XexunProtocolDecoder(getDataManager(), resetDelay)); } }); serverList.add(server); } } /** * Init Gps103 server */ private void initGps103Server(Properties properties) throws SQLException { String protocol = "gps103"; if (isProtocolEnabled(properties, protocol)) { TrackerServer server = new TrackerServer(getProtocolPort(properties, protocol)); final Integer resetDelay = getProtocolResetDelay(properties, protocol); server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), geocoder) { protected void addSpecificHandlers(ChannelPipeline pipeline) { byte delimiter[] = { (byte) ';' }; pipeline.addLast("frameDecoder", new DelimiterBasedFrameDecoder(1024, ChannelBuffers.wrappedBuffer(delimiter))); pipeline.addLast("stringDecoder", new StringDecoder()); pipeline.addLast("stringEncoder", new StringEncoder()); pipeline.addLast("objectDecoder", new Gps103ProtocolDecoder(getDataManager(), resetDelay)); } }); serverList.add(server); } } /** * Init Tk103 server */ private void initTk103Server(Properties properties) throws SQLException { String protocol = "tk103"; if (isProtocolEnabled(properties, protocol)) { TrackerServer server = new TrackerServer(getProtocolPort(properties, protocol)); final Integer resetDelay = getProtocolResetDelay(properties, protocol); server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), geocoder) { protected void addSpecificHandlers(ChannelPipeline pipeline) { byte delimiter[] = { (byte) ')' }; pipeline.addLast("frameDecoder", new DelimiterBasedFrameDecoder(1024, ChannelBuffers.wrappedBuffer(delimiter))); pipeline.addLast("stringDecoder", new StringDecoder()); pipeline.addLast("stringEncoder", new StringEncoder()); pipeline.addLast("objectDecoder", new Tk103ProtocolDecoder(getDataManager(), resetDelay)); } }); serverList.add(server); } } /** * Init Gl100 server */ private void initGl100Server(Properties properties) throws SQLException { String protocol = "gl100"; if (isProtocolEnabled(properties, protocol)) { TrackerServer server = new TrackerServer(getProtocolPort(properties, protocol)); final Integer resetDelay = getProtocolResetDelay(properties, protocol); server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), geocoder) { protected void addSpecificHandlers(ChannelPipeline pipeline) { byte delimiter[] = { (byte) 0x0 }; pipeline.addLast("frameDecoder", new DelimiterBasedFrameDecoder(1024, ChannelBuffers.wrappedBuffer(delimiter))); pipeline.addLast("stringDecoder", new StringDecoder()); pipeline.addLast("stringEncoder", new StringEncoder()); pipeline.addLast("objectDecoder", new Gl100ProtocolDecoder(getDataManager(), resetDelay)); } }); serverList.add(server); } } /** * Init Gl200 server */ private void initGl200Server(Properties properties) throws SQLException { String protocol = "gl200"; if (isProtocolEnabled(properties, protocol)) { TrackerServer server = new TrackerServer(getProtocolPort(properties, protocol)); final Integer resetDelay = getProtocolResetDelay(properties, protocol); server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), geocoder) { protected void addSpecificHandlers(ChannelPipeline pipeline) { byte delimiter[] = { (byte) '$' }; pipeline.addLast("frameDecoder", new DelimiterBasedFrameDecoder(1024, ChannelBuffers.wrappedBuffer(delimiter))); pipeline.addLast("stringDecoder", new StringDecoder()); pipeline.addLast("stringEncoder", new StringEncoder()); pipeline.addLast("objectDecoder", new Gl200ProtocolDecoder(getDataManager(), resetDelay)); } }); serverList.add(server); } } /** * Init T55 server */ private void initT55Server(Properties properties) throws SQLException { String protocol = "t55"; if (isProtocolEnabled(properties, protocol)) { TrackerServer server = new TrackerServer(getProtocolPort(properties, protocol)); final Integer resetDelay = getProtocolResetDelay(properties, protocol); server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), geocoder) { protected void addSpecificHandlers(ChannelPipeline pipeline) { byte delimiter[] = { (byte) '\r', (byte) '\n' }; pipeline.addLast("frameDecoder", new DelimiterBasedFrameDecoder(1024, ChannelBuffers.wrappedBuffer(delimiter))); pipeline.addLast("stringDecoder", new StringDecoder()); pipeline.addLast("stringEncoder", new StringEncoder()); pipeline.addLast("objectDecoder", new T55ProtocolDecoder(getDataManager(), resetDelay)); } }); serverList.add(server); } } /** * Init Xexun 2 server */ private void initXexun2Server(Properties properties) throws SQLException { String protocol = "xexun2"; if (isProtocolEnabled(properties, protocol)) { TrackerServer server = new TrackerServer(getProtocolPort(properties, protocol)); final Integer resetDelay = getProtocolResetDelay(properties, protocol); server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), geocoder) { protected void addSpecificHandlers(ChannelPipeline pipeline) { byte delimiter[] = { (byte) '\n' }; // tracker bug \n\r pipeline.addLast("frameDecoder", new DelimiterBasedFrameDecoder(1024, ChannelBuffers.wrappedBuffer(delimiter))); pipeline.addLast("stringDecoder", new StringDecoder()); pipeline.addLast("objectDecoder", new Xexun2ProtocolDecoder(getDataManager(), resetDelay)); } }); serverList.add(server); } } /** * Init AVL-08 server */ private void initAvl08Server(Properties properties) throws SQLException { String protocol = "avl08"; if (isProtocolEnabled(properties, protocol)) { TrackerServer server = new TrackerServer(getProtocolPort(properties, protocol)); final Integer resetDelay = getProtocolResetDelay(properties, protocol); server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), geocoder) { protected void addSpecificHandlers(ChannelPipeline pipeline) { byte delimiter[] = { (byte) '\r', (byte) '\n' }; pipeline.addLast("frameDecoder", new DelimiterBasedFrameDecoder(1024, ChannelBuffers.wrappedBuffer(delimiter))); pipeline.addLast("stringDecoder", new StringDecoder()); pipeline.addLast("objectDecoder", new Avl08ProtocolDecoder(getDataManager(), resetDelay)); } }); serverList.add(server); } } /** * Init Enfora server */ private void initEnforaServer(Properties properties) throws SQLException { String protocol = "enfora"; if (isProtocolEnabled(properties, protocol)) { TrackerServer server = new TrackerServer(getProtocolPort(properties, protocol)); final Integer resetDelay = getProtocolResetDelay(properties, protocol); server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), geocoder) { protected void addSpecificHandlers(ChannelPipeline pipeline) { pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1024, 0, 2, -2, 2)); pipeline.addLast("objectDecoder", new EnforaProtocolDecoder(getDataManager(), resetDelay)); } }); serverList.add(server); } } /** * Init Meiligao server */ private void initMeiligaoServer(Properties properties) throws SQLException { String protocol = "meiligao"; if (isProtocolEnabled(properties, protocol)) { TrackerServer server = new TrackerServer(getProtocolPort(properties, protocol)); final Integer resetDelay = getProtocolResetDelay(properties, protocol); server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), geocoder) { protected void addSpecificHandlers(ChannelPipeline pipeline) { pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1024, 2, 2, -4, 4)); pipeline.addLast("objectDecoder", new MeiligaoProtocolDecoder(getDataManager(), resetDelay)); } }); serverList.add(server); } } private void initMaxonServer(Properties properties) throws SQLException { String protocol = "maxon"; if (isProtocolEnabled(properties, protocol)) { TrackerServer server = new TrackerServer(getProtocolPort(properties, protocol)); final Integer resetDelay = getProtocolResetDelay(properties, protocol); server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), geocoder) { protected void addSpecificHandlers(ChannelPipeline pipeline) { byte delimiter[] = { (byte) '\r', (byte) '\n' }; pipeline.addLast("frameDecoder", new DelimiterBasedFrameDecoder(1024, ChannelBuffers.wrappedBuffer(delimiter))); pipeline.addLast("stringDecoder", new StringDecoder()); pipeline.addLast("stringEncoder", new StringEncoder()); pipeline.addLast("objectDecoder", new MaxonProtocolDecoder(getDataManager(), resetDelay)); } }); serverList.add(server); } } private void initST210Server(Properties properties) throws SQLException { String protocol = "st210"; if (isProtocolEnabled(properties, protocol)) { TrackerServer server = new TrackerServer(getProtocolPort(properties, protocol)); final Integer resetDelay = getProtocolResetDelay(properties, protocol); server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), geocoder) { protected void addSpecificHandlers(ChannelPipeline pipeline) { byte delimiter[] = { (byte) '\r' }; pipeline.addLast("frameDecoder", new DelimiterBasedFrameDecoder(1024, ChannelBuffers.wrappedBuffer(delimiter))); pipeline.addLast("stringDecoder", new StringDecoder()); pipeline.addLast("objectDecoder", new ST210ProtocolDecoder(getDataManager(), resetDelay)); } }); serverList.add(server); } } private void initProgressServer(Properties properties) throws SQLException { String protocol = "progress"; if (isProtocolEnabled(properties, protocol)) { TrackerServer server = new TrackerServer(getProtocolPort(properties, protocol)); server.setEndianness(java.nio.ByteOrder.LITTLE_ENDIAN); final Integer resetDelay = getProtocolResetDelay(properties, protocol); server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), geocoder) { protected void addSpecificHandlers(ChannelPipeline pipeline) { pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1024, 2, 2, 0, 0)); pipeline.addLast("objectDecoder", new ProgressProtocolDecoder(getDataManager(), resetDelay)); } }); serverList.add(server); } } /** * Init H02 server */ private void initH02Server(Properties properties) throws SQLException { String protocol = "h02"; if (isProtocolEnabled(properties, protocol)) { TrackerServer server = new TrackerServer(getProtocolPort(properties, protocol)); final Integer resetDelay = getProtocolResetDelay(properties, protocol); server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), geocoder) { protected void addSpecificHandlers(ChannelPipeline pipeline) { byte delimiter[] = { (byte) '#' }; pipeline.addLast("frameDecoder", new DelimiterBasedFrameDecoder(1024, ChannelBuffers.wrappedBuffer(delimiter))); pipeline.addLast("stringDecoder", new StringDecoder()); pipeline.addLast("objectDecoder", new H02ProtocolDecoder(getDataManager(), resetDelay)); } }); serverList.add(server); } } /** * Init JT600 server */ private void initJt600Server(Properties properties) throws SQLException { String protocol = "jt600"; if (isProtocolEnabled(properties, protocol)) { TrackerServer server = new TrackerServer(getProtocolPort(properties, protocol)); final Integer resetDelay = getProtocolResetDelay(properties, protocol); server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), geocoder) { protected void addSpecificHandlers(ChannelPipeline pipeline) { pipeline.addLast("frameDecoder", new Jt600FrameDecoder()); pipeline.addLast("objectDecoder", new Jt600ProtocolDecoder(getDataManager(), resetDelay)); } }); serverList.add(server); } } }