2 * Copyright (C) 2005 The Mir-coders group
4 * This file is part of Mir.
6 * Mir is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Mir is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Mir; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * In addition, as a special exception, The Mir-coders gives permission to link
21 * the code of this program with any library licensed under the Apache Software License.
22 * You must obey the GNU General Public License in all respects for all of the code used
23 * other than the above mentioned libraries. If you modify this file, you may extend this
24 * exception to your version of the file, but you are not obligated to do so.
25 * If you do not wish to do so, delete this exception statement from your version.
30 import gnu.regexp.REException;
32 import java.text.NumberFormat;
33 import java.util.Calendar;
34 import java.util.Date;
35 import java.util.GregorianCalendar;
36 import java.util.TimeZone;
40 public final class StringUtil {
42 private static TimeZone UTC = TimeZone.getTimeZone("UTC");
43 private static RE re_newline2br, re_brbr2p, re_mail, re_url, re_tags,
44 re_tables, re_forbiddenTags;
46 private StringUtil() { } // this avoids contruction
51 re_newline2br = new RE("(\r?\n){1}");
52 re_brbr2p = new RE("(<br>\r?\n<br>){1,}");
53 re_mail = new RE("\\b([a-zA-Z0-9_.-]+)@([a-zA-Z0-9_-]+)\\.([a-zA-Z0-9_.-]+)\\b");
54 re_url = new RE("((https://)|(http://)|(ftp://)){1}([a-zA-Z0-9_-]+).([a-zA-Z0-9_.:-]+)/?([^ \t\r\n<>\\)\\]]+[^ \t\r\n.,<>\\)\\]])");
55 re_tags = new RE("<[^>]*>",RE.REG_ICASE);
56 re_tables = new RE("<[ \t\r\n/]*(table|td|tr)[ \t\r\n]*>",RE.REG_ICASE);
57 re_forbiddenTags = new RE("<[ \t\r\n/]*(html|meta|body|head|script)[ \t\r\n]*>",RE.REG_ICASE);
59 catch (REException e){
60 System.err.println("FATAL: StringUtil: could not precompile REGEX: "+e.toString());
65 * Formats a number with the specified minimum and maximum number of digits.
67 public static synchronized String zeroPaddingNumber(long value, int minDigits,
70 NumberFormat numberFormat = NumberFormat.getInstance();
71 numberFormat.setMinimumIntegerDigits(minDigits);
72 numberFormat.setMaximumIntegerDigits(maxDigits);
73 return numberFormat.format(value);
77 * Wandelt Datum in einen 8-ziffrigen String um (yyyymmdd)
79 * @return 8-ziffriger String (yyyymmdd)
82 public static final String date2webdbDate (GregorianCalendar theDate) {
83 StringBuffer webdbDate = new StringBuffer();
84 webdbDate.append(String.valueOf(theDate.get(Calendar.YEAR)));
85 webdbDate.append(pad2(theDate.get(Calendar.MONTH) + 1));
86 webdbDate.append(pad2(theDate.get(Calendar.DATE)));
88 return webdbDate.toString();
92 * Wandelt Calendar in einen 12-ziffrigen String um (yyyymmddhhmm)
94 * @return 12-ziffriger String (yyyymmdd)
97 public static final String date2webdbDateTime (GregorianCalendar theDate) {
98 StringBuffer webdbDate = new StringBuffer();
99 webdbDate.append(String.valueOf(theDate.get(Calendar.YEAR)));
100 webdbDate.append(pad2(theDate.get(Calendar.MONTH) + 1));
101 webdbDate.append(pad2(theDate.get(Calendar.DATE)));
102 webdbDate.append(pad2(theDate.get(Calendar.HOUR)));
103 webdbDate.append(pad2(theDate.get(Calendar.MINUTE)));
105 return webdbDate.toString();
109 * Return a http://www.w3.org/TR/NOTE-datetime formatted date (yyyy-mm-ddThh:mm:ssTZ)
111 * @return w3approved datetime
114 public static final String date2w3DateTime (GregorianCalendar theDate) {
115 StringBuffer webdbDate = new StringBuffer();
116 webdbDate.append(String.valueOf(theDate.get(Calendar.YEAR)));
117 webdbDate.append("-");
118 webdbDate.append(pad2(theDate.get(Calendar.MONTH) + 1));
119 webdbDate.append("-");
120 webdbDate.append(pad2(theDate.get(Calendar.DATE)));
121 webdbDate.append("T");
122 webdbDate.append(pad2(theDate.get(Calendar.HOUR_OF_DAY)));
123 webdbDate.append(":");
124 webdbDate.append(pad2(theDate.get(Calendar.MINUTE)));
125 webdbDate.append(":");
126 webdbDate.append(pad2(theDate.get(Calendar.SECOND)));
127 //assumes you are an hour-multiple away from UTC....
128 int offset=(theDate.get(Calendar.ZONE_OFFSET)/(60*60*1000));
130 webdbDate.append("-");
133 webdbDate.append("+");
135 webdbDate.append(pad2(Math.abs(offset)));
136 webdbDate.append(":00");
137 return webdbDate.toString();
141 * wandelt Calendar in dd.mm.yyyy / hh.mm um
143 * @return String mit (dd.mm.yyyy / hh.mm um)
145 public static String date2readableDateTime (GregorianCalendar theDate) {
146 String readable = "";
148 readable += pad2(theDate.get(Calendar.DATE));
149 readable += "." + pad2(theDate.get(Calendar.MONTH) + 1);
150 readable += "." + String.valueOf(theDate.get(Calendar.YEAR));
151 hour = theDate.get(Calendar.HOUR);
152 if (theDate.get(Calendar.AM_PM) == Calendar.PM)
154 readable += " / " + pad2(hour);
155 readable += ":" + pad2(theDate.get(Calendar.MINUTE));
160 * deleteForbiddenTags
161 * this method deletes all <script>, <body> and <head>-tags
163 public static final String deleteForbiddenTags(String haystack) {
164 return re_forbiddenTags.substituteAll(haystack,"");
168 * deleteHTMLTableTags
169 * this method deletes all <table>, <tr> and <td>-tags
171 public static final String deleteHTMLTableTags(String haystack) {
172 return re_tables.substituteAll(haystack,"");
176 * wandelt eine Datum in einen 8-buchstabigen String, der durch <code>/</code>
180 * @return String mit <code>/yyyy/mm/dd</code>
182 public static final String webdbDate2path (String webdbDate) {
183 StringBuffer path = new StringBuffer();
184 path.append("/").append(webdbDate.substring(0, 4));
185 path.append("/").append(webdbDate.substring(4, 6));
188 //path.append("/").append(webdbDate.substring(6, 8));
189 return path.toString();
193 * Replaces in <code>haystack</code> matching <code>pattern</code> by <code>substitute</code>
197 * @return String with replacements.
199 public static String regexpReplace(String haystack, String pattern, String substitute) {
201 RE regex = new RE(pattern);
202 return regex.substituteAll(haystack,substitute);
203 } catch(REException ex){
209 * L?scht <code>/</code> am Ende des Strings, falls vorhanden
211 * @return String ohne <code>/</code> am Ende
213 public static final String removeSlash (String path) {
214 return path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length()
219 * formatiert eine Zahl (0-99) zweistellig (z.B. 5 -> 05)
220 * @return zwistellige Zahl
222 public static String pad2 (int number) {
223 return number < 10 ? "0" + number : String.valueOf(number);
227 * formatiert eine Zahl (0-999) dreistellig (z.B. 7 -> 007)
229 * @return 3-stellige Zahl
231 public static String pad3 (int number) {
232 return number < 10 ? "00" + number : number < 100 ? "0" + number : String.valueOf(number);
236 * Liefert Default-Wert def zur?ck, wenn String <code>s</code>
241 * @return geparster int aus s oder def
243 public static int parseInt(String s, int def) {
244 if (s == null) return def;
246 return Integer.parseInt(s);
247 } catch (NumberFormatException e) {
254 * convertNewline2P ist eine regex-routine zum umwandeln von 2 oder mehr newlines (\n)
255 * in den html-tag <p>
256 * nur sinnvoll, wenn text nicht im html-format eingegeben
258 private static String convertNewline2P(String haystack) {
259 return re_brbr2p.substituteAll(haystack,"\n</p><p>");
263 * convertNewline2Break ist eine regex-routine zum umwandeln von 1 newline (\n)
264 * in den html-tag <br>
265 * nur sinnvoll, wenn text nicht im html-format eingegeben
267 private static String convertNewline2Break(String haystack) {
268 return re_newline2br.substituteAll(haystack,"$0<br />");
272 * createMailLinks wandelt text im email-adressenformat
273 * in einen klickbaren link um
274 * nur sinnvoll, wenn text nicht im html-format eingegeben
276 private static String createMailLinks(String haystack) {
277 return re_mail.substituteAll(haystack,"<a href=\"mailto:$0\">$0</a>");
282 * createMailLinks wandelt text im email-adressenformat
283 * in einen klickbaren link um
284 * nur sinnvoll, wenn text nicht im html-format eingegeben
286 private static String createMailLinks(String haystack, String imageRoot, String mailImage) {
287 return re_mail.substituteAll(haystack,"<img src=\""+imageRoot+"/"+mailImage+"\" border=\"0\"/> <a href=\"mailto:$0\">$0</a>");
292 * createURLLinks wandelt text im url-format
293 * in einen klickbaren link um
294 * nur sinnvoll, wenn text nicht im html-format eingegeben
296 private static String createURLLinks(String haystack) {
297 return re_url.substituteAll(haystack,"<a href=\"$0\">$0</a>");
301 * this routine takes text in url format and makes
302 * a clickaeble "<href>" link removing any "illegal" html tags
303 * @param haystack the url
304 * @param title the href link text
305 * @param imageRoot the place to find icons
306 * @param extImage the url of the icon to show next to the link
307 * @return a String containing the url
309 private static String createURLLinks(String haystack, String title, String imageRoot,String extImage) {
311 return re_url.substituteAll(haystack,"<img src=\""+imageRoot+"/"+extImage+"\" border=\"0\"/> <a href=\"$0\">$0</a>");
313 title = removeHTMLTags(title);
314 return re_url.substituteAll(haystack,"<img src=\""+imageRoot+"/"+extImage+"\" border=\"0\"/> <a href=\"$0\">"+title+"</a>");
318 * this routine takes text in url format and makes
319 * a clickaeble "<href>" link removing any "illegal" html tags
320 * @param haystack the url
321 * @param imageRoot the place to find icons
322 * @param extImage the url of the icon to show next to the link
323 * @param intImage unused
324 * @return a String containing the url
326 private static String createURLLinks(String haystack, String title, String imageRoot,String extImage,String intImage) {
327 return createURLLinks(haystack, title, imageRoot, extImage);
331 * this method deletes all html tags
333 public static String removeHTMLTags(String haystack){
334 return re_tags.substituteAll(haystack,"");
339 * createHTML ruft alle regex-methoden zum unwandeln eines nicht
340 * htmlcodierten string auf und returnt einen htmlcodierten String
342 public static String createHTML(String content){
343 content=convertNewline2Break(content);
344 content=convertNewline2P(content);
345 content=createMailLinks(content);
346 content=createURLLinks(content);
352 * createHTML ruft alle regex-methoden zum unwandeln eines nicht
353 * htmlcodierten string auf und returnt einen htmlcodierten String
355 public static String createHTML(String content,String producerDocRoot,String mailImage,String extImage,String intImage){
356 content=convertNewline2Break(content);
357 content=convertNewline2P(content);
358 content=createMailLinks(content, producerDocRoot,mailImage);
359 content=createURLLinks(content, null, producerDocRoot, extImage, intImage);
365 * Converts mir's horrible internal date format (yyyy-MM-dd HH:mm:ss+zz) into a java Date
367 * @param anInternalDate
369 public static Date convertMirInternalDateToDate(String anInternalDate) {
370 Calendar calendar = new GregorianCalendar();
380 year = Integer.parseInt(anInternalDate.substring(0,4));
381 month = Integer.parseInt(anInternalDate.substring(5,7));
382 day = Integer.parseInt(anInternalDate.substring(8,10));
383 hours = Integer.parseInt(anInternalDate.substring(11,13));
384 minutes = Integer.parseInt(anInternalDate.substring(14,16));
385 seconds = Integer.parseInt(anInternalDate.substring(17,19));
387 timezoneOffset = Integer.parseInt(anInternalDate.substring(20,22));
388 if (anInternalDate.charAt(19) == '-') {
389 timezoneOffset = -timezoneOffset;
392 calendar.setTimeZone(UTC);
393 calendar.set(year, month-1, day, hours, minutes, seconds);
394 calendar.add(Calendar.HOUR, -timezoneOffset);
396 return calendar.getTime();