Java tutorial
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright (C) 2015, Markus Staudt <info@braffdev.com> * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see <http://www.gnu.org/licenses/>. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ package com.braffdev.server.core.module.mapping; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; import com.braffdev.server.core.Constants; import com.braffdev.server.core.http.method.HttpMethod; import com.braffdev.server.core.module.Module; import com.braffdev.server.core.module.mapping.exception.MappingAlreadyExistsException; import com.braffdev.server.core.module.mapping.pattern.PatternConverter; import com.braffdev.server.core.module.mapping.pattern.PatternInfo; import com.braffdev.server.core.module.mapping.requesthandler.RequestHandler; import com.braffdev.server.core.module.mapping.requesthandler.RequestHandlerInfo; /** * */ public class MappingModule extends Module { private List<Mapping> mappings; /** * */ public MappingModule() { this.mappings = new ArrayList<Mapping>(); } /** * */ @Override public String getName() { return Constants.Module.NAME_MAPPING; } /** * @param m * @throws MappingAlreadyExistsException */ public void add(String uri, HttpMethod method, RequestHandler handler) throws MappingAlreadyExistsException { this.add(new PatternConverter().convert(uri), method, handler); } /** * @param pattern * @param method * @param handler * @throws MappingAlreadyExistsException */ public void add(PatternInfo patternInfo, HttpMethod method, RequestHandler handler) throws MappingAlreadyExistsException { int index = this.indexOf(patternInfo); if (index == -1) { // there is no such mapping yet // create a new one! this.createMapping(patternInfo, method, handler); } else { // mapping already exists Mapping mapping = this.mappings.get(index); // check if the method we want to map is already mapped if (!mapping.getHandlerMapping().containsKey(method)) { mapping.getHandlerMapping().put(method, handler); } else { throw new MappingAlreadyExistsException( "There is already a mapping for " + patternInfo.getPattern() + " on the method " + method); } } Collections.sort(this.mappings); } /** * @param pattern * @param method * @param handler */ public void remove(PatternInfo patternInfo, HttpMethod method, RequestHandler handler) { int index = this.indexOf(patternInfo); if (index != -1) { Mapping mapping = this.mappings.get(index); mapping.getHandlerMapping().remove(method); if (mapping.getHandlerMapping().isEmpty()) { this.mappings.remove(index);// empty - remove whole mapping } } } /** * @param pattern * @return */ private int indexOf(PatternInfo patternInfo) { synchronized (this.mappings) { for (int i = 0; i < this.mappings.size(); i++) { Mapping mapping = this.mappings.get(i); if (mapping.getPatternInfo().getPattern().pattern().equals(patternInfo.getPattern().pattern())) { return i; } } } return -1; } /** * @param pattern * @param method * @param handler */ private void createMapping(PatternInfo patternInfo, HttpMethod method, RequestHandler handler) { String pattern = patternInfo.getPattern().pattern(); Mapping mapping = new Mapping(); mapping.setPatternInfo(patternInfo); mapping.setLevels(StringUtils.countMatches(pattern, "/")); mapping.getHandlerMapping().put(method, handler); mapping.setType(MappingType.get(pattern)); this.mappings.add(mapping); } /** * @return */ public RequestHandlerInfo lookup(String uri, HttpMethod method) { Mapping mapping = this.lookupInternalMapping(uri); if (mapping != null) { return this.mappingLookup(mapping, method); } return null; } /** * @param uri * @return */ public Mapping lookupInternalMapping(String uri) { // check all direct mappings first for (Mapping mapping : this.mappings) { if (mapping.getType() != MappingType.DIRECT) { continue; } Pattern pattern = mapping.getPatternInfo().getPattern(); if (pattern.matcher(uri).matches()) { return mapping; } } // check wildcard mappings for (Mapping mapping : this.mappings) { if (mapping.getType() != MappingType.WILDCARD) { continue; } Pattern pattern = mapping.getPatternInfo().getPattern(); if (pattern.matcher(uri).matches()) { return mapping; } } return null; } /** * @param mapping * @param method * @return */ private RequestHandlerInfo mappingLookup(Mapping mapping, HttpMethod method) { Map<HttpMethod, RequestHandler> handlerMapping = mapping.getHandlerMapping(); RequestHandler requestHandler = handlerMapping.get(method); if ((requestHandler == null) && (method != HttpMethod.ALL)) { // fallback requestHandler = handlerMapping.get(HttpMethod.ALL); } RequestHandlerInfo info = null; if (requestHandler != null) { info = new RequestHandlerInfo(); info.setRequestHandler(requestHandler); info.setPatternInfo(mapping.getPatternInfo()); } return info; } /** * */ public List<Mapping> getMappings() { return this.mappings; } }