001 /* Copyright (c) 2005-2008, Torbjorn Ekman 002 * All rights reserved. 003 * 004 * Redistribution and use in source and binary forms, with or without 005 * modification, are permitted provided that the following conditions are met: 006 * 007 * 1. Redistributions of source code must retain the above copyright notice, 008 * this list of conditions and the following disclaimer. 009 * 010 * 2. Redistributions in binary form must reproduce the above copyright notice, 011 * this list of conditions and the following disclaimer in the documentation 012 * and/or other materials provided with the distribution. 013 * 014 * 3. Neither the name of the copyright holder nor the names of its 015 * contributors may be used to endorse or promote products derived from this 016 * software without specific prior written permission. 017 * 018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 021 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 022 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 028 * POSSIBILITY OF SUCH DAMAGE. 029 */ 030 031 aspect Java2Rewrites { 032 int TypeDecl.uniqueIndexCounter = 1; 033 syn lazy int TypeDecl.uniqueIndex() = topLevelType().uniqueIndexCounter++; 034 035 036 syn lazy String TypeDecl.jvmName() { 037 throw new Error("Jvm name only supported for reference types and not " + getClass().getName()); 038 } 039 eq ReferenceType.jvmName() { 040 if (!isNestedType()) { 041 return fullName(); 042 } else if (isAnonymous() || isLocalClass()) { 043 return enclosingType().jvmName() + "$" + uniqueIndex() + name(); 044 } else { 045 return enclosingType().jvmName() + "$" + name(); 046 } 047 } 048 eq ArrayDecl.jvmName() { 049 StringBuffer dim = new StringBuffer(); 050 for (int i = 0; i < dimension(); i++) { 051 dim.append("["); 052 } 053 if (elementType().isReferenceType()) { 054 return dim.toString() + "L" + elementType().jvmName() + ";"; 055 } else { 056 return dim.toString() + elementType().jvmName(); 057 } 058 } 059 eq ByteType.jvmName() = "B"; 060 eq CharType.jvmName() = "C"; 061 eq ShortType.jvmName() = "S"; 062 eq IntType.jvmName() = "I"; 063 eq LongType.jvmName() = "J"; 064 eq FloatType.jvmName() = "F"; 065 eq DoubleType.jvmName() = "D"; 066 eq BooleanType.jvmName() = "Z"; 067 068 syn String TypeDecl.primitiveClassName() { 069 throw new Error("primitiveClassName not supported for " + name() + " of type " + getClass().getName()); 070 } 071 eq ByteType.primitiveClassName() = "Byte"; 072 eq CharType.primitiveClassName() = "Character"; 073 eq ShortType.primitiveClassName() = "Short"; 074 eq IntType.primitiveClassName() = "Integer"; 075 eq LongType.primitiveClassName() = "Long"; 076 eq FloatType.primitiveClassName() = "Float"; 077 eq DoubleType.primitiveClassName() = "Double"; 078 eq BooleanType.primitiveClassName() = "Boolean"; 079 eq VoidType.primitiveClassName() = "Void"; 080 081 syn String TypeDecl.referenceClassFieldName() { 082 throw new Error("referenceClassFieldName not supported for " + name() + " of type " + getClass().getName()); 083 } 084 eq ReferenceType.referenceClassFieldName() = "class$" + jvmName().replace('[', '$').replace('.', '$').replace(';', ' ').trim(); 085 eq ArrayDecl.referenceClassFieldName() = "array" + jvmName().replace('[', '$').replace('.', '$').replace(';', ' ').trim(); 086 087 088 // lazily build a static field for assertionsDisabled 089 private FieldDeclaration TypeDecl.createAssertionsDisabled = null; 090 public FieldDeclaration TypeDecl.createAssertionsDisabled() { 091 if (createAssertionsDisabled != null) { 092 return createAssertionsDisabled; 093 } 094 // static final boolean $assertionsDisabled = !TypeName.class.desiredAssertionStatus(); 095 createAssertionsDisabled = new FieldDeclaration( 096 new Modifiers(new List().add(new Modifier("public")).add(new Modifier("static")).add(new Modifier("final"))), 097 new PrimitiveTypeAccess("boolean"), 098 "$assertionsDisabled", 099 new Opt( 100 new LogNotExpr( 101 topLevelType().createQualifiedAccess().qualifiesAccess( 102 new ClassAccess().qualifiesAccess( 103 new MethodAccess( 104 "desiredAssertionStatus", 105 new List() 106 ) 107 ) 108 ) 109 ) 110 ) 111 ); 112 getBodyDeclList().insertChild(createAssertionsDisabled, 0); 113 // TODO remove this! 114 // explicit read to trigger possible rewrites 115 createAssertionsDisabled = (FieldDeclaration) getBodyDeclList().getChild(0); 116 // transform the generated initalization, e.g., the ClassAccess construct 117 createAssertionsDisabled.transformation(); 118 return createAssertionsDisabled; 119 } 120 121 public FieldDeclaration InterfaceDecl.createStaticClassField(String name) { 122 return methodHolder().createStaticClassField(name); 123 } 124 public MethodDecl InterfaceDecl.createStaticClassMethod() { 125 return methodHolder().createStaticClassMethod(); 126 } 127 // create anonymous class to delegate to 128 private TypeDecl InterfaceDecl.methodHolder = null; 129 public TypeDecl InterfaceDecl.methodHolder() { 130 if (methodHolder != null) { 131 return methodHolder; 132 } 133 String name = "$" + nextAnonymousIndex(); 134 ClassDecl c = addMemberClass(new ClassDecl( 135 new Modifiers(new List()), 136 name, 137 new Opt(), 138 new List(), 139 new List() 140 )); 141 methodHolder = c; 142 return c; 143 } 144 145 // lazily build a static field for each typename used in a .class expression 146 private HashMap TypeDecl.createStaticClassField = null; 147 public FieldDeclaration TypeDecl.createStaticClassField(String name) { 148 if (createStaticClassField == null) { 149 createStaticClassField = new HashMap(); 150 } 151 if (createStaticClassField.containsKey(name)) { 152 return (FieldDeclaration) createStaticClassField.get(name); 153 } 154 // static synthetic Class class$java$lang$String; 155 FieldDeclaration f = new FieldDeclaration( 156 new Modifiers(new List().add(new Modifier("public")).add(new Modifier("static"))), 157 lookupType("java.lang", "Class").createQualifiedAccess(), 158 name, 159 new Opt() 160 ) { 161 public boolean isConstant() { 162 return true; 163 } 164 }; 165 createStaticClassField.put(name, f); 166 return addMemberField(f); 167 } 168 169 // lazily build a static class$ method in this type declaration 170 private MethodDecl TypeDecl.createStaticClassMethod = null; 171 public MethodDecl TypeDecl.createStaticClassMethod() { 172 if (createStaticClassMethod != null) { 173 return createStaticClassMethod; 174 } 175 // static synthetic Class class$(String name) { 176 // try { 177 // return java.lang.Class.forName(name); 178 // } catch(java.lang.ClassNotFoundException e) { 179 // throw new java.lang.NoClassDefFoundError(e.getMessage()); 180 // } 181 // } 182 createStaticClassMethod = new MethodDecl( 183 new Modifiers(new List().add(new Modifier("public")).add(new Modifier("static"))), 184 lookupType("java.lang", "Class").createQualifiedAccess(), 185 "class$", 186 new List().add( 187 new ParameterDeclaration( 188 new Modifiers(new List()), 189 lookupType("java.lang", "String").createQualifiedAccess(), 190 "name" 191 ) 192 ), 193 new List(), 194 new Opt( 195 new Block( 196 new List().add( 197 new TryStmt( 198 new Block( 199 new List().add( 200 new ReturnStmt( 201 new Opt( 202 lookupType("java.lang", "Class").createQualifiedAccess().qualifiesAccess( 203 new MethodAccess( 204 "forName", 205 new List().add( 206 new VarAccess("name") 207 ) 208 ) 209 ) 210 ) 211 ) 212 ) 213 ), 214 new List().add( 215 new BasicCatch( 216 new ParameterDeclaration( 217 new Modifiers(new List()), 218 lookupType("java.lang", "ClassNotFoundException").createQualifiedAccess(), 219 "e" 220 ), 221 new Block( 222 new List().add( 223 new ThrowStmt( 224 new ClassInstanceExpr( 225 lookupType("java.lang", "NoClassDefFoundError").createQualifiedAccess(), 226 new List().add( 227 new VarAccess("e").qualifiesAccess( 228 new MethodAccess( 229 "getMessage", 230 new List() 231 ) 232 ) 233 ), 234 new Opt() 235 ) 236 ) 237 ) 238 ) 239 ) 240 ), 241 new Opt() 242 ) 243 ) 244 ) 245 ) 246 ) { 247 public boolean isConstant() { 248 return true; 249 } 250 }; 251 return addMemberMethod(createStaticClassMethod); 252 } 253 254 }