1 /*
2  * Copyright (c) 1999, 2012, 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 com.sun.tools.jdi;
27 
28 import com.sun.jdi.*;
29 import com.sun.jdi.connect.*;
30 import com.sun.jdi.connect.spi.*;
31 
32 import java.io.IOException;
33 import java.util.Map;
34 import java.util.ResourceBundle;
35 
36 class SharedMemoryTransportService extends TransportService {
37     private ResourceBundle messages = null;
38 
39     /**
40      * The listener returned by startListening
41      */
42     static class SharedMemoryListenKey extends ListenKey {
43         long id;
44         String name;
45 
SharedMemoryListenKey(long id, String name)46         SharedMemoryListenKey(long id, String name) {
47             this.id = id;
48             this.name = name;
49         }
50 
id()51         long id() {
52             return id;
53         }
54 
setId(long id)55         void setId(long id) {
56             this.id = id;
57         }
58 
address()59         public String address() {
60             return name;
61         }
62 
toString()63         public String toString() {
64             return address();
65         }
66     }
67 
SharedMemoryTransportService()68     SharedMemoryTransportService() {
69         System.loadLibrary("dt_shmem");
70         initialize();
71     }
72 
name()73     public String name() {
74         return "SharedMemory";
75     }
76 
defaultAddress()77     public String defaultAddress() {
78         return "javadebug";
79     }
80 
81     /**
82      * Return localized description of this transport service
83      */
description()84     public String description() {
85         synchronized (this) {
86             if (messages == null) {
87                 messages = ResourceBundle.getBundle("com.sun.tools.jdi.resources.jdi");
88             }
89         }
90         return messages.getString("memory_transportservice.description");
91     }
92 
capabilities()93     public Capabilities capabilities() {
94         return new SharedMemoryTransportServiceCapabilities();
95     }
96 
initialize()97     private native void initialize();
startListening0(String address)98     private native long startListening0(String address) throws IOException;
attach0(String address, long attachTimeout)99     private native long attach0(String address, long attachTimeout) throws IOException;
stopListening0(long id)100     private native void stopListening0(long id) throws IOException;
accept0(long id, long acceptTimeout)101     private native long accept0(long id, long acceptTimeout) throws IOException;
name(long id)102     private native String name(long id) throws IOException;
103 
attach(String address, long attachTimeout, long handshakeTimeout)104     public Connection attach(String address, long attachTimeout, long handshakeTimeout) throws IOException {
105         if (address == null) {
106             throw new NullPointerException("address is null");
107         }
108         long id = attach0(address, attachTimeout);
109         SharedMemoryConnection conn = new SharedMemoryConnection(id);
110         conn.handshake(handshakeTimeout);
111         return conn;
112     }
113 
startListening(String address)114     public TransportService.ListenKey startListening(String address) throws IOException {
115         if (address == null || address.length() == 0) {
116             address = defaultAddress();
117         }
118         long id = startListening0(address);
119         return new SharedMemoryListenKey(id, name(id));
120     }
121 
startListening()122     public ListenKey startListening() throws IOException {
123         return startListening(null);
124     }
125 
stopListening(ListenKey listener)126     public void stopListening(ListenKey listener) throws IOException {
127         if (!(listener instanceof SharedMemoryListenKey)) {
128             throw new IllegalArgumentException("Invalid listener");
129         }
130 
131         long id;
132         SharedMemoryListenKey key = (SharedMemoryListenKey)listener;
133         synchronized (key) {
134             id = key.id();
135             if (id == 0) {
136                 throw new IllegalArgumentException("Invalid listener");
137             }
138 
139             // invalidate the id
140             key.setId(0);
141         }
142         stopListening0(id);
143     }
144 
accept(ListenKey listener, long acceptTimeout, long handshakeTimeout)145     public Connection accept(ListenKey listener, long acceptTimeout, long handshakeTimeout) throws IOException {
146         if (!(listener instanceof SharedMemoryListenKey)) {
147             throw new IllegalArgumentException("Invalid listener");
148         }
149 
150         long transportId;
151         SharedMemoryListenKey key = (SharedMemoryListenKey)listener;
152         synchronized (key) {
153             transportId = key.id();
154             if (transportId == 0) {
155                 throw new IllegalArgumentException("Invalid listener");
156             }
157         }
158 
159         // in theory another thread could call stopListening before
160         // accept0 is called. In that case accept0 will try to accept
161         // with an invalid "transport id" - this should result in an
162         // IOException.
163 
164         long connectId = accept0(transportId, acceptTimeout);
165         SharedMemoryConnection conn = new SharedMemoryConnection(connectId);
166         conn.handshake(handshakeTimeout);
167         return conn;
168     }
169 }
170 
171 
172 class SharedMemoryTransportServiceCapabilities extends TransportService.Capabilities {
173 
supportsMultipleConnections()174     public boolean supportsMultipleConnections() {
175         return false;
176     }
177 
supportsAttachTimeout()178     public boolean supportsAttachTimeout() {
179         return true;
180     }
181 
supportsAcceptTimeout()182     public boolean supportsAcceptTimeout() {
183         return true;
184     }
185 
supportsHandshakeTimeout()186     public boolean supportsHandshakeTimeout() {
187         return false;
188     }
189 
190 }
191