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