Added
Link Here
|
1 |
/* |
2 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
3 |
* |
4 |
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. |
5 |
* |
6 |
* The contents of this file are subject to the terms of either the GNU |
7 |
* General Public License Version 2 only ("GPL") or the Common |
8 |
* Development and Distribution License("CDDL") (collectively, the |
9 |
* "License"). You may not use this file except in compliance with the |
10 |
* License. You can obtain a copy of the License at |
11 |
* http://www.netbeans.org/cddl-gplv2.html |
12 |
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the |
13 |
* specific language governing permissions and limitations under the |
14 |
* License. When distributing the software, include this License Header |
15 |
* Notice in each file and include the License file at |
16 |
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this |
17 |
* particular file as subject to the "Classpath" exception as provided |
18 |
* by Sun in the GPL Version 2 section of the License file that |
19 |
* accompanied this code. If applicable, add the following below the |
20 |
* License Header, with the fields enclosed by brackets [] replaced by |
21 |
* your own identifying information: |
22 |
* "Portions Copyrighted [year] [name of copyright owner]" |
23 |
* |
24 |
* If you wish your version of this file to be governed by only the CDDL |
25 |
* or only the GPL Version 2, indicate your decision by adding |
26 |
* "[Contributor] elects to include this software in this distribution |
27 |
* under the [CDDL or GPL Version 2] license." If you do not indicate a |
28 |
* single choice of license, a recipient has the option to distribute |
29 |
* your version of this file under either the CDDL, the GPL Version 2 or |
30 |
* to extend the choice of license to its licensees as provided above. |
31 |
* However, if you add GPL Version 2 code and therefore, elected the GPL |
32 |
* Version 2 license, then the option applies only if the new code is |
33 |
* made subject to such option by the copyright holder. |
34 |
* |
35 |
* Contributor(s): |
36 |
* |
37 |
* Portions Copyrighted 2008 Sun Microsystems, Inc. |
38 |
*/ |
39 |
|
40 |
package org.netbeans.performance.j2se.actions; |
41 |
|
42 |
import java.io.File; |
43 |
import java.io.FileDescriptor; |
44 |
import java.io.IOException; |
45 |
import java.io.PrintWriter; |
46 |
import java.io.StringWriter; |
47 |
import java.security.Permission; |
48 |
import java.util.Collections; |
49 |
import java.util.Comparator; |
50 |
import java.util.HashMap; |
51 |
import java.util.Map; |
52 |
import java.util.TreeSet; |
53 |
import java.util.concurrent.atomic.AtomicLong; |
54 |
import junit.framework.Assert; |
55 |
import org.openide.util.Exceptions; |
56 |
|
57 |
/** |
58 |
* |
59 |
* @author Jaroslav Tulach <jaroslav.tulach@netbeans.org> |
60 |
*/ |
61 |
public final class CountingSecurityManager extends SecurityManager { |
62 |
private static int cnt; |
63 |
private static StringWriter msgs; |
64 |
private static PrintWriter pw; |
65 |
private static String prefix = "NONE"; |
66 |
|
67 |
public static void register() { |
68 |
initialize("NONE"); |
69 |
} |
70 |
|
71 |
public static void initialize(String prefix) { |
72 |
Assert.assertNotNull(prefix); |
73 |
|
74 |
if (! (System.getSecurityManager() instanceof CountingSecurityManager)) { |
75 |
setAllowedReplace(true); |
76 |
System.setSecurityManager(new CountingSecurityManager()); |
77 |
setAllowedReplace(false); |
78 |
} |
79 |
if (!System.getSecurityManager().getClass().getName().equals(CountingSecurityManager.class.getName())) { |
80 |
throw new IllegalStateException("Wrong security manager: " + System.getSecurityManager()); |
81 |
} |
82 |
cnt = 0; |
83 |
msgs = new StringWriter(); |
84 |
pw = new PrintWriter(msgs); |
85 |
Statistics.reset(); |
86 |
CountingSecurityManager.prefix = prefix; |
87 |
try { |
88 |
CountingSecurityManager.prefix = new File(prefix).getCanonicalPath(); |
89 |
} catch (IOException ex) { |
90 |
Exceptions.printStackTrace(ex); |
91 |
} |
92 |
System.err.println("setting prefix to " + CountingSecurityManager.prefix); |
93 |
} |
94 |
|
95 |
public static void assertCounts(String msg, int expectedCnt, AtomicLong property) { |
96 |
msgs = new StringWriter(); |
97 |
pw = new PrintWriter(msgs); |
98 |
Statistics.getDefault().print(pw); |
99 |
|
100 |
property.set(cnt); |
101 |
|
102 |
if (cnt < expectedCnt / 10) { |
103 |
throw new AssertionError("Too small expectations:\n" + msg + "\n" + msgs + " exp: " + expectedCnt + " was: " + cnt); |
104 |
} |
105 |
if (expectedCnt < cnt) { |
106 |
throw new AssertionError(msg + " exp: " + expectedCnt + " was: " + cnt + "\n" + msgs); |
107 |
} |
108 |
cnt = 0; |
109 |
msgs = new StringWriter(); |
110 |
pw = new PrintWriter(msgs); |
111 |
Statistics.getDefault().print(pw); |
112 |
} |
113 |
|
114 |
@Override |
115 |
public void checkRead(String file) { |
116 |
if (file.startsWith(prefix)) { |
117 |
cnt++; |
118 |
Statistics.fileIsDirectory(file); |
119 |
// pw.println("checkRead: " + file); |
120 |
// new Exception().printStackTrace(pw); |
121 |
} |
122 |
} |
123 |
|
124 |
@Override |
125 |
public void checkRead(String file, Object context) { |
126 |
if (file.startsWith(prefix)) { |
127 |
cnt++; |
128 |
Statistics.fileIsDirectory(file); |
129 |
pw.println("checkRead2: " + file); |
130 |
} |
131 |
} |
132 |
|
133 |
@Override |
134 |
public void checkWrite(FileDescriptor fd) { |
135 |
cnt++; |
136 |
pw.println("Fd: " + fd); |
137 |
} |
138 |
|
139 |
@Override |
140 |
public void checkWrite(String file) { |
141 |
if (file.startsWith(prefix)) { |
142 |
cnt++; |
143 |
Statistics.fileIsDirectory(file); |
144 |
pw.println("checkWrite: " + file); |
145 |
} |
146 |
} |
147 |
|
148 |
@Override |
149 |
public void checkPermission(Permission perm) { |
150 |
if (perm.getName().equals("setSecurityManager")) { // NOI18N - hardcoded in java.lang |
151 |
if (!isAllowedReplace()) { |
152 |
throw new SecurityException(); |
153 |
} |
154 |
} |
155 |
} |
156 |
|
157 |
@Override |
158 |
public void checkPermission(Permission perm, Object context) { |
159 |
} |
160 |
|
161 |
private static boolean isAllowedReplace() { |
162 |
return Boolean.getBoolean("CountingSecurityManager.allowReplace"); |
163 |
} |
164 |
|
165 |
private static void setAllowedReplace(boolean aAllowedReplace) { |
166 |
System.setProperty("CountingSecurityManager.allowReplace", String.valueOf(aAllowedReplace)); |
167 |
} |
168 |
|
169 |
/** |
170 |
* Collects data and print them when JVM shutting down. |
171 |
* |
172 |
* @author Pavel Flaška |
173 |
*/ |
174 |
private static class Statistics implements Comparator<Map.Entry<String,Integer>> { |
175 |
|
176 |
private static final boolean streamLog = false; |
177 |
private static final boolean dirLog = true; |
178 |
private static final boolean streamCreation = false; |
179 |
/** singleton instance */ |
180 |
private static Statistics INSTANCE; |
181 |
private Map<String, Integer> isDirInvoc = Collections.synchronizedMap(new HashMap<String, Integer>()); |
182 |
private Map<String, Integer> stacks = Collections.synchronizedMap(new HashMap<String, Integer>()); |
183 |
|
184 |
private Statistics() { |
185 |
} |
186 |
|
187 |
/** |
188 |
* Get the class instance. |
189 |
* |
190 |
* @return singleton of Statistics class. |
191 |
*/ |
192 |
static synchronized Statistics getDefault() { |
193 |
if (INSTANCE == null) { |
194 |
INSTANCE = new Statistics(); |
195 |
} |
196 |
return INSTANCE; |
197 |
} |
198 |
|
199 |
static synchronized void reset() { |
200 |
INSTANCE = null; |
201 |
} |
202 |
|
203 |
/** |
204 |
* Counts in isDirectory() call on <tt>file</tt>. |
205 |
* |
206 |
* @param file file name |
207 |
*/ |
208 |
public static void fileIsDirectory(String file) { |
209 |
if (!dirLog) { |
210 |
return; |
211 |
} |
212 |
Integer i = Statistics.getDefault().isDirInvoc.get(file); |
213 |
if (i == null) { |
214 |
i = 1; |
215 |
} else { |
216 |
i++; |
217 |
} |
218 |
Statistics.getDefault().isDirInvoc.put(file, i); |
219 |
|
220 |
//////////////////// |
221 |
StringBuilder sb = new StringBuilder(300); |
222 |
StackTraceElement[] ste = Thread.currentThread().getStackTrace(); |
223 |
for (i = 2; i < ste.length; i++) { |
224 |
sb.append(ste[i].toString()).append('\n'); |
225 |
} |
226 |
String s = sb.toString(); |
227 |
i = Statistics.getDefault().stacks.get(s); |
228 |
if (i == null) { |
229 |
i = 1; |
230 |
} else { |
231 |
i++; |
232 |
} |
233 |
Statistics.getDefault().stacks.put(s, i); |
234 |
} |
235 |
|
236 |
public int compare(Map.Entry<String,Integer> one, Map.Entry<String,Integer> two) { |
237 |
int r = one.getValue().compareTo(two.getValue()); |
238 |
if (r == 0) { |
239 |
return one.getKey().compareTo(two.getKey()); |
240 |
} else { |
241 |
return r; |
242 |
} |
243 |
} |
244 |
|
245 |
//////////////////////////////////////////////////////////////////////////// |
246 |
// private members |
247 |
void print(PrintWriter out) { |
248 |
synchronized (isDirInvoc) { |
249 |
TreeSet<Map.Entry<String,Integer>> sort = new TreeSet<Map.Entry<String,Integer>>(Collections.reverseOrder(this)); |
250 |
sort.addAll(isDirInvoc.entrySet()); |
251 |
int cnt = 0; |
252 |
for (Map.Entry<String, Integer> e : sort) { |
253 |
if (cnt++ > 100) { |
254 |
break; |
255 |
} |
256 |
String s = e.getKey(); |
257 |
out.printf("%4d", isDirInvoc.get(s)); |
258 |
out.println("; " + s); |
259 |
} |
260 |
} |
261 |
int absoluteStacks = 0; |
262 |
synchronized (stacks) { |
263 |
for (String s : stacks.keySet()) { |
264 |
int value = stacks.get(s); |
265 |
absoluteStacks += value; |
266 |
} |
267 |
int min = absoluteStacks / 50; |
268 |
for (String s : stacks.keySet()) { |
269 |
int value = stacks.get(s); |
270 |
if (value > min) { |
271 |
out.printf("count %5d; Stack:\n", value); |
272 |
for (String line : s.split("\n")) { |
273 |
out.printf(" %s\n", line); |
274 |
} |
275 |
} |
276 |
} |
277 |
} |
278 |
out.println("Total stacks recorded: " + absoluteStacks); |
279 |
} |
280 |
} |
281 |
|
282 |
} |