/* Copyright 2008 Ben Gunter
*
* Licensed 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 net.sourceforge.stripes.exception;
import java.util.Collection;
import net.sourceforge.stripes.action.ActionBean;
/**
* <p>
* This exception indicates that a URL does not contain enough information to map it to a single
* {@link ActionBean} class. In some cases, a URL may match more than one URL binding.
* </p>
* <p>
* For example, suppose you have two ActionBeans with the URL bindings <code>/foo/{param}/bar</code>
* and <code>/foo/{param}/blah</code>. The paths {@code /foo} and {@code /foo/X} -- while legal,
* since any number of parameters or literals may be omitted from the end of a clean URL -- match
* both of the URL bindings. Since Stripes cannot determine from the URL the ActionBean to which to
* dispatch the request, it throws this exception to indicate the conflict.
* </p>
*
* @author Ben Gunter
* @since Stripes 1.5.1
*/
public class UrlBindingConflictException extends StripesRuntimeException {
private static final long serialVersionUID = 1L;
/** Generate the message to pass to the superclass constructor */
protected static String getMessage(Class<? extends ActionBean> targetClass, String path,
Collection<String> matches) {
return (targetClass == null ? "" : "Failure generating URL for " + targetClass + ". ")
+ "The path " + path + " cannot be mapped to a single ActionBean because multiple "
+ "URL bindings match it. The matching URL bindings are " + matches + ". If you "
+ "generated the URL using the Stripes tag library (stripes:link, stripes:url, "
+ "stripes:form, etc.) then you must embed enough stripes:param tags within the "
+ "parent tag to produce a URL that maps to exactly one of the indicated matches. "
+ "If you generated the URL by some other means, then you must embed enough "
+ "information in the URL to achieve the same end.";
}
private String path;
private Collection<String> matches;
private Class<? extends ActionBean> targetClass;
/**
* New exception indicating that the {@code path} does not map to a single ActionBean because it
* potentially matches all the URL bindings in the {@code matches} collection.
*
* @param message An informative message about what went wrong
* @param targetClass The class for which a URL could not be generated.
* @param path The offending path
* @param matches A collection of all the potentially matching URL bindings
*/
public UrlBindingConflictException(String message, Class<? extends ActionBean> targetClass,
String path, Collection<String> matches) {
super(message);
this.targetClass = targetClass;
this.path = path;
this.matches = matches;
}
/**
* New exception indicating that the {@code path} does not map to a single ActionBean because it
* potentially matches all the URL bindings in the {@code matches} collection.
*
* @param targetClass The class for which a URL could not be generated.
* @param path The offending path
* @param matches A collection of all the potentially matching URL bindings
*/
public UrlBindingConflictException(Class<? extends ActionBean> targetClass, String path,
Collection<String> matches) {
this(getMessage(targetClass, path, matches), targetClass, path, matches);
}
/**
* New exception indicating that the {@code path} does not map to a single ActionBean because it
* potentially matches all the URL bindings in the {@code matches} collection.
*
* @param message An informative message about what went wrong
* @param path The offending path
* @param matches A collection of all the potentially matching URL bindings
*/
public UrlBindingConflictException(String message, String path, Collection<String> matches) {
this(message, null, path, matches);
}
/**
* New exception indicating that the {@code path} does not map to a single ActionBean because it
* potentially matches all the URL bindings in the {@code matches} collection.
*
* @param path The offending path
* @param matches A collection of all the potentially matching URL bindings
*/
public UrlBindingConflictException(String path, Collection<String> matches) {
this(getMessage(null, path, matches), path, matches);
}
/** Get the path that failed to map to a single ActionBean */
public String getPath() {
return path;
}
/** Get all the URL bindings on existing ActionBeans that match the path */
public Collection<String> getMatches() {
return matches;
}
/**
* Get the {@link ActionBean} class for which a URL was being generated when this exception was
* thrown. If the exception occurred while dispatching a request, then this property will be
* null since the path cannot be associated with an ActionBean class. However, if it is thrown
* while generating a URL that is intended to point to an ActionBean, then this property will
* indicate the class that was being targeted.
*/
public Class<? extends ActionBean> getTargetClass() {
return targetClass;
}
}