source: josm/trunk/src/org/openstreetmap/josm/io/remotecontrol/handler/RequestHandler.java@ 5095

Last change on this file since 5095 was 5085, checked in by simon04, 12 years ago

fix #5824 - remotecontrol: add command for opening local files + refactoring of permission preference

  • Property svn:eol-style set to native
File size: 8.0 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.io.remotecontrol.handler;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.text.MessageFormat;
7import java.util.HashMap;
8import java.util.LinkedList;
9import java.util.List;
10
11import javax.swing.JOptionPane;
12
13import org.openstreetmap.josm.Main;
14import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault;
15import org.openstreetmap.josm.tools.Utils;
16
17/**
18 * This is the parent of all classes that handle a specific remote control command
19 *
20 * @author Bodo Meissner
21 */
22public abstract class RequestHandler {
23
24 public static final String globalConfirmationKey = "remotecontrol.always-confirm";
25 public static final boolean globalConfirmationDefault = false;
26 public static final String loadInNewLayerKey = "remotecontrol.new-layer";
27 public static final boolean loadInNewLayerDefault = false;
28
29 /** The GET request arguments */
30 protected HashMap<String,String> args;
31
32 /** The request URL without "GET". */
33 protected String request;
34
35 /** default response */
36 protected String content = "OK\r\n";
37 /** default content type */
38 protected String contentType = "text/plain";
39
40 /** will be filled with the command assigned to the subclass */
41 protected String myCommand;
42
43 /**
44 * Check permission and parameters and handle request.
45 *
46 * @throws RequestHandlerForbiddenException
47 * @throws RequestHandlerBadRequestException
48 * @throws RequestHandlerErrorException
49 */
50 public final void handle() throws RequestHandlerForbiddenException, RequestHandlerBadRequestException, RequestHandlerErrorException
51 {
52 checkMandatoryParams();
53 checkPermission();
54 handleRequest();
55 }
56
57 /**
58 * Handle a specific command sent as remote control.
59 *
60 * This method of the subclass will do the real work.
61 *
62 * @throws RequestHandlerErrorException
63 * @throws RequestHandlerBadRequestException
64 */
65 protected abstract void handleRequest() throws RequestHandlerErrorException, RequestHandlerBadRequestException;
66
67 /**
68 * Get a specific message to ask the user for permission for the operation
69 * requested via remote control.
70 *
71 * This message will be displayed to the user if the preference
72 * remotecontrol.always-confirm is true.
73 *
74 * @return the message
75 */
76 abstract public String getPermissionMessage();
77
78 /**
79 * Get a PermissionPref object containing the name of a special permission
80 * preference to individually allow the requested operation and an error
81 * message to be displayed when a disabled operation is requested.
82 *
83 * Default is not to check any special preference. Override this in a
84 * subclass to define permission preference and error message.
85 *
86 * @return the preference name and error message or null
87 */
88 abstract public PermissionPrefWithDefault getPermissionPref();
89
90 abstract public String[] getMandatoryParams();
91
92 /**
93 * Check permissions in preferences and display error message
94 * or ask for permission.
95 *
96 * @throws RequestHandlerForbiddenException
97 */
98 final public void checkPermission() throws RequestHandlerForbiddenException
99 {
100 /*
101 * If the subclass defines a specific preference and if this is set
102 * to false, abort with an error message.
103 *
104 * Note: we use the deprecated class here for compatibility with
105 * older versions of WMSPlugin.
106 */
107 PermissionPrefWithDefault permissionPref = getPermissionPref();
108 if((permissionPref != null) && (permissionPref.pref != null))
109 {
110 if (!Main.pref.getBoolean(permissionPref.pref, permissionPref.defaultVal)) {
111 String err = MessageFormat.format("RemoteControl: ''{0}'' forbidden by preferences", myCommand);
112 System.out.println(err);
113 throw new RequestHandlerForbiddenException(err);
114 }
115 }
116
117 /* Does the user want to confirm everything?
118 * If yes, display specific confirmation message.
119 */
120 if (Main.pref.getBoolean(globalConfirmationKey, globalConfirmationDefault)) {
121 if (JOptionPane.showConfirmDialog(Main.parent,
122 "<html>" + getPermissionMessage() +
123 "<br>" + tr("Do you want to allow this?"),
124 tr("Confirm Remote Control action"),
125 JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) {
126 String err = MessageFormat.format("RemoteControl: ''{0}'' forbidden by user''s choice", myCommand);
127 throw new RequestHandlerForbiddenException(err);
128 }
129 }
130 }
131
132 /**
133 * Set request URL and parse args.
134 *
135 * @param url The request URL.
136 */
137 public void setUrl(String url) {
138 this.request = url;
139 parseArgs();
140 }
141
142 /**
143 * Parse the request parameters as key=value pairs.
144 * The result will be stored in this.args.
145 *
146 * Can be overridden by subclass.
147 */
148 protected void parseArgs() {
149 HashMap<String, String> args = new HashMap<String, String>();
150 if (this.request.indexOf('?') != -1) {
151 String query = this.request.substring(this.request.indexOf('?') + 1);
152 if (query.indexOf('#') != -1) {
153 query = query.substring(0, query.indexOf('#'));
154 }
155 String[] params = query.split("&", -1);
156 for (String param : params) {
157 int eq = param.indexOf('=');
158 if (eq != -1) {
159 args.put(param.substring(0, eq), param.substring(eq + 1));
160 }
161 }
162 }
163 this.args = args;
164 }
165
166 void checkMandatoryParams() throws RequestHandlerBadRequestException {
167 String[] mandatory = getMandatoryParams();
168 if(mandatory == null) return;
169
170 List<String> missingKeys = new LinkedList<String>();
171 boolean error = false;
172 for (String key : mandatory) {
173 String value = args.get(key);
174 if ((value == null) || (value.length() == 0)) {
175 error = true;
176 System.out.println("'" + myCommand + "' remote control request must have '" + key + "' parameter");
177 missingKeys.add(key);
178 }
179 }
180 if (error) {
181 throw new RequestHandlerBadRequestException(
182 "The following keys are mandatory, but have not been provided: "
183 + Utils.join(", ", missingKeys));
184 }
185 }
186
187 /**
188 * Save command associated with this handler.
189 *
190 * @param command The command.
191 */
192 public void setCommand(String command)
193 {
194 if (command.charAt(0) == '/') {
195 command = command.substring(1);
196 }
197 myCommand = command;
198 }
199
200 public String getContent() {
201 return content;
202 }
203
204 public String getContentType() {
205 return contentType;
206 }
207
208 protected boolean isLoadInNewLayer() {
209 return args.get("new_layer") != null && !args.get("new_layer").isEmpty()
210 ? Boolean.parseBoolean(args.get("new_layer"))
211 : Main.pref.getBoolean(loadInNewLayerKey, loadInNewLayerDefault);
212 }
213
214 public static class RequestHandlerException extends Exception {
215
216 public RequestHandlerException(String message) {
217 super(message);
218 }
219
220 public RequestHandlerException() {
221 }
222 }
223
224 public static class RequestHandlerErrorException extends RequestHandlerException {
225 }
226
227 public static class RequestHandlerBadRequestException extends RequestHandlerException {
228
229 public RequestHandlerBadRequestException(String message) {
230 super(message);
231 }
232 }
233
234 public static class RequestHandlerForbiddenException extends RequestHandlerException {
235 private static final long serialVersionUID = 2263904699747115423L;
236
237 public RequestHandlerForbiddenException(String message) {
238 super(message);
239 }
240 }
241}
Note: See TracBrowser for help on using the repository browser.