// Copyright (c) 2003-present, Jodd Team (http://jodd.org) // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. package jodd.madvoc; import jodd.util.ArraysUtil; import jodd.util.StringPool; import jodd.util.StringUtil; import java.util.HashMap; import java.util.Map; /** * Collection of root packages. */ public class RootPackages { protected String[] packages; protected String[] mappings; protected Map<String, String> packagePaths; /** * Resets all root packages mappings. */ public void reset() { packages = null; mappings = null; packagePaths = null; } /** * Adds root package with no additional mapping. */ public void addRootPackage(String rootPackage) { addRootPackage(rootPackage, StringPool.EMPTY); } /** * Sets root package to package of given class. */ public void addRootPackageOf(Class actionClass) { addRootPackageOf(actionClass, StringPool.EMPTY); } /** * Adds root package and its path mapping. Duplicate root packages * are ignored, if mapping path is equals, otherwise exception is thrown. */ public void addRootPackage(String rootPackage, String mapping) { if (packages == null) { packages = new String[0]; } if (mappings == null) { mappings = new String[0]; } // fix mapping if (mapping.length() > 0) { // mapping must start with the slash if (!mapping.startsWith(StringPool.SLASH)) { mapping = StringPool.SLASH + mapping; } // mapping must NOT end with the slash if (mapping.endsWith(StringPool.SLASH)) { mapping = StringUtil.substring(mapping, 0, -1); } } // detect duplicates for (int i = 0; i < packages.length; i++) { if (packages[i].equals(rootPackage)) { if (mappings[i].equals(mapping)) { // both package and the mappings are the same return; } throw new MadvocException("Different mappings for the same root package: " + rootPackage); } } packages = ArraysUtil.append(packages, rootPackage); mappings = ArraysUtil.append(mappings, mapping); } /** * Sets root package to package of given class. */ public void addRootPackageOf(Class actionClass, String mapping) { addRootPackage(actionClass.getPackage().getName(), mapping); } /** * Returns total count of root packages. */ public int getRootPackagesCount() { if (packages == null) { return 0; } return packages.length; } /** * Returns root package for given index. */ public String getRootPackage(int ndx) { return packages[ndx]; } /** * Returns root package mapping for given index. */ public String getRootPackageMapping(int ndx) { return mappings[ndx]; } // ---------------------------------------------------------------- find /** * Finds closest root package for the given action path. */ public String findRootPackageForActionPath(String actionPath) { if (mappings == null) { return null; } int ndx = -1; int delta = Integer.MAX_VALUE; for (int i = 0; i < mappings.length; i++) { String mapping = mappings[i]; boolean found = false; if (actionPath.equals(mapping)) { found = true; } else { mapping += StringPool.SLASH; if (actionPath.startsWith(mapping)) { found = true; } } if (found) { int distance = actionPath.length() - mapping.length(); if (distance < delta) { ndx = i; delta = distance; } } } if (ndx == -1) { return null; } return packages[ndx]; } /** * Returns package action path. Returns <code>null</code> if package has not been * already defined. */ public String getPackageActionPath(String actionPackage) { if (packagePaths == null) { return null; } return packagePaths.get(actionPackage); } /** * Registers package action path. */ public void registerPackageActionPath(String actionPackage, String packageActionPath) { if (packagePaths == null) { packagePaths = new HashMap<>(); } packagePaths.put(actionPackage, packageActionPath); } /** * Finds mapping for given action class. Returns <code>null</code> * if no mapping is found. If there is more then one matching root * package, the closest one will be returned. */ public String findPackagePathForActionPackage(String actionPackage) { if (packages == null) { return null; } int ndx = -1; int delta = Integer.MAX_VALUE; for (int i = 0; i < packages.length; i++) { String rootPackage = packages[i]; if (rootPackage.equals(actionPackage)) { // exact match ndx = i; delta = 0; break; } rootPackage += '.'; if (actionPackage.startsWith(rootPackage)) { // found, action package contains root package int distanceFromTheRoot = actionPackage.length() - rootPackage.length(); if (distanceFromTheRoot < delta) { ndx = i; delta = distanceFromTheRoot; } } } if (ndx == -1) { return null; } String packageActionPath = delta == 0 ? StringPool.EMPTY : StringUtil.substring(actionPackage, - delta - 1, 0); packageActionPath = packageActionPath.replace('.', '/'); return mappings[ndx] + packageActionPath; } // ---------------------------------------------------------------- toString public String toString() { if (packages == null) { return "null"; } StringBuilder sb = new StringBuilder(); for (int i = 0; i < packages.length; i++) { String rootPackage = packages[i]; String mapping = mappings[i]; sb.append(rootPackage).append(" --> ").append(mapping).append(StringPool.NEWLINE); } return sb.toString(); } }