1 /**
2 * Licensed under the Artistic License; you may not use this file
3 * except in compliance with the License.
4 * You may obtain a copy of the License at
5 *
6 * http://displaytag.sourceforge.net/license.html
7 *
8 * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
10 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11 */
12 package org.displaytag.decorator;
13
14 import javax.servlet.jsp.PageContext;
15
16 import org.apache.commons.lang.ArrayUtils;
17 import org.apache.commons.lang.StringUtils;
18 import org.displaytag.properties.MediaTypeEnum;
19 import org.displaytag.util.TagConstants;
20
21
22 /**
23 * This takes the string that is passed in, and "auto-links" it, it turns email addresses into hyperlinks, and also
24 * turns things that looks like URLs into hyperlinks as well.
25 * @author Fabrizio Giustina
26 * @version $Revision: 1081 $ ($Author: fgiust $)
27 */
28 public class AutolinkColumnDecorator implements DisplaytagColumnDecorator
29 {
30
31 /**
32 * Instance used for the "autolink" tag attribute.
33 */
34 public static final DisplaytagColumnDecorator INSTANCE = new AutolinkColumnDecorator();
35
36 /**
37 * "://".
38 */
39 private static final String URL_DELIM = "://"; //$NON-NLS-1$
40
41 /**
42 * Urls.
43 */
44 private static final String[] URLS_PREFIXES = //
45 new String[]{"http", "https", "ftp"}; //$NON-NLS-1$ //$NON-NLS-1$ //$NON-NLS-1$
46
47 /**
48 * @see org.displaytag.decorator.DisplaytagColumnDecorator#decorate(Object, PageContext, MediaTypeEnum)
49 */
50 public Object decorate(Object columnValue, PageContext pageContext, MediaTypeEnum media)
51 {
52
53 if (columnValue == null)
54 {
55 return null;
56 }
57 String work = columnValue.toString();
58
59 int urlBegin;
60 StringBuffer buffer = new StringBuffer();
61
62 // First check for email addresses.
63 while ((urlBegin = work.indexOf('@')) != -1)
64 {
65 int start = 0;
66 int end = work.length() - 1;
67
68 // scan backwards...
69 for (int j = urlBegin; j >= 0; j--)
70 {
71 if (Character.isWhitespace(work.charAt(j)))
72 {
73 start = j + 1;
74 break;
75 }
76 }
77
78 // scan forwards...
79 for (int j = urlBegin; j <= end; j++)
80 {
81 if (Character.isWhitespace(work.charAt(j)))
82 {
83 end = j - 1;
84 break;
85 }
86 }
87
88 String email = work.substring(start, end + 1);
89
90 buffer.append(work.substring(0, start)).append("<a href=\"mailto:") //$NON-NLS-1$
91 .append(email + "\">") //$NON-NLS-1$
92 .append(email).append("</a>"); //$NON-NLS-1$
93
94 if (end == work.length())
95 {
96 work = TagConstants.EMPTY_STRING;
97 }
98 else
99 {
100 work = work.substring(end + 1);
101 }
102 }
103
104 work = buffer.toString() + work;
105 buffer = new StringBuffer();
106
107 // Now check for urls...
108 while ((urlBegin = work.indexOf(URL_DELIM)) != -1)
109 {
110
111 // scan backwards...
112 int fullUrlBegin = urlBegin;
113 StringBuffer prefixBuffer = new StringBuffer(10);
114 for (int j = fullUrlBegin - 1; j >= 0; j--)
115 {
116 if (Character.isWhitespace(work.charAt(j)))
117 {
118 fullUrlBegin = j + 1;
119 break;
120 }
121 fullUrlBegin = j;
122 prefixBuffer.append(work.charAt(j));
123 }
124
125 if (!ArrayUtils.contains(URLS_PREFIXES, StringUtils.reverse(prefixBuffer.toString())))
126 {
127
128 buffer.append(work.substring(0, urlBegin + 3));
129 work = work.substring(urlBegin + 3);
130 continue;
131 }
132
133 int urlEnd = work.length();
134
135 // scan forwards...
136 for (int j = urlBegin; j < urlEnd; j++)
137 {
138 if (Character.isWhitespace(work.charAt(j)))
139 {
140 urlEnd = j;
141 break;
142 }
143 }
144
145 String url = work.substring(fullUrlBegin, urlEnd);
146
147 buffer.append(work.substring(0, fullUrlBegin)).append("<a href=\"")//$NON-NLS-1$
148 .append(url).append("\">")//$NON-NLS-1$
149 .append(url).append("</a>"); //$NON-NLS-1$
150
151 if (urlEnd >= work.length())
152 {
153 work = TagConstants.EMPTY_STRING;
154 }
155 else
156 {
157 work = work.substring(urlEnd);
158 }
159 }
160
161 buffer.append(work);
162 return buffer.toString();
163 }
164
165 }