src/org/sonews/daemon/command/XDaemonCommand.java
author František Kučera <franta-hg@frantovo.cz>
Thu Jul 05 13:19:19 2012 +0200 (2012-07-05)
changeset 119 f5b57e221e38
parent 48 b78e77619152
permissions -rwxr-xr-x
mezery, tabulátory
     1 /*
     2  *   SONEWS News Server
     3  *   see AUTHORS for the list of contributors
     4  *
     5  *   This program is free software: you can redistribute it and/or modify
     6  *   it under the terms of the GNU General Public License as published by
     7  *   the Free Software Foundation, either version 3 of the License, or
     8  *   (at your option) any later version.
     9  *
    10  *   This program is distributed in the hope that it will be useful,
    11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  *   GNU General Public License for more details.
    14  *
    15  *   You should have received a copy of the GNU General Public License
    16  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17  */
    18 package org.sonews.daemon.command;
    19 
    20 import java.io.IOException;
    21 import java.net.InetSocketAddress;
    22 import java.util.List;
    23 import org.sonews.config.Config;
    24 import org.sonews.daemon.NNTPConnection;
    25 import org.sonews.storage.StorageBackendException;
    26 import org.sonews.storage.StorageManager;
    27 import org.sonews.feed.FeedManager;
    28 import org.sonews.feed.Subscription;
    29 import org.sonews.storage.Group;
    30 import org.sonews.util.Stats;
    31 
    32 /**
    33  * The XDAEMON command allows a client to get/set properties of the
    34  * running server daemon. Only locally connected clients are allowed to
    35  * use this command.
    36  * The restriction to localhost connection can be suppressed by overriding
    37  * the sonews.xdaemon.host bootstrap config property.
    38  * @author Christian Lins
    39  * @since sonews/0.5.0
    40  */
    41 public class XDaemonCommand implements Command {
    42 
    43 	@Override
    44 	public String[] getSupportedCommandStrings() {
    45 		return new String[]{"XDAEMON"};
    46 	}
    47 
    48 	@Override
    49 	public boolean hasFinished() {
    50 		return true;
    51 	}
    52 
    53 	@Override
    54 	public String impliedCapability() {
    55 		return null;
    56 	}
    57 
    58 	@Override
    59 	public boolean isStateful() {
    60 		return false;
    61 	}
    62 
    63 	private void channelAdd(String[] commands, NNTPConnection conn)
    64 			throws IOException, StorageBackendException {
    65 		String groupName = commands[2];
    66 		if (StorageManager.current().isGroupExisting(groupName)) {
    67 			conn.println("400 group " + groupName + " already existing!");
    68 		} else {
    69 			StorageManager.current().addGroup(groupName, Integer.parseInt(commands[3]));
    70 			conn.println("200 group " + groupName + " created");
    71 		}
    72 	}
    73 
    74 	// TODO: Refactor this method to reduce complexity!
    75 	@Override
    76 	public void processLine(NNTPConnection conn, String line, byte[] raw)
    77 			throws IOException, StorageBackendException {
    78 		InetSocketAddress addr = (InetSocketAddress)conn.getSocketChannel()
    79 				.socket().getRemoteSocketAddress();
    80 		if (addr.getHostName().equals(
    81 				Config.inst().get(Config.XDAEMON_HOST, "localhost"))) {
    82 			String[] commands = line.split(" ", 4);
    83 			if (commands.length == 3 && commands[1].equalsIgnoreCase("LIST")) {
    84 				if (commands[2].equalsIgnoreCase("CONFIGKEYS")) {
    85 					conn.println("100 list of available config keys follows");
    86 					for (String key : Config.AVAILABLE_KEYS) {
    87 						conn.println(key);
    88 					}
    89 					conn.println(".");
    90 				} else if (commands[2].equalsIgnoreCase("PEERINGRULES")) {
    91 					List<Subscription> pull =
    92 							StorageManager.current().getSubscriptions(FeedManager.TYPE_PULL);
    93 					List<Subscription> push =
    94 							StorageManager.current().getSubscriptions(FeedManager.TYPE_PUSH);
    95 					conn.println("100 list of peering rules follows");
    96 					for (Subscription sub : pull) {
    97 						conn.println("PULL " + sub.getHost() + ":" + sub.getPort()
    98 								+ " " + sub.getGroup());
    99 					}
   100 					for (Subscription sub : push) {
   101 						conn.println("PUSH " + sub.getHost() + ":" + sub.getPort()
   102 								+ " " + sub.getGroup());
   103 					}
   104 					conn.println(".");
   105 				} else {
   106 					conn.println("401 unknown sub command");
   107 				}
   108 			} else if (commands.length == 3 && commands[1].equalsIgnoreCase("DELETE")) {
   109 				StorageManager.current().delete(commands[2]);
   110 				conn.println("200 article " + commands[2] + " deleted");
   111 			} else if (commands.length == 4 && commands[1].equalsIgnoreCase("GROUPADD")) {
   112 				channelAdd(commands, conn);
   113 			} else if (commands.length == 3 && commands[1].equalsIgnoreCase("GROUPDEL")) {
   114 				Group group = StorageManager.current().getGroup(commands[2]);
   115 				if (group == null) {
   116 					conn.println("400 group not found");
   117 				} else {
   118 					group.setFlag(Group.DELETED);
   119 					group.update();
   120 					conn.println("200 group " + commands[2] + " marked as deleted");
   121 				}
   122 			} else if (commands.length == 5 && commands[1].equalsIgnoreCase("GROUPFLAG")) {
   123 				Group group = StorageManager.current().getGroup(commands[2]);
   124 				String flagName = commands[4];
   125 				if (commands[3].equalsIgnoreCase("SET")) {
   126 					if (flagName.equals("MAILINGLIST")) {
   127 						group.setFlag(Group.MAILINGLIST);
   128 					} else if (flagName.equals("DELETED")) {
   129 						group.setFlag(Group.DELETED);
   130 					} else if (flagName.equals("READONLY")) {
   131 						group.setFlag(Group.READONLY);
   132 					}
   133 				} else if (commands[3].equalsIgnoreCase("UNSET")) {
   134 					if (flagName.equals("MAILINGLIST")) {
   135 						group.unsetFlag(Group.MAILINGLIST);
   136 					} else if (flagName.equals("DELETED")) {
   137 						group.unsetFlag(Group.DELETED);
   138 					} else if (flagName.equals("READONLY")) {
   139 						group.unsetFlag(Group.READONLY);
   140 					}
   141 				} else {
   142 					conn.println("500 invalid command usage");
   143 				}
   144 				StorageManager.current().update(group);
   145 			} else if (commands.length == 4 && commands[1].equalsIgnoreCase("SET")) {
   146 				String key = commands[2];
   147 				String val = commands[3];
   148 				Config.inst().set(key, val);
   149 				conn.println("200 new config value set");
   150 			} else if (commands.length == 3 && commands[1].equalsIgnoreCase("GET")) {
   151 				String key = commands[2];
   152 				String val = Config.inst().get(key, null);
   153 				if (val != null) {
   154 					conn.println("100 config value for " + key + " follows");
   155 					conn.println(val);
   156 					conn.println(".");
   157 				} else {
   158 					conn.println("400 config value not set");
   159 				}
   160 			} else if (commands.length >= 3 && commands[1].equalsIgnoreCase("LOG")) {
   161 				Group group = null;
   162 				if (commands.length > 3) {
   163 					group = StorageManager.current().getGroup(commands[3]);
   164 				}
   165 
   166 				if (commands[2].equalsIgnoreCase("CONNECTED_CLIENTS")) {
   167 					conn.println("100 number of connections follow");
   168 					conn.println(Integer.toString(Stats.getInstance().connectedClients()));
   169 					conn.println(".");
   170 				} else if (commands[2].equalsIgnoreCase("POSTED_NEWS")) {
   171 					conn.println("100 hourly numbers of posted news yesterday");
   172 					for (int n = 0; n < 24; n++) {
   173 						conn.println(n + " " + Stats.getInstance().getYesterdaysEvents(Stats.POSTED_NEWS, n, group));
   174 					}
   175 					conn.println(".");
   176 				} else if (commands[2].equalsIgnoreCase("GATEWAYED_NEWS")) {
   177 					conn.println("100 hourly numbers of gatewayed news yesterday");
   178 					for (int n = 0; n < 24; n++) {
   179 						conn.println(n + " " + Stats.getInstance().getYesterdaysEvents(Stats.GATEWAYED_NEWS, n, group));
   180 					}
   181 					conn.println(".");
   182 				} else if (commands[2].equalsIgnoreCase("TRANSMITTED_NEWS")) {
   183 					conn.println("100 hourly numbers of news transmitted to peers yesterday");
   184 					for (int n = 0; n < 24; n++) {
   185 						conn.println(n + " " + Stats.getInstance().getYesterdaysEvents(Stats.FEEDED_NEWS, n, group));
   186 					}
   187 					conn.println(".");
   188 				} else if (commands[2].equalsIgnoreCase("HOSTED_NEWS")) {
   189 					conn.println("100 number of overall hosted news");
   190 					conn.println(Integer.toString(Stats.getInstance().getNumberOfNews()));
   191 					conn.println(".");
   192 				} else if (commands[2].equalsIgnoreCase("HOSTED_GROUPS")) {
   193 					conn.println("100 number of hosted groups");
   194 					conn.println(Integer.toString(Stats.getInstance().getNumberOfGroups()));
   195 					conn.println(".");
   196 				} else if (commands[2].equalsIgnoreCase("POSTED_NEWS_PER_HOUR")) {
   197 					conn.println("100 posted news per hour");
   198 					conn.println(Double.toString(Stats.getInstance().postedPerHour(-1)));
   199 					conn.println(".");
   200 				} else if (commands[2].equalsIgnoreCase("FEEDED_NEWS_PER_HOUR")) {
   201 					conn.println("100 feeded news per hour");
   202 					conn.println(Double.toString(Stats.getInstance().feededPerHour(-1)));
   203 					conn.println(".");
   204 				} else if (commands[2].equalsIgnoreCase("GATEWAYED_NEWS_PER_HOUR")) {
   205 					conn.println("100 gatewayed news per hour");
   206 					conn.println(Double.toString(Stats.getInstance().gatewayedPerHour(-1)));
   207 					conn.println(".");
   208 				} else {
   209 					conn.println("401 unknown sub command");
   210 				}
   211 			} else if (commands.length >= 3 && commands[1].equalsIgnoreCase("PLUGIN")) {
   212 				conn.println("400 invalid command usage");
   213 			} else {
   214 				conn.println("400 invalid command usage");
   215 			}
   216 		} else {
   217 			conn.println("501 not allowed");
   218 		}
   219 	}
   220 }