001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036: package com.sun.xml.ws.tx.coordinator;
037:
038: import com.sun.istack.NotNull;
039: import com.sun.istack.Nullable;
040: import com.sun.xml.ws.api.tx.Protocol;
041: import static com.sun.xml.ws.api.tx.Protocol.*;
042: import com.sun.xml.ws.developer.MemberSubmissionEndpointReference;
043: import com.sun.xml.ws.tx.common.Identifier;
044: import com.sun.xml.ws.tx.common.RegistrantIdentifier;
045: import com.sun.xml.ws.tx.common.TxLogger;
046: import com.sun.xml.ws.tx.webservice.member.coord.RegisterType;
047:
048: import javax.xml.ws.EndpointReference;
049: import java.util.HashMap;
050: import java.util.Map;
051: import java.util.concurrent.Semaphore;
052: import java.util.concurrent.TimeUnit;
053: import java.util.logging.Level;
054:
055: /**
056: * This class encapsulates a coordination registrant.
057: * <p/>
058: * The coordination protocol implementations will extend this class and
059: * add protocol specific functionality.
060: *
061: * @author Ryan.Shoemaker@Sun.COM
062: * @version $Revision: 1.8 $
063: * @since 1.0
064: */
065: public abstract class Registrant {
066:
067: /* The actual SOAP message containing the register message */
068: private RegisterType registerRequest = null;
069:
070: /* reference to the parent coordinator */
071: private final Coordinator parent;
072:
073: /* the protocol the registrant is registering for */
074: private final Protocol protocol;
075:
076: // coordinator(received from coord:registerReply from coordinator)
077: private EndpointReference coordinatorProtocolService = null;
078:
079: private static long nextId = 1;
080:
081: private final RegistrantIdentifier id;
082:
083: static private TxLogger logger = TxLogger
084: .getCoordLogger(Registrant.class);
085:
086: // only set to false when constucting a Registrant with a remote coordination service.
087: // when this value is true, coordination protocol service will be properly set.
088: private Boolean registrationCompleted = true;
089:
090: /* mutex used for asynch register / registerResponse MEP with REMOTE CPS */
091: private Semaphore registrationCompletedGate;
092:
093: /**
094: * Create a new registrant
095: *
096: * @param registerRequest <register> request
097: * @param parent parent coordinator
098: */
099: public Registrant(@NotNull
100: Coordinator parent, @NotNull
101: RegisterType registerRequest) {
102: this (parent, registerRequest.getProtocolIdentifier());
103: this .registerRequest = registerRequest;
104: // no need to add to outstanding registrants, the PPS is in registerRequest
105: }
106:
107: protected Registrant(Coordinator parent, String protocolId) {
108: this (parent, Protocol.getProtocol(protocolId));
109: }
110:
111: /**
112: * Create a Registratant with its coordinator parent for protocol.
113: *
114: * @param parent parent coordinator
115: * @param protocol activity protocol
116: */
117: protected Registrant(@NotNull
118: Coordinator parent, @NotNull
119: Protocol protocol) {
120: id = new RegistrantIdentifier(Long.toString(nextId++));
121:
122: this .parent = parent;
123: this .protocol = protocol;
124: if (parent.isSubordinate()) {
125: outstandingRegistrants.put(getIdValue(), this );
126: registrationCompleted = false;
127: registrationCompletedGate = new Semaphore(0); // initially closed
128: } else {
129: if (registerRequest == null) {
130: this
131: .setParticpantProtocolService(getLocalParticipantProtocolService());
132: }
133: }
134: }
135:
136: @NotNull
137: private String getProtocolIdentifier() {
138: switch (protocol) {
139: case COMPLETION:
140: return COMPLETION.getUri();
141: case DURABLE:
142: return DURABLE.getUri();
143: case VOLATILE:
144: return VOLATILE.getUri();
145: default:
146: return UNKNOWN.getUri();
147: }
148: }
149:
150: public void setParticpantProtocolService(@NotNull
151: final EndpointReference pps) {
152: if (registerRequest == null) {
153: registerRequest = new RegisterType();
154: }
155: registerRequest.setProtocolIdentifier(this
156: .getProtocolIdentifier());
157: registerRequest
158: .setParticipantProtocolService((MemberSubmissionEndpointReference) pps);
159: }
160:
161: @NotNull
162: public EndpointReference getParticipantProtocolService() {
163: return (registerRequest == null) ? getLocalParticipantProtocolService()
164: : registerRequest.getParticipantProtocolService();
165: }
166:
167: /**
168: * Get the SOAP register request
169: *
170: * @return the SOAP register message
171: */
172: @Nullable
173: public RegisterType getRegisterRequest() {
174: return registerRequest;
175: }
176:
177: /**
178: * Get the protocol for this registrant
179: *
180: * @return the protocol identifier
181: */
182: @NotNull
183: public Protocol getProtocol() {
184: return protocol;
185: }
186:
187: /**
188: * Get the parent coordinator for this Registrant
189: *
190: * @return the parent coordinator
191: */
192: @NotNull
193: public Coordinator getCoordinator() {
194: return parent;
195: }
196:
197: @NotNull
198: synchronized public EndpointReference getCoordinatorProtocolService() {
199: return coordinatorProtocolService;
200: }
201:
202: /**
203: * Set the coordinator protocol service received by coor:registerResponse.
204: *
205: * @param cps cps epr
206: */
207: public synchronized void setCoordinatorProtocolService(@NotNull
208: final EndpointReference cps) {
209: coordinatorProtocolService = cps;
210: setRegistrationCompleted(true);
211: }
212:
213: public void register() {
214: RegistrationManager.getInstance().register(parent, this );
215: }
216:
217: @NotNull
218: public Identifier getId() {
219: return id;
220: }
221:
222: @NotNull
223: public String getIdValue() {
224: return id.getValue();
225: }
226:
227: // extent of participants
228: protected static final Map<String, Registrant> outstandingRegistrants = new HashMap<String, Registrant>();
229:
230: /**
231: * Lookup outstanding registrant by id
232: *
233: * @param id registrant id
234: * @return the outstanding registrant or null if it doesn't exist
235: */
236: @Nullable
237: public static Registrant getOutstandingRegistrant(final String id) {
238: return outstandingRegistrants.get(id);
239: }
240:
241: /**
242: * Remove outstanding registrant by its id.
243: *
244: * @param id registrant id
245: * @return the outstanding registrant or null if it doesn't exist
246: */
247: @Nullable
248: public static Registrant removeOutstandingRegistrant(final String id) {
249: return outstandingRegistrants.remove(id);
250: }
251:
252: private boolean remoteCPS = false;
253:
254: public void setRemoteCPS(final boolean value) {
255: remoteCPS = value;
256: }
257:
258: public boolean isRemoteCPS() {
259: return remoteCPS;
260: }
261:
262: public boolean isRegistrationCompleted() {
263: return registrationCompleted;
264: }
265:
266: public synchronized void setRegistrationCompleted(
267: final boolean value) {
268: registrationCompleted = value;
269:
270: if (isRemoteCPS()) {
271: if (logger.isLogging(Level.FINEST)) {
272: logger.finest(
273: "setRegistrationCompleted(" + value + ")",
274: "semaphore has "
275: + registrationCompletedGate
276: .availablePermits()
277: + " permits.");
278: }
279: if (value) {
280: assert (registrationCompletedGate.availablePermits() <= 0);
281: registrationCompletedGate.release();
282: if (logger.isLogging(Level.FINEST)) {
283: logger.finest("setRegistrationCompleted(" + value
284: + ")",
285: "released a permit, semaphore now has "
286: + registrationCompletedGate
287: .availablePermits()
288: + " permits.");
289: }
290: }
291: }
292: }
293:
294: /**
295: * wait for a registerResponse to arrive - this method is only used with remote CPSs
296: *
297: * @return true if <RegistrationResponse> was received, false if there was a timeout.
298: */
299: public boolean waitForRegistrationResponse() {
300: try {
301: if (logger.isLogging(Level.FINEST)) {
302: logger.finest("waitForRegistrationResponse",
303: "semaphore should have 0 permits. actual available permits: "
304: + registrationCompletedGate
305: .availablePermits());
306: assert (registrationCompletedGate.availablePermits() <= 0);
307: logger
308: .finest("waitForRegistrationResponse",
309: "Waiting for registration response. Calling tryAcquire()...");
310: }
311: return !registrationCompletedGate.tryAcquire(1, 40,
312: TimeUnit.SECONDS);
313: } catch (InterruptedException e) {
314: e.printStackTrace();
315: return false;
316: }
317: }
318:
319: abstract public EndpointReference getLocalParticipantProtocolService();
320:
321: /**
322: * Forget all resources associated with this Registrant
323: */
324: public abstract void forget();
325: }
|