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.wiki.auth;
020
021import java.io.Serializable;
022import java.security.Principal;
023import java.util.Arrays;
024import java.util.Comparator;
025
026/**
027 *  A lightweight, immutable Principal class. WikiPrincipals can be created with
028 *  and optional "type" to denote what type of user profile Principal it represents
029 *  (FULL_NAME, WIKI_NAME, LOGIN_NAME). Types are used to determine suitable
030 *  user and login Principals in classes like WikiSession. However, the type
031 *  property of a WikiPrincipal does not affect a WikiPrincipal's logical equality
032 *  or hash code; two WikiPrincipals with the same name but different types are still
033 *  considered equal.
034 *
035 *  @since  2.2
036 */
037public final class WikiPrincipal implements Principal, Comparable<Principal>, Serializable
038{
039    private static final long serialVersionUID = 1L;
040
041    /**
042     * Represents an anonymous user. WikiPrincipals may be
043     * created with an optional type designator: 
044     * LOGIN_NAME, WIKI_NAME, FULL_NAME or UNSPECIFIED.
045     */
046    public static final Principal GUEST = new WikiPrincipal( "Guest" );
047
048    /** WikiPrincipal type denoting a user's full name. */
049    public static final String FULL_NAME  = "fullName";
050    
051    /** WikiPrincipal type denoting a user's login name. */
052    public static final String LOGIN_NAME = "loginName";
053    
054    /** WikiPrincipal type denoting a user's wiki name. */
055    public static final String WIKI_NAME  = "wikiName";
056    
057    /** Generic WikiPrincipal of unspecified type. */
058    public static final String UNSPECIFIED  = "unspecified";
059    
060    /** Static instance of Comparator that allows Principals to be sorted. */
061    public static final Comparator<Principal> COMPARATOR = new PrincipalComparator();
062    
063    private static final String[] VALID_TYPES;
064    
065    static
066    {
067        VALID_TYPES = new String[] { FULL_NAME, LOGIN_NAME, WIKI_NAME, UNSPECIFIED };
068        Arrays.sort( VALID_TYPES );
069    }
070
071    private final String          m_name;
072    private final String          m_type;
073
074    /** For serialization purposes */
075    protected WikiPrincipal()
076    {
077        this(null);
078    }
079    
080    /**
081     * Constructs a new WikiPrincipal with a given name and a type of
082     * {@link #UNSPECIFIED}.
083     * @param name the name of the Principal
084     */
085    public WikiPrincipal( String name )
086    {
087        m_name = name;
088        m_type = UNSPECIFIED;
089    }
090    
091    /**
092     * Constructs a new WikiPrincipal with a given name and optional type
093     * designator. If the supplied <code>type</code> parameter is not
094     * {@link #LOGIN_NAME}, {@link #FULL_NAME}, {@link #WIKI_NAME}
095     * or {@link #WIKI_NAME}, this method throws
096     * an {@link IllegalArgumentException}.
097     * @param name the name of the Principal
098     * @param type the type for this principal, which may be {@link #LOGIN_NAME},
099     *            {@link #FULL_NAME}, {@link #WIKI_NAME} or {@link #WIKI_NAME}.
100     */
101    public WikiPrincipal( String name, String type )
102    {
103        m_name = name;
104        if ( Arrays.binarySearch( VALID_TYPES, type ) < 0 )
105        {
106            throw new IllegalArgumentException( "Principal type '" + type + "' is invalid.");
107        }
108        m_type = type;
109    }
110
111    /**
112     *  Returns the wiki name of the Principal.
113     *  @return the name
114     */
115    public String getName()
116    {
117        return m_name;
118    }
119
120    /**
121     * Two <code>WikiPrincipal</code>s are considered equal if their
122     * names are equal (case-sensitive).
123     * @param obj the object to compare
124     * @return the result of the equality test
125     */
126    public boolean equals( Object obj )
127    {
128        if ( obj == null || !( obj instanceof WikiPrincipal ) )
129        {
130            return false;
131        }
132        return m_name.equals( ( (WikiPrincipal) obj ).getName() );
133    }
134
135    /**
136     *  The hashCode() returned for the WikiPrincipal is the same as
137     *  for its name.
138     *  @return the hash code
139     */
140    public int hashCode()
141    {
142        return m_name.hashCode();
143    }
144    
145    /**
146     * Returns the Principal "type": {@link #LOGIN_NAME}, {@link #FULL_NAME},
147     * {@link #WIKI_NAME} or {@link #WIKI_NAME}
148     * @return the type
149     */
150    public String getType()
151    {
152        return m_type;
153    }
154    
155    /**
156     * Returns a human-readable representation of the object.
157     * @return the string representation
158     */
159    public String toString()
160    {
161        return "[WikiPrincipal (" + m_type + "): " + getName() + "]";
162    }
163
164    /**
165     *  Allows comparisons to any other Principal objects.  Primary sorting
166     *  order is by the principal name, as returned by getName().
167     *  
168     *  @param o {@inheritDoc}
169     *  @return {@inheritDoc}
170     *  @since 2.7.0
171     */
172    public int compareTo(Principal o)
173    {
174        return getName().compareTo( o.getName() );
175    }
176    
177
178}