001    /* ProtectionDomain.java -- A security domain
002       Copyright (C) 1998, 2003, 2004  Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    package java.security;
039    
040    import gnu.classpath.SystemProperties;
041    
042    /**
043     * This class represents a group of classes, along with their granted
044     * permissions. The classes are identified by a {@link CodeSource}. Thus, any
045     * class loaded from the specified {@link CodeSource} is treated as part of
046     * this domain. The set of permissions is represented by an instance of
047     * {@link PermissionCollection}.
048     * 
049     * <p>Every class in the system will belong to one and only one
050     * <code>ProtectionDomain</code>.</p>
051     *
052     * @author Aaron M. Renn (arenn@urbanophile.com)
053     * @version 0.0
054     */
055    public class ProtectionDomain
056    {
057      /** This is the <code>CodeSource</code> for this protection domain. */
058      private CodeSource code_source;
059    
060      /** This is the set of permissions granted to this domain. */
061      private PermissionCollection perms;
062    
063      /** The {@link ClassLoader} associated with this domain. */
064      private ClassLoader classloader;
065    
066      /** The array of Principals associated with this domain.. */
067      private Principal[] principals;
068    
069      /** Post 1.4 the policy may be refreshed! use false for pre 1.4. */
070      private boolean staticBinding;
071    
072      /**
073       * Initializes a new instance of <code>ProtectionDomain</code> representing
074       * the specified {@link CodeSource} and set of permissions. No permissions
075       * can be added later to the {@link PermissionCollection} and this contructor
076       * will call the <code>setReadOnly</code> method on the specified set of
077       * permissions.
078       * 
079       * @param codesource
080       *          The {@link CodeSource} for this domain.
081       * @param permissions
082       *          The set of permissions for this domain.
083       * @see PermissionCollection#setReadOnly()
084       */
085      public ProtectionDomain(CodeSource codesource, PermissionCollection permissions)
086      {
087        this(codesource, permissions, null, null, true);
088      }
089    
090      /**
091       * This method initializes a new instance of <code>ProtectionDomain</code>
092       * given its {@link CodeSource}, granted permissions, associated
093       * {@link ClassLoader} and {@link Principal}s.
094       * 
095       * <p>Similar to the previous constructor, if the designated set of
096       * permissions is not <code>null</code>, the <code>setReadOnly</code> method
097       * is called on that set.</p>
098       * 
099       * @param codesource
100       *          The {@link CodeSource} for this domain.
101       * @param permissions
102       *          The permission set for this domain.
103       * @param classloader
104       *          the ClassLoader associated with this domain.
105       * @param principals
106       *          the array of {@link Principal}s associated with this domain.
107       * @since 1.4
108       * @see PermissionCollection#setReadOnly()
109       */
110      public ProtectionDomain(CodeSource codesource,
111                              PermissionCollection permissions,
112                              ClassLoader classloader, Principal[] principals)
113      {
114        this(codesource, permissions, classloader, principals, false);
115      }
116    
117      private ProtectionDomain(CodeSource codesource,
118                               PermissionCollection permissions,
119                               ClassLoader classloader, Principal[] principals,
120                               boolean staticBinding)
121      {
122        super();
123    
124        code_source = codesource;
125        if (permissions != null)
126          {
127            perms = permissions;
128            perms.setReadOnly();
129          }
130    
131        this.classloader = classloader;
132        this.principals =
133            (principals != null ? (Principal[]) principals.clone() : new Principal[0]);
134        this.staticBinding = staticBinding;
135      }
136    
137      /**
138       * Returns the {@link CodeSource} of this domain.
139       * 
140       * @return the {@link CodeSource} of this domain.
141       * @since 1.2
142       */
143      public final CodeSource getCodeSource()
144      {
145        return code_source;
146      }
147    
148      /**
149       * Returns the {@link ClassLoader} of this domain.
150       * 
151       * @return the {@link ClassLoader} of this domain.
152       * @since 1.4
153       */
154      public final ClassLoader getClassLoader()
155      {
156        return this.classloader;
157      }
158    
159      /**
160       * Returns a clone of the {@link Principal}s of this domain.
161       * 
162       * @return a clone of the {@link Principal}s of this domain.
163       * @since 1.4
164       */
165      public final Principal[] getPrincipals()
166      {
167        return (Principal[]) principals.clone();
168      }
169    
170      /**
171       * Returns the {@link PermissionCollection} of this domain.
172       * 
173       * @return The {@link PermissionCollection} of this domain.
174       */
175      public final PermissionCollection getPermissions()
176      {
177        return perms;
178      }
179    
180      /**
181       * Tests whether or not the specified {@link Permission} is implied by the
182       * set of permissions granted to this domain.
183       * 
184       * @param permission
185       *          the {@link Permission} to test.
186       * @return <code>true</code> if the specified {@link Permission} is implied
187       *         for this domain, <code>false</code> otherwise.
188       */
189      public boolean implies(Permission permission)
190      {
191        if (staticBinding)
192          return (perms == null ? false : perms.implies(permission));
193        // Else dynamically bound.  Do we have it?
194        // NOTE: this will force loading of Policy.currentPolicy
195        return Policy.getCurrentPolicy().implies(this, permission);
196      }
197    
198      /**
199       * Returns a string representation of this object. It will include the
200       * {@link CodeSource} and set of permissions associated with this domain.
201       * 
202       * @return A string representation of this object.
203       */
204      public String toString()
205      {
206        String linesep = SystemProperties.getProperty("line.separator");
207        StringBuffer sb = new StringBuffer("ProtectionDomain (").append(linesep);
208    
209        if (code_source == null)
210          sb.append("CodeSource:null");
211        else
212          sb.append(code_source);
213    
214        sb.append(linesep);
215        if (classloader == null)
216          sb.append("ClassLoader:null");
217        else
218          sb.append(classloader);
219    
220        sb.append(linesep);
221        sb.append("Principals:");
222        if (principals != null && principals.length > 0)
223          {
224            sb.append("[");
225            Principal pal;
226            for (int i = 0; i < principals.length; i++)
227              {
228                pal = principals[i];
229                sb.append("'").append(pal.getName())
230                    .append("' of type ").append(pal.getClass().getName());
231                if (i < principals.length-1)
232                  sb.append(", ");
233              }
234            sb.append("]");
235          }
236        else
237          sb.append("none");
238    
239        sb.append(linesep);
240        if (!staticBinding) // include all but dont force loading Policy.currentPolicy
241          if (Policy.isLoaded())
242            sb.append(Policy.getCurrentPolicy().getPermissions(this));
243          else // fallback on this one's permissions
244            sb.append(perms);
245        else
246          sb.append(perms);
247    
248        return sb.append(linesep).append(")").append(linesep).toString();
249      }
250    }