    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 */
    017package org.apache.bcel.verifier.structurals;
    018
    019import java.util.HashMap;
    020import java.util.HashSet;
    021import java.util.Map;
    022import java.util.Set;
    023
    024import org.apache.bcel.generic.CodeExceptionGen;
    025import org.apache.bcel.generic.InstructionHandle;
    026import org.apache.bcel.generic.MethodGen;
    027
    028/**
    029 * This class allows easy access to ExceptionHandler objects.
    030 */
    031public class ExceptionHandlers {
    032
    033    /**
    034     * Empty array.
    035     */
    036    private static final ExceptionHandler[] EMPTY_ARRAY = {};
    037
    038    /**
    039     * The ExceptionHandler instances. Key: InstructionHandle objects, Values: HashSet<ExceptionHandler> instances.
    040     */
    041    private final Map<InstructionHandle, Set<ExceptionHandler>> exceptionHandlers;
    042
    043    /**
    044     * Constructor. Creates a new ExceptionHandlers instance.
    045     */
    046    public ExceptionHandlers(final MethodGen mg) {
    047        exceptionHandlers = new HashMap<>();
    048        final CodeExceptionGen[] cegs = mg.getExceptionHandlers();
    049        for (final CodeExceptionGen ceg : cegs) {
    050            final ExceptionHandler eh = new ExceptionHandler(ceg.getCatchType(), ceg.getHandlerPC());
    051            for (InstructionHandle ih = ceg.getStartPC(); ih != ceg.getEndPC().getNext(); ih = ih.getNext()) {
    052                exceptionHandlers.computeIfAbsent(ih, k -> new HashSet<>()).add(eh);
    053                exceptionHandlers.computeIfAbsent(ih, k -> new HashSet<>()).add(eh);
    054            }
    055        }
    056    }
    057
    058    /**
    059     * Returns all the ExceptionHandler instances representing exception handlers that protect the instruction ih.
    060     */
    061    public ExceptionHandler[] getExceptionHandlers(final InstructionHandle ih) {
    062        final Set<ExceptionHandler> hsSet = exceptionHandlers.get(ih);
    063        if (hsSet == null) {
    064            return EMPTY_ARRAY;
    065        }
    066        return hsSet.toArray(ExceptionHandler.EMPTY_ARRAY);
    067    }
    068
    069}