Package org.apache.felix.dm.impl.index

Source Code of org.apache.felix.dm.impl.index.AspectFilterIndex

/*
* 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.dm.impl.index;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;

import org.apache.felix.dm.DependencyManager;
import org.apache.felix.dm.FilterIndex;
import org.apache.felix.dm.ServiceUtil;
import org.apache.felix.dm.tracker.ServiceTracker;
import org.apache.felix.dm.tracker.ServiceTrackerCustomizer;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;

/**
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class AspectFilterIndex extends AbstractFactoryFilterIndex implements FilterIndex, ServiceTrackerCustomizer {
  // (&(objectClass=foo.Bar)(|(!(service.ranking=*))(service.ranking<=99))(|(service.id=4451)(org.apache.felix.dependencymanager.aspect=4451)))
    private static final String FILTER_START = "(&(" + Constants.OBJECTCLASS + "=";
    private static final String FILTER_SUBSTRING_0 = ")(&(|(!(" + Constants.SERVICE_RANKING + "=*))(" + Constants.SERVICE_RANKING + "<=";
    private static final String FILTER_SUBSTRING_1 = "))(|(" + Constants.SERVICE_ID + "=";
    private static final String FILTER_SUBSTRING_2 = ")(" + DependencyManager.ASPECT + "=";
    private static final String FILTER_END = "))))";
    private final Object m_lock = new Object();
    private ServiceTracker m_tracker;
    private BundleContext m_context;
   
    private final Map /* <Long, Map<String, SortedMap<Integer, Collection<ServiceListener>>> */ m_sidToObjectClassToRankingToListenersMap = new HashMap();

    public void open(BundleContext context) {
        synchronized (m_lock) {
            if (m_context != null) {
                throw new IllegalStateException("Filter already open.");
            }
            try {
                m_tracker = new ServiceTracker(context, context.createFilter("(" + Constants.OBJECTCLASS + "=*)"), this);
            }
            catch (InvalidSyntaxException e) {
                throw new Error();
            }
            m_context = context;
        }
        m_tracker.open(true, true);
    }

    public void close() {
        ServiceTracker tracker;
        synchronized (m_lock) {
            if (m_context == null) {
                throw new IllegalStateException("Filter already closed.");
            }
            tracker = m_tracker;
            m_tracker = null;
            m_context = null;
        }
        tracker.close();
    }

    public boolean isApplicable(String clazz, String filter) {
        return getFilterData(clazz, filter) != null;
    }

    /** Returns a value object with the relevant filter data, or <code>null</code> if this filter was not valid. */
    private FilterData getFilterData(String clazz, String filter) {
        // something like:
        // (&(objectClass=foo.Bar)(&(|(!(service.ranking=*))(service.ranking<=9))(|(service.id=37)(org.apache.felix.dependencymanager.aspect=37))))
        if ((filter != null)
            && (filter.startsWith(FILTER_START)) // (&(objectClass=
            && (filter.endsWith(FILTER_END)) // ))))
            ) {
            int i0 = filter.indexOf(FILTER_SUBSTRING_0);
            if (i0 == -1) {
                return null;
            }
            int i1 = filter.indexOf(FILTER_SUBSTRING_1);
            if (i1 == -1 || i1 <= i0) {
                return null;
            }
            int i2 = filter.indexOf(FILTER_SUBSTRING_2);
            if (i2 == -1 || i2 <= i1) {
                return null;
            }
            long sid = Long.parseLong(filter.substring(i1 + FILTER_SUBSTRING_1.length(), i2));
            long sid2 = Long.parseLong(filter.substring(i2 + FILTER_SUBSTRING_2.length(), filter.length() - FILTER_END.length()));
            if (sid != sid2) {
                return null;
            }
            FilterData result = new FilterData();
            result.objectClass = filter.substring(FILTER_START.length(), i0);
            result.serviceId = sid;
            result.ranking = Integer.parseInt(filter.substring(i0 + FILTER_SUBSTRING_0.length(), i1));
            return result;
        }
        return null;
    }

    public List getAllServiceReferences(String clazz, String filter) {
        List /* <ServiceReference> */ result = new ArrayList();
        FilterData data = getFilterData(clazz, filter);
        if (data != null) {
          SortedSet /* <ServiceReference> */ list = null;
          synchronized (m_sidToServiceReferencesMap) {
            list = (SortedSet) m_sidToServiceReferencesMap.get(Long.valueOf(data.serviceId));
            if (list != null) {
              Iterator iterator = list.iterator();
              while (iterator.hasNext()) {
                ServiceReference reference = (ServiceReference) iterator.next();
                if (referenceMatchesObjectClass(reference, data.objectClass) && ServiceUtil.getRanking(reference) <= data.ranking) {
                  result.add(reference);
                }
              }
            }
      }
        }
        return result;
    }

    public void serviceChanged(ServiceEvent event) {
        List list = new ArrayList();
        ServiceReference reference = event.getServiceReference();
        Long sidObject = ServiceUtil.getServiceIdObject(reference);
        int ranking = ServiceUtil.getRanking(reference);
        String[] objectClasses = (String[]) reference.getProperty(Constants.OBJECTCLASS);
       
        synchronized (m_sidToObjectClassToRankingToListenersMap) {
          for (int i = 0; i < objectClasses.length; i++) {
            // handle each of the object classes separately since aspects only work on one object class at a time
            String objectClass = objectClasses[i];
            Map /* <String, Map<Integer, Collection<ServiceListener>>> */ objectClassToRankingToListenersMap = (SortedMap) m_sidToObjectClassToRankingToListenersMap.get(sidObject);
            if (objectClassToRankingToListenersMap != null) {
              SortedMap /* Integer, ServiceListener> */ rankingToListenersMap = (SortedMap) objectClassToRankingToListenersMap.get(objectClass);
              if (rankingToListenersMap != null) {
                Iterator iterator = rankingToListenersMap.entrySet().iterator();
                while (iterator.hasNext()) {
                  Entry entry = (Entry) iterator.next();
                  if (ranking <= ((Integer) entry.getKey()).intValue()) {
                    list.addAll((Collection)entry.getValue());
                  }
                }
              }
            }
          }
    }
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            ServiceListener listener = (ServiceListener) iterator.next();
            listener.serviceChanged(event);
        }
    }

    public void addServiceListener(ServiceListener listener, String filter) {
        FilterData data = getFilterData(null, filter);
        if (data != null) {
            Long sidObject = Long.valueOf(data.serviceId);
            synchronized (m_sidToObjectClassToRankingToListenersMap) {
              Map /* <String, Map<Integer, Collection<ServiceListener>>> */ objectClassToRankingToListenersMap = (SortedMap) m_sidToObjectClassToRankingToListenersMap.get(sidObject);
              if (objectClassToRankingToListenersMap == null) {
                objectClassToRankingToListenersMap = new TreeMap();
                m_sidToObjectClassToRankingToListenersMap.put(sidObject, objectClassToRankingToListenersMap);
              }
             
              SortedMap /* Integer, ServiceListener> */ rankingToListenersMap = (SortedMap) objectClassToRankingToListenersMap.get(data.objectClass);
                if (rankingToListenersMap == null) {
                    rankingToListenersMap = new TreeMap();
                    objectClassToRankingToListenersMap.put(data.objectClass, rankingToListenersMap);
                }             
             
              Collection listeners = (Collection) rankingToListenersMap.get(Integer.valueOf(data.ranking));
              if (listeners == null) {
                listeners = new ArrayList();
                rankingToListenersMap.put(Integer.valueOf(data.ranking), listeners);
              }
             
              listeners.add(listener);
                m_listenerToFilterMap.put(listener, filter);
            }
        }
    }

    public void removeServiceListener(ServiceListener listener) {
      synchronized (m_sidToObjectClassToRankingToListenersMap) {
        String filter = (String) m_listenerToFilterMap.remove(listener);
        if (filter != null) {
          // the listener does exist
          FilterData data = getFilterData(null, filter);
          if (data != null) {
            // this index is applicable
            Long sidObject = Long.valueOf(data.serviceId);
                  Map /* <String, Map<Integer, Collection<ServiceListener>>> */ objectClassToRankingToListenersMap = (SortedMap) m_sidToObjectClassToRankingToListenersMap.get(sidObject);
                  if (objectClassToRankingToListenersMap != null) {
                    SortedMap /* Integer, ServiceListener> */ rankingToListenersMap = (SortedMap) objectClassToRankingToListenersMap.get(data.objectClass);
                    if (rankingToListenersMap != null) {
                      Collection listeners = (Collection) rankingToListenersMap.get(Integer.valueOf(data.ranking));
                      if (listeners != null) {
                        listeners.remove(listener);
                      }
                      // cleanup
                      if (listeners.isEmpty()) {
                        rankingToListenersMap.remove(Integer.valueOf(data.ranking));
                      }
                      if (rankingToListenersMap.isEmpty()) {
                        objectClassToRankingToListenersMap.remove(data.objectClass);
                      }
                      if (objectClassToRankingToListenersMap.isEmpty()) {
                        m_sidToObjectClassToRankingToListenersMap.remove(sidObject);
                      }
                    }
                  }
          }
        }
    }
    }

    public Object addingService(ServiceReference reference) {
        BundleContext context;
        synchronized (m_lock) {
            context = m_context;
        }
        if (context != null) {
            return context.getService(reference);
        }
        else {
            throw new IllegalStateException("No valid bundle context.");
        }
    }
   
    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("AspectFilterIndex[");
        sb.append("S2R2L: " + m_sidToObjectClassToRankingToListenersMap.size());
        sb.append(", S2SR: " + m_sidToServiceReferencesMap.size());
        sb.append(", L2F: " + m_listenerToFilterMap.size());
        sb.append("]");
        return sb.toString();
    }
}
TOP

Related Classes of org.apache.felix.dm.impl.index.AspectFilterIndex

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.