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 */ 019package org.apache.shiro.web.tags; 020 021import java.beans.BeanInfo; 022import java.beans.Introspector; 023import java.beans.PropertyDescriptor; 024import java.io.IOException; 025import javax.servlet.jsp.JspException; 026import javax.servlet.jsp.JspTagException; 027 028import org.slf4j.Logger; 029import 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 */ 045public 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}