/******************************************************************************* * Copyright (c) 2014, 2015 IBH SYSTEMS GmbH. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBH SYSTEMS GmbH - initial API and implementation *******************************************************************************/ package org.eclipse.packagedrone.web; import java.lang.reflect.Method; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import javax.servlet.ServletRequest; import javax.servlet.jsp.PageContext; import org.eclipse.packagedrone.web.controller.Controllers; import org.eclipse.packagedrone.web.controller.routing.RequestMappingInformation; import org.eclipse.scada.utils.str.StringReplacer; import org.eclipse.scada.utils.str.StringReplacer.ReplaceSource; import com.google.common.escape.Escaper; import com.google.common.net.UrlEscapers; public class LinkTarget { public class EscaperSource implements ReplaceSource { private final ReplaceSource source; private final Escaper escaper; public EscaperSource ( final ReplaceSource source, final Escaper escaper ) { this.source = source; this.escaper = escaper; } @Override public String replace ( final String context, final String key ) { final String result = this.source.replace ( context, key ); if ( result != null ) { return this.escaper.escape ( result ); } else { return result; } } } private static final Pattern PATTERN = Pattern.compile ( "\\{(.*?)\\}" ); private final String url; public LinkTarget ( final String url ) { this.url = url; } public String render ( final ServletRequest request ) { return expandSource ( new ReplaceSource () { @Override public String replace ( final String context, final String key ) { final Object v = request.getAttribute ( key ); if ( v == null ) { return context; } else { return v.toString (); } } } ).getUrl (); } public String render ( final PageContext pageContext ) { return render ( pageContext.getRequest () ); } public String renderFull ( final PageContext pageContext ) { final StringBuilder sb = new StringBuilder ( pageContext.getServletContext ().getContextPath () ); if ( sb.length () > 0 && !sb.substring ( sb.length () - 1 ).equals ( "/" ) ) { sb.append ( '/' ); } sb.append ( render ( pageContext.getRequest () ) ); return sb.toString (); } public String render ( final Map<String, ?> model ) { return expandSource ( StringReplacer.newExtendedSource ( model ) ).getUrl (); } public LinkTarget expand ( final Map<String, ?> model ) { return expandSource ( StringReplacer.newExtendedSource ( model ) ); } public LinkTarget expandSource ( final ReplaceSource source ) { if ( this.url == null || source == null ) { return this; } final ReplaceSource encodeSource = new EscaperSource ( source, UrlEscapers.urlPathSegmentEscaper () ); return new LinkTarget ( StringReplacer.replace ( this.url, encodeSource, PATTERN, false ) ); } public String getUrl () { return this.url; } @Override public String toString () { return String.format ( "[LinkTarget: %s]", this.url ); } private static Set<String> getRawPaths ( final Method method ) { final RequestMappingInformation rmi = Controllers.fromMethod ( method ); if ( rmi == null ) { return null; } return rmi.getRawPaths (); } public static LinkTarget createFromController ( final Class<?> controllerClazz, final String methodName ) { final Method m = getControllerMethod ( controllerClazz, methodName ); if ( m != null ) { final Set<String> paths = getRawPaths ( m ); if ( paths != null && !paths.isEmpty () ) { return new LinkTarget ( paths.iterator ().next () ); } } throw new IllegalArgumentException ( String.format ( "Controller class '%s' has no request method '%s'", controllerClazz.getName (), methodName ) ); } public static Method getControllerMethod ( final Object controller, final String methodName ) { if ( controller == null ) { return null; } return getControllerMethod ( controller.getClass (), methodName ); } public static Method getControllerMethod ( final Class<?> controllerClazz, final String methodName ) { for ( final Method m : controllerClazz.getMethods () ) { if ( !m.getName ().equals ( methodName ) ) { continue; } return m; } return null; } public static LinkTarget createFromController ( final Method method ) { if ( method == null ) { throw new IllegalStateException ( "No method provided" ); } final Set<String> paths = getRawPaths ( method ); if ( paths.isEmpty () ) { throw new IllegalStateException ( String.format ( "Method '%s' has no @RequestMapping information assigned", method ) ); } return new LinkTarget ( paths.iterator ().next () ); } }