1 /*
2  * Copyright (c) 1998, 2019, 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 /*
27  * This source code is provided to illustrate the usage of a given feature
28  * or technique and has been deliberately simplified. Additional steps
29  * required for a production-quality application, such as security checks,
30  * input validation and proper error handling, might not be present in
31  * this sample code.
32  */
33 
34 
35 package com.sun.tools.example.debug.tty;
36 
37 import com.sun.jdi.request.EventRequest;
38 import com.sun.jdi.event.ClassPrepareEvent;
39 import com.sun.jdi.ThreadReference;
40 
41 import java.util.ArrayList;
42 import java.util.Collections;
43 import java.util.List;
44 
45 class EventRequestSpecList {
46 
47     private static final int statusResolved = 1;
48     private static final int statusUnresolved = 2;
49     private static final int statusError = 3;
50 
51     // all specs
52     private List<EventRequestSpec> eventRequestSpecs = Collections.synchronizedList(
53                                                   new ArrayList<EventRequestSpec>());
54 
EventRequestSpecList()55     EventRequestSpecList() {
56     }
57 
58     /**
59      * Resolve all deferred eventRequests waiting for 'refType'.
60      * @return true if it completes successfully, false on error.
61      */
resolve(ClassPrepareEvent event)62     boolean resolve(ClassPrepareEvent event) {
63         boolean failure = false;
64         synchronized(eventRequestSpecs) {
65             for (EventRequestSpec spec : eventRequestSpecs) {
66                 if (!spec.isResolved()) {
67                     try {
68                         EventRequest eventRequest = spec.resolve(event);
69                         if (eventRequest != null) {
70                             MessageOutput.println("Set deferred", spec.toString());
71                         }
72                     } catch (Exception e) {
73                         MessageOutput.println("Unable to set deferred",
74                                               new Object [] {spec.toString(),
75                                                              spec.errorMessageFor(e)});
76                         failure = true;
77                     }
78                 }
79             }
80         }
81         return !failure;
82     }
83 
resolveAll()84     void resolveAll() {
85         for (EventRequestSpec spec : eventRequestSpecs) {
86             try {
87                 EventRequest eventRequest = spec.resolveEagerly();
88                 if (eventRequest != null) {
89                     MessageOutput.println("Set deferred", spec.toString());
90                 }
91             } catch (Exception e) {
92             }
93         }
94     }
95 
addEagerlyResolve(EventRequestSpec spec)96     boolean addEagerlyResolve(EventRequestSpec spec) {
97         try {
98             eventRequestSpecs.add(spec);
99             EventRequest eventRequest = spec.resolveEagerly();
100             if (eventRequest != null) {
101                 MessageOutput.println("Set", spec.toString());
102             }
103             return true;
104         } catch (Exception exc) {
105             MessageOutput.println("Unable to set",
106                                   new Object [] {spec.toString(),
107                                                  spec.errorMessageFor(exc)});
108             return false;
109         }
110     }
111 
createBreakpoint(String classPattern, int line, ThreadReference threadFilter)112     BreakpointSpec createBreakpoint(String classPattern, int line, ThreadReference threadFilter)
113         throws ClassNotFoundException {
114         ReferenceTypeSpec refSpec =
115             new PatternReferenceTypeSpec(classPattern);
116         return new BreakpointSpec(refSpec, line, threadFilter);
117     }
118 
createBreakpoint(String classPattern, String methodId, ThreadReference threadFilter, List<String> methodArgs)119     BreakpointSpec createBreakpoint(String classPattern,
120                                     String methodId, ThreadReference threadFilter,
121                                     List<String> methodArgs)
122                                 throws MalformedMemberNameException,
123                                        ClassNotFoundException {
124         ReferenceTypeSpec refSpec =
125             new PatternReferenceTypeSpec(classPattern);
126         return new BreakpointSpec(refSpec, methodId, threadFilter, methodArgs);
127     }
128 
createExceptionCatch(String classPattern, boolean notifyCaught, boolean notifyUncaught)129     EventRequestSpec createExceptionCatch(String classPattern,
130                                           boolean notifyCaught,
131                                           boolean notifyUncaught)
132                                             throws ClassNotFoundException {
133         ReferenceTypeSpec refSpec =
134             new PatternReferenceTypeSpec(classPattern);
135         return new ExceptionSpec(refSpec, notifyCaught, notifyUncaught);
136     }
137 
createAccessWatchpoint(String classPattern, String fieldId)138     WatchpointSpec createAccessWatchpoint(String classPattern,
139                                        String fieldId)
140                                       throws MalformedMemberNameException,
141                                              ClassNotFoundException {
142         ReferenceTypeSpec refSpec =
143             new PatternReferenceTypeSpec(classPattern);
144         return new AccessWatchpointSpec(refSpec, fieldId);
145     }
146 
createModificationWatchpoint(String classPattern, String fieldId)147     WatchpointSpec createModificationWatchpoint(String classPattern,
148                                        String fieldId)
149                                       throws MalformedMemberNameException,
150                                              ClassNotFoundException {
151         ReferenceTypeSpec refSpec =
152             new PatternReferenceTypeSpec(classPattern);
153         return new ModificationWatchpointSpec(refSpec, fieldId);
154     }
155 
delete(EventRequestSpec proto)156     boolean delete(EventRequestSpec proto) {
157         synchronized (eventRequestSpecs) {
158             int inx = eventRequestSpecs.indexOf(proto);
159             if (inx != -1) {
160                 EventRequestSpec spec = eventRequestSpecs.get(inx);
161                 spec.remove();
162                 eventRequestSpecs.remove(inx);
163                 return true;
164             } else {
165                 return false;
166             }
167         }
168     }
169 
eventRequestSpecs()170     List<EventRequestSpec> eventRequestSpecs() {
171        // We need to make a copy to avoid synchronization problems
172         synchronized (eventRequestSpecs) {
173             return new ArrayList<EventRequestSpec>(eventRequestSpecs);
174         }
175     }
176 }
177