001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019 package org.apache.shiro.web.tags;
020
021 import java.beans.BeanInfo;
022 import java.beans.Introspector;
023 import java.beans.PropertyDescriptor;
024 import java.io.IOException;
025 import javax.servlet.jsp.JspException;
026 import javax.servlet.jsp.JspTagException;
027
028 import org.slf4j.Logger;
029 import org.slf4j.LoggerFactory;
030
031 /**
032 * <p>Tag used to print out the String value of a user's default principal,
033 * or a specific principal as specified by the tag's attributes.</p>
034 *
035 * <p> If no attributes are specified, the tag prints out the <tt>toString()</tt>
036 * value of the user's default principal. If the <tt>type</tt> attribute
037 * is specified, the tag looks for a principal with the given type. If the
038 * <tt>property</tt> attribute is specified, the tag prints the string value of
039 * the specified property of the principal. If no principal is found or the user
040 * is not authenticated, the tag displays nothing unless a <tt>defaultValue</tt>
041 * is specified.</p>
042 *
043 * @since 0.2
044 */
045 public class PrincipalTag extends SecureTag {
046
047 //TODO - complete JavaDoc
048
049 /*--------------------------------------------
050 | C O N S T A N T S |
051 ============================================*/
052
053 /*--------------------------------------------
054 | I N S T A N C E V A R I A B L E S |
055 ============================================*/
056 private static final Logger log = LoggerFactory.getLogger(PrincipalTag.class);
057
058 /**
059 * The type of principal to be retrieved, or null if the default principal should be used.
060 */
061 private String type;
062
063 /**
064 * The property name to retrieve of the principal, or null if the <tt>toString()</tt> value should be used.
065 */
066 private String property;
067
068 /**
069 * The default value that should be displayed if the user is not authenticated, or no principal is found.
070 */
071 private String defaultValue;
072
073 /*--------------------------------------------
074 | C O N S T R U C T O R S |
075 ============================================*/
076
077 /*--------------------------------------------
078 | A C C E S S O R S / M O D I F I E R S |
079 ============================================*/
080
081
082 public String getType() {
083 return type;
084 }
085
086
087 public void setType(String type) {
088 this.type = type;
089 }
090
091
092 public String getProperty() {
093 return property;
094 }
095
096
097 public void setProperty(String property) {
098 this.property = property;
099 }
100
101
102 public String getDefaultValue() {
103 return defaultValue;
104 }
105
106
107 public void setDefaultValue(String defaultValue) {
108 this.defaultValue = defaultValue;
109 }
110
111 /*--------------------------------------------
112 | M E T H O D S |
113 ============================================*/
114
115
116 @SuppressWarnings({"unchecked"})
117 public int onDoStartTag() throws JspException {
118 String strValue = null;
119
120 if (getSubject() != null) {
121
122 // Get the principal to print out
123 Object principal;
124
125 if (type == null) {
126 principal = getSubject().getPrincipal();
127 } else {
128 principal = getPrincipalFromClassName();
129 }
130
131 // Get the string value of the principal
132 if (principal != null) {
133 if (property == null) {
134 strValue = principal.toString();
135 } else {
136 strValue = getPrincipalProperty(principal, property);
137 }
138 }
139
140 }
141
142 // Print out the principal value if not null
143 if (strValue != null) {
144 try {
145 pageContext.getOut().write(strValue);
146 } catch (IOException e) {
147 throw new JspTagException("Error writing [" + strValue + "] to JSP.", e);
148 }
149 }
150
151 return SKIP_BODY;
152 }
153
154 @SuppressWarnings({"unchecked"})
155 private Object getPrincipalFromClassName() {
156 Object principal = null;
157
158 try {
159 Class cls = Class.forName(type);
160 principal = getSubject().getPrincipals().oneByType(cls);
161 } catch (ClassNotFoundException e) {
162 if (log.isErrorEnabled()) {
163 log.error("Unable to find class for name [" + type + "]");
164 }
165 }
166 return principal;
167 }
168
169
170 private String getPrincipalProperty(Object principal, String property) throws JspTagException {
171 String strValue = null;
172
173 try {
174 BeanInfo bi = Introspector.getBeanInfo(principal.getClass());
175
176 // Loop through the properties to get the string value of the specified property
177 boolean foundProperty = false;
178 for (PropertyDescriptor pd : bi.getPropertyDescriptors()) {
179 if (pd.getName().equals(property)) {
180 Object value = pd.getReadMethod().invoke(principal, (Object[]) null);
181 strValue = String.valueOf(value);
182 foundProperty = true;
183 break;
184 }
185 }
186
187 if (!foundProperty) {
188 final String message = "Property [" + property + "] not found in principal of type [" + principal.getClass().getName() + "]";
189 if (log.isErrorEnabled()) {
190 log.error(message);
191 }
192 throw new JspTagException(message);
193 }
194
195 } catch (Exception e) {
196 final String message = "Error reading property [" + property + "] from principal of type [" + principal.getClass().getName() + "]";
197 if (log.isErrorEnabled()) {
198 log.error(message, e);
199 }
200 throw new JspTagException(message, e);
201 }
202
203 return strValue;
204 }
205 }