blob: 34abf4ac6295d98e35879ae58d392c344208313c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.felix.webconsole.plugins.upnp.internal;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.upnp.UPnPDevice;
import org.osgi.service.upnp.UPnPEventListener;
import org.osgi.service.upnp.UPnPService;
/**
* The reason for having this SessionObject is the strange event delivery in UPnP. It's not possible
* read a state variable value, but if register a listener, you will get notified when the value has
* changed.
*/
final class SessionObject implements HttpSessionBindingListener, UPnPEventListener
{
static final String LISTENER_CLASS = UPnPEventListener.class.getName();
private final Map vars = new HashMap();
private final String sessionID;
private final Map store;
private String udn, urn;
private final BundleContext bc;
private final Hashtable regProps = new Hashtable(3);
private ServiceRegistration reg;
SessionObject(BundleContext bc, String sessionID, Map store)
{
this.bc = bc;
this.sessionID = sessionID;
this.store = store;
}
/**
* @see javax.servlet.http.HttpSessionBindingListener#valueBound(javax.servlet.http.HttpSessionBindingEvent)
*/
public void valueBound(HttpSessionBindingEvent event)
{
store.put(sessionID, this);
}
/**
* @see javax.servlet.http.HttpSessionBindingListener#valueUnbound(javax.servlet.http.HttpSessionBindingEvent)
*/
public final void valueUnbound(HttpSessionBindingEvent event)
{
unsubscribe();
store.remove(sessionID); // remove from list of sessions
}
/**
* @see org.osgi.service.upnp.UPnPEventListener#notifyUPnPEvent(java.lang.String,
* java.lang.String, java.util.Dictionary)
*/
public final void notifyUPnPEvent(String deviceId, String serviceId, Dictionary events)
{
if (sameDevice(deviceId, serviceId))
{
for (Enumeration e = events.keys(); e.hasMoreElements();)
{
Object key = e.nextElement();
vars.put(key, events.get(key));
}
}
}
private final boolean sameDevice(String udn, String urn)
{
String _udn = this.udn;
String _urn = this.urn;
if (_udn == null || _urn == null)
return false; // not subscribed
return _udn.equals(udn) && _urn.equals(urn);
}
final synchronized SessionObject subscribe(String udn, String urn)
{
if (!sameDevice(udn, urn))
{
unsubscribe();
this.udn = udn;
this.urn = urn;
try
{
regProps.put(UPnPEventListener.UPNP_FILTER, bc.createFilter(//
"(&(" + UPnPDevice.UDN + '=' + udn + ")(" + //$NON-NLS-1$ //$NON-NLS-2$
UPnPService.ID + '=' + urn + "))")); //$NON-NLS-1$
}
catch (InvalidSyntaxException e)
{ /* will not happen */
}
reg = bc.registerService(LISTENER_CLASS, this, regProps);
}
return this;
}
final synchronized SessionObject unsubscribe()
{
this.udn = this.urn = null;
vars.clear();
if (reg != null)
{
try
{
reg.unregister();
}
catch (Throwable t)
{
// When the bundle is stopped, the session object might remain hanging
// in the session, until it expires. After being stopped, the framework
// however will automatically destroy the registration. But after session
// expires this method will be called once again and will try to
// unregister the service. This will throw exception, that should be caught.
}
reg = null;
}
return this;
}
final Object getValue(String name)
{
return vars.get(name);
}
/**
* @see java.lang.Object#toString()
*/
public final String toString()
{
StringBuffer buffer = new StringBuffer();
buffer.append("SessionObject [sessionID=").append(sessionID) //$NON-NLS-1$
.append(", udn=").append(udn) //$NON-NLS-1$
.append(", urn=").append(urn) //$NON-NLS-1$
.append(", vars=").append(vars) //$NON-NLS-1$
.append(']');
return buffer.toString();
}
}