/* * 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(); } }