Util.java revision 154
0N/A/*
0N/A * CDDL HEADER START
0N/A *
0N/A * The contents of this file are subject to the terms of the
0N/A * Common Development and Distribution License (the "License").
0N/A * You may not use this file except in compliance with the License.
0N/A *
0N/A * See LICENSE.txt included in this distribution for the specific
0N/A * language governing permissions and limitations under the License.
0N/A *
0N/A * When distributing Covered Code, include this CDDL HEADER in each
0N/A * file and include the License file at LICENSE.txt.
0N/A * If applicable, add the following below this CDDL HEADER, with the
0N/A * fields enclosed by brackets "[]" replaced with your own identifying
0N/A * information: Portions Copyright [yyyy] [name of copyright owner]
0N/A *
0N/A * CDDL HEADER END
0N/A */
0N/A
0N/A/*
154N/A * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
0N/A * Use is subject to license terms.
0N/A */
0N/Apackage org.opensolaris.opengrok.web;
0N/A
154N/Aimport java.io.BufferedReader;
154N/Aimport java.io.File;
154N/Aimport java.io.FileReader;
154N/Aimport java.io.IOException;
154N/Aimport java.io.Writer;
154N/Aimport java.text.DecimalFormat;
154N/Aimport java.text.NumberFormat;
89N/Aimport org.opensolaris.opengrok.history.Annotation;
0N/A
0N/A/**
0N/A * File for useful functions
0N/A */
0N/Apublic class Util {
92N/A /**
92N/A * Return a string which represents a <code>CharSequence</code> in HTML.
92N/A *
92N/A * @param q a character sequence
92N/A * @return a string representing the character sequence in HTML
92N/A */
154N/A
92N/A public static String Htmlize(CharSequence q) {
0N/A StringBuilder sb = new StringBuilder(q.length() * 2);
92N/A Htmlize(q, sb);
0N/A return sb.toString();
0N/A }
92N/A
92N/A /**
92N/A * Append a character sequence to an <code>Appendable</code> object. Escape
92N/A * special characters for HTML.
92N/A *
92N/A * @param q a character sequence
92N/A * @param out the object to append the character sequence to
92N/A * @exception IOException if an I/O error occurs
92N/A */
92N/A public static void Htmlize(CharSequence q, Appendable out)
92N/A throws IOException {
92N/A for (int i = 0; i < q.length(); i++) {
92N/A Htmlize(q.charAt(i), out);
0N/A }
0N/A }
92N/A
92N/A /**
92N/A * Append a character sequence to a <code>StringBuilder</code>
92N/A * object. Escape special characters for HTML. This method is identical to
92N/A * <code>Htmlize(CharSequence,Appendable)</code>, except that it is
92N/A * guaranteed not to throw <code>IOException</code> because it uses a
92N/A * <code>StringBuilder</code>.
92N/A *
92N/A * @param q a character sequence
92N/A * @param out the object to append the character sequence to
92N/A * @see #Htmlize(CharSequence, Appendable)
92N/A */
92N/A public static void Htmlize(CharSequence q, StringBuilder out) {
92N/A try {
92N/A Htmlize(q, (Appendable) out);
92N/A } catch (IOException ioe) {
92N/A // StringBuilder's append methods are not declared to throw
92N/A // IOException, so this should never happen.
154N/A throw new RuntimeException("StringBuilder should not throw IOException", ioe);
92N/A }
92N/A }
92N/A
92N/A public static void Htmlize(char[] cs, int length, Appendable out)
92N/A throws IOException {
154N/A for (int i = 0; i < length && i < cs.length; i++) {
92N/A Htmlize(cs[i], out);
92N/A }
92N/A }
92N/A
92N/A /**
92N/A * Append a character to a an <code>Appendable</code> object. If the
92N/A * character has special meaning in HTML, append a sequence of characters
92N/A * representing the special character.
92N/A *
92N/A * @param c the character to append
92N/A * @param out the object to append the character to
92N/A * @exception IOException if an I/O error occurs
92N/A */
92N/A private static void Htmlize(char c, Appendable out) throws IOException {
92N/A switch (c) {
154N/A case '&':
154N/A out.append("&amp;");
154N/A break;
154N/A case '>':
154N/A out.append("&gt;");
154N/A break;
154N/A case '<':
154N/A out.append("&lt;");
154N/A break;
154N/A case '\n':
154N/A out.append("<br/>");
154N/A break;
154N/A default:
154N/A out.append(c);
92N/A }
92N/A }
92N/A
0N/A public static String breadcrumbPath(String urlPrefix, String l) {
0N/A return breadcrumbPath(urlPrefix, l, '/');
0N/A }
154N/A
0N/A public static String breadcrumbPath(String urlPrefix, String l, char sep) {
154N/A if (l == null || l.length() <= 1) {
0N/A return l;
154N/A }
0N/A StringBuilder hyperl = new StringBuilder(20);
154N/A if (l.charAt(0) == sep) {
0N/A hyperl.append(sep);
0N/A }
154N/A int s = 0,
154N/A e = 0;
154N/A while ((e = l.indexOf(sep, s)) >= 0) {
154N/A if (e - s > 0) {
0N/A hyperl.append("<a href=\"" + urlPrefix);
154N/A hyperl.append(l.substring(0, e));
0N/A hyperl.append("/\">");
154N/A hyperl.append(l.substring(s, e));
0N/A hyperl.append("</a>");
0N/A hyperl.append(sep);
0N/A }
154N/A s = e + 1;
0N/A }
0N/A if (s < l.length()) {
0N/A hyperl.append("<a href=\"" + urlPrefix);
0N/A hyperl.append(l);
0N/A hyperl.append("\">");
0N/A hyperl.append(l.substring(s, l.length()));
0N/A hyperl.append("</a>");
0N/A }
0N/A return hyperl.toString();
0N/A }
154N/A
0N/A public static String redableSize(long num) {
0N/A float l = (float) num;
0N/A NumberFormat formatter = new DecimalFormat("#,###,###,###.#");
154N/A if (l < 1024) {
0N/A return formatter.format(l);
154N/A } else if (l < 1048576) {
0N/A return (formatter.format(l / 1024) + "K");
0N/A } else {
154N/A return ("<b>" + formatter.format(l / 1048576) + "M</b>");
0N/A }
0N/A }
154N/A
89N/A public static void readableLine(int num, Writer out, Annotation annotation)
89N/A throws IOException {
0N/A String snum = String.valueOf(num);
54N/A if (num > 1) {
54N/A out.write("\n");
54N/A }
54N/A out.write("<a class=\"");
0N/A out.write((num % 10 == 0 ? "hl" : "l"));
0N/A out.write("\" name=\"");
0N/A out.write(snum);
0N/A out.write("\">");
0N/A out.write((num > 999 ? " " : (num > 99 ? " " : (num > 9 ? " " : " "))));
0N/A out.write(snum);
0N/A out.write(" </a>");
89N/A if (annotation != null) {
89N/A String r = annotation.getRevision(num);
89N/A out.write("<span class=\"l\"> ");
89N/A for (int i = r.length(); i < annotation.getWidestRevision(); i++) {
89N/A out.write(" ");
89N/A }
154N/A
141N/A out.write("<a href=\"");
141N/A out.write(URIEncode(annotation.getFilename()));
141N/A out.write("?a=true&r=");
141N/A out.write(URIEncode(r));
141N/A out.write("\">");
92N/A Htmlize(r, out);
154N/A out.write("</a>");
89N/A out.write(" </span>");
89N/A
89N/A String a = annotation.getAuthor(num);
89N/A out.write("<span class=\"l\"> ");
89N/A for (int i = a.length(); i < annotation.getWidestAuthor(); i++) {
89N/A out.write(" ");
89N/A }
92N/A Htmlize(a, out);
89N/A out.write(" </span>");
89N/A }
0N/A }
154N/A
0N/A /**
0N/A * Append path and date into a string in such a way that lexicographic
0N/A * sorting gives the same results as a walk of the file hierarchy. Thus
0N/A * null (\u0000) is used both to separate directory components and to
0N/A * separate the path from the date.
0N/A */
0N/A public static String uid(String path, String date) {
153N/A return path.replace('/', '\u0000') + "\u0000" + date;
0N/A }
154N/A
0N/A public static String uid2url(String uid) {
0N/A String url = uid.replace('\u0000', '/'); // replace nulls with slashes
0N/A return url.substring(0, url.lastIndexOf('/')); // remove date from end
0N/A }
0N/A private static char[] hexdigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
154N/A
0N/A public static String URIEncode(String q) {
0N/A StringBuilder sb = new StringBuilder();
0N/A char c;
154N/A for (int i = 0; i < q.length(); i++) {
0N/A c = q.charAt(i);
154N/A if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) {
0N/A sb.append(c);
0N/A } else {
0N/A sb.append("%");
154N/A sb.append(hexdigits[(0xf0 & c) >>> 4]);
0N/A sb.append(hexdigits[0x0f & c]);
0N/A }
0N/A }
0N/A return sb.toString();
0N/A }
154N/A
0N/A public static String formQuoteEscape(String q) {
58N/A if (q == null) {
58N/A return "";
58N/A }
0N/A StringBuilder sb = new StringBuilder();
0N/A char c;
154N/A for (int i = 0; i < q.length(); i++) {
0N/A c = q.charAt(i);
154N/A if (c == '"') {
0N/A sb.append("&quot;");
0N/A } else {
0N/A sb.append(c);
0N/A }
0N/A }
0N/A return sb.toString();
0N/A }
0N/A}