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.commons.compress.harmony.unpack200.bytecode;
020
021import java.io.DataOutputStream;
022import java.io.IOException;
023import java.util.Arrays;
024
025/**
026 * Exceptions class file attribute
027 */
028public class ExceptionsAttribute extends Attribute {
029
030    private static CPUTF8 attributeName;
031
032    private static int hashCode(final Object[] array) {
033        final int prime = 31;
034        if (array == null) {
035            return 0;
036        }
037        int result = 1;
038        for (final Object element : array) {
039            result = prime * result + (element == null ? 0 : element.hashCode());
040        }
041        return result;
042    }
043
044    public static void setAttributeName(final CPUTF8 cpUTF8Value) {
045        attributeName = cpUTF8Value;
046    }
047
048    private transient int[] exceptionIndexes;
049
050    private final CPClass[] exceptions;
051
052    public ExceptionsAttribute(final CPClass[] exceptions) {
053        super(attributeName);
054        this.exceptions = exceptions;
055    }
056
057    @Override
058    public boolean equals(final Object obj) {
059        if (this == obj) {
060            return true;
061        }
062        if (!super.equals(obj) || getClass() != obj.getClass()) {
063            return false;
064        }
065        final ExceptionsAttribute other = (ExceptionsAttribute) obj;
066        if (!Arrays.equals(exceptions, other.exceptions)) {
067            return false;
068        }
069        return true;
070    }
071
072    @Override
073    protected int getLength() {
074        return 2 + 2 * exceptions.length;
075    }
076
077    @Override
078    protected ClassFileEntry[] getNestedClassFileEntries() {
079        final ClassFileEntry[] result = new ClassFileEntry[exceptions.length + 1];
080        System.arraycopy(exceptions, 0, result, 0, exceptions.length);
081        result[exceptions.length] = getAttributeName();
082        return result;
083    }
084
085    @Override
086    public int hashCode() {
087        final int prime = 31;
088        int result = super.hashCode();
089        result = prime * result + hashCode(exceptions);
090        return result;
091    }
092
093    @Override
094    protected void resolve(final ClassConstantPool pool) {
095        super.resolve(pool);
096        exceptionIndexes = new int[exceptions.length];
097        for (int i = 0; i < exceptions.length; i++) {
098            exceptions[i].resolve(pool);
099            exceptionIndexes[i] = pool.indexOf(exceptions[i]);
100        }
101    }
102
103    @Override
104    public String toString() {
105        final StringBuilder sb = new StringBuilder("Exceptions: ");
106        for (final CPClass exception : exceptions) {
107            sb.append(exception);
108            sb.append(' ');
109        }
110        return sb.toString();
111    }
112
113    @Override
114    protected void writeBody(final DataOutputStream dos) throws IOException {
115        dos.writeShort(exceptionIndexes.length);
116        for (final int element : exceptionIndexes) {
117            dos.writeShort(element);
118        }
119    }
120
121}