001    /*
002     * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered
003     * by the modified BSD License. You should have received a copy of the
004     * modified BSD license with this compiler.
005     * 
006     * Copyright (c) 2005-2008, Torbjorn Ekman
007     * All rights reserved.
008     */
009    
010    aspect AccessControl {
011      // 6.6 Access Control
012      
013      syn lazy boolean ArrayDecl.accessibleFrom(TypeDecl type) = elementType().accessibleFrom(type);
014     
015      syn lazy boolean TypeDecl.accessibleFromPackage(String packageName) =
016        !isPrivate() && (isPublic() || hostPackage().equals(packageName));
017      
018      syn lazy boolean TypeDecl.accessibleFromExtend(TypeDecl type) {
019        if(type == this)
020          return true;
021        if(isInnerType()) { 
022          if(!enclosingType().accessibleFrom(type)) {
023            return false;
024          }
025        }
026        if(isPublic()) 
027          return true;
028        else if(isProtected()) {
029          // isProtected implies a nested type
030          if(hostPackage().equals(type.hostPackage())) {
031            return true;
032          }
033          if(type.isNestedType() && type.enclosingType().withinBodyThatSubclasses(enclosingType()) != null)
034            return true;
035          return false;
036        }
037        else if(isPrivate()) {
038          return topLevelType() == type.topLevelType();
039        }
040        else
041          return hostPackage().equals(type.hostPackage());
042      }
043     
044      syn lazy boolean TypeDecl.accessibleFrom(TypeDecl type) {
045        if(type == this)
046          return true;
047        if(isInnerType()) { 
048          if(!enclosingType().accessibleFrom(type)) {
049            return false;
050          }
051        }
052        if(isPublic()) {  
053          return true;
054        }
055        else if(isProtected()) {
056          if(hostPackage().equals(type.hostPackage())) {
057            return true;
058          }
059          if(isMemberType()) {
060            TypeDecl typeDecl = type;
061            while(typeDecl != null && !typeDecl.instanceOf(enclosingType()))
062              typeDecl = typeDecl.enclosingType();
063            if(typeDecl != null) {
064              return true;
065            }
066          }
067          return false;
068        }
069        else if(isPrivate()) {
070          return topLevelType() == type.topLevelType();
071        }
072        else {
073          return hostPackage().equals(type.hostPackage());
074        }
075      }
076    
077      syn lazy boolean MethodDecl.accessibleFrom(TypeDecl type) {
078        if(isPublic()) {
079          return true;
080        }
081        else if(isProtected()) {
082          if(hostPackage().equals(type.hostPackage()))
083            return true;
084          if(type.withinBodyThatSubclasses(hostType()) != null)
085            return true;
086          return false;
087        }
088        else if(isPrivate())
089          return hostType().topLevelType() == type.topLevelType();
090        else
091          return hostPackage().equals(type.hostPackage());
092      }
093      
094      syn lazy boolean ConstructorDecl.accessibleFrom(TypeDecl type) {
095        if(!hostType().accessibleFrom(type))
096          return false;
097        else if(isPublic())
098          return true;
099        else if(isProtected()) {
100          return true;
101        }
102        else if(isPrivate()) {
103          return hostType().topLevelType() == type.topLevelType();
104        }
105        else
106          return hostPackage().equals(type.hostPackage());
107      }
108      
109      syn lazy boolean FieldDeclaration.accessibleFrom(TypeDecl type) {
110        if(isPublic())
111          return true;
112        else if(isProtected()) {
113          if(hostPackage().equals(type.hostPackage()))
114            return true;
115          if(type.withinBodyThatSubclasses(hostType()) != null)
116            return true;
117          return false;
118        }
119        else if(isPrivate())
120          return hostType().topLevelType() == type.topLevelType();
121        else
122          return hostPackage().equals(type.hostPackage());
123      }
124        
125      public void ASTNode.accessControl() {
126      }
127      
128      public void TypeAccess.accessControl() {
129        super.accessControl();
130        TypeDecl hostType = hostType();
131        if(hostType != null && !hostType.isUnknown() && !type().accessibleFrom(hostType)) {
132          error("" + this + " in " + hostType().fullName() + " can not access type " + type().fullName());
133        }
134        else if((hostType == null || hostType.isUnknown())  && !type().accessibleFromPackage(hostPackage())) {
135          error("" + this + " can not access type " + type().fullName());
136        }
137      }
138    
139      public void ClassInstanceExpr.accessControl() {
140        super.accessControl();
141        if(type().isAbstract())
142          error("Can not instantiate abstract class " + type().fullName());
143        if(!decl().accessibleFrom(hostType()))
144          error("constructor " + decl().signature() + " is not accessible");
145      }
146      
147      public void ClassDecl.accessControl() {
148        super.accessControl();
149        
150        // 8.1.1.2 final Classes
151        TypeDecl typeDecl = hasSuperclass() ? superclass() : null;
152        if(typeDecl != null && !typeDecl.accessibleFromExtend(this))
153        //if(typeDecl != null && !isCircular() && !typeDecl.accessibleFrom(this))
154          error("class " + fullName() + " may not extend non accessible type " + typeDecl.fullName());
155    
156        if(hasSuperclass() && !superclass().accessibleFrom(this))
157          error("a superclass must be accessible which " + superclass().name() + " is not");
158    
159        // 8.1.4
160        for(int i = 0; i < getNumImplements(); i++) {
161          TypeDecl decl = getImplements(i).type();
162          if(!decl.isCircular() && !decl.accessibleFrom(this))
163            error("class " + fullName() + " can not implement non accessible type " + decl.fullName());
164        }
165      }
166    
167      public void InterfaceDecl.accessControl() {
168        super.accessControl();
169        
170        if(!isCircular()) {
171          // 9.1.2
172          HashSet set = new HashSet();
173          for(int i = 0; i < getNumSuperInterfaceId(); i++) {
174            TypeDecl decl = getSuperInterfaceId(i).type();
175    
176            if(!decl.isInterfaceDecl() && !decl.isUnknown())
177              error("interface " + fullName() + " tries to extend non interface type " + decl.fullName());
178            if(!decl.isCircular() && !decl.accessibleFrom(this))
179              error("interface " + fullName() + " can not extend non accessible type " + decl.fullName());
180    
181            if(set.contains(decl))
182              error("extended interface " + decl.fullName() + " mentionened multiple times in extends clause");
183            set.add(decl);
184          }
185        }
186      }
187    }