3131import javax .annotation .security .RolesAllowed ;
3232import javax .inject .Inject ;
3333import javax .ws .rs .Consumes ;
34+ import javax .ws .rs .DELETE ;
3435import javax .ws .rs .FormParam ;
3536import javax .ws .rs .GET ;
3637import javax .ws .rs .POST ;
4445import javax .xml .bind .annotation .XmlRootElement ;
4546
4647import com .fasterxml .jackson .core .JsonParser ;
48+ import org .apache .commons .lang3 .StringUtils ;
4749import org .apache .drill .common .exceptions .ExecutionSetupException ;
4850import org .apache .drill .common .logical .StoragePluginConfig ;
4951import org .apache .drill .exec .server .rest .DrillRestServer .UserAuthEnabled ;
@@ -76,10 +78,17 @@ public class StorageResources {
7678 private static final Comparator <PluginConfigWrapper > PLUGIN_COMPARATOR =
7779 Comparator .comparing (PluginConfigWrapper ::getName );
7880
81+ /**
82+ * Regex allows the following paths:
83+ * /storage/{group}/plugins/export
84+ * /storage/{group}/plugins/export/{format}
85+ * Note: for the second case the format involves the leading slash, therefore it should be removed then
86+ */
7987 @ GET
80- @ Path ("/storage/{group}/plugins/export/ {format}" )
88+ @ Path ("/storage/{group}/plugins/export{format: (/[^/]+?)* }" )
8189 @ Produces (MediaType .APPLICATION_JSON )
8290 public Response getConfigsFor (@ PathParam ("group" ) String pluginGroup , @ PathParam ("format" ) String format ) {
91+ format = StringUtils .isNotEmpty (format ) ? format .replace ("/" , "" ) : JSON_FORMAT ;
8392 return isSupported (format )
8493 ? Response .ok ()
8594 .entity (getConfigsFor (pluginGroup ).toArray ())
@@ -146,10 +155,17 @@ public JsonResult enablePlugin(@PathParam("name") String name, @PathParam("val")
146155 }
147156 }
148157
158+ /**
159+ * Regex allows the following paths:
160+ * /storage/{name}/export
161+ * "/storage/{name}/export/{format}
162+ * Note: for the second case the format involves the leading slash, therefore it should be removed then
163+ */
149164 @ GET
150- @ Path ("/storage/{name}/export/ {format}" )
165+ @ Path ("/storage/{name}/export{format: (/[^/]+?)* }" )
151166 @ Produces (MediaType .APPLICATION_JSON )
152167 public Response exportPlugin (@ PathParam ("name" ) String name , @ PathParam ("format" ) String format ) {
168+ format = StringUtils .isNotEmpty (format ) ? format .replace ("/" , "" ) : JSON_FORMAT ;
153169 return isSupported (format )
154170 ? Response .ok (getPluginConfig (name ))
155171 .header (HttpHeaders .CONTENT_DISPOSITION , String .format ("attachment;filename=\" %s.%s\" " , name , format ))
@@ -159,8 +175,8 @@ public Response exportPlugin(@PathParam("name") String name, @PathParam("format"
159175 .build ();
160176 }
161177
162- @ GET
163- @ Path ("/storage/{name}/delete " )
178+ @ DELETE
179+ @ Path ("/storage/{name}.json " )
164180 @ Produces (MediaType .APPLICATION_JSON )
165181 public JsonResult deletePlugin (@ PathParam ("name" ) String name ) {
166182 return getPluginConfig (name ).deleteFromStorage (storage )
@@ -212,7 +228,17 @@ private boolean isSupported(String format) {
212228 return JSON_FORMAT .equalsIgnoreCase (format ) || HOCON_FORMAT .equalsIgnoreCase (format );
213229 }
214230
215- private List <PluginConfigWrapper > getConfigsFor (String pluginGroup ) {
231+ /**
232+ * Regex allows the following paths:
233+ * /storage.json
234+ * /storage/{group}-plugins.json
235+ * Note: for the second case the group involves the leading slash, therefore it should be removed then
236+ */
237+ @ GET
238+ @ Path ("/storage{group: (/[^/]+?)*}-plugins.json" )
239+ @ Produces (MediaType .APPLICATION_JSON )
240+ public List <PluginConfigWrapper > getConfigsFor (@ PathParam ("group" ) String pluginGroup ) {
241+ pluginGroup = StringUtils .isNotEmpty (pluginGroup ) ? pluginGroup .replace ("/" , "" ) : ALL_PLUGINS ;
216242 return StreamSupport .stream (
217243 Spliterators .spliteratorUnknownSize (storage .getStore ().getAll (), Spliterator .ORDERED ), false )
218244 .filter (byPluginGroup (pluginGroup ))
@@ -221,6 +247,31 @@ private List<PluginConfigWrapper> getConfigsFor(String pluginGroup) {
221247 .collect (Collectors .toList ());
222248 }
223249
250+ /**
251+ * @deprecated use {@link #createOrUpdatePluginJSON} instead
252+ */
253+ @ POST
254+ @ Path ("/storage/{name}" )
255+ @ Consumes (MediaType .APPLICATION_JSON )
256+ @ Produces (MediaType .APPLICATION_JSON )
257+ @ Deprecated
258+ public JsonResult createOrUpdatePlugin (PluginConfigWrapper plugin ) {
259+ return createOrUpdatePluginJSON (plugin );
260+ }
261+
262+ /**
263+ * @deprecated use the method with DELETE request {@link #deletePlugin(String)} instead
264+ */
265+ @ GET
266+ @ Path ("/storage/{name}/delete" )
267+ @ Produces (MediaType .APPLICATION_JSON )
268+ @ Deprecated
269+ public JsonResult deletePluginViaGet (@ PathParam ("name" ) String name ) {
270+ return getPluginConfig (name ).deleteFromStorage (storage )
271+ ? message ("Success" )
272+ : message ("Error (unable to delete %s storage plugin)" , name );
273+ }
274+
224275 private Predicate <Map .Entry <String , StoragePluginConfig >> byPluginGroup (String pluginGroup ) {
225276 if (ALL_PLUGINS .equalsIgnoreCase (pluginGroup )) {
226277 return entry -> true ;
0 commit comments