00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 package org.knopflerfish.framework;
00036
00037 import java.util.Set;
00038 import java.util.List;
00039 import java.util.ArrayList;
00040 import java.util.Map;
00041 import java.util.HashSet;
00042 import java.util.HashMap;
00043 import java.util.Iterator;
00044 import java.util.EventListener;
00045
00046 import org.osgi.framework.*;
00047
00054 public class Listeners
00055 implements BundleListener, FrameworkListener, ServiceListener {
00056
00060 private HashSet bundleListeners = new HashSet();
00061 private HashSet syncBundleListeners = new HashSet();
00062
00066 private HashSet frameworkListeners = new HashSet();
00067
00071 private ServiceListenerState serviceListeners = new ServiceListenerState();
00072
00076 private PermissionOps secure;
00077
00078
00079 Listeners(PermissionOps perm) {
00080 secure = perm;
00081 }
00082
00083
00090 void addBundleListener(Bundle bundle, BundleListener listener) {
00091 ListenerEntry le = new ListenerEntry(bundle, listener);
00092 if (listener instanceof SynchronousBundleListener) {
00093 secure.checkListenerAdminPerm(bundle);
00094 synchronized (syncBundleListeners) {
00095 syncBundleListeners.add(le);
00096 }
00097 }
00098 else {
00099 synchronized (bundleListeners) {
00100 bundleListeners.add(le);
00101 }
00102 }
00103 }
00104
00105
00114 void removeBundleListener(Bundle bundle, BundleListener listener) {
00115 ListenerEntry le = new ListenerEntry(bundle, listener);
00116 if (listener instanceof SynchronousBundleListener) {
00117 synchronized (syncBundleListeners) {
00118 secure.checkListenerAdminPerm(bundle);
00119 syncBundleListeners.remove(le);
00120 }
00121 } else {
00122 synchronized (bundleListeners) {
00123 bundleListeners.remove(le);
00124 }
00125 }
00126 }
00127
00128
00135 void addFrameworkListener(Bundle bundle, FrameworkListener listener) {
00136 ListenerEntry le = new ListenerEntry(bundle, listener);
00137 synchronized (frameworkListeners) {
00138 frameworkListeners.add(le);
00139 }
00140 }
00141
00142
00151 void removeFrameworkListener(Bundle bundle, FrameworkListener listener) {
00152 synchronized (frameworkListeners) {
00153 frameworkListeners.remove(new ListenerEntry(bundle, listener));
00154 }
00155 }
00156
00157
00166 void addServiceListener(Bundle bundle, ServiceListener listener, String filter)
00167 throws InvalidSyntaxException {
00168 serviceListeners.add(bundle, listener, filter);
00169 }
00170
00171
00180 void removeServiceListener(Bundle bundle, ServiceListener listener) {
00181 serviceListeners.remove(bundle, listener);
00182 }
00183
00184
00190 void removeAllListeners(Bundle b) {
00191 removeAllListeners(syncBundleListeners, b);
00192 removeAllListeners(bundleListeners, b);
00193 removeAllListeners(frameworkListeners, b);
00194 serviceListeners.removeAll(b);
00195 }
00196
00197
00204 void frameworkError(Bundle b, Throwable t) {
00205 frameworkEvent(new FrameworkEvent(FrameworkEvent.ERROR, b, t));
00206 }
00207
00208
00215 void frameworkInfo(Bundle b, Throwable t) {
00216 frameworkEvent(new FrameworkEvent(FrameworkEvent.INFO, b, t));
00217 }
00218
00219
00220
00221
00222
00228 public void bundleChanged(final BundleEvent evt) {
00229 ListenerEntry [] bl, tmp;
00230 int type = evt.getType();
00231 if(type == BundleEvent.STARTING || type == BundleEvent.STOPPING){
00232 synchronized (syncBundleListeners) {
00233 bl = new ListenerEntry[syncBundleListeners.size()];
00234 syncBundleListeners.toArray(bl);
00235 }
00236 }
00237 else{
00238 synchronized (bundleListeners) {
00239 tmp = new ListenerEntry[bundleListeners.size()];
00240 bundleListeners.toArray(tmp);
00241 }
00242 synchronized (syncBundleListeners) {
00243 bl = new ListenerEntry[tmp.length + syncBundleListeners.size()];
00244 syncBundleListeners.toArray(bl);
00245 }
00246 System.arraycopy(tmp, 0, bl, bl.length - tmp.length, tmp.length);
00247 }
00248
00249 for (int i = 0; i < bl.length; i++) {
00250 final ListenerEntry l = bl[i];
00251 try {
00252 secure.callBundleChanged((BundleListener)l.listener, evt);
00253 } catch (Throwable pe) {
00254 frameworkError(l.bundle, pe);
00255 }
00256 }
00257 }
00258
00259
00260
00261
00262
00268 public void frameworkEvent(final FrameworkEvent evt) {
00269 if (Debug.errors) {
00270 if (evt.getType() == FrameworkEvent.ERROR) {
00271 Debug.println("errors - FrameworkErrorEvent bundle #" + evt.getBundle().getBundleId());
00272 Debug.printStackTrace("errors - FrameworkErrorEvent throwable: ", evt.getThrowable());
00273 }
00274 }
00275 ListenerEntry [] fl;
00276 synchronized (frameworkListeners) {
00277 fl = new ListenerEntry[frameworkListeners.size()];
00278 frameworkListeners.toArray(fl);
00279 }
00280 for (int i = 0; i < fl.length; i++) {
00281 final ListenerEntry l = fl[i];
00282 try {
00283 secure.callFrameworkEvent((FrameworkListener)l.listener, evt);
00284 } catch (Throwable pe) {
00285
00286 if (evt.getType() != FrameworkEvent.ERROR) {
00287 frameworkError(l.bundle, pe);
00288 }
00289 }
00290 }
00291 }
00292
00293
00294
00295
00296
00302 public void serviceChanged(final ServiceEvent evt) {
00303 ServiceReferenceImpl sr = (ServiceReferenceImpl)evt.getServiceReference();
00304 String[] classes = (String[])sr.getProperty(Constants.OBJECTCLASS);
00305 Set sl = serviceListeners.getMatchingListeners(sr);
00306 int n = 0;
00307 for (Iterator it = sl.iterator(); it.hasNext(); n++) {
00308 final ServiceListenerEntry l = (ServiceListenerEntry)it.next();
00309 boolean testAssignable = false;
00310 if(!(l.listener instanceof AllServiceListener)){
00311 testAssignable = true;
00312 }
00313 try {
00314 int length = classes.length;
00315 for (int i = 0; i < length; i++) {
00316 if(testAssignable && !sr.isAssignableTo(l.bundle, classes[i])){
00317 continue;
00318 }
00319 if (l.bundle.hasPermission(new ServicePermission(classes[i],
00320 ServicePermission.GET))) {
00321 try {
00322 secure.callServiceChanged((ServiceListener)l.listener, evt);
00323 } catch (Throwable pe) {
00324 frameworkError(l.bundle, pe);
00325 }
00326 break;
00327 }
00328 }
00329 } catch (Exception le) {
00330 frameworkError(l.bundle, le);
00331 }
00332 }
00333 if (Debug.ldap) {
00334 Debug.println("Notified " + n + " listeners");
00335 }
00336 }
00337
00338
00339
00340
00341
00349 private void removeAllListeners(Set s, Bundle b) {
00350 synchronized (s) {
00351 for (Iterator i = s.iterator(); i.hasNext();) {
00352 if (((ListenerEntry)i.next()).bundle == b) {
00353 i.remove();
00354 }
00355 }
00356 }
00357 }
00358
00359 static boolean nocacheldap =
00360 "true".equals(System.getProperty("org.knopflerfish.framework.ldap.nocache"));
00361 }
00362
00368 class ListenerEntry {
00369 Bundle bundle;
00370 EventListener listener;
00371
00372 ListenerEntry(Bundle b, EventListener l) {
00373 bundle = b;
00374 listener = l;
00375 }
00376
00377 public boolean equals(Object o) {
00378 if (o instanceof ListenerEntry) {
00379 return bundle == ((ListenerEntry)o).bundle &&
00380 listener == ((ListenerEntry)o).listener;
00381 }
00382 return false;
00383 }
00384
00385 public int hashCode() {
00386 return bundle.hashCode();
00387 }
00388 }
00389
00395 class ServiceListenerEntry extends ListenerEntry {
00396 LDAPExpr ldap;
00397
00417 List[] local_cache;
00418
00419 ServiceListenerEntry(Bundle b, EventListener l, String filter)
00420 throws InvalidSyntaxException {
00421 super(b, l);
00422 if (filter != null) {
00423 ldap = new LDAPExpr(filter);
00424 } else {
00425 ldap = null;
00426 }
00427 }
00428
00429 ServiceListenerEntry(Bundle b, EventListener l) {
00430 super(b, l);
00431 ldap = null;
00432 }
00433
00434 }
00435
00439 class ServiceListenerState {
00440 protected final static String[] hashedKeys =
00441 new String[] { Constants.OBJECTCLASS.toLowerCase(),
00442 Constants.SERVICE_ID.toLowerCase(),
00443 Constants.SERVICE_PID.toLowerCase()
00444 };
00445 private final static int OBJECTCLASS_IX = 0;
00446 private final static int SERVICE_ID_IX = 1;
00447 private final static int SERVICE_PID_IX = 2;
00448 protected static List hashedKeysV;
00449
00450
00451 List complicatedListeners = new ArrayList();
00452
00453
00454 Map[]
00455 cache = new HashMap[hashedKeys.length];
00456
00457 Set serviceSet = new HashSet();
00458
00459 ServiceListenerState() {
00460 hashedKeysV = new ArrayList();
00461 for (int i = 0; i < hashedKeys.length; i++) {
00462 hashedKeysV.add(hashedKeys[i]);
00463 cache[i] = new HashMap();
00464 }
00465 }
00466
00477 synchronized void add(Bundle bundle, ServiceListener listener, String filter)
00478 throws InvalidSyntaxException {
00479 ServiceListenerEntry sle = new ServiceListenerEntry(bundle, listener, filter);
00480 if (serviceSet.contains(sle)) {
00481 remove(bundle, listener);
00482 }
00483 serviceSet.add(sle);
00484 checkSimple(sle);
00485 }
00486
00493 synchronized void remove(Bundle bundle, ServiceListener listener) {
00494 for (Iterator it = serviceSet.iterator(); it.hasNext();) {
00495 ServiceListenerEntry sle = (ServiceListenerEntry)it.next();
00496 if (sle.bundle == bundle && sle.listener == listener) {
00497 removeFromCache(sle);
00498 it.remove();
00499 break;
00500 }
00501 }
00502 }
00503
00508 private void removeFromCache(ServiceListenerEntry sle) {
00509 if (sle.local_cache != null) {
00510 for (int i = 0; i < hashedKeys.length; i++) {
00511 HashMap keymap = (HashMap)cache[i];
00512 List l = (List)sle.local_cache[i];
00513 if (l != null) {
00514 for (Iterator it = l.iterator(); it.hasNext();) {
00515 Object value = it.next();
00516 List sles = (List)keymap.get(value);
00517 sles.remove(sles.indexOf(sle));
00518 if (sles.isEmpty()) {
00519 keymap.remove(value);
00520 }
00521 }
00522 }
00523 }
00524 } else {
00525 complicatedListeners.remove(sle);
00526 }
00527 }
00528
00534 synchronized void removeAll(Bundle bundle) {
00535 for (Iterator it = serviceSet.iterator(); it.hasNext();) {
00536 ServiceListenerEntry sle = (ServiceListenerEntry)it.next();
00537 if (sle.bundle == bundle) {
00538 removeFromCache(sle);
00539 it.remove();
00540 }
00541 }
00542 }
00543
00548 public void checkSimple(ServiceListenerEntry sle) {
00549 if (sle.ldap == null || Listeners.nocacheldap) {
00550 complicatedListeners.add(sle);
00551 } else {
00552 List[] local_cache = new List[hashedKeys.length];
00553 if (sle.ldap.isSimple(hashedKeysV, local_cache)) {
00554 sle.local_cache = local_cache;
00555 for (int i = 0; i < hashedKeys.length; i++) {
00556 if (local_cache[i] != null) {
00557 for (Iterator it = local_cache[i].iterator(); it.hasNext();) {
00558 Object value = it.next();
00559 List sles = (List)cache[i].get(value);
00560 if (sles == null)
00561 cache[i].put(value, sles = new ArrayList());
00562 sles.add(sle);
00563 }
00564 }
00565 }
00566 } else {
00567 if (Debug.ldap)
00568 Debug.println("Too complicated filter: " + sle.ldap);
00569 complicatedListeners.add(sle);
00570 }
00571 }
00572 }
00573
00580 synchronized Set getMatchingListeners(ServiceReferenceImpl sr) {
00581 Set set = new HashSet();
00582
00583 int n = 0;
00584 for (Iterator it = complicatedListeners.iterator(); it.hasNext(); n++) {
00585 ServiceListenerEntry sle = (ServiceListenerEntry)it.next();
00586 if (sle.ldap == null || sle.ldap.evaluate(sr.getProperties(), false)) {
00587 set.add(sle);
00588 }
00589 }
00590 if (Debug.ldap) {
00591 Debug.println("Added " + set.size() + " out of " + n + " listeners with complicated filters");
00592 }
00593
00594 String[] c = (String[])sr.getProperty(Constants.OBJECTCLASS);
00595 for (int i = 0; i < c.length; i++) {
00596 if (Debug.ldap) {
00597 System.err.print("objectclass matches: ");
00598 }
00599 addToSet(set, (List)cache[OBJECTCLASS_IX].get(c[i]));
00600 }
00601 Long service_id = (Long)sr.getProperty(Constants.SERVICE_ID);
00602 if (service_id != null) {
00603 if (Debug.ldap) {
00604 System.err.print("service_id matches: ");
00605 }
00606 addToSet(set, (List)cache[SERVICE_ID_IX].get(service_id.toString()));
00607 }
00608 Object service_pid = sr.getProperty(Constants.SERVICE_PID);
00609 if (service_pid != null && service_pid instanceof String) {
00610 if (Debug.ldap) {
00611 System.err.print("service_pid matches: ");
00612 }
00613 addToSet(set, (List)cache[SERVICE_PID_IX].get(service_pid));
00614 }
00615 return set;
00616 }
00617
00621 private void addToSet(Set set, List l) {
00622 if (l != null) {
00623 if (Debug.ldap) {
00624 Debug.println(Integer.toString(l.size()));
00625 }
00626 for (Iterator it = l.iterator(); it.hasNext();) {
00627 set.add(it.next());
00628 }
00629 } else {
00630 if (Debug.ldap) {
00631 Debug.println("0");
00632 }
00633 }
00634 }
00635 }