1 /*******************************************************************************
2  * Copyright (c) 2000, 2012 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.jdi.internal.event;
15 
16 import java.io.DataInputStream;
17 import java.io.IOException;
18 import java.lang.reflect.Field;
19 import java.util.HashMap;
20 import java.util.Map;
21 
22 import org.eclipse.jdi.internal.MirrorImpl;
23 import org.eclipse.jdi.internal.ThreadReferenceImpl;
24 import org.eclipse.jdi.internal.VirtualMachineImpl;
25 import org.eclipse.jdi.internal.request.RequestID;
26 
27 import com.sun.jdi.ThreadReference;
28 import com.sun.jdi.event.Event;
29 import com.sun.jdi.request.EventRequest;
30 
31 /**
32  * This class implements the corresponding interfaces declared by the JDI
33  * specification. See the com.sun.jdi package for more information.
34  *
35  */
36 public abstract class EventImpl extends MirrorImpl implements Event {
37 	/** Constants for EventKind. */
38 	public static final byte EVENT_SINGLE_STEP = 1;
39 	public static final byte EVENT_BREAKPOINT = 2;
40 	public static final byte EVENT_FRAME_POP = 3;
41 	public static final byte EVENT_EXCEPTION = 4;
42 	public static final byte EVENT_USER_DEFINED = 5;
43 	public static final byte EVENT_THREAD_START = 6;
44 	public static final byte EVENT_THREAD_END = 7;
45 	public static final byte EVENT_CLASS_PREPARE = 8;
46 	public static final byte EVENT_CLASS_UNLOAD = 9;
47 	public static final byte EVENT_CLASS_LOAD = 10;
48 	public static final byte EVENT_FIELD_ACCESS = 20;
49 	public static final byte EVENT_FIELD_MODIFICATION = 21;
50 	public static final byte EVENT_EXCEPTION_CATCH = 30;
51 	public static final byte EVENT_METHOD_ENTRY = 40;
52 	public static final byte EVENT_METHOD_EXIT = 41;
53 	public static final byte EVENT_METHOD_EXIT_WITH_RETURN_VALUE = 42;
54 	public static final byte EVENT_MONITOR_CONTENDED_ENTER = 43;
55 	public static final byte EVENT_MONITOR_CONTENDED_ENTERED = 44;
56 	public static final byte EVENT_MONITOR_WAIT = 45;
57 	public static final byte EVENT_MONITOR_WAITED = 46;
58 	public static final byte EVENT_VM_INIT = 90;
59 	public static final byte EVENT_VM_DEATH = 99;
60 	public static final byte EVENT_VM_DISCONNECTED = 100; // Never sent by
61 															// across JDWP.
62 	public static final byte EVENT_VM_START = EVENT_VM_INIT;
63 	public static final byte EVENT_THREAD_DEATH = EVENT_THREAD_END;
64 
65 	/** ThreadReference of thread that generated this event. */
66 	protected ThreadReferenceImpl fThreadRef;
67 
68 	/** Mapping of command codes to strings. */
69 	private static HashMap<Integer, String> fEventKindMap = null;
70 
71 	/** Request ID of event. */
72 	private RequestID fRequestID;
73 
74 	/** The EventRequest that requested this event. */
75 	private EventRequest fRequest;
76 
77 	/**
78 	 * Creates new EventImpl, only used by subclasses.
79 	 */
EventImpl(String description, VirtualMachineImpl vmImpl, RequestID requestID)80 	protected EventImpl(String description, VirtualMachineImpl vmImpl,
81 			RequestID requestID) {
82 		super(description, vmImpl);
83 		fRequestID = requestID;
84 	}
85 
86 	/**
87 	 * @return Returns ThreadReference of thread that generated this event.
88 	 */
thread()89 	public ThreadReference thread() {
90 		return fThreadRef;
91 	}
92 
93 	/**
94 	 * @return Returns requestID.
95 	 */
requestID()96 	public RequestID requestID() {
97 		return fRequestID;
98 	}
99 
100 	/**
101 	 * @return Returns string representation.
102 	 */
103 	@Override
toString()104 	public String toString() {
105 		return super.toString() + ": " + fRequestID; //$NON-NLS-1$
106 	}
107 
108 	/**
109 	 * @return Creates, reads and returns new EventImpl.
110 	 */
read(MirrorImpl target, DataInputStream dataInStream)111 	public static EventImpl read(MirrorImpl target, DataInputStream dataInStream)
112 			throws IOException {
113 		byte eventKind = target.readByte(
114 				"event kind", eventKindMap(), dataInStream); //$NON-NLS-1$
115 		RequestID requestID = RequestID.read(target, dataInStream);
116 
117 		// Create, read and return Event of eventKind.
118 		EventImpl result;
119 		switch (eventKind) {
120 		case 0:
121 			return null;
122 		case AccessWatchpointEventImpl.EVENT_KIND:
123 			result = AccessWatchpointEventImpl.read(target, requestID,
124 					dataInStream);
125 			break;
126 		case BreakpointEventImpl.EVENT_KIND:
127 			result = BreakpointEventImpl.read(target, requestID, dataInStream);
128 			break;
129 		case ClassPrepareEventImpl.EVENT_KIND:
130 			result = ClassPrepareEventImpl
131 					.read(target, requestID, dataInStream);
132 			break;
133 		case ClassUnloadEventImpl.EVENT_KIND:
134 			result = ClassUnloadEventImpl.read(target, requestID, dataInStream);
135 			break;
136 		case ExceptionEventImpl.EVENT_KIND:
137 			result = ExceptionEventImpl.read(target, requestID, dataInStream);
138 			break;
139 		case MethodEntryEventImpl.EVENT_KIND:
140 			result = MethodEntryEventImpl.read(target, requestID, dataInStream);
141 			break;
142 		case MethodExitEventImpl.EVENT_KIND:
143 			result = MethodExitEventImpl.read(target, requestID, dataInStream);
144 			break;
145 		case EVENT_METHOD_EXIT_WITH_RETURN_VALUE:
146 			result = MethodExitEventImpl.readWithReturnValue(target, requestID,
147 					dataInStream);
148 			break;
149 		case MonitorContendedEnteredEventImpl.EVENT_KIND:
150 			result = MonitorContendedEnteredEventImpl.read(target, requestID,
151 					dataInStream);
152 			break;
153 		case MonitorContendedEnterEventImpl.EVENT_KIND:
154 			result = MonitorContendedEnterEventImpl.read(target, requestID,
155 					dataInStream);
156 			break;
157 		case MonitorWaitedEventImpl.EVENT_KIND:
158 			result = MonitorWaitedEventImpl.read(target, requestID,
159 					dataInStream);
160 			break;
161 		case MonitorWaitEventImpl.EVENT_KIND:
162 			result = MonitorWaitEventImpl.read(target, requestID, dataInStream);
163 			break;
164 		case ModificationWatchpointEventImpl.EVENT_KIND:
165 			result = ModificationWatchpointEventImpl.read(target, requestID,
166 					dataInStream);
167 			break;
168 		case StepEventImpl.EVENT_KIND:
169 			result = StepEventImpl.read(target, requestID, dataInStream);
170 			break;
171 		case ThreadDeathEventImpl.EVENT_KIND:
172 			result = ThreadDeathEventImpl.read(target, requestID, dataInStream);
173 			break;
174 		case ThreadStartEventImpl.EVENT_KIND:
175 			result = ThreadStartEventImpl.read(target, requestID, dataInStream);
176 			break;
177 		case VMDeathEventImpl.EVENT_KIND:
178 			result = VMDeathEventImpl.read(target, requestID, dataInStream);
179 			break;
180 		case VMDisconnectEventImpl.EVENT_KIND:
181 			result = VMDisconnectEventImpl
182 					.read(target, requestID, dataInStream);
183 			break;
184 		case VMStartEventImpl.EVENT_KIND:
185 			result = VMStartEventImpl.read(target, requestID, dataInStream);
186 			break;
187 		default:
188 			throw new IOException(
189 					EventMessages.EventImpl_Read_invalid_EventKind___1
190 							+ eventKind);
191 		}
192 
193 		// Find and store original request.
194 		if (!requestID.isNull())
195 			result.fRequest = target.virtualMachineImpl().eventRequestManagerImpl().findRequest(result);
196 
197 		return result;
198 	}
199 
200 	/**
201 	 * @return Returns EventRequest that caused this event to be generated by
202 	 *         the Virtual Machine.
203 	 */
204 	@Override
request()205 	public EventRequest request() {
206 		return fRequest;
207 	}
208 
209 	/**
210 	 * Retrieves constant mappings.
211 	 */
getConstantMaps()212 	public static void getConstantMaps() {
213 		if (fEventKindMap != null)
214 			return;
215 
216 		java.lang.reflect.Field[] fields = EventImpl.class.getDeclaredFields();
217 		fEventKindMap = new HashMap<>();
218 		for (Field field : fields) {
219 			if ((field.getModifiers() & java.lang.reflect.Modifier.PUBLIC) == 0
220 					|| (field.getModifiers() & java.lang.reflect.Modifier.STATIC) == 0
221 					|| (field.getModifiers() & java.lang.reflect.Modifier.FINAL) == 0)
222 				continue;
223 
224 			try {
225 				String name = field.getName();
226 				Integer intValue = Integer.valueOf(field.getInt(null));
227 
228 				if (name.startsWith("EVENT_")) { //$NON-NLS-1$
229 					name = name.substring(6);
230 					fEventKindMap.put(intValue, name);
231 				}
232 			} catch (IllegalAccessException e) {
233 				// Will not occur for own class.
234 			} catch (IllegalArgumentException e) {
235 				// Should not occur.
236 				// We should take care that all public static final constants
237 				// in this class are numbers that are convertible to int.
238 			}
239 		}
240 	}
241 
242 	/**
243 	 * @return Returns a map with string representations of tags.
244 	 */
eventKindMap()245 	public static Map<Integer, String> eventKindMap() {
246 		getConstantMaps();
247 		return fEventKindMap;
248 	}
249 }
250