1 /* 2 * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.net.www.http; 27 28 import java.io.*; 29 import java.util.ArrayList; 30 import java.util.regex.*; 31 import sun.net.NetProperties; 32 import sun.util.logging.PlatformLogger; 33 34 /** 35 * Main class of the HTTP traffic capture tool. 36 * Captures are triggered by the sun.net.http.captureRules system property. 37 * If set, it should point to a file containing the capture rules. 38 * Format for the file is simple: 39 * - 1 rule per line 40 * - Lines starting with a # are considered comments and ignored 41 * - a rule is a pair of a regular expression and file pattern, separated by a comma 42 * - The regular expression is applied to URLs, if it matches, the traffic for 43 * that URL will be captured in the associated file. 44 * - if the file name contains a '%d', then that sequence will be replaced by a 45 * unique random number for each URL. This allow for multi-threaded captures 46 * of URLs matching the same pattern. 47 * - Rules are checked in sequence, in the same order as in the file, until a 48 * match is found or the end of the list is reached. 49 * 50 * Examples of rules: 51 * www\.sun\.com , sun%d.log 52 * yahoo\.com\/.*asf , yahoo.log 53 * 54 * @author jccollet 55 */ 56 public class HttpCapture { 57 private File file = null; 58 private boolean incoming = true; 59 private BufferedWriter out = null; 60 private static boolean initialized = false; 61 private static volatile ArrayList<Pattern> patterns = null; 62 private static volatile ArrayList<String> capFiles = null; 63 64 private static synchronized void init() { 65 initialized = true; 66 String rulesFile = java.security.AccessController.doPrivileged( 67 new java.security.PrivilegedAction<String>() { 68 public String run() { 69 return NetProperties.get("sun.net.http.captureRules"); 70 } 71 }); 72 if (rulesFile != null && !rulesFile.isEmpty()) { 73 BufferedReader in; 74 try { 75 in = new BufferedReader(new FileReader(rulesFile)); 76 } catch (FileNotFoundException ex) { 77 return; 78 } 79 try { 80 String line = in.readLine(); 81 while (line != null) { 82 line = line.trim(); 83 if (!line.startsWith("#")) { 84 // skip line if it's a comment 85 String[] s = line.split(","); 86 if (s.length == 2) { 87 if (patterns == null) { 88 patterns = new ArrayList<Pattern>(); 89 capFiles = new ArrayList<String>(); 90 } 91 patterns.add(Pattern.compile(s[0].trim())); 92 capFiles.add(s[1].trim()); 93 } 94 } 95 line = in.readLine(); 96 } 97 } catch (IOException ioe) { 98 99 } finally { 100 try { 101 in.close(); 102 } catch (IOException ex) { 103 } 104 } 105 } 106 } 107 108 private static synchronized boolean isInitialized() { 109 return initialized; 110 } 111 112 private HttpCapture(File f, java.net.URL url) { 113 file = f; 114 try { 115 out = new BufferedWriter(new FileWriter(file, true)); 116 out.write("URL: " + url + "\n"); 117 } catch (IOException ex) { 118 PlatformLogger.getLogger(HttpCapture.class.getName()).severe(null, ex); 119 } 120 } 121 122 public synchronized void sent(int c) throws IOException { 123 if (incoming) { 124 out.write("\n------>\n"); 125 incoming = false; 126 out.flush(); 127 } 128 out.write(c); 129 } 130 131 public synchronized void received(int c) throws IOException { 132 if (!incoming) { 133 out.write("\n<------\n"); 134 incoming = true; 135 out.flush(); 136 } 137 out.write(c); 138 } 139 140 public synchronized void flush() throws IOException { 141 out.flush(); 142 } 143 144 public static HttpCapture getCapture(java.net.URL url) { 145 if (!isInitialized()) { 146 init(); 147 } 148 if (patterns == null || patterns.isEmpty()) { 149 return null; 150 } 151 String s = url.toString(); 152 for (int i = 0; i < patterns.size(); i++) { 153 Pattern p = patterns.get(i); 154 if (p.matcher(s).find()) { 155 String f = capFiles.get(i); 156 File fi; 157 if (f.indexOf("%d") >= 0) { 158 java.util.Random rand = new java.util.Random(); 159 do { 160 String f2 = f.replace("%d", Integer.toString(rand.nextInt())); 161 fi = new File(f2); 162 } while (fi.exists()); 163 } else { 164 fi = new File(f); 165 } 166 return new HttpCapture(fi, url); 167 } 168 } 169 return null; 170 } 171 } 172