1 16 17 package org.apache.velocity.tools.view.tools; 18 19 import java.lang.reflect.InvocationTargetException ; 20 import java.lang.reflect.Method ; 21 import java.net.URLEncoder ; 22 import java.util.ArrayList ; 23 import java.util.List ; 24 25 import javax.servlet.http.HttpServletRequest ; 26 import javax.servlet.http.HttpServletResponse ; 27 import javax.servlet.http.HttpSession ; 28 import javax.servlet.ServletContext ; 29 30 import org.apache.velocity.app.Velocity; 31 import org.apache.velocity.tools.view.context.ViewContext; 32 import org.apache.velocity.tools.view.tools.ViewTool; 33 34 57 public class LinkTool implements ViewTool, Cloneable 58 { 59 60 61 62 public static final String HTML_QUERY_DELIMITER = "&"; 63 64 65 public static final String XHTML_QUERY_DELIMITER = "&"; 66 67 68 69 protected ServletContext application; 70 71 72 protected HttpServletRequest request; 73 74 75 protected HttpServletResponse response; 76 77 78 79 private String uri; 80 81 82 private String anchor; 83 84 85 private ArrayList queryData; 86 87 88 private String queryDataDelim; 89 90 91 92 private static Method encode = null; 93 94 96 static 97 { 98 try 99 { 100 101 Class [] args = new Class [] { String .class, String .class }; 102 encode = URLEncoder .class.getMethod("encode", args); 103 } 104 catch (NoSuchMethodException e) 105 { 106 Velocity.debug("LinkTool: Can't find JDK 1.4 encode method. Using JDK 1.3 version."); 107 } 108 } 109 110 111 114 public LinkTool() 115 { 116 uri = null; 117 anchor = null; 118 queryData = null; 119 queryDataDelim = HTML_QUERY_DELIMITER; 120 } 121 122 123 125 137 protected void setXhtml(boolean useXhtml) 138 { 139 queryDataDelim = 140 (useXhtml) ? XHTML_QUERY_DELIMITER : HTML_QUERY_DELIMITER; 141 } 142 143 144 151 protected LinkTool copyWith(QueryPair pair) 152 { 153 LinkTool copy = duplicate(); 154 if (copy.queryData != null) 155 { 156 copy.queryData = (ArrayList )this.queryData.clone(); 159 } 160 else 161 { 162 copy.queryData = new ArrayList (); 163 } 164 copy.queryData.add(pair); 166 return copy; 167 } 168 169 170 177 protected LinkTool copyWith(String uri) 178 { 179 LinkTool copy = duplicate(); 180 copy.uri = uri; 181 return copy; 182 } 183 184 185 193 protected LinkTool copyWithAnchor(String anchor) 194 { 195 LinkTool copy = duplicate(); 196 copy.anchor = anchor; 197 return copy; 198 } 199 200 201 204 private LinkTool duplicate() 205 { 206 try 207 { 208 return (LinkTool)this.clone(); 209 } 210 catch (CloneNotSupportedException e) 211 { 212 Velocity.warn("LinkTool: could not properly clone " + getClass() + 213 " - " + e); 214 215 LinkTool copy; 217 try 218 { 219 copy = (LinkTool)getClass().newInstance(); 221 } 222 catch (Exception ee) 223 { 224 copy = new LinkTool(); 226 } 227 copy.application = this.application; 228 copy.request = this.request; 229 copy.response = this.response; 230 copy.uri = this.uri; 231 copy.anchor = this.anchor; 232 copy.queryData = this.queryData; 233 copy.queryDataDelim = this.queryDataDelim; 234 return copy; 235 } 236 } 237 238 239 241 247 public void init(Object obj) 248 { 249 if (!(obj instanceof ViewContext)) 250 { 251 throw new IllegalArgumentException ("Tool can only be initialized with a ViewContext"); 252 } 253 254 ViewContext context = (ViewContext)obj; 255 this.request = context.getRequest(); 256 this.response = context.getResponse(); 257 this.application = context.getServletContext(); 258 Boolean b = (Boolean )context.getAttribute(ViewContext.XHTML); 259 if (b != null) 260 { 261 setXhtml(b.booleanValue()); 262 } 263 } 264 265 266 268 281 public LinkTool setAnchor(String anchor) 282 { 283 return copyWithAnchor(anchor); 284 } 285 286 287 290 public String getAnchor() 291 { 292 return anchor; 293 } 294 295 296 312 public LinkTool setRelative(String uri) 313 { 314 if (uri.startsWith("/")) 315 { 316 return copyWith(request.getContextPath() + uri); 317 } 318 else 319 { 320 return copyWith(request.getContextPath() + '/' + uri); 321 } 322 } 323 324 325 337 public LinkTool setURI(String uri) 338 { 339 return copyWith(uri); 340 } 341 342 343 349 public String getURI() 350 { 351 return uri; 352 } 353 354 355 365 public LinkTool addQueryData(String key, Object value) 366 { 367 return copyWith(new QueryPair(key, value)); 368 } 369 370 371 375 public String getQueryData() 376 { 377 if (queryData != null && !queryData.isEmpty()) 378 { 379 380 StringBuffer out = new StringBuffer (); 381 for(int i=0; i < queryData.size(); i++) 382 { 383 out.append(queryData.get(i)); 384 if (i+1 < queryData.size()) 385 { 386 out.append(queryDataDelim); 387 } 388 } 389 return out.toString(); 390 } 391 return null; 392 } 393 394 395 401 public String getContextURL() 402 { 403 String scheme = request.getScheme(); 404 int port = request.getServerPort(); 405 406 StringBuffer out = new StringBuffer (); 407 out.append(request.getScheme()); 408 out.append("://"); 409 out.append(request.getServerName()); 410 if ((scheme.equals("http") && port != 80) || 411 (scheme.equals("https") && port != 443)) 412 { 413 out.append(':'); 414 out.append(port); 415 } 416 out.append(request.getContextPath()); 417 return out.toString(); 418 } 419 420 421 428 public String getContextPath() 429 { 430 return request.getContextPath(); 431 } 432 433 434 442 public String getBaseRef() 443 { 444 StringBuffer out = new StringBuffer (); 445 out.append(getContextURL()); 446 out.append(request.getServletPath()); 447 return out.toString(); 448 } 449 450 451 459 public String toString() 460 { 461 StringBuffer out = new StringBuffer (); 462 463 if (uri != null) 464 { 465 out.append(uri); 466 } 467 468 String query = getQueryData(); 469 if (query != null) 470 { 471 if ( uri == null || uri.indexOf('?') < 0) 473 { 474 out.append('?'); 476 } 477 else 478 { 479 out.append(queryDataDelim); 481 } 482 out.append(query); 483 } 484 485 if (anchor != null) 486 { 487 out.append('#'); 488 out.append(encodeURL(anchor)); 489 } 490 491 return response.encodeURL(out.toString()); 494 } 495 496 497 505 public String encodeURL(String url) 506 { 507 508 if (encode != null) 509 { 510 try 511 { 512 Object [] args = 513 new Object [] { url, this.response.getCharacterEncoding() }; 514 return (String )encode.invoke(null, args); 515 } 516 catch (IllegalAccessException e) 517 { 518 encode = null; 520 521 Velocity.debug("LinkTool: Can't access JDK 1.4 encode method (" 522 + e + "). Using deprecated version from now on."); 523 } 524 catch (InvocationTargetException e) 525 { 526 Velocity.debug("LinkTool: Error using JDK 1.4 encode method (" 527 + e + "). Using deprecated version."); 528 } 529 } 530 return URLEncoder.encode(url); 531 } 532 533 534 535 537 541 protected final class QueryPair 542 { 543 544 private final String key; 545 private final Object value; 546 547 548 554 public QueryPair(String key, Object value) 555 { 556 this.key = key; 557 this.value = value; 558 } 559 560 563 public String toString() 564 { 565 StringBuffer out = new StringBuffer (); 566 if (value == null) 567 { 568 out.append(encodeURL(key)); 569 out.append('='); 570 571 } 572 else if (value instanceof List ) 573 { 574 appendAsArray(out, key, ((List )value).toArray()); 575 } 576 else if (value instanceof Object []) 577 { 578 appendAsArray(out, key, (Object [])value); 579 } 580 else 581 { 582 out.append(encodeURL(key)); 583 out.append('='); 584 out.append(encodeURL(String.valueOf(value))); 585 } 586 return out.toString(); 587 } 588 589 590 private void appendAsArray(StringBuffer out, String key, Object [] arr) 591 { 592 String encKey = encodeURL(key); 593 for (int i=0; i < arr.length; i++) 594 { 595 out.append(encKey); 596 out.append('='); 597 if (arr[i] != null) 598 { 599 out.append(encodeURL(String.valueOf(arr[i]))); 600 } 601 if (i+1 < arr.length) 602 { 603 out.append(queryDataDelim); 604 } 605 } 606 } 607 608 } 609 610 611 } 612 | Popular Tags |