// Do not apply Lily license header // This file was copied from the Apache Cocoon 2.1.x source tree. // Please keep the original license on this file. /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.lilyproject.util.location; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * A cascading and located <code>RuntimeException</code>. It is also {@link MultiLocatable} to easily build * location stack traces. * <p> * If a <code>LocatedRuntimeException</code> is built with a location and a cause which is also a * <code>LocatedRuntimeException</code>, then the default behavior is to add the location to the cause * exception and immediately rethrow the cause. This avoids exception nesting and builds a location * stack. * * @since 2.1.8 */ public class LocatedRuntimeException extends RuntimeException implements LocatableException, MultiLocatable { private List locations; public LocatedRuntimeException(String message) { this(message, null, null, true); } public LocatedRuntimeException(String message, Throwable cause) throws LocatedRuntimeException { this(message, cause, null, true); } public LocatedRuntimeException(String message, Location location) { this(message, null, location, true); } public LocatedRuntimeException(String message, Throwable cause, Location location) throws LocatedRuntimeException { this(message, cause, location, true); } public LocatedRuntimeException(String message, Throwable cause, Location location, boolean rethrowLocated) throws LocatedRuntimeException { super(message, cause); if (rethrowLocated && cause instanceof LocatedRuntimeException) { LocatedRuntimeException lreCause = (LocatedRuntimeException)cause; lreCause.addLocation(location); // Rethrow the cause throw lreCause; } LocatedException.ensureCauseChainIsSet(cause); LocatedException.addCauseLocations(this, cause); addLocation(location); } @Override public Location getLocation() { return locations == null ? null : (Location) locations.get(0); } @Override public List getLocations() { return locations == null ? Collections.EMPTY_LIST : locations; } @Override public String getRawMessage() { return super.getMessage(); } @Override public String getMessage() { return LocatedException.getMessage(super.getMessage(), locations); } @Override public void addLocation(Location loc) { if (LocationUtils.isUnknown(loc)) { return; } if (locations == null) { this.locations = new ArrayList(1); // Start small } locations.add(LocationImpl.get(loc)); } }