001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 *  Unless required by applicable law or agreed to in writing, software
012 *  distributed under the License is distributed on an "AS IS" BASIS,
013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 *  See the License for the specific language governing permissions and
015 *  limitations under the License.
016 *
017 */
018package org.apache.bcel.classfile;
019
020import java.io.DataInput;
021import java.io.DataOutputStream;
022import java.io.IOException;
023
024import org.apache.bcel.Const;
025
026/**
027 * This class is derived from <em>Attribute</em> and declares this class as
028 * `synthetic', i.e., it needs special handling.  The JVM specification
029 * states "A class member that does not appear in the source code must be
030 * marked using a Synthetic attribute."  It may appear in the ClassFile
031 * attribute table, a field_info table or a method_info table.  This class
032 * is intended to be instantiated from the
033 * <em>Attribute.readAttribute()</em> method.
034 *
035 * @version $Id: Synthetic.java 1749603 2016-06-21 20:50:19Z ggregory $
036 * @see     Attribute
037 */
038public final class Synthetic extends Attribute {
039
040    private byte[] bytes;
041
042
043    /**
044     * Initialize from another object. Note that both objects use the same
045     * references (shallow copy). Use copy() for a physical copy.
046     */
047    public Synthetic(final Synthetic c) {
048        this(c.getNameIndex(), c.getLength(), c.getBytes(), c.getConstantPool());
049    }
050
051
052    /**
053     * @param name_index Index in constant pool to CONSTANT_Utf8, which
054     * should represent the string "Synthetic".
055     * @param length Content length in bytes - should be zero.
056     * @param bytes Attribute contents
057     * @param constant_pool The constant pool this attribute is associated
058     * with.
059     */
060    public Synthetic(final int name_index, final int length, final byte[] bytes, final ConstantPool constant_pool) {
061        super(Const.ATTR_SYNTHETIC, name_index, length, constant_pool);
062        this.bytes = bytes;
063    }
064
065
066    /**
067     * Construct object from input stream.
068     * 
069     * @param name_index Index in constant pool to CONSTANT_Utf8
070     * @param length Content length in bytes
071     * @param input Input stream
072     * @param constant_pool Array of constants
073     * @throws IOException
074     */
075    Synthetic(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool)
076            throws IOException {
077        this(name_index, length, (byte[]) null, constant_pool);
078        if (length > 0) {
079            bytes = new byte[length];
080            input.readFully(bytes);
081            System.err.println("Synthetic attribute with length > 0");
082        }
083    }
084
085
086    /**
087     * Called by objects that are traversing the nodes of the tree implicitely
088     * defined by the contents of a Java class. I.e., the hierarchy of methods,
089     * fields, attributes, etc. spawns a tree of objects.
090     *
091     * @param v Visitor object
092     */
093    @Override
094    public void accept( final Visitor v ) {
095        v.visitSynthetic(this);
096    }
097
098
099    /**
100     * Dump source file attribute to file stream in binary format.
101     *
102     * @param file Output file stream
103     * @throws IOException
104     */
105    @Override
106    public final void dump( final DataOutputStream file ) throws IOException {
107        super.dump(file);
108        if (super.getLength() > 0) {
109            file.write(bytes, 0, super.getLength());
110        }
111    }
112
113
114    /**
115     * @return data bytes.
116     */
117    public final byte[] getBytes() {
118        return bytes;
119    }
120
121
122    /**
123     * @param bytes
124     */
125    public final void setBytes( final byte[] bytes ) {
126        this.bytes = bytes;
127    }
128
129
130    /**
131     * @return String representation.
132     */
133    @Override
134    public final String toString() {
135        final StringBuilder buf = new StringBuilder("Synthetic");
136        if (super.getLength() > 0) {
137            buf.append(" ").append(Utility.toHexString(bytes));
138        }
139        return buf.toString();
140    }
141
142
143    /**
144     * @return deep copy of this attribute
145     */
146    @Override
147    public Attribute copy( final ConstantPool _constant_pool ) {
148        final Synthetic c = (Synthetic) clone();
149        if (bytes != null) {
150            c.bytes = new byte[bytes.length];
151            System.arraycopy(bytes, 0, c.bytes, 0, bytes.length);
152        }
153        c.setConstantPool(_constant_pool);
154        return c;
155    }
156}