1 /*
2  * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.tools.java;
27 
28 import sun.tools.tree.*;
29 import java.util.Vector;
30 import java.util.Hashtable;
31 import java.io.IOException;
32 import java.io.DataInputStream;
33 import java.io.ByteArrayInputStream;
34 
35 /**
36  * This class represents a binary member
37  *
38  * WARNING: The contents of this source file are not part of any
39  * supported API.  Code that depends on them does so at its own risk:
40  * they are subject to change or removal without notice.
41  */
42 public final
43 class BinaryMember extends MemberDefinition {
44     Expression value;
45     BinaryAttribute atts;
46 
47     /**
48      * Constructor
49      */
BinaryMember(ClassDefinition clazz, int modifiers, Type type, Identifier name, BinaryAttribute atts)50     public BinaryMember(ClassDefinition clazz, int modifiers, Type type,
51                        Identifier name, BinaryAttribute atts) {
52         super(0, clazz, modifiers, type, name, null, null);
53         this.atts = atts;
54 
55         // Was it compiled as deprecated?
56         if (getAttribute(idDeprecated) != null) {
57             this.modifiers |= M_DEPRECATED;
58         }
59 
60         // Was it synthesized by the compiler?
61         if (getAttribute(idSynthetic) != null) {
62             this.modifiers |= M_SYNTHETIC;
63         }
64     }
65 
66     /**
67      * Constructor for an inner class.
68      */
BinaryMember(ClassDefinition innerClass)69     public BinaryMember(ClassDefinition innerClass) {
70         super(innerClass);
71     }
72 
73     /**
74      * Inline allowed (currently only allowed for the constructor of Object).
75      */
isInlineable(Environment env, boolean fromFinal)76     public boolean isInlineable(Environment env, boolean fromFinal) {
77         // It is possible for 'getSuperClass()' to return null due to error
78         // recovery from cyclic inheritace.  Can this cause a problem here?
79         return isConstructor() && (getClassDefinition().getSuperClass() == null);
80     }
81 
82     /**
83      * Get arguments
84      */
getArguments()85     public Vector<MemberDefinition> getArguments() {
86         if (isConstructor() && (getClassDefinition().getSuperClass() == null)) {
87             Vector<MemberDefinition> v = new Vector<>();
88             v.addElement(new LocalMember(0, getClassDefinition(), 0,
89                                         getClassDefinition().getType(), idThis));
90             return v;
91         }
92         return null;
93     }
94 
95     /**
96      * Get exceptions
97      */
getExceptions(Environment env)98     public ClassDeclaration[] getExceptions(Environment env) {
99         if ((!isMethod()) || (exp != null)) {
100             return exp;
101         }
102         byte data[] = getAttribute(idExceptions);
103         if (data == null) {
104             return new ClassDeclaration[0];
105         }
106 
107         try {
108             BinaryConstantPool cpool = ((BinaryClass)getClassDefinition()).getConstants();
109             DataInputStream in = new DataInputStream(new ByteArrayInputStream(data));
110             // JVM 4.7.5 Exceptions_attribute.number_of_exceptions
111             int n = in.readUnsignedShort();
112             exp = new ClassDeclaration[n];
113             for (int i = 0 ; i < n ; i++) {
114                 // JVM 4.7.5 Exceptions_attribute.exception_index_table[]
115                 exp[i] = cpool.getDeclaration(env, in.readUnsignedShort());
116             }
117             return exp;
118         } catch (IOException e) {
119             throw new CompilerError(e);
120         }
121     }
122 
123     /**
124      * Get documentation
125      */
getDocumentation()126     public String getDocumentation() {
127         if (documentation != null) {
128             return documentation;
129         }
130         byte data[] = getAttribute(idDocumentation);
131         if (data == null) {
132             return null;
133         }
134         try {
135             return documentation = new DataInputStream(new ByteArrayInputStream(data)).readUTF();
136         } catch (IOException e) {
137             throw new CompilerError(e);
138         }
139     }
140 
141     /**
142      * Check if constant:  Will it inline away to a constant?
143      * This override is needed to solve bug 4128266.  It is also
144      * integral to the solution of 4119776.
145      */
146     private boolean isConstantCache = false;
147     private boolean isConstantCached = false;
isConstant()148     public boolean isConstant() {
149         if (!isConstantCached) {
150             isConstantCache = isFinal()
151                               && isVariable()
152                               && getAttribute(idConstantValue) != null;
153             isConstantCached = true;
154         }
155         return isConstantCache;
156     }
157 
158     /**
159      * Get the value
160      */
getValue(Environment env)161     public Node getValue(Environment env) {
162         if (isMethod()) {
163             return null;
164         }
165         if (!isFinal()) {
166             return null;
167         }
168         if (getValue() != null) {
169             return (Expression)getValue();
170         }
171         byte data[] = getAttribute(idConstantValue);
172         if (data == null) {
173             return null;
174         }
175 
176         try {
177             BinaryConstantPool cpool = ((BinaryClass)getClassDefinition()).getConstants();
178             // JVM 4.7.3 ConstantValue.constantvalue_index
179             Object obj = cpool.getValue(new DataInputStream(new ByteArrayInputStream(data)).readUnsignedShort());
180             switch (getType().getTypeCode()) {
181               case TC_BOOLEAN:
182                 setValue(new BooleanExpression(0, ((Number)obj).intValue() != 0));
183                 break;
184               case TC_BYTE:
185               case TC_SHORT:
186               case TC_CHAR:
187               case TC_INT:
188                 setValue(new IntExpression(0, ((Number)obj).intValue()));
189                 break;
190               case TC_LONG:
191                 setValue(new LongExpression(0, ((Number)obj).longValue()));
192                 break;
193               case TC_FLOAT:
194                 setValue(new FloatExpression(0, ((Number)obj).floatValue()));
195                 break;
196               case TC_DOUBLE:
197                 setValue(new DoubleExpression(0, ((Number)obj).doubleValue()));
198                 break;
199               case TC_CLASS:
200                 setValue(new StringExpression(0, (String)cpool.getValue(((Number)obj).intValue())));
201                 break;
202             }
203             return (Expression)getValue();
204         } catch (IOException e) {
205             throw new CompilerError(e);
206         }
207     }
208 
209     /**
210      * Get a field attribute
211      */
getAttribute(Identifier name)212     public byte[] getAttribute(Identifier name) {
213         for (BinaryAttribute att = atts ; att != null ; att = att.next) {
214             if (att.name.equals(name)) {
215                 return att.data;
216             }
217         }
218         return null;
219     }
220 
deleteAttribute(Identifier name)221     public boolean deleteAttribute(Identifier name) {
222         BinaryAttribute walker = null, next = null;
223 
224         boolean succeed = false;
225 
226         while (atts.name.equals(name)) {
227             atts = atts.next;
228             succeed = true;
229         }
230         for (walker = atts; walker != null; walker = next) {
231             next = walker.next;
232             if (next != null) {
233                 if (next.name.equals(name)) {
234                     walker.next = next.next;
235                     next = next.next;
236                     succeed = true;
237                 }
238             }
239         }
240         for (walker = atts; walker != null; walker = walker.next) {
241             if (walker.name.equals(name)) {
242                 throw new InternalError("Found attribute " + name);
243             }
244         }
245 
246         return succeed;
247     }
248 
249 
250 
251     /*
252      * Add an attribute to a field
253      */
addAttribute(Identifier name, byte data[], Environment env)254     public void addAttribute(Identifier name, byte data[], Environment env) {
255         this.atts = new BinaryAttribute(name, data, this.atts);
256         // Make sure that the new attribute is in the constant pool
257         ((BinaryClass)(this.clazz)).cpool.indexString(name.toString(), env);
258     }
259 
260 }
261