001 // Copyright 2009 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.tapestry5.internal.services;
016
017 import javax.servlet.http.HttpServletRequest;
018
019 import org.apache.tapestry5.Link;
020 import org.apache.tapestry5.ioc.Invocation;
021 import org.apache.tapestry5.ioc.MethodAdvice;
022 import org.apache.tapestry5.ioc.internal.util.Defense;
023 import org.apache.tapestry5.services.*;
024 import org.apache.tapestry5.urlrewriter.SimpleRequestWrapper;
025 import org.apache.tapestry5.urlrewriter.URLRewriteContext;
026
027 /**
028 * Advices
029 * {@linkplain ComponentEventLinkEncoder#createComponentEventLink(org.apache.tapestry5.services.ComponentEventRequestParameters, boolean)}
030 * and
031 * {@linkplain ComponentEventLinkEncoder#createPageRenderLink(org.apache.tapestry5.services.PageRenderRequestParameters)}
032 * to rewrites the returned links using {@linkplain URLRewriter}.
033 */
034 public class ComponentEventLinkEncoderMethodAdvice implements MethodAdvice
035 {
036
037 private final URLRewriter urlRewriter;
038
039 private final Request request;
040
041 private final HttpServletRequest httpServletRequest;
042
043 private final Response response;
044
045 private final boolean forPageLink;
046
047 /**
048 * Index of the invocation parameter that contains either the ComponentEventRequestParameter
049 * or the PageRenderRequestParameter objects.
050 */
051 private static final int CONTEXT_PARAMETER_INDEX =0;
052
053 /**
054 * Single constructor of this class.
055 *
056 * @param urlRewriter
057 * an {@link URLRewriter}. It cannot be null.
058 * @param request
059 * a {@link Request}. It cannot be null.
060 * @param httpServletRequest
061 * an {@link HttpServletRequest}. It cannot be null.
062 * @param response
063 * a {@link Response}. It cannot be null.
064 * @param forPageLink
065 * true if the advice is for page link creation, false for component event link creation.
066 */
067 public ComponentEventLinkEncoderMethodAdvice(URLRewriter urlRewriter,
068 Request request, HttpServletRequest httpServletRequest, Response response,
069 boolean forPageLink)
070 {
071
072 Defense.notNull(urlRewriter, "urlRewriter");
073 Defense.notNull(request, "request");
074 Defense.notNull(httpServletRequest, "httpServletRequest");
075 Defense.notNull(response, "response");
076
077 this.httpServletRequest = httpServletRequest;
078 this.urlRewriter = urlRewriter;
079 this.request = request;
080 this.response = response;
081 this.forPageLink = forPageLink;
082 }
083
084 public void advise(Invocation invocation)
085 {
086 invocation.proceed();
087 String name = invocation.getMethodName();
088
089 Link link = (Link) invocation.getResult();
090 URLRewriteContext context = setupContext(invocation);
091 Link newLink = rewriteIfNeeded(link,context);
092
093 if (newLink != null)
094 {
095 invocation.overrideResult(newLink);
096 }
097
098 }
099
100 private URLRewriteContext setupContext(final Invocation invocation) {
101
102 if (forPageLink) {
103 return new URLRewriteContext()
104 {
105
106 public boolean isIncoming()
107 {
108 return false;
109 }
110
111 public PageRenderRequestParameters getPageParameters()
112 {
113 return (PageRenderRequestParameters) invocation.getParameter(CONTEXT_PARAMETER_INDEX);
114 }
115
116 public ComponentEventRequestParameters getComponentEventParameters()
117 {
118 return null;
119 }
120 };
121 }
122 return new URLRewriteContext()
123 {
124
125 public boolean isIncoming()
126 {
127 return false;
128 }
129
130 public PageRenderRequestParameters getPageParameters()
131 {
132 return null;
133 }
134
135 public ComponentEventRequestParameters getComponentEventParameters()
136 {
137 return (ComponentEventRequestParameters) invocation.getParameter(CONTEXT_PARAMETER_INDEX);
138 }
139 };
140 }
141
142 /**
143 * Returns a rewritten Link or null.
144 *
145 * @param link
146 * a {@link Link}.
147 */
148 Link rewriteIfNeeded(Link link, URLRewriteContext context)
149 {
150 Link newLink = null;
151 SimpleRequestWrapper fakeRequest = new SimpleRequestWrapper(request, link.toAbsoluteURI());
152
153 Request rewritten = urlRewriter.processLink(fakeRequest,context);
154
155 // if the original request is equal to the rewritten one, no
156 // rewriting is needed
157 if (fakeRequest != rewritten)
158 {
159
160 final String originalServerName = request.getServerName();
161 final String rewrittenServerName = rewritten.getServerName();
162 boolean absolute = originalServerName.equals(rewrittenServerName) == false;
163 final String newPath = rewritten.getPath();
164
165 String newUrl = absolute ? fullUrl(rewritten) : newPath;
166
167 newLink = new LinkImpl(newUrl, false, false, response, null);
168
169 }
170
171 return newLink;
172
173 }
174
175 String fullUrl(Request request)
176 {
177
178 String protocol = request.isSecure() ? "https://" : "http://";
179 final int localPort = httpServletRequest.getLocalPort();
180 String port = localPort == 80 ? "" : ":" + localPort;
181
182 final String path = request.getPath();
183 final String contextPath = request.getContextPath();
184 return String.format("%s%s%s%s%s", protocol, request.getServerName(), port, contextPath, path);
185
186 }
187
188 }