001/* 002 * Copyright 2002-2012 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.util; 018 019import javax.servlet.jsp.PageContext; 020import javax.servlet.jsp.tagext.Tag; 021 022import org.springframework.util.Assert; 023 024/** 025 * Utility class for tag library related code, exposing functionality 026 * such as translating {@link String Strings} to web scopes. 027 * 028 * <p> 029 * <ul> 030 * <li>{@code page} will be transformed to 031 * {@link javax.servlet.jsp.PageContext#PAGE_SCOPE PageContext.PAGE_SCOPE} 032 * <li>{@code request} will be transformed to 033 * {@link javax.servlet.jsp.PageContext#REQUEST_SCOPE PageContext.REQUEST_SCOPE} 034 * <li>{@code session} will be transformed to 035 * {@link javax.servlet.jsp.PageContext#SESSION_SCOPE PageContext.SESSION_SCOPE} 036 * <li>{@code application} will be transformed to 037 * {@link javax.servlet.jsp.PageContext#APPLICATION_SCOPE PageContext.APPLICATION_SCOPE} 038 * </ul> 039 * 040 * @author Alef Arendsen 041 * @author Rob Harrop 042 * @author Juergen Hoeller 043 * @author Rick Evans 044 */ 045public abstract class TagUtils { 046 047 /** Constant identifying the page scope */ 048 public static final String SCOPE_PAGE = "page"; 049 050 /** Constant identifying the request scope */ 051 public static final String SCOPE_REQUEST = "request"; 052 053 /** Constant identifying the session scope */ 054 public static final String SCOPE_SESSION = "session"; 055 056 /** Constant identifying the application scope */ 057 public static final String SCOPE_APPLICATION = "application"; 058 059 060 /** 061 * Determines the scope for a given input {@code String}. 062 * <p>If the {@code String} does not match 'request', 'session', 063 * 'page' or 'application', the method will return {@link PageContext#PAGE_SCOPE}. 064 * @param scope the {@code String} to inspect 065 * @return the scope found, or {@link PageContext#PAGE_SCOPE} if no scope matched 066 * @throws IllegalArgumentException if the supplied {@code scope} is {@code null} 067 */ 068 public static int getScope(String scope) { 069 Assert.notNull(scope, "Scope to search for cannot be null"); 070 if (scope.equals(SCOPE_REQUEST)) { 071 return PageContext.REQUEST_SCOPE; 072 } 073 else if (scope.equals(SCOPE_SESSION)) { 074 return PageContext.SESSION_SCOPE; 075 } 076 else if (scope.equals(SCOPE_APPLICATION)) { 077 return PageContext.APPLICATION_SCOPE; 078 } 079 else { 080 return PageContext.PAGE_SCOPE; 081 } 082 } 083 084 /** 085 * Determine whether the supplied {@link Tag} has any ancestor tag 086 * of the supplied type. 087 * @param tag the tag whose ancestors are to be checked 088 * @param ancestorTagClass the ancestor {@link Class} being searched for 089 * @return {@code true} if the supplied {@link Tag} has any ancestor tag 090 * of the supplied type 091 * @throws IllegalArgumentException if either of the supplied arguments is {@code null}; 092 * or if the supplied {@code ancestorTagClass} is not type-assignable to 093 * the {@link Tag} class 094 */ 095 public static boolean hasAncestorOfType(Tag tag, Class<?> ancestorTagClass) { 096 Assert.notNull(tag, "Tag cannot be null"); 097 Assert.notNull(ancestorTagClass, "Ancestor tag class cannot be null"); 098 if (!Tag.class.isAssignableFrom(ancestorTagClass)) { 099 throw new IllegalArgumentException( 100 "Class '" + ancestorTagClass.getName() + "' is not a valid Tag type"); 101 } 102 Tag ancestor = tag.getParent(); 103 while (ancestor != null) { 104 if (ancestorTagClass.isAssignableFrom(ancestor.getClass())) { 105 return true; 106 } 107 ancestor = ancestor.getParent(); 108 } 109 return false; 110 } 111 112 /** 113 * Determine whether the supplied {@link Tag} has any ancestor tag 114 * of the supplied type, throwing an {@link IllegalStateException} 115 * if not. 116 * @param tag the tag whose ancestors are to be checked 117 * @param ancestorTagClass the ancestor {@link Class} being searched for 118 * @param tagName the name of the {@code tag}; for example '{@code option}' 119 * @param ancestorTagName the name of the ancestor {@code tag}; for example '{@code select}' 120 * @throws IllegalStateException if the supplied {@code tag} does not 121 * have a tag of the supplied {@code parentTagClass} as an ancestor 122 * @throws IllegalArgumentException if any of the supplied arguments is {@code null}, 123 * or in the case of the {@link String}-typed arguments, is composed wholly 124 * of whitespace; or if the supplied {@code ancestorTagClass} is not 125 * type-assignable to the {@link Tag} class 126 * @see #hasAncestorOfType(javax.servlet.jsp.tagext.Tag, Class) 127 */ 128 public static void assertHasAncestorOfType(Tag tag, Class<?> ancestorTagClass, String tagName, String ancestorTagName) { 129 Assert.hasText(tagName, "'tagName' must not be empty"); 130 Assert.hasText(ancestorTagName, "'ancestorTagName' must not be empty"); 131 if (!TagUtils.hasAncestorOfType(tag, ancestorTagClass)) { 132 throw new IllegalStateException("The '" + tagName + "' tag can only be used inside a valid '" + ancestorTagName + "' tag."); 133 } 134 } 135 136}