All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.atmosphere.cpr.AtmosphereSession Maven / Gradle / Ivy

/*
 * Copyright 2017 Async-IO.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.atmosphere.cpr;

import com.vaadin.external.org.slf4j.Logger;
import com.vaadin.external.org.slf4j.LoggerFactory;

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/**
 * An AtmosphereSession allow an application to keep track of the AtmosphereResource associated with a remote client.
 * For example, with the long-polling transport, a new {@link AtmosphereResource} will be created every time a
 * reconnect occurs. If an application has a reference to the {@link AtmosphereResource}, the object will become
 * out of scope, or unusable, after the reconnection. To fix this problem, you can use this class to track and invoke
 * {@link #tryAcquire()} ()} or {@link #acquire()}} in order to get the {@link AtmosphereResource}.
 * 

* AtmosphereResource are tracked using the list of associated {@link Broadcaster}, e.g you must make sure the AtmosphereResource * has called {@link Broadcaster#addAtmosphereResource(AtmosphereResource)} once if you want this class to work. * * @author Jeanfrancois Arcand */ public class AtmosphereSession { protected final Logger logger = LoggerFactory.getLogger(AtmosphereSession.class); protected final AtomicReference resource = new AtomicReference(); protected String uuid; protected final Semaphore latch = new Semaphore(1); protected BroadcasterListenerAdapter broadcasterListener; protected Broadcaster[] relatedBroadcasters; protected final boolean usesLongPolling; public AtmosphereSession(final AtmosphereResource r, Broadcaster... broadcasters) { this.uuid = r.uuid(); this.relatedBroadcasters = broadcasters; this.usesLongPolling = AtmosphereResource.TRANSPORT.LONG_POLLING == r.transport(); resource.set(r); broadcasterListener = new BroadcasterListenerAdapter() { @Override public void onAddAtmosphereResource(Broadcaster b, AtmosphereResource r) { boolean found = false; if (r.uuid().equalsIgnoreCase(uuid)) { logger.trace("AtmosphereSession tracking : AtmosphereResource {} added", uuid); resource.set(r); found = true; } if (found && latch.availablePermits() == 0) latch.release(); } @Override public void onRemoveAtmosphereResource(Broadcaster b, AtmosphereResource r) { if (r.uuid().equalsIgnoreCase(uuid)) { logger.trace("AtmosphereSession tracking : AtmosphereResource {} removed", uuid); resource.set(null); latch.tryAcquire(); } } }; for (Broadcaster b : broadcasters) { b.addBroadcasterListener(broadcasterListener); } } /** * Track the current {@link AtmosphereResource} with all created {@link Broadcaster} * * @param resource an {@link AtmosphereResource} * @return this */ public AtmosphereSession(AtmosphereResource resource) { this(resource, resource.getAtmosphereConfig().getBroadcasterFactory().lookupAll().toArray(new Broadcaster[]{})); } /** * Retrieve the {@link AtmosphereResource} associated with this session. If there is no {@link AtmosphereResource} * associated, return null. * * @return an {@link AtmosphereResource} */ public AtmosphereResource acquire() { return resource.get(); } /** * Retrieve the {@link AtmosphereResource} associated with this session. If there is no {@link AtmosphereResource} * associated, wait until the {@link AtmosphereResource} is retrieved. This method will wait 60 seconds and then return. * * @return an {@link AtmosphereResource} */ public AtmosphereResource tryAcquire() throws InterruptedException { return tryAcquire(60); } /** * Retrieve the {@link AtmosphereResource} associated with this session. If there is no {@link AtmosphereResource} * associated, wait until the {@link AtmosphereResource} is retrieved. * *

If the resource uses long polling as its transport, this method treats the resource as a single use connection * and will make subsequent callers wait until the client reconnects and the {@link #broadcasterListener}'s * {@link BroadcasterListenerAdapter#onAddAtmosphereResource} method gets called again.

* *

WARNING: Use this method with long polling only if you intend to broadcast to the returned resource. If no broadcast is made, * the client won't have to reconnect, the resource won't get re-added, and any subsequent calls will have to wait until the timeout is reached.

* * @param timeInSecond The timeToWait before continuing the execution * @return an {@link AtmosphereResource} or {@code null} if the resource was not set and it didn't get set during the timeout */ public AtmosphereResource tryAcquire(int timeInSecond) throws InterruptedException { if (usesLongPolling || resource.get() == null) { latch.tryAcquire(timeInSecond, TimeUnit.SECONDS); } return resource.get(); } public void close() { for(Broadcaster br : relatedBroadcasters) { br.removeBroadcasterListener(broadcasterListener); } } public String uuid() { return uuid; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy