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