
org.impalaframework.web.integration.PrefixTreeHolder Maven / Gradle / Ivy
/*
* Copyright 2007-2010 the original author or authors.
*
* 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 org.impalaframework.web.integration;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.impalaframework.exception.InvalidStateException;
import org.impalaframework.radixtree.ConcurrentRadixTree;
import org.impalaframework.radixtree.TreeNode;
import org.springframework.util.Assert;
/**
* Holds a {@link ConcurrentRadixTree}, used to resolve URL prefixes to modules.
* Also holds a mapping of modules to contributed prefix keys, so that if module is unloaded,
* relevant keys can be removed.
* @author Phil Zoio
*/
public class PrefixTreeHolder {
private ConcurrentRadixTree trie = new ConcurrentRadixTree();
private Map> contributions = new ConcurrentHashMap>();
/**
* Used to add prefix key to module name mapping. This will be called zero to n times
* for each module which is interested in receiving URLs
*/
public void add(String moduleName, String key, String contextPath, String servletPath) {
//FIXME add concurrency control
Assert.notNull(moduleName, "moduleName cannot be null");
Assert.notNull(key, "key cannot be null");
if (this.trie.contains(key)) {
ModuleNameWithPath value = trie.findContainedValue(key);
throw new InvalidStateException("Module '" + moduleName + "' cannot use key '" + key + "', as it is already being used by module '" + value.getModuleName() + "'");
}
this.trie.insert(key, new ModuleNameWithPath(moduleName, contextPath, servletPath));
List list = this.contributions.get(moduleName);
if (list == null) {
list = new LinkedList();
this.contributions.put(moduleName, list);
}
list.add(key);
}
public boolean remove(String moduleName, String prefix) {
List list = contributions.get(moduleName);
if (list != null && list.contains(prefix)) {
list.remove(prefix);
trie.delete(prefix);
if (list.isEmpty()) {
contributions.remove(moduleName);
}
return true;
}
return false;
}
/**
* Called when module is unloaded to remove all the prefix keys to module name associations
* contributed by the module concerned
*/
public int unloadForModule(String moduleName) {
int unloaded = 0;
List list = contributions.get(moduleName);
if (list != null) {
for (String key : list) {
trie.delete(key);
unloaded++;
}
contributions.remove(moduleName);
}
return unloaded;
}
public TreeNode getModuleForURI(String requestURI) {
return trie.findContainedNode(requestURI);
}
ConcurrentRadixTree getTrie() {
return trie;
}
Map> getContributions() {
return Collections.unmodifiableMap(contributions);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy