/* * Copyright 2007-2009 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 net.paoding.rose.controllers; import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import javax.servlet.http.HttpServletRequest; import net.paoding.rose.load.ResourceRef; import net.paoding.rose.load.RoseScanner; import net.paoding.rose.web.InterceptorDelegate; import net.paoding.rose.web.Invocation; import net.paoding.rose.web.RequestPath; import net.paoding.rose.web.annotation.HttpFeatures; import net.paoding.rose.web.annotation.Path; import net.paoding.rose.web.annotation.ReqMethod; import net.paoding.rose.web.annotation.rest.Get; import net.paoding.rose.web.impl.mapping.EngineGroup; import net.paoding.rose.web.impl.mapping.MappingNode; import net.paoding.rose.web.impl.mapping.MatchResult; import net.paoding.rose.web.impl.module.ControllerRef; import net.paoding.rose.web.impl.module.Module; import net.paoding.rose.web.impl.thread.ActionEngine; import net.paoding.rose.web.impl.thread.InvocationBean; import net.paoding.rose.web.impl.thread.LinkedEngine; import net.paoding.rose.web.impl.thread.Rose; /** * * @author 王志亮 [qieqie.wang@gmail.com] * */ @Path("") public class ToolsController { private Date startupTime = new Date(); @Get public String tools(Invocation inv) { String prefix = inv.getRequestPath().getUri(); if (!prefix.endsWith("/")) { prefix = prefix + "/"; } String s = "tool list:<p>"; s += "<div style='margin-left:20px'>"; s += "<a href=\"" + prefix + "tree\">/rose-info/tree</a></div>"; s += "<div style='margin-left:20px'>"; s += "<a href=\"" + prefix + "modules\">/rose-info/modules</a></div>"; s += "<div style='margin-left:20px'>"; s += "<a href=\"" + prefix + "resources\">/rose-info/resources</a></div>"; s += "<div style='margin-left:20px'>"; s += "<a href=\"" + prefix + "method\">/rose-info/method</a></div>"; s += "<div style='margin-left:20px'>"; s += "<a href=\"" + prefix + "startupInfo\">/rose-info/startupInfo</a></div>"; s += "<p>"; return Utils.wrap(s); } @Get("tree") @HttpFeatures(contentType = "application/xml") public String tree(Rose rose) throws Exception { MappingNode root = rose.getMappingTree(); StringBuilder sb = new StringBuilder(2048); sb.append("@<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); sb.append("<rose-web>"); printNode(root, "", sb); sb.append("</rose-web>"); return sb.toString(); } @Get("method") public Object method(Invocation pinv) { InvocationBean inv = (InvocationBean) pinv; RequestPath curpath = inv.getRequestPath(); String testUri = inv.getRequest().getQueryString(); // queryString as uri if (testUri == null || testUri.length() == 0) { return "@e.g. <a href='/rose-info/method?get=/rose-info/tree'>/rose-info/method?get=/rose-info/tree</a>"; } ReqMethod testMethod = curpath.getMethod(); if (testUri.indexOf('=') > 0) { int index = testUri.indexOf('='); testMethod = ReqMethod.parse(testUri.substring(0, index)); testUri = testUri.substring(index + 1); } if (!testUri.startsWith(curpath.getCtxpath())) { return "@wrong uri:" + testUri; } MappingNode tree = inv.getRose().getMappingTree(); RequestPath testPath = new RequestPath(// testMethod, testUri, curpath.getCtxpath(), curpath.getDispatcher()); // ArrayList<MatchResult> matchResults = tree.match(testPath); if (matchResults == null) { // not rose uri return ("@404: <br>not rose uri: '" + testUri + "'"); } final MatchResult lastMatched = matchResults.get(matchResults.size() - 1); final EngineGroup leafEngineGroup = lastMatched.getMappingNode().getLeafEngines(); final LinkedEngine leafEngine = select(leafEngineGroup.getEngines(testMethod), inv .getRequest()); if (leafEngine == null) { if (leafEngineGroup.size() == 0) { // not rose uri return ("@404: <br>not rose uri, not exits leaf engines for it: '" + testUri + "'"); } else { // 405 Method Not Allowed StringBuilder allow = new StringBuilder(); final String gap = ", "; for (ReqMethod m : leafEngineGroup.getAllowedMethods()) { allow.append(m.toString()).append(gap); } if (allow.length() > 0) { allow.setLength(allow.length() - gap.length()); } // true: don't forward to next filter or servlet return "@405: allowed=" + allow.toString(); } } StringBuilder sb = new StringBuilder(); sb.append("@200:"); ActionEngine actionEngine = (ActionEngine) leafEngine.getTarget(); sb.append(" <br>mapped '" + testUri + "' to " + actionEngine.getControllerClass().getName() + "#" + actionEngine.getMethod().getName()); sb.append("<br>intectptors:"); for (InterceptorDelegate i : actionEngine.getRegisteredInterceptors()) { sb.append("<br>").append(i.getName()).append("=").append( InterceptorDelegate.getMostInnerInterceptor(i).getClass().getName()).append( "(p=").append(i.getPriority()).append(")"); } return sb; } @Get("modules") public Object modules(Rose rose) throws Exception { List<Module> modules = rose.getModules(); StringBuilder sb = new StringBuilder(2048); int i = 1; for (Module module : modules) { printModule(sb, i++, module); } return Utils.wrap(sb.toString()); } @Get("resources") public String resources() throws Exception { List<ResourceRef> resources = RoseScanner.getInstance().getJarOrClassesFolderResources(); StringBuilder sb = new StringBuilder(1024).append("<ul>"); for (ResourceRef resource : resources) { sb.append("<li>"); sb.append(resource.getResource().getURL()); sb.append(Arrays.toString(resource.getModifiers())); sb.append("</li>"); } sb.append("</ul>"); return Utils.wrap(sb.toString()); } @Get("startupInfo") public String startupInfo() { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String time = simpleDateFormat.format(startupTime); String startup = String.format("<strong>startup</strong>=%s", time); return Utils.wrap(startup); } //------------rewriter-------- @Get("module") public String module() { return "r:a:modules"; } @Get("jar") public String jar() { return "r:a:resources"; } //---privates /** * @see #modules(Rose) */ private void printModule(StringBuilder sb, int i, Module module) { sb.append("<div style=\"margin-top:5px;border-top:solid black 1px;\"><table>"); // number sb.append("<tr valign=\"top\"><td>").append(i).append("</td><td></td></tr>"); // mappingPath sb.append("<tr><td>mappingPath</td><td>").append(module.getMappingPath()).append( "</td></tr>"); // relativePackagePath sb.append("<tr><td>relativePackagePath</td><td>").append(module.getRelativePath()).append( "</td></tr>"); // url sb.append("<tr valign=\"top\"><td>url</td><td>").append(module.getUrl()).append( "</td></tr>"); sb.append("<tr valign=\"top\"><td>controllers</td><td>"); for (ControllerRef controller : module.getControllers()) { sb.append("'").append(Arrays.toString(controller.getMappingPaths())).append("'=") .append(controller.getControllerClass().getName()).append(";<br>"); } sb.append("</td></tr>"); // resolvers sb.append("<tr><td valign=\"top\">resolvers</td><td>").append( Arrays.toString(module.getCustomerResolvers().toArray())).append("</td></tr>"); // validators sb.append("<tr><td valign=\"top\">validators</td><td>").append( Arrays.toString(module.getValidators().toArray())).append("</td></tr>"); // interceptors sb.append("<tr><td valign=\"top\">interceptors</td><td>").append( Arrays.toString(module.getInterceptors().toArray())).append("</td></tr>"); // errorhandler sb.append("<tr><td>errorHanlder</td><td>").append( module.getErrorHandler() == null ? "" : module.getErrorHandler()).append( "</td></tr>"); // end sb.append("</table></div>"); } /** * @see #method(Invocation) * @param engines * @param request * @return */ private LinkedEngine select(LinkedEngine[] engines, HttpServletRequest request) { LinkedEngine selectedEngine = null; int score = 0; for (LinkedEngine engine : engines) { int candidate = engine.isAccepted(request); if (candidate > score) { selectedEngine = engine; score = candidate; } } return selectedEngine; } /** * @see #tree(Rose) * @param node * @param prefix * @param sb */ private void printNode(final MappingNode node, String prefix, StringBuilder sb) { sb.append("<node path=\"").append(prefix + node.getMappingPath()).append("\">"); // EngineGroup leaf = node.getLeafEngines(); if (leaf.size() > 0) { for (ReqMethod method : leaf.getAllowedMethods()) { for (LinkedEngine engine : leaf.getEngines(method)) { ActionEngine action = (ActionEngine) engine.getTarget(); Method m = action.getMethod(); Class<?> cc = action.getControllerClass(); String rm = method.toString(); sb.append("<allowed "); sb.append(rm + "=\"" + cc.getSimpleName() + "#" + m.getName() + "\" "); sb.append("package=\"" + m.getDeclaringClass().getPackage().getName() + "\" "); sb.append(" />"); } } } MappingNode child = node.getLeftMostChild(); while (child != null) { printNode(child, prefix + node.getMappingPath(), sb); child = child.getSibling(); } sb.append("</node>"); } }