1   /*
2    * Copyright 2000-2001,2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  /* 
18  
19   */
20  
21  package org.apache.wsrp4j.consumer.driver;
22  
23  import java.net.URLDecoder;
24  import java.util.HashMap;
25  import java.util.Iterator;
26  import java.util.Map;
27  import java.util.Set;
28  
29  import org.apache.wsrp4j.consumer.URLGenerator;
30  import org.apache.wsrp4j.consumer.URLRewriter;
31  import org.apache.wsrp4j.log.LogManager;
32  import org.apache.wsrp4j.log.Logger;
33  import org.apache.wsrp4j.util.Constants;
34  
35  import com.liferay.util.SystemProperties;
36  
37  /**
38   * This class implements the URLRewriter-interface providing a method
39   * to rewrite urls (Consumer URL Rewriting).
40   *
41   * @author <a href="mailto:stefan.behl@de.ibm.com">Stefan Behl</a>
42   * @author Richard Jacob
43   */
44  public class URLRewriterImpl implements URLRewriter {
45  
46      private static URLRewriter instance = null;
47  
48      private URLGenerator urlGenerator = null;
49  
50      // log and trace support
51      private Logger logger = LogManager.getLogManager().getLogger(
52              this.getClass());
53  
54      public static URLRewriter getInstance() {
55          if (instance == null) {
56              instance = new URLRewriterImpl();
57          }
58  
59          return instance;
60      }
61  
62      private URLRewriterImpl() {
63      }
64  
65      /**
66       * Sets the url generator. This is required to enable url rewriting.
67       */
68      public void setURLGenerator(URLGenerator urlGenerator) {
69  
70          String MN = "setURLGenerator";
71          if (logger.isLogging(Logger.TRACE_HIGH)) {
72              logger.entry(Logger.TRACE_HIGH, MN);
73          }
74  
75          this.urlGenerator = urlGenerator;
76  
77          if (logger.isLogging(Logger.TRACE_HIGH)) {
78              logger.exit(Logger.TRACE_HIGH, MN);
79          }
80  
81      }
82  
83      /**
84       * Parses markup and performs URL rewriting.
85       *
86       * Principle:
87       * - Iterate over markup-string once and copy processed markup to result
88       *   buffer (StringBuffer)
89       * - If url to be rewritten found (during markup iteration),
90       *   ... append markup before url to result buffer,
91       *   ... perform rewriting (call URLGenerator) and append rewritten url to result buffer.
92       *
93       * Incomplete rewrite-pairs (e.g. a rewrite-begin-token not followed by a
94       * rewrite-end-token) are considered as 'normal' markup.
95       *
96       * @param markup           String representing the markup to be processed.
97       *
98       * @return String representing the processed markup.    
99       */
100     /**
101      * Rewriting: get url from URLGenerator and append it
102      */
103     private void rewrite(StringBuffer markup, String rewriteURL) {
104         String MN = "rewrite";
105         if (this.urlGenerator != null) {
106             if (rewriteURL.startsWith(Constants.REWRITE_START
107                     + Constants.PARAMS_START)) {
108                 // handle URL rewriting             
109                 Map params = createParameterMap(rewriteURL);
110 
111                 // What kind of link has to be rewritten?
112                 if (rewriteURL.indexOf(Constants.URL_TYPE_BLOCKINGACTION) != -1) {
113                     markup.append(urlGenerator.getBlockingActionURL(params));
114                 }
115                 else if (rewriteURL.indexOf(Constants.URL_TYPE_RENDER) != -1) {
116                     markup.append(urlGenerator.getRenderURL(params));
117                 }
118                 else if (rewriteURL.indexOf(Constants.URL_TYPE_RESOURCE) != -1) {
119                     markup.append(urlGenerator.getResourceURL(params));
120                 }
121             }
122             else if (rewriteURL.startsWith(Constants.REWRITE_START
123                     + Constants.NAMESPACE_START)) {
124                 // handle namespace rewriting
125                 markup.append(urlGenerator.getNamespacedToken(""));
126             }
127             else {
128                 if (logger.isLogging(Logger.ERROR)) {
129                     logger.text(Logger.ERROR, MN,
130                             "no valid rewrite expression found in: "
131                                     + rewriteURL);
132                 }
133             }
134 
135         }
136         else {
137 
138             if (logger.isLogging(Logger.ERROR)) {
139                 String message = "URLGenerator has not been set for class URLRewriterImpl. URL-Rewriting not possible.";
140                 logger.text(Logger.ERROR, MN, message);
141             }
142 
143         }
144 
145     }
146 
147     /**
148      * Extracts parameters from url to be rewritten copies them into a map.
149      * Returns this map.
150      */
151     private Map createParameterMap(String rewriteURL) {
152 
153         Map params = new HashMap();
154 
155         if (rewriteURL.indexOf(Constants.URL_TYPE_BLOCKINGACTION) != -1) {
156 
157             params.put(Constants.URL_TYPE, Constants.URL_TYPE_BLOCKINGACTION);
158 
159         }
160         else if (rewriteURL.indexOf(Constants.URL_TYPE_RENDER) != -1) {
161 
162             params.put(Constants.URL_TYPE, Constants.URL_TYPE_RENDER);
163 
164         }
165         else if (rewriteURL.indexOf(Constants.URL_TYPE_RESOURCE) != -1) {
166 
167             params.put(Constants.URL_TYPE, Constants.URL_TYPE_RESOURCE);
168 
169         }
170         else {
171             // TODO: throw exception...
172         }
173 
174         // begin parsing
175         int equals = 0;
176         int next = 0;
177         int end = rewriteURL.indexOf(Constants.REWRITE_END);
178         int index = rewriteURL.indexOf(Constants.NEXT_PARAM);
179         int lengthNext = 0;
180         String subNext = null;
181 
182         while (index != -1) {
183 
184             // support "&amp;" as parameter seperator
185             // see if &amp; was used
186             subNext = rewriteURL.substring(index, index
187                     + Constants.NEXT_PARAM_AMP.length());
188             if (subNext.equals(Constants.NEXT_PARAM_AMP)) {
189                 lengthNext = Constants.NEXT_PARAM_AMP.length();
190             }
191             else {
192                 lengthNext = Constants.NEXT_PARAM.length();
193             }
194 
195             equals = rewriteURL.indexOf(Constants.EQUALS, index + lengthNext);
196             next = rewriteURL.indexOf(Constants.NEXT_PARAM, equals);
197 
198             if (equals != -1) {
199 
200                 if (next != -1) {
201                     params.put(
202                             rewriteURL.substring(index + lengthNext, equals),
203                             rewriteURL.substring(equals + 1, next));
204                 }
205                 else {
206                     params.put(
207                             rewriteURL.substring(index + lengthNext, equals),
208                             rewriteURL.substring(equals + 1, end));
209                 }
210 
211             }
212 
213             index = next;
214         }
215 
216         Set keys = params.keySet();
217         String encoding = SystemProperties.get("file.encoding");
218         
219         for (Iterator i = keys.iterator(); i.hasNext();) {
220             Object key = i.next();
221             String value = (String)params.get(key);
222             try {
223                 params.put(key, URLDecoder.decode(value, encoding));
224             } 
225             catch (Exception e) {
226             }
227         }
228         
229         return params;
230 
231     }
232 
233     /**
234      * @param markup
235      * @return
236      */
237     public String rewriteURLs(String markup) {
238         final String MN = "rewriteURLs";
239         if (logger.isLogging(Logger.TRACE_HIGH)) {
240             logger.entry(Logger.TRACE_HIGH, MN);
241         }
242 
243         if (this.urlGenerator == null) {
244             if (logger.isLogging(Logger.ERROR)) {
245                 String message = "URLGenerator has not been set for class URLRewriterImpl. URL-Rewriting not possible.";
246                 logger.text(Logger.ERROR, MN, message);
247             }
248             return markup;
249         }
250 
251         StringBuffer resultMarkup = new StringBuffer("");
252         int markupIndex = 0;
253         int rewriteStartPos = -1;
254         int rewriteEndPos = -1;
255         int currentPos = 0;
256         String exprType = null;
257 
258         // loop through the markup, find rewrite expressions, rewrite them 
259         while (markupIndex < markup.length()) {
260 
261             rewriteStartPos = -1;
262             rewriteEndPos = -1;
263 
264             // get fist occurance of wsrp rewrite expression
265             rewriteStartPos = markup.indexOf(Constants.REWRITE_START,
266                     markupIndex);
267 
268             if (!(rewriteStartPos == -1 || (rewriteStartPos
269                     + Constants.REWRITE_START.length() - 1) > (markup.length() - 2))) {
270                 // found a rewrite start token, and token is not at the end of markup so we can
271                 // determine the rewrite type, i.e. there is at least 1 char after the rewrite start token
272 
273                 // namespace or URL? The single char string after the token decides
274                 exprType = markup.substring(rewriteStartPos
275                         + Constants.REWRITE_START.length() - 1 + 1,
276                         rewriteStartPos + Constants.REWRITE_START.length() - 1
277                                 + 2);
278 
279                 if (exprType.equals(Constants.NAMESPACE_START)) {
280                     // ok, we have a namespace rewrite here                     
281                     rewriteEndPos = rewriteStartPos
282                             + Constants.REWRITE_START.length()
283                             + Constants.NAMESPACE_START.length() - 1;
284                 }
285                 else if (exprType.equals(Constants.PARAMS_START)) {
286                     // ok, we have a URL rewrite here
287                     // get the position of the end token
288                     rewriteEndPos = markup.indexOf(Constants.REWRITE_END,
289                             markupIndex);
290                     if (rewriteEndPos != -1) {
291                         // now let's see if we find a rewrite start token nearer to the end token
292                         currentPos = rewriteStartPos;
293 
294                         while ((currentPos != -1)
295                                 && (currentPos < rewriteEndPos)) {
296                             // update rewriteStartPos with position of found rewrite begin token being 'nearer' 
297                             rewriteStartPos = currentPos;
298                             // look for next URL rewrite start expression
299                             currentPos = markup.indexOf(Constants.REWRITE_START
300                                     + Constants.PARAMS_START, rewriteStartPos
301                                     + Constants.REWRITE_START.length()
302                                     + Constants.PARAMS_START.length());
303                         }
304                         rewriteEndPos = rewriteEndPos
305                                 + Constants.REWRITE_END.length() - 1;
306                     }
307                 }
308             }
309 
310             if ((rewriteStartPos != -1) && (rewriteEndPos != -1)) {
311                 // append markup before rewrite expression
312                 resultMarkup.append(markup.substring(markupIndex,
313                         rewriteStartPos));
314                 // append rewritten expression
315                 rewrite(resultMarkup, markup.substring(rewriteStartPos,
316                         rewriteEndPos + 1));
317                 // set markup index after the last char of the rewriteExpression
318                 markupIndex = rewriteEndPos + 1;
319             }
320             else {
321                 // append rest of markup
322                 resultMarkup.append(markup.substring(markupIndex, markup
323                         .length()));
324                 markupIndex = markup.length();
325             }
326         }
327 
328         if (logger.isLogging(Logger.TRACE_HIGH)) {
329             logger.exit(Logger.TRACE_HIGH, MN);
330         }
331 
332         return resultMarkup.toString();
333     }
334 
335 }
336 
337