View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.shiro.web.tags;
20  
21  import java.beans.BeanInfo;
22  import java.beans.Introspector;
23  import java.beans.PropertyDescriptor;
24  import java.io.IOException;
25  import javax.servlet.jsp.JspException;
26  import javax.servlet.jsp.JspTagException;
27  
28  import org.slf4j.Logger;
29  import org.slf4j.LoggerFactory;
30  
31  /**
32   * <p>Tag used to print out the String value of a user's default principal,
33   * or a specific principal as specified by the tag's attributes.</p>
34   *
35   * <p> If no attributes are specified, the tag prints out the <tt>toString()</tt>
36   * value of the user's default principal.  If the <tt>type</tt> attribute
37   * is specified, the tag looks for a principal with the given type.  If the
38   * <tt>property</tt> attribute is specified, the tag prints the string value of
39   * the specified property of the principal.  If no principal is found or the user
40   * is not authenticated, the tag displays nothing unless a <tt>defaultValue</tt>
41   * is specified.</p>
42   *
43   * @since 0.2
44   */
45  public class PrincipalTag extends SecureTag {
46  
47      //TODO - complete JavaDoc
48  
49      /*--------------------------------------------
50      |             C O N S T A N T S             |
51      ============================================*/
52  
53      /*--------------------------------------------
54      |    I N S T A N C E   V A R I A B L E S    |
55      ============================================*/
56      private static final Logger log = LoggerFactory.getLogger(PrincipalTag.class);
57  
58      /**
59       * The type of principal to be retrieved, or null if the default principal should be used.
60       */
61      private String type;
62  
63      /**
64       * The property name to retrieve of the principal, or null if the <tt>toString()</tt> value should be used.
65       */
66      private String property;
67  
68      /**
69       * The default value that should be displayed if the user is not authenticated, or no principal is found.
70       */
71      private String defaultValue;
72  
73      /*--------------------------------------------
74      |         C O N S T R U C T O R S           |
75      ============================================*/
76  
77      /*--------------------------------------------
78      |  A C C E S S O R S / M O D I F I E R S    |
79      ============================================*/
80  
81  
82      public String getType() {
83          return type;
84      }
85  
86  
87      public void setType(String type) {
88          this.type = type;
89      }
90  
91  
92      public String getProperty() {
93          return property;
94      }
95  
96  
97      public void setProperty(String property) {
98          this.property = property;
99      }
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 }