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:
037: /*
038: * ServerInboundSequence.java
039: *
040: * @author Mike Grogan
041: * Created on November 21, 2005, 2:50 PM
042: *
043: */
044:
045: package com.sun.xml.ws.rm.jaxws.runtime.server;
046:
047: import com.sun.xml.ws.api.rm.SequenceSettings;
048: import com.sun.xml.ws.api.rm.server.ServerSequence;
049: import com.sun.xml.ws.rm.InvalidMessageNumberException;
050: import com.sun.xml.ws.rm.Message;
051: import com.sun.xml.ws.rm.RMException;
052: import com.sun.xml.ws.rm.jaxws.runtime.InboundSequence;
053: import com.sun.xml.ws.rm.jaxws.runtime.OutboundSequence;
054: import com.sun.xml.ws.rm.jaxws.runtime.SequenceConfig;
055: import com.sun.xml.ws.rm.jaxws.util.LoggingHelper;
056: import com.sun.xml.ws.runtime.util.Session;
057:
058: import java.net.URI;
059: import java.util.UUID;
060: import java.util.logging.Level;
061: import java.util.logging.Logger;
062:
063: /**
064: * An <code>ServerInboundSequence</code> represents a sequence of incoming messages. For an
065: * <code>RMDestination</code>, an <code>InboundSequnce</code> consists of all
066: * the requests to a service from a particular proxy.
067: */
068: public class ServerInboundSequence extends InboundSequence implements
069: ServerSequence {
070:
071: /**
072: * Session associated with this sequence.
073: */
074:
075: private static final Logger logger = Logger.getLogger(LoggingHelper
076: .getLoggerName(ServerInboundSequence.class));
077:
078: private Session session;
079:
080: public ServerInboundSequence(URI acksTo, String inboundId,
081: String outboundId, SequenceConfig config) {
082:
083: super (acksTo, config);
084: this .outboundSequence = new ServerOutboundSequence(this ,
085: outboundId, config);
086:
087: if (inboundId == null) {
088: String newid = "uuid:" + UUID.randomUUID();
089: setId(newid);
090: } else {
091: setId(inboundId);
092: }
093:
094: //if flow control is enabled, set buffer size.
095: //don't try to use flow control if ordered delivery
096: //is needed. Even if the buffer is full, we
097: //would still need to accept messages that "fill in the gaps"
098: if (config.flowControl && !config.ordered) {
099: maxMessages = config.bufferSize;
100: } else {
101: maxMessages = -1;
102: }
103:
104: allowDuplicates = config.allowDuplicates;
105: }
106:
107: /**
108: * Gets the original message in a the Sequence with a given message number.
109: *
110: * @param duplicate Subsequent message with same number.
111: * @return the original message.
112: */
113: public com.sun.xml.ws.rm.Message getOriginalMessage(
114: com.sun.xml.ws.rm.Message duplicate)
115: throws InvalidMessageNumberException {
116:
117: int number = duplicate.getMessageNumber();
118: return get(number);
119: }
120:
121: /**
122: * Accessor for the <code>session</code> field.
123: *
124: * @return The value of the session field.
125: */
126: public Session getSession() {
127: return session;
128: }
129:
130: /**
131: * Mutator for the <code>session</code> field.
132: */
133: public void setSession(Session s) {
134: session = s;
135: }
136:
137: /**
138: * If ordered delivery is required, resume processing the next Message
139: * in the Sequence if it is waiting for this message to be delivered.
140: * This method is called after ServerPipe.process returns for this message.
141: * while waiting for gaps in the sequence to fill that can now be processed.
142: *
143: *@param message The message to be processed
144: */
145: /*
146: public void holdIfUndeliverable(Message message)
147: throws BufferFullException {
148: if (!config.ordered) {
149: return;
150: }
151:
152: try {
153: int num = message.getMessageNumber();
154:
155: //if immediate predecessor has not been processed, wait fcor it
156: if (num > 1) {
157: Message mess = get(num - 1);
158: if (mess == null || !mess.isComplete()) {
159: message.block();
160: }
161: }
162: } catch (InvalidMessageNumberException e) {}
163: }
164: *
165: */
166:
167: public boolean isDeliverable(Message message) {
168: if (!config.ordered) {
169: return true;
170: }
171:
172: try {
173: int num = message.getMessageNumber();
174:
175: //if immediate predecessor has not been processed, wait fcor it
176: if (num > 1) {
177: Message mess = get(num - 1);
178: if (mess == null || !mess.isComplete()) {
179: return false;
180: }
181: }
182: } catch (Exception e) {
183: }
184: return true;
185: }
186:
187: /**
188: * Used to re-populate a sequence with persisted messages
189: * after a restart. Do not use for other purposes.
190: *
191: * @param index The index to add message at.
192: * @param message The JAX-WS message to add
193: * @param complete Indicates whether to mark the message
194: * as complete.
195: */
196: public void resetMessage(int index,
197: com.sun.xml.ws.api.message.Message message, boolean complete) {
198:
199: try {
200: com.sun.xml.ws.rm.Message mess = new com.sun.xml.ws.rm.Message(
201: message, config.rmVersion);
202: set(index, mess);
203:
204: if (complete) {
205: mess.complete();
206: }
207:
208: } catch (RMException e) {
209: String m = Messages.COULD_NOT_RESET_MESSAGE.format(index,
210: getId());
211: logger.log(Level.SEVERE, m, e);
212: }
213:
214: }
215:
216: /**
217: * Implementation of ServerSequence.getSequenceSettings..
218: */
219: public SequenceSettings getSequenceSettings() {
220: SequenceSettings settings = getSequenceConfig();
221: settings.sequenceId = getId();
222:
223: OutboundSequence oseq = getOutboundSequence();
224:
225: settings.companionSequenceId = (oseq != null) ? oseq.getId()
226: : null;
227: return settings;
228: }
229:
230: /**
231: * Return value determines whether the interval since last activity
232: * exceeds the inactivity timeout setting.
233: *
234: * @return true if sequence has expired.
235: * false otherwise.
236: */
237: public boolean isExpired() {
238:
239: return System.currentTimeMillis() - this .getLastActivityTime() > config
240: .getInactivityTimeout();
241: }
242:
243: /**
244: * Return value reports whether ordered delivery is configured for this
245: * sequence.
246: *
247: * @return true if sequence is ordered.
248: * false otherwise.
249: */
250: public boolean isOrdered() {
251: return config.ordered;
252: }
253:
254: /**
255: * When ordered delivery is required, this method is used to determine
256: * whether the messages with lower message numbers have already been
257: * processed.
258: */
259: public boolean IsPredecessorComplete(Message message) {
260: try {
261: int num = message.getMessageNumber();
262:
263: //if immediate predecessor has not been processed, wait fcor it
264: if (num > 1) {
265: Message mess = get(num - 1);
266: if (mess == null || !mess.isComplete()) {
267: return false;
268: }
269: }
270:
271: } catch (InvalidMessageNumberException e) {
272: }
273: return true;
274: }
275:
276: /**
277: * If ordered delivery is required, resume processing the next Message
278: * in the Sequence if it is waiting for this message to be delivered.
279: * This method is called when RMServerTube.processResponse is called for this message.
280: * while waiting for gaps in the sequence to fill that can now be processed.
281: *
282: * @param message The message to be processed
283: */
284: public void releaseNextMessage(Message message) throws RMException {
285:
286: message.complete();
287: --storedMessages;
288:
289: //notify immediate successor if it is waiting
290: int num = message.getMessageNumber();
291:
292: if (num < nextIndex - 1 && get(num + 1) != null) {
293: System.out.println("resuming " + (num + 1));
294: get(num + 1).resume();
295: }
296: }
297:
298: }
|