001package de.deepamehta.core.util;
002
003import javax.servlet.http.Cookie;
004import javax.servlet.http.HttpServletRequest;
005import javax.ws.rs.core.Response;
006
007import java.io.File;
008import java.io.FileInputStream;
009import java.io.InputStream;
010import java.io.UnsupportedEncodingException;
011
012import java.math.BigInteger;
013
014import java.net.FileNameMap;
015import java.net.InetAddress;
016import java.net.Inet4Address;
017import java.net.Inet6Address;
018import java.net.URL;
019import java.net.URLConnection;
020import java.net.URLDecoder;
021import java.net.URLEncoder;
022
023import java.security.MessageDigest;
024import java.security.NoSuchAlgorithmException;
025
026import java.util.Map;
027import java.util.Scanner;
028
029
030
031/**
032 * Generic Java utilities.
033 */
034public class JavaUtils {
035
036
037
038    // === Text ===
039
040    public static String stripHTML(String html) {
041        return html.replaceAll("<.*?>", "");    // *? is the reluctant version of the * quantifier (which is greedy)
042    }
043
044    public static String times(String str, int times) {
045        StringBuilder sb = new StringBuilder(times * str.length());
046        for (int i = 0; i < times; i++) {
047            sb.append(str);
048        }
049        return sb.toString();
050    }
051
052
053
054    // === Files ===
055
056    private static FileNameMap fileTypeMap = URLConnection.getFileNameMap();
057
058    public static String getFileType(String fileName) {
059        String extension = getExtension(fileName);
060        if (!extension.equals("avi")) {
061            // Note: for .avi Sun's file type map returns strange media type "application/x-troff-msvideo"
062            String fileType = fileTypeMap.getContentTypeFor(fileName);
063            if (fileType != null) {
064                return fileType;
065            }
066        }
067        // fallback
068        if (extension.equals("mp3")) {
069            return "audio/mpeg";
070        } else if (extension.equals("mp4")) {
071            return "video/mp4";
072        } else if (extension.equals("avi")) {
073            return "video/avi";
074        } else if (extension.equals("wmv")) {
075            return "video/x-ms-wmv";
076        } else if (extension.equals("flv")) {
077            return "video/x-flv";
078        } else if (extension.equals("svg")) {
079            return "image/svg+xml";
080        }
081        // TODO: use a system property instead a hardcoded list
082        //
083        return null;
084    }
085
086    public static String getFilename(String path) {
087        return path.substring(path.lastIndexOf('/') + 1);
088    }
089
090    public static String getBasename(String fileName) {
091        int i = fileName.lastIndexOf(".");
092        if (i == -1) {
093            return fileName;
094        }
095        return fileName.substring(0, i);
096    }
097
098    public static String getExtension(String fileName) {
099        return fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
100    }
101
102    public static String stripDriveLetter(String path) {
103        return path.replaceFirst("^[A-Z]:", "");
104    }
105
106    // ---
107
108    public static File findUnusedFile(File file) {
109        String parent = file.getParent();
110        String fileName = file.getName();
111        String basename = getBasename(fileName);
112        String extension = getExtension(fileName);
113        int nr = 1;
114        while (file.exists()) {
115            nr++;
116            file = new File(parent, basename + "-" + nr + "." + extension);
117        }
118        return file;
119    }
120
121    // ---
122
123    public static String readTextFile(File file) {
124        try {
125            return readText(new FileInputStream(file));
126        } catch (Exception e) {
127            throw new RuntimeException("Reading text file \"" + file + "\" failed", e);
128        }
129    }
130
131    public static String readText(InputStream in) {
132        StringBuilder text = new StringBuilder();
133        Scanner scanner = new Scanner(in);
134        while (scanner.hasNextLine()) {
135            text.append(scanner.nextLine() + "\n");
136        }
137        return text.toString();
138    }
139
140    // ---
141
142    public static File createTempDirectory(String prefix) {
143        try {
144            File f = File.createTempFile(prefix, ".dir");
145            String n = f.getAbsolutePath();
146            f.delete();
147            f = new File(n);
148            f.mkdir();
149            return f;
150        } catch (Exception e) {
151            throw new RuntimeException("Creating temporary directory failed", e);
152        }
153    }
154
155
156
157    // === URLs ===
158
159    public static String readTextURL(URL url) {
160        try {
161            return readText(url.openStream());
162        } catch (Exception e) {
163            throw new RuntimeException("Reading from URL \"" + url + "\" failed", e);
164        }
165    }
166
167    // ---
168
169    public static String encodeURIComponent(String uriComp) {
170        try {
171            return URLEncoder.encode(uriComp, "UTF-8").replaceAll("\\+", "%20");
172        } catch (UnsupportedEncodingException e) {
173            throw new RuntimeException("Encoding URI component \"" + uriComp + "\" failed", e);
174        }
175    }
176
177    public static String decodeURIComponent(String uriComp) {
178        try {
179            return URLDecoder.decode(uriComp, "UTF-8");
180        } catch (UnsupportedEncodingException e) {
181            throw new RuntimeException("Decoding URI component \"" + uriComp + "\" failed", e);
182        }
183    }
184
185
186
187    // === Networking ===
188
189    /**
190     * @param   inetAddress     IPv4 or IPv6 address or a machine name, e.g. "172.68.8.12"
191     * @param   range           IPv4 or IPv6 address range in CIDR notation, e.g. "172.68.8.0/24"
192     */
193    public static boolean isInRange(String inetAddress, String range) {
194        try {
195            String[] r = range.split("/");
196            BigInteger networkAddr = inetAddress(r[0]);
197            int maskNumber = Integer.parseInt(r[1]);
198            InetAddress addr = InetAddress.getByName(inetAddress);
199            BigInteger networkMask = networkMask(addr, maskNumber);
200            //
201            return inetAddress(addr).xor(networkAddr).and(networkMask).equals(BigInteger.ZERO);
202        } catch (Exception e) {
203            throw new RuntimeException("Checking IP range failed (inetAddress=\"" + inetAddress +
204                "\", range=\"" + range + "\"", e);
205        }
206    }
207
208    // ---
209
210    public static BigInteger inetAddress(String inetAddress) {
211        try {
212            return inetAddress(InetAddress.getByName(inetAddress));
213        } catch (Exception e) {
214            throw new RuntimeException("Parsing inet address \"" + inetAddress + "\" failed", e);
215        }
216    }
217
218    public static BigInteger inetAddress(InetAddress inetAddress) {
219        return new BigInteger(1, inetAddress.getAddress());     // signum=1 (positive)
220    }
221
222    // ---
223
224    public static BigInteger networkMask(InetAddress addr, int maskNumber) {
225        if (addr instanceof Inet4Address) {
226            return networkMask(maskNumber, 32);
227        } else if (addr instanceof Inet6Address) {
228            return networkMask(maskNumber, 128);
229        } else {
230            throw new RuntimeException("Unexpected InetAddress object: " + addr.getClass().getName());
231        }
232    }
233
234    public static BigInteger networkMask(int maskNumber, int size) {
235        String networkMask = times("1", maskNumber) + times("0", size - maskNumber);
236        return new BigInteger(networkMask, 2);      // radix=2 (binary)
237    }
238
239    // ---
240
241    public static String requestInfo(HttpServletRequest request) {
242        String queryString = request.getQueryString();
243        return request.getMethod() + " " + request.getRequestURI() + (queryString != null ? "?" + queryString : "");
244    }
245
246    public static String responseInfo(Response.StatusType status) {
247        return status.getStatusCode() + " (" + status.getReasonPhrase() + ")";
248    }
249
250    // ---
251
252    public static String requestDump(HttpServletRequest request) {
253        StringBuilder dump = new StringBuilder(request + ", session=" + request.getSession(false) + ", cookies=");
254        for (Cookie cookie : request.getCookies()) {
255            dump.append("\n  " + cookie.getName() + "=" + cookie.getValue());
256        }
257        return dump.toString();
258    }
259
260
261
262    // === Encoding ===
263
264    /* static {
265        for (Provider p : Security.getProviders()) {
266            System.out.println("### Security Provider " + p);
267            for (Provider.Service s : p.getServices()) {
268                System.out.println("        " + s);
269            }
270        }
271    } */
272
273    public static String encodeSHA256(String data) {
274        try {
275            MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
276            return new String(encodeHex(sha256.digest(data.getBytes())));
277        } catch (NoSuchAlgorithmException e) {
278            throw new RuntimeException("SHA256 encoding failed", e);
279        }
280    }
281
282    private static char[] encodeHex(byte[] data) {
283        final String DIGITS = "0123456789abcdef";
284        int l = data.length;
285        char[] out = new char[l << 1];
286        // two characters form the hex value
287        for (int i = 0, j = 0; i < l; i++) {
288            out[j++] = DIGITS.charAt((0xF0 & data[i]) >>> 4);
289            out[j++] = DIGITS.charAt(0x0F & data[i]);
290        }
291        return out;
292    }
293}