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 *   https://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.bcel.generic;
020
021import java.util.ArrayList;
022import java.util.Collections;
023import java.util.List;
024
025import org.apache.bcel.Const;
026import org.apache.bcel.classfile.AccessFlags;
027import org.apache.bcel.classfile.Attribute;
028
029/**
030 * Super class for FieldGen and MethodGen objects, since they have some methods in common!
031 */
032public abstract class FieldGenOrMethodGen extends AccessFlags implements NamedAndTyped, Cloneable {
033
034    /**
035     * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
036     */
037    @Deprecated
038    protected String name;
039
040    /**
041     * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
042     */
043    @Deprecated
044    protected Type type;
045
046    /**
047     * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
048     */
049    @Deprecated
050    protected ConstantPoolGen cp;
051
052    private final List<Attribute> attributeList = new ArrayList<>();
053
054    // @since 6.0
055    private final List<AnnotationEntryGen> annotationList = new ArrayList<>();
056
057    /**
058     * Constructs a FieldGenOrMethodGen.
059     */
060    protected FieldGenOrMethodGen() {
061    }
062
063    /**
064     * Constructs a FieldGenOrMethodGen.
065     *
066     * @param accessFlags the access flags.
067     * @since 6.0
068     */
069    protected FieldGenOrMethodGen(final int accessFlags) { // TODO could this be package protected?
070        super(accessFlags);
071    }
072
073    /**
074     * Adds all attributes from an array.
075     *
076     * @param attributes the attributes to add.
077     */
078    protected void addAll(final Attribute[] attributes) {
079        if (attributes != null) {
080            Collections.addAll(attributeList, attributes);
081        }
082    }
083
084    /**
085     * Adds an annotation entry.
086     *
087     * @param ag the annotation entry.
088     * @since 6.0
089     */
090    public void addAnnotationEntry(final AnnotationEntryGen ag) {
091        annotationList.add(ag);
092    }
093
094    /**
095     * Add an attribute to this method. Currently, the JVM knows about the 'Code', 'ConstantValue', 'Synthetic' and
096     * 'Exceptions' attributes. Other attributes will be ignored by the JVM but do no harm.
097     *
098     * @param a attribute to be added.
099     */
100    public void addAttribute(final Attribute a) {
101        attributeList.add(a);
102    }
103
104    @Override
105    public Object clone() {
106        try {
107            return super.clone();
108        } catch (final CloneNotSupportedException e) {
109            throw new UnsupportedOperationException("Clone Not Supported", e); // never happens
110        }
111    }
112
113    /**
114     * Gets all annotation entries.
115     *
116     * @return all annotation entries.
117     */
118    public AnnotationEntryGen[] getAnnotationEntries() {
119        return annotationList.toArray(AnnotationEntryGen.EMPTY_ARRAY);
120    }
121
122    /**
123     * Gets all attributes of this method or field.
124     *
125     * @return all attributes of this method.
126     */
127    public Attribute[] getAttributes() {
128        return attributeList.toArray(Attribute.EMPTY_ARRAY);
129    }
130
131    /**
132     * Gets the constant pool.
133     *
134     * @return the constant pool.
135     */
136    public ConstantPoolGen getConstantPool() {
137        return cp;
138    }
139
140    /**
141     * @return name of method/field.
142     */
143    @Override
144    public String getName() {
145        return name;
146    }
147
148    /**
149     * Gets the signature of method or field.
150     *
151     * @return signature of method/field.
152     */
153    public abstract String getSignature();
154
155    @Override
156    public Type getType() {
157        return type;
158    }
159
160    /**
161     * Removes all annotation entries.
162     *
163     * @since 6.0
164     */
165    public void removeAnnotationEntries() {
166        annotationList.clear();
167    }
168
169    /**
170     * Removes an annotation entry.
171     *
172     * @param ag the annotation entry to remove.
173     * @since 6.0
174     */
175    public void removeAnnotationEntry(final AnnotationEntryGen ag) {
176        annotationList.remove(ag);
177    }
178
179    /**
180     * Removes an attribute.
181     *
182     * @param a the attribute to remove.
183     */
184    public void removeAttribute(final Attribute a) {
185        attributeList.remove(a);
186    }
187
188    /**
189     * Removes all attributes.
190     */
191    public void removeAttributes() {
192        attributeList.clear();
193    }
194
195    /**
196     * Sets the constant pool.
197     *
198     * @param cp the constant pool.
199     */
200    public void setConstantPool(final ConstantPoolGen cp) { // TODO could be package-protected?
201        this.cp = cp;
202    }
203
204    @Override
205    public void setName(final String name) { // TODO could be package-protected?
206        this.name = name;
207    }
208
209    @Override
210    public void setType(final Type type) { // TODO could be package-protected?
211        if (type.getType() == Const.T_ADDRESS) {
212            throw new IllegalArgumentException("Type cannot be " + type);
213        }
214        this.type = type;
215    }
216}