All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.dell.doradus.service.rest.RESTCommandSet Maven / Gradle / Ivy

/*
 * Copyright (C) 2014 Dell, Inc.
 * 
 * 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 com.dell.doradus.service.rest;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;

import com.dell.doradus.common.Utils;

/**
 * Holds a set of {@link RESTCommand}s and organizes them in the correct order for
 * evaluation. For example, if the command set contains the following two commands:
 * 
 *      GET /{application}/_statstatus
 *      GET /_applications/{application}
 * 
 * The second command must appear before the first command because nodes with literal
 * values must appear before parameterized nodes. Similarly, a command with more nodes
 * but otherwise the same as another command must appear first.
 * 

* Commands are added by calling {@link #addCommand(RESTCommand)}. When * {@link #findMatch(String, String, String, Map)} is called, a search is made for a * matching command. */ public class RESTCommandSet { // RESTCommands organized by HTTP method. Note that RESTCommand's compareTo() method // does the work of sorting commands in the proper sequence. private final Map> m_cmdMap = new HashMap<>(); // When this is true, new commands are not allowed. This allows us to search the // command set without a lock after it's built. private boolean m_bCmdSetIsFrozen; /** * Create a new REST command set with no commands. */ public RESTCommandSet() { } /** * Add the given command to this command set. An exception is thrown if another * command has already been added with the same method, nodes, and query parameter. * * @param command {@link RESTCommand} to add to this set. */ public void addCommand(RESTCommand command) { assert command != null; if (m_bCmdSetIsFrozen) { throw new RuntimeException("New commands cannot be added: command set is frozen"); } // Get or create the map for this command's HTTP method. synchronized (m_cmdMap) { SortedSet cmdSet = m_cmdMap.get(command.getMethod()); if (cmdSet == null) { cmdSet = new TreeSet(); m_cmdMap.put(command.getMethod(), cmdSet); } Utils.require(!cmdSet.contains(command), "Duplicate REST command added: [" + command + "]"); cmdSet.add(command); } } // addCommand /** * Clear the registered REST command set. */ public void clear() { synchronized (m_cmdMap) { m_cmdMap.clear(); } } // clear /** * Freeze or unfreeze the command set. This should be called after the command set has * been frozen so that findMatch() does not need to acquire a lock, thus single- * threading command searching. If this is called with "true", subsequent calls to * {@link #addCommand(RESTCommand)} will throw an exception. * * @param bFreeze True to freeze the command set. */ public void freezeCommandSet(boolean bFreeze) { m_bCmdSetIsFrozen = bFreeze; } // freezeCommandSet /** * Attempt to find a command that matches the given parameters. If a match is found, * parameters are extracted and added to the given parameter map. If no match is found. * null is returned and the given variableMap is left unmodified. * * @param method Request HTTP method (case-insensitive: GET, PUT, etc.) * @param uri Request URI (case-sensitive: /A/B/C) * @param query Optional query parameter. For example, if the query parameter * is "?foo=bar", the string "foo=bar". * @param variableMap Populated with *encoded* variable values, if any, if a * command matches the given request parameters. * @return Matching RESTCommand, if found, otherwise null. */ public RESTCommand findMatch(String method, String uri, String query, Map variableMap) { // Find the sorted command set for the given HTTP method. SortedSet cmdSet = m_cmdMap.get(method.toUpperCase()); if (cmdSet == null) { return null; } // Split uri into a list of non-empty nodes. List pathNodeList = new ArrayList<>(); String[] pathNodes = uri.split("/"); for (String pathNode : pathNodes) { if (pathNode.length() > 0) { pathNodeList.add(pathNode); } } // Attempt to match commands in this set in order. for (RESTCommand cmd : cmdSet) { if (cmd.matchesURL(method, pathNodeList, query, variableMap)) { return cmd; } } return null; } // findMatch /** * Get all registered REST commands as a map of HTTP method names to a sorted set of * {@link RESTCommand}s. The commands are sorted in their evaluation order. * * @return Map of HTTP method-to-sorted commands. Example: *

     *          GET -> {"/foo/bar", "/foo"}
     *          PUT -> {"/foo/bar/bat", "/foo?{params}"}
     * 
*/ public Map> getCommands() { return m_cmdMap; } // getCommands } // class RESTCommandSet




© 2015 - 2025 Weber Informatics LLC | Privacy Policy