You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2008/09/01 17:08:10 UTC

svn commit: r690991 [6/20] - in /cxf/sandbox/dosgi: ./ discovery/ discovery/local/ discovery/local/src/ discovery/local/src/main/ discovery/local/src/main/java/ discovery/local/src/main/java/org/ discovery/local/src/main/java/org/apache/ discovery/loca...

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/Felix.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/Felix.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/FelixBundle.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/FelixBundle.java?rev=690991&view=auto
==============================================================================
--- cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/FelixBundle.java (added)
+++ cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/FelixBundle.java Mon Sep  1 08:08:01 2008
@@ -0,0 +1,26 @@
+/*
+ * 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.framework;
+
+import org.osgi.framework.Bundle;
+
+abstract class FelixBundle implements Bundle
+{
+    /* package private */ abstract BundleInfo getInfo();
+}

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/FelixBundle.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/FelixBundle.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/FilterImpl.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/FilterImpl.java?rev=690991&view=auto
==============================================================================
--- cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/FilterImpl.java (added)
+++ cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/FilterImpl.java Mon Sep  1 08:08:01 2008
@@ -0,0 +1,316 @@
+/* 
+ * 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.framework;
+
+import java.io.CharArrayReader;
+import java.io.IOException;
+import java.util.*;
+import java.lang.ref.SoftReference;
+
+import org.apache.felix.framework.util.StringMap;
+import org.apache.felix.framework.util.ldap.*;
+import org.osgi.framework.*;
+
+/**
+ * This class implements an RFC 1960-based filter. The syntax of the
+ * filter string is the string representation of LDAP search filters
+ * as defined in RFC 1960. These filters are used to search for services
+ * and to track services using <tt>ServiceTracker</tt> objects.
+**/
+public class FilterImpl implements Filter
+{
+    private static final WeakHashMap m_programCache = new WeakHashMap();
+    private final ThreadLocal m_cache = new ThreadLocal();
+    private final Logger m_logger;
+    private final Object[] m_program;
+    private volatile String m_toString;
+
+// TODO: FilterImpl needs a logger, this is a hack for FrameworkUtil.
+    public FilterImpl(String expr) throws InvalidSyntaxException
+    {
+        this(null, expr);
+    }
+
+    /**
+     * Construct a filter for a given filter expression string.
+     * @param expr the filter expression string for the filter.
+    **/
+    public FilterImpl(Logger logger, String expr) throws InvalidSyntaxException
+    {
+        m_logger = logger;
+        if (expr == null)
+        {
+            throw new InvalidSyntaxException("Filter cannot be null", null);
+        }
+        Object[] program = null;
+        synchronized (m_programCache)
+        {
+            program = (Object[]) m_programCache.get(expr);
+        }
+        if (program == null)
+        {
+            CharArrayReader car = new CharArrayReader(expr.toCharArray());
+            LdapLexer lexer = new LdapLexer(car);
+            Parser parser = new Parser(lexer);
+            try
+            {
+                if (!parser.start())
+                {
+                    throw new InvalidSyntaxException(
+                        "Failed to parse LDAP query.", expr);
+                }
+            }
+            catch (ParseException ex)
+            {
+                throw new InvalidSyntaxException(
+                   ex.getMessage(), expr);
+            }
+            catch (IOException ex)
+            {
+                throw new InvalidSyntaxException(
+                    ex.getMessage(), expr);
+            }
+            program = parser.getProgram();
+            synchronized (m_programCache)
+            {
+                if (!m_programCache.containsKey(expr))
+                {
+                    m_programCache.put(expr, program);
+                }
+            }
+        }
+        m_program = program;
+    }
+
+    /**
+     * Compares the <tt>Filter</tt> object to another.
+     * @param o the object to compare this <tt>Filter</tt> against.
+     * @return If the other object is a <tt>Filter</tt> object, it
+     *         returns <tt>this.toString().equals(obj.toString())</tt>;
+     *         <tt>false</tt> otherwise.
+    **/
+    public boolean equals(Object o)
+    {
+        if (o == null)
+        {
+            return false;
+        }
+        else if (o instanceof Filter)
+        {
+            return toString().equals(o.toString());
+        }
+        return false;
+    }
+
+    /**
+     * Returns the hash code for the <tt>Filter</tt> object.
+     * @return The value <tt>this.toString().hashCode()</tt>.
+    **/
+    public int hashCode()
+    {
+        return toString().hashCode();
+    }
+
+    private boolean match(Dictionary dict, ServiceReference ref, boolean caseSensitive) 
+        throws IllegalArgumentException
+    {
+        SoftReference tupleRef = (SoftReference) m_cache.get();
+        Evaluator evaluator = null;
+        SimpleMapper mapper = null;
+        Object[] tuple = null;
+
+        if (tupleRef != null) 
+        {
+            tuple = (Object[]) tupleRef.get();
+        }
+
+        if (tuple == null) 
+        {
+            evaluator = new Evaluator(m_program);
+            mapper = new SimpleMapper();
+        }
+        else 
+        {
+            evaluator = (Evaluator) tuple[0];
+            mapper = (SimpleMapper) tuple[1];
+            m_cache.set(null);
+        }
+
+        try 
+        {
+            if (dict != null) 
+            {
+                mapper.setSource(dict, caseSensitive);
+            }
+            else 
+            {
+                mapper.setSource(ref);
+            }
+
+            return evaluator.evaluate(mapper);
+        } 
+        catch (AttributeNotFoundException ex)
+        {
+            log(Logger.LOG_DEBUG, "FilterImpl: Attribute not found.", ex);
+        }
+        catch (EvaluationException ex)
+        {
+            log(Logger.LOG_ERROR, "FilterImpl: " + toString(), ex);
+        }
+        finally 
+        {
+            if (dict != null) 
+            {
+                mapper.setSource(null, caseSensitive);
+            }
+            else 
+            {
+                mapper.setSource(null);
+            }
+            
+            if (tuple == null) 
+            {
+                m_cache.set(new SoftReference(new Object[] {evaluator, mapper}));
+            }
+            else
+            {
+                m_cache.set(tupleRef);
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Filter using a <tt>Dictionary</tt> object. The <tt>Filter</tt>
+     * is executed using the <tt>Dictionary</tt> object's keys and values.
+     * @param dict the <tt>Dictionary</tt> object whose keys and values
+     *             are used to determine a match.
+     * @return <tt>true</tt> if the <tt>Dictionary</tt> object's keys
+     *         and values match this filter; <tt>false</tt> otherwise.
+     * @throws IllegalArgumentException if the dictionary contains case
+     *         variants of the same key name.
+    **/
+    public boolean match(Dictionary dict)
+        throws IllegalArgumentException
+    {
+        return match(dict, null, false);
+    }
+
+    /**
+     * Filter using a service's properties. The <tt>Filter</tt>
+     * is executed using the properties of the referenced service.
+     * @param ref A reference to the service whose properties
+     *             are used to determine a match.
+     * @return <tt>true</tt> if the service's properties match this
+     *         filter; <tt>false</tt> otherwise.
+    **/
+    public boolean match(ServiceReference ref)
+    {
+        return match(null, ref, false);
+    }
+
+    public boolean matchCase(Dictionary dict)
+    {
+        return match(dict, null, true);
+    }
+
+    /**
+     * Returns the <tt>Filter</tt> object's filter string.
+     * @return Filter string.
+    **/
+    public String toString()
+    {
+        if (m_toString == null)
+        {
+            m_toString = new Evaluator(m_program).toStringInfix();
+        }
+        return m_toString;
+    }
+
+    private void log(int flag, String msg, Throwable th)
+    {
+        if (m_logger == null)
+        {
+            System.out.println(msg + ": " + th);
+        }
+        else
+        {
+            m_logger.log(flag, msg, th);
+        }
+    }
+
+    static class SimpleMapper implements Mapper
+    {
+        private ServiceReference m_ref = null;
+        private StringMap m_map = null;
+
+        public void setSource(ServiceReference ref)
+        {
+            m_ref = ref;
+            m_map = null;
+        }
+
+        public void setSource(Dictionary dict, boolean caseSensitive)
+        {
+            // Create a map if we don't have one.
+
+            if (m_map == null)
+            {
+                m_map = new StringMap();
+            }
+            else
+            {
+                m_map.clear();
+            }
+
+            // Set case comparison accordingly.
+            m_map.setCaseSensitive(caseSensitive);
+
+            // Put all dictionary entries into the map.
+            if (dict != null)
+            {
+                Enumeration keys = dict.keys();
+                while (keys.hasMoreElements())
+                {
+                    Object key = keys.nextElement();
+                    if (m_map.get(key) == null)
+                    {
+                        m_map.put(key, dict.get(key));
+                    }
+                    else
+                    {
+                        throw new IllegalArgumentException(
+                            "Duplicate attribute: " + key.toString());
+                    }
+                }
+            }
+            m_ref = null;
+        }
+
+        public Object lookup(String name)
+        {
+            if (m_map == null)
+            {
+                return m_ref.getProperty(name);
+            }
+            return m_map.get(name);
+        }
+    }
+}
\ No newline at end of file

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/FilterImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/FilterImpl.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/FindEntriesEnumeration.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/FindEntriesEnumeration.java?rev=690991&view=auto
==============================================================================
--- cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/FindEntriesEnumeration.java (added)
+++ cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/FindEntriesEnumeration.java Mon Sep  1 08:08:01 2008
@@ -0,0 +1,263 @@
+/* 
+ * 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.framework;
+
+import java.util.*;
+
+class FindEntriesEnumeration implements Enumeration
+{
+    private FelixBundle m_bundle = null;
+    private Enumeration m_enumeration = null;
+    private String m_path = null;
+    private String[] m_filePattern = null;
+    private boolean m_recurse = false;
+    private Object m_next = null;
+
+    public FindEntriesEnumeration(
+        FelixBundle bundle, String path, String filePattern, boolean recurse)
+    {
+        m_bundle = bundle;
+        m_path = path;
+        m_enumeration = (m_bundle.getInfo().getCurrentModule().getContentLoader().getContent() == null)
+            ? null : m_bundle.getInfo().getCurrentModule().getContentLoader().getContent().getEntries();
+        m_recurse = recurse;
+
+        // Sanity check the parameters.
+        if (m_path == null)
+        {
+            throw new IllegalArgumentException("The path for findEntries() cannot be null.");
+        }
+        // Strip leading '/' if present.
+        if ((m_path.length() > 0) && (m_path.charAt(0) == '/'))
+        {
+            m_path = m_path.substring(1);
+        }
+        // Add a '/' to the end if not present.
+        if ((m_path.length() > 0) && (m_path.charAt(m_path.length() - 1) != '/'))
+        {
+            m_path = m_path + "/";
+        }
+
+        // File pattern defaults to "*" if not specified.
+        filePattern = (filePattern == null) ? "*" : filePattern;
+
+        m_filePattern = parseSubstring(filePattern);
+
+        m_next = findNext();
+    }
+
+    public boolean hasMoreElements()
+    {
+        return (m_next != null);
+    }
+
+    public Object nextElement()
+    {
+        if (m_next == null)
+        {
+            throw new NoSuchElementException("No more entry paths.");
+        }
+        Object last = m_next;
+        m_next = findNext();
+        return last;
+    }
+
+    private Object findNext()
+    {
+        // This method filters the content entry enumeration, such that
+        // it only displays the contents of the directory specified by
+        // the path argument either recursively or not; much like using
+        // "ls -R" or "ls" to list the contents of a directory, respectively.
+        while ((m_enumeration != null) && m_enumeration.hasMoreElements())
+        {
+            // Get the next entry name.
+            String entryName = (String) m_enumeration.nextElement();
+            // Check to see if it is a descendent of the specified path.
+            if (!entryName.equals(m_path) && entryName.startsWith(m_path))
+            {
+                // If this is recursive search, then try to match any
+                // entry path that starts with the specified path;
+                // otherwise, only try to match children of the specified
+                // path and not any grandchild. This code uses the knowledge
+                // that content entries corresponding to directories end in '/'.
+                int idx = entryName.indexOf('/', m_path.length());
+                if (m_recurse || (idx < 0) || (idx == (entryName.length() - 1)))
+                {
+                    // Get the last element of the entry path, not including
+                    // the '/' if it is a directory.
+                    int endIdx = (entryName.charAt(entryName.length() - 1) == '/')
+                        ? entryName.length() - 1
+                        : entryName.length();
+                    int startIdx = (entryName.charAt(entryName.length() - 1) == '/')
+                        ? entryName.lastIndexOf('/', endIdx - 1) + 1
+                        : entryName.lastIndexOf('/', endIdx) + 1;
+                    String lastElement = entryName.substring(startIdx, endIdx);
+                    
+                    // See if the file pattern matches the last element of the path.
+                    if (checkSubstring(m_filePattern, lastElement))
+                    {
+                        // Convert entry name into an entry URL.
+                        return m_bundle.getInfo().getCurrentModule()
+                            .getContentLoader().getResourceFromContent(entryName);
+                    }
+                }
+            }
+        }
+
+        return null;
+    }
+
+    //
+    // The following substring-related code was lifted and modified
+    // from the LDAP parser code.
+    //
+
+    private static String[] parseSubstring(String target)
+    {
+        List pieces = new ArrayList();
+        StringBuffer ss = new StringBuffer();
+        // int kind = SIMPLE; // assume until proven otherwise
+        boolean wasStar = false; // indicates last piece was a star
+        boolean leftstar = false; // track if the initial piece is a star
+        boolean rightstar = false; // track if the final piece is a star
+
+        int idx = 0;
+
+        // We assume (sub)strings can contain leading and trailing blanks
+        for (;;)
+        {
+            if (idx >= target.length())
+            {
+                if (wasStar)
+                {
+                    // insert last piece as "" to handle trailing star
+                    rightstar = true;
+                }
+                else
+                {
+                    pieces.add(ss.toString());
+                    // accumulate the last piece
+                    // note that in the case of
+                    // (cn=); this might be
+                    // the string "" (!=null)
+                }
+                ss.setLength(0);
+                break;
+            }
+    
+            char c = target.charAt(idx++);
+            if (c == '*')
+            {
+                if (wasStar)
+                {
+                    // encountered two successive stars;
+                    // I assume this is illegal
+                    throw new IllegalArgumentException("Invalid filter string: " + target);
+                }
+                if (ss.length() > 0)
+                {
+                    pieces.add(ss.toString()); // accumulate the pieces
+                    // between '*' occurrences
+                }
+                ss.setLength(0);
+                // if this is a leading star, then track it
+                if (pieces.size() == 0)
+                {
+                    leftstar = true;
+                }
+                ss.setLength(0);
+                wasStar = true;
+            }
+            else
+            {
+                wasStar = false;
+                ss.append(c);
+            }
+        }
+        if (leftstar || rightstar || pieces.size() > 1)
+        {
+            // insert leading and/or trailing "" to anchor ends
+            if (rightstar)
+            {
+                pieces.add("");
+            }
+            if (leftstar)
+            {
+                pieces.add(0, "");
+            }
+        }
+
+        return (String[]) pieces.toArray(new String[pieces.size()]);
+    }
+
+    private static boolean checkSubstring(String[] pieces, String s)
+    {
+        // Walk the pieces to match the string
+        // There are implicit stars between each piece,
+        // and the first and last pieces might be "" to anchor the match.
+        // assert (pieces.length > 1)
+        // minimal case is <string>*<string>
+
+        boolean result = false;
+        int len = pieces.length;
+        int index = 0;
+
+        for (int i = 0; i < len; i++)
+        {
+            String piece = (String) pieces[i];
+            if (i == len - 1)
+            {
+                // this is the last piece
+                if (s.endsWith(piece))
+                {
+                    result = true;
+                }
+                else
+                {
+                    result = false;
+                }
+                break;
+            }
+            // initial non-star; assert index == 0
+            else if (i == 0)
+            {
+                if (!s.startsWith(piece))
+                {
+                    result = false;
+                    break;
+                }
+            }
+            // assert i > 0 && i < len-1
+            else
+            {
+                // Sure wish stringbuffer supported e.g. indexOf
+                index = s.indexOf(piece, index);
+                if (index < 0)
+                {
+                    result = false;
+                    break;
+                }
+            }
+            // start beyond the matching piece
+            index += piece.length();
+        }
+
+        return result;
+    }
+}
\ No newline at end of file

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/FindEntriesEnumeration.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/FindEntriesEnumeration.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/GetEntryPathsEnumeration.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/GetEntryPathsEnumeration.java?rev=690991&view=auto
==============================================================================
--- cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/GetEntryPathsEnumeration.java (added)
+++ cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/GetEntryPathsEnumeration.java Mon Sep  1 08:08:01 2008
@@ -0,0 +1,102 @@
+/* 
+ * 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.framework;
+
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+
+class GetEntryPathsEnumeration implements Enumeration
+{
+    private FelixBundle m_bundle = null;
+    private Enumeration m_enumeration = null;
+    private String m_path = null;
+    private Object m_next = null;
+
+    public GetEntryPathsEnumeration(FelixBundle bundle, String path)
+    {
+        m_bundle = bundle;
+        m_path = path;
+        m_enumeration = m_bundle.getInfo().getCurrentModule()
+            .getContentLoader().getContent().getEntries();
+
+        // Sanity check the parameters.
+        if (m_path == null)
+        {
+            throw new IllegalArgumentException("The path for findEntries() cannot be null.");
+        }
+        // Strip leading '/' if present.
+        if ((m_path.length() > 0) && (m_path.charAt(0) == '/'))
+        {
+            m_path = m_path.substring(1);
+        }
+        // Add a '/' to the end if not present.
+        if ((m_path.length() > 0) && (m_path.charAt(m_path.length() - 1) != '/'))
+        {
+            m_path = m_path + "/";
+        }
+
+        m_next = findNext();
+    }
+
+    public boolean hasMoreElements()
+    {
+        return (m_next != null);
+    }
+
+    public Object nextElement()
+    {
+        if (m_next == null)
+        {
+            throw new NoSuchElementException("No more entry paths.");
+        }
+        Object last = m_next;
+        m_next = findNext();
+        return last;
+    }
+
+    private Object findNext()
+    {
+        // This method filters the content entry enumeration, such that
+        // it only displays the contents of the directory specified by
+        // the path argument; much like using "ls" to list the contents
+        // of a directory.
+        while (m_enumeration.hasMoreElements())
+        {
+            // Get the next entry name.
+            String entryName = (String) m_enumeration.nextElement();
+            // Check to see if it is a descendent of the specified path.
+            if (!entryName.equals(m_path) && entryName.startsWith(m_path))
+            {
+                // Verify that it is a child of the path and not a
+                // grandchild by examining its remaining path length.
+                // This code uses the knowledge that content entries
+                // corresponding to directories end in '/'. It checks
+                // to see if the next occurrence of '/' is also the
+                // end of the string, which means that this entry
+                // represents a child directory of the path.
+                int idx = entryName.indexOf('/', m_path.length());
+                if ((idx < 0) || (idx == (entryName.length() - 1)))
+                {
+                    return entryName;
+                }
+            }
+        }
+        return null;
+    }
+}
\ No newline at end of file

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/GetEntryPathsEnumeration.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/GetEntryPathsEnumeration.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/Logger.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/Logger.java?rev=690991&view=auto
==============================================================================
--- cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/Logger.java (added)
+++ cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/Logger.java Mon Sep  1 08:08:01 2008
@@ -0,0 +1,299 @@
+/*
+ * 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.framework;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import org.osgi.framework.*;
+
+/**
+ * <p>
+ * This class mimics the standard OSGi <tt>LogService</tt> interface. An
+ * instance of this class is used by the framework for all logging. By default
+ * this class logs messages to standard out. The log level can be set to
+ * control the amount of logging performed, where a higher number results in
+ * more logging. A log level of zero turns off logging completely.
+ * </p>
+ * <p>
+ * The log levels match those specified in the OSGi Log Service (i.e., 1 = error,
+ * 2 = warning, 3 = information, and 4 = debug). The default value is 1.
+ * </p>
+ * <p>
+ * This class also uses the System Bundle's context to track log services
+ * and will use the highest ranking log service, if present, as a back end
+ * instead of printing to standard out. The class uses reflection to invoking
+ * the log service's method to avoid a dependency on the log interface.
+ * </p>
+**/
+public class Logger implements ServiceListener
+{
+    public static final int LOG_ERROR = 1;
+    public static final int LOG_WARNING = 2;
+    public static final int LOG_INFO = 3;
+    public static final int LOG_DEBUG = 4;
+
+    private int m_logLevel = 1;
+    private BundleContext m_context = null;
+
+    private final static int LOGGER_OBJECT_IDX = 0;
+    private final static int LOGGER_METHOD_IDX = 1;
+    private ServiceReference m_logRef = null;
+    private Object[] m_logger = null;
+
+    public Logger()
+    {
+    }
+
+    public final synchronized void setLogLevel(int i)
+    {
+        m_logLevel = i;
+    }
+
+    public final synchronized int getLogLevel()
+    {
+        return m_logLevel;
+    }
+
+    protected void setSystemBundleContext(BundleContext context)
+    {
+        // TODO: Find a way to log to a log service inside the framework.
+        // The issue is that we log messages while holding framework
+        // internal locks -- hence, when a log service calls back into 
+        // the framework (e.g., by loading a class) we might deadlock. 
+        // One instance of this problem is tracked in FELIX-536.
+        // For now we just disable logging to log services inside the
+        // framework. 
+
+        // m_context = context;
+        // startListeningForLogService();
+    }
+
+    public final void log(int level, String msg)
+    {
+        _log(null, level, msg, null);
+    }
+
+    public final void log(int level, String msg, Throwable throwable)
+    {
+        _log(null, level, msg, throwable);
+    }
+
+    public final void log(ServiceReference sr, int level, String msg)
+    {
+        _log(sr, level, msg, null);
+    }
+
+    public final void log(ServiceReference sr, int level, String msg, Throwable throwable)
+    {
+        _log(sr, level, msg, throwable);
+    }
+
+    protected void doLog(ServiceReference sr, int level, String msg, Throwable throwable)
+    {
+        String s = (sr == null) ? null : "SvcRef " + sr;
+        s = (s == null) ? msg : s + " " + msg;
+        s = (throwable == null) ? s : s + " (" + throwable + ")";
+        switch (level)
+        {
+            case LOG_DEBUG:
+                System.out.println("DEBUG: " + s);
+                break;
+            case LOG_ERROR:
+                System.out.println("ERROR: " + s);
+                if (throwable != null)
+                {
+                    if ((throwable instanceof BundleException) &&
+                        (((BundleException) throwable).getNestedException() != null))
+                    {
+                        throwable = ((BundleException) throwable).getNestedException();
+                    }
+                    throwable.printStackTrace();
+                }
+                break;
+            case LOG_INFO:
+                System.out.println("INFO: " + s);
+                break;
+            case LOG_WARNING:
+                System.out.println("WARNING: " + s);
+                break;
+            default:
+                System.out.println("UNKNOWN[" + level + "]: " + s);
+        }
+    }
+
+    private void _log(ServiceReference sr, int level, String msg, Throwable throwable)
+    {
+        // Save our own copy just in case it changes. We could try to do
+        // more conservative locking here, but let's be optimistic.
+        Object[] logger = m_logger;
+
+        if (m_logLevel >= level)
+        {
+            // Use the log service if available.
+            if (logger != null)
+            {
+                _logReflectively(logger, sr, level, msg, throwable);
+            }
+            // Otherwise, default logging action.
+            else
+            {
+                doLog(sr, level, msg, throwable);
+            }
+        }
+    }
+
+    private void _logReflectively(
+        Object[] logger, ServiceReference sr, int level, String msg, Throwable throwable)
+    {
+        if (logger != null)
+        {
+            Object[] params = {
+                sr, new Integer(level), msg, throwable
+            };
+            try
+            {
+                ((Method) logger[LOGGER_METHOD_IDX]).invoke(logger[LOGGER_OBJECT_IDX], params);
+            }
+            catch (InvocationTargetException ex)
+            {
+                System.err.println("Logger: " + ex);
+            }
+            catch (IllegalAccessException ex)
+            {
+                System.err.println("Logger: " + ex);
+            }
+        }
+    }
+
+    /**
+     * This method is called when the system bundle context is set;
+     * it simply adds a service listener so that the system bundle can track
+     * log services to be used as the back end of the logging mechanism. It also
+     * attempts to get an existing log service, if present, but in general
+     * there will never be a log service present since the system bundle is
+     * started before every other bundle.
+    **/
+    private synchronized void startListeningForLogService()
+    {
+        // Add a service listener for log services.
+        try
+        {
+            m_context.addServiceListener(
+                this, "(objectClass=org.osgi.service.log.LogService)");
+        }
+        catch (InvalidSyntaxException ex) {
+            // This will never happen since the filter is hard coded.
+        }
+        // Try to get an existing log service.
+        m_logRef = m_context.getServiceReference("org.osgi.service.log.LogService");
+        // Get the service object if available and set it in the logger.
+        if (m_logRef != null)
+        {
+            setLogger(m_context.getService(m_logRef));
+        }
+    }
+
+    /**
+     * This method implements the callback for the ServiceListener interface.
+     * It is public as a byproduct of implementing the interface and should
+     * not be called directly. This method tracks run-time changes to log
+     * service availability. If the log service being used by the framework's
+     * logging mechanism goes away, then this will try to find an alternative.
+     * If a higher ranking log service is registered, then this will switch
+     * to the higher ranking log service.
+    **/
+    public final synchronized void serviceChanged(ServiceEvent event)
+    {
+        // If no logger is in use, then grab this one.
+        if ((event.getType() == ServiceEvent.REGISTERED) && (m_logRef == null))
+        {
+            m_logRef = event.getServiceReference();
+            // Get the service object and set it in the logger.
+            setLogger(m_context.getService(m_logRef));
+        }
+        // If a logger is in use, but this one has a higher ranking, then swap
+        // it for the existing logger.
+        else if ((event.getType() == ServiceEvent.REGISTERED) && (m_logRef != null))
+        {
+            ServiceReference ref =
+                m_context.getServiceReference("org.osgi.service.log.LogService");
+            if (!ref.equals(m_logRef))
+            {
+                m_context.ungetService(m_logRef);
+                m_logRef = ref;
+                setLogger(m_context.getService(m_logRef));
+            }
+
+        }
+        // If the current logger is going away, release it and try to
+        // find another one.
+        else if ((event.getType() == ServiceEvent.UNREGISTERING) &&
+            m_logRef.equals(event.getServiceReference()))
+        {
+            // Unget the service object.
+            m_context.ungetService(m_logRef);
+            // Try to get an existing log service.
+            m_logRef = m_context.getServiceReference(
+                "org.osgi.service.log.LogService");
+            // Get the service object if available and set it in the logger.
+            if (m_logRef != null)
+            {
+                setLogger(m_context.getService(m_logRef));
+            }
+            else
+            {
+                setLogger(null);
+            }
+        }
+    }
+
+    /**
+     * This method sets the new log service object. It also caches the method to
+     * invoke. The service object and method are stored in array to optimistically
+     * eliminate the need to locking when logging.
+    **/
+    private void setLogger(Object logObj)
+    {
+        if (logObj == null)
+        {
+            m_logger = null;
+        }
+        else
+        {
+            Class[] formalParams = {
+                ServiceReference.class,
+                Integer.TYPE,
+                String.class,
+                Throwable.class
+            };
+
+            try
+            {
+                Method logMethod = logObj.getClass().getMethod("log", formalParams);
+                logMethod.setAccessible(true);
+                m_logger = new Object[] { logObj, logMethod };
+            }
+            catch (NoSuchMethodException ex)
+            {
+                System.err.println("Logger: " + ex);
+                m_logger = null;
+            }
+        }
+    }
+}
\ No newline at end of file

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/Logger.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/Logger.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/PackageAdminActivator.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/PackageAdminActivator.java?rev=690991&view=auto
==============================================================================
--- cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/PackageAdminActivator.java (added)
+++ cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/PackageAdminActivator.java Mon Sep  1 08:08:01 2008
@@ -0,0 +1,47 @@
+/* 
+ * 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.framework;
+
+import org.osgi.framework.*;
+
+class PackageAdminActivator implements BundleActivator
+{
+    private Felix m_felix = null;
+    private ServiceRegistration m_reg = null;
+    private PackageAdminImpl m_packageAdmin = null;
+
+    public PackageAdminActivator(Felix felix)
+    {
+        m_felix = felix;
+    }
+
+    public void start(BundleContext context) throws Exception
+    {
+        m_packageAdmin = new PackageAdminImpl(m_felix);
+        m_reg = context.registerService(
+            org.osgi.service.packageadmin.PackageAdmin.class.getName(),
+            m_packageAdmin, null);
+    }
+
+    public void stop(BundleContext context) throws Exception
+    {
+        m_reg.unregister();
+        m_packageAdmin.stop();
+    }
+}
\ No newline at end of file

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/PackageAdminActivator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/PackageAdminActivator.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java?rev=690991&view=auto
==============================================================================
--- cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java (added)
+++ cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java Mon Sep  1 08:08:01 2008
@@ -0,0 +1,309 @@
+/* 
+ * 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.framework;
+
+import java.util.*;
+
+import org.apache.felix.framework.util.VersionRange;
+import org.osgi.framework.*;
+import org.osgi.service.packageadmin.*;
+
+class PackageAdminImpl implements PackageAdmin, Runnable
+{
+    private static final Comparator COMPARATOR = new Comparator() {
+        public int compare(Object o1, Object o2)
+        {
+            // Reverse arguments to sort in descending order.
+            return ((ExportedPackage) o2).getVersion().compareTo(
+                ((ExportedPackage) o1).getVersion());
+        }
+    };
+
+    private Felix m_felix = null;
+    private Bundle[][] m_reqBundles = null;
+    private Bundle m_systemBundle = null;
+    private Thread m_thread = null;
+
+    public PackageAdminImpl(Felix felix)
+    {
+        m_felix = felix;
+        m_systemBundle = m_felix.getBundle(0);
+
+        // Start a thread to perform asynchronous package refreshes.
+        m_thread = new Thread(this, "FelixPackageAdmin");
+        m_thread.setDaemon(true);
+        m_thread.start();
+    }
+
+    /**
+     * Stops the FelixPackageAdmin thread on system shutdown. Shutting down the
+     * thread explicitly is required in the embedded case, where Felix may be
+     * stopped without the Java VM being stopped. In this case the
+     * FelixPackageAdmin thread must be stopped explicitly.
+     * <p>
+     * This method is called by the
+     * {@link PackageAdminActivator#stop(BundleContext)} method.
+     */
+    synchronized void stop()
+    {
+        if (m_thread != null)
+        {
+            // Null thread variable to signal to the thread that
+            // we want it to exit.
+            m_thread = null;
+            
+            // Wake up the thread, if it is currently in the wait() state
+            // for more work.
+            notifyAll();
+        }
+    }
+    
+    /**
+     * Returns the bundle associated with this class if the class was
+     * loaded from a bundle, otherwise returns null.
+     * 
+     * @param clazz the class for which to determine its associated bundle.
+     * @return the bundle associated with the specified class, otherwise null.
+    **/
+    public Bundle getBundle(Class clazz)
+    {
+        return m_felix.getBundle(clazz);
+    }
+
+    /**
+     * Returns all bundles that have a specified symbolic name and whose
+     * version is in the specified version range. If no version range is
+     * specified, then all bundles with the specified symbolic name are
+     * returned. The array is sorted in descending version order.
+     * 
+     * @param symbolicName the target symbolic name.
+     * @param versionRange the target version range.
+     * @return an array of matching bundles sorted in descending version order.
+    **/
+    public Bundle[] getBundles(String symbolicName, String versionRange)
+    {
+// TODO: PACKAGEADMIN - This could be made more efficient by reducing object creation.
+        VersionRange vr = (versionRange == null)
+            ? null : VersionRange.parse(versionRange);
+        Bundle[] bundles = m_felix.getBundles();
+        List list = new ArrayList();
+        for (int i = 0; (bundles != null) && (i < bundles.length); i++)
+        {
+            String sym = (String) ((FelixBundle) bundles[i])
+                .getInfo().getCurrentHeader().get(Constants.BUNDLE_SYMBOLICNAME);
+            if ((sym != null) && sym.equals(symbolicName))
+            {
+                String s = (String) ((FelixBundle) bundles[i])
+                    .getInfo().getCurrentHeader().get(Constants.BUNDLE_VERSION);
+                Version v = (s == null) ? new Version("0.0.0") : new Version(s);
+                if ((vr == null) || vr.isInRange(v))
+                {
+                    list.add(bundles[i]);
+                }
+            }
+        }
+        if (list.size() == 0)
+        {
+            return null;
+        }
+        bundles = (Bundle[]) list.toArray(new Bundle[list.size()]);
+        Arrays.sort(bundles,new Comparator() {
+            public int compare(Object o1, Object o2)
+            {
+                String s1 = (String) ((FelixBundle) o1)
+                    .getInfo().getCurrentHeader().get(Constants.BUNDLE_VERSION);
+                String s2 = (String) ((FelixBundle) o2)
+                    .getInfo().getCurrentHeader().get(Constants.BUNDLE_VERSION);
+                Version v1 = (s1 == null) ? new Version("0.0.0") : new Version(s1);
+                Version v2 = (s2 == null) ? new Version("0.0.0") : new Version(s2);
+                // Compare in reverse order to get descending sort.
+                return v2.compareTo(v1);
+            }
+        });
+        return bundles;
+    }
+
+    public int getBundleType(Bundle bundle)
+    {
+        return 0;
+    }
+
+    /**
+     * Returns the exported package associated with the specified
+     * package name. If there are more than one version of the package
+     * being exported, then the highest version is returned.
+     *
+     * @param name the name of the exported package to find.
+     * @return the exported package or null if no matching package was found.
+    **/
+    public ExportedPackage getExportedPackage(String name)
+    {
+        // Get all versions of the exported package.
+        ExportedPackage[] pkgs = m_felix.getExportedPackages(name);
+        // If there are no versions exported, then return null.
+        if ((pkgs == null) || (pkgs.length == 0))
+        {
+            return null;
+        }
+        // Sort the exported versions.
+        Arrays.sort(pkgs, COMPARATOR);
+        // Return the highest version.
+        return pkgs[0];
+    }
+
+    public ExportedPackage[] getExportedPackages(String name)
+    {
+        ExportedPackage[] pkgs = m_felix.getExportedPackages(name);
+        return ((pkgs == null) || pkgs.length == 0) ? null : pkgs;
+    }
+
+    /**
+     * Returns the packages exported by the specified bundle.
+     *
+     * @param bundle the bundle whose exported packages are to be returned.
+     * @return an array of packages exported by the bundle or null if the
+     *         bundle does not export any packages.
+    **/
+    public ExportedPackage[] getExportedPackages(Bundle bundle)
+    {
+        return m_felix.getExportedPackages(bundle);
+    }
+
+    /**
+     * The OSGi specification states that refreshing packages is
+     * asynchronous; this method simply notifies the package admin
+     * thread to do a refresh.
+     * @param bundles array of bundles to refresh or <tt>null</tt> to refresh
+     *                any bundles in need of refreshing.
+    **/
+    public synchronized void refreshPackages(Bundle[] bundles)
+        throws SecurityException
+    {
+        Object sm = System.getSecurityManager();
+        
+        if (sm != null)
+        {
+            ((SecurityManager) sm).checkPermission(
+                new AdminPermission(m_systemBundle, AdminPermission.RESOLVE));
+        }
+        
+        // Save our request parameters and notify all.
+        if (m_reqBundles == null)
+        {
+            m_reqBundles = new Bundle[][] { bundles };
+        }
+        else
+        {
+            Bundle[][] newReqBundles = new Bundle[m_reqBundles.length + 1][];
+            System.arraycopy(m_reqBundles, 0,
+                newReqBundles, 0, m_reqBundles.length);
+            newReqBundles[m_reqBundles.length] = bundles;
+            m_reqBundles = newReqBundles;
+        }
+        notifyAll();
+    }
+
+    /**
+     * The OSGi specification states that package refreshes happen
+     * asynchronously; this is the run() method for the package
+     * refreshing thread.
+    **/
+    public void run()
+    {
+        // This thread loops forever, thus it should
+        // be a daemon thread.
+        Bundle[] bundles = null;
+        while (true)
+        {
+            synchronized (this)
+            {
+                // Wait for a refresh request.
+                while (m_reqBundles == null)
+                {
+                    // Terminate the thread if requested to do so (see stop()).
+                    if (m_thread == null)
+                    {
+                        return;
+                    }
+                    
+                    try
+                    {
+                        wait();
+                    }
+                    catch (InterruptedException ex)
+                    {
+                    }
+                }
+
+                // Get the bundles parameter for the current refresh request.
+                bundles = m_reqBundles[0];
+            }
+
+            // Perform refresh.
+            m_felix.refreshPackages(bundles);
+
+            // Remove the first request since it is now completed.
+            synchronized (this)
+            {
+                if (m_reqBundles.length == 1)
+                {
+                    m_reqBundles = null;
+                }
+                else
+                {
+                    Bundle[][] newReqBundles = new Bundle[m_reqBundles.length - 1][];
+                    System.arraycopy(m_reqBundles, 1,
+                        newReqBundles, 0, m_reqBundles.length - 1);
+                    m_reqBundles = newReqBundles;
+                }
+            }
+        }
+    }
+
+    public boolean resolveBundles(Bundle[] bundles)
+    {
+        Object sm = System.getSecurityManager();
+        
+        if (sm != null)
+        {
+            ((SecurityManager) sm).checkPermission(
+                new AdminPermission(m_systemBundle, AdminPermission.RESOLVE));
+        }
+        
+        return m_felix.resolveBundles(bundles);
+    }
+
+    public RequiredBundle[] getRequiredBundles(String symbolicName)
+    {
+        // TODO: Implement PackageAdmin.getRequiredBundles()
+        return null;
+    }
+
+    public Bundle[] getFragments(Bundle bundle)
+    {
+        // TODO: Implement PackageAdmin.getFragments()
+        return null;
+    }
+
+    public Bundle[] getHosts(Bundle bundle)
+    {
+        // TODO: Implement PackageAdmin.getHosts()
+        return null;
+    }
+}
\ No newline at end of file

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/ServiceReferenceImpl.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/ServiceReferenceImpl.java?rev=690991&view=auto
==============================================================================
--- cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/ServiceReferenceImpl.java (added)
+++ cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/ServiceReferenceImpl.java Mon Sep  1 08:08:01 2008
@@ -0,0 +1,195 @@
+/*
+ * 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.framework;
+
+import org.apache.felix.framework.util.Util;
+import org.apache.felix.moduleloader.IModule;
+import org.apache.felix.moduleloader.IWire;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+
+class ServiceReferenceImpl implements ServiceReference
+{
+    private ServiceRegistrationImpl m_registration = null;
+    private Bundle m_bundle = null;
+
+    public ServiceReferenceImpl(ServiceRegistrationImpl reg, Bundle bundle)
+    {
+        m_registration = reg;
+        m_bundle = bundle;
+    }
+
+    protected ServiceRegistrationImpl getServiceRegistration()
+    {
+        return m_registration;
+    }
+
+    public Object getProperty(String s)
+    {
+        return m_registration.getProperty(s);
+    }
+
+    public String[] getPropertyKeys()
+    {
+    	return m_registration.getPropertyKeys();
+    }
+
+    public Bundle getBundle()
+    {
+        // The spec says that this should return null if
+        // the service is unregistered.
+        return (m_registration.isValid()) ? m_bundle : null;
+    }
+
+    public Bundle[] getUsingBundles()
+    {
+        return m_registration.getUsingBundles();
+    }
+
+    public boolean equals(Object obj)
+    {
+        try
+        {
+            ServiceReferenceImpl ref = (ServiceReferenceImpl) obj;
+            return ref.m_registration == m_registration;
+        }
+        catch (ClassCastException ex)
+        {
+            // Ignore and return false.
+        }
+        catch (NullPointerException ex)
+        {
+            // Ignore and return false.
+        }
+
+        return false;
+    }
+
+    public int hashCode()
+    {
+        if (m_registration.getReference() != null)
+        {
+            if (m_registration.getReference() != this)
+            {
+                return m_registration.getReference().hashCode();
+            }
+            return super.hashCode();
+        }
+        return 0;
+    }
+
+    public String toString()
+    {
+        String[] ocs = (String[]) getProperty("objectClass");
+        String oc = "[";
+        for(int i = 0; i < ocs.length; i++)
+        {
+            oc = oc + ocs[i];
+            if (i < ocs.length - 1)
+                oc = oc + ", ";
+        }
+        oc = oc + "]";
+        return oc;
+    }
+
+    public boolean isAssignableTo(Bundle requester, String className)
+    {
+        // Always return true if the requester is the same as the provider.
+        if (requester == m_bundle)
+        {
+            return true;
+        }
+
+        // Boolean flag.
+        boolean allow = true;
+        // Get the package.
+        String pkgName =
+            Util.getClassPackage(className);
+        IModule requesterModule = 
+            ((FelixBundle) requester).getInfo().getCurrentModule();
+        // Get package wiring from service requester.
+        IWire requesterWire = Util.getWire(requesterModule, pkgName);
+
+        // There are three situations that may occur here:
+        //   1. The requester does not have a wire for the package.
+        //   2. The provider does not have a wire for the package.
+        //   3. Both have a wire for the package.
+        // For case 1, we do not filter the service reference since we
+        // assume that the bundle is using reflection or that it won't
+        // use that class at all since it does not import it. For
+        // case 2, we have to try to load the class from the class
+        // loader of the service object and then compare the class
+        // loaders to determine if we should filter the service
+        // refernce. In case 3, we simply compare the exporting
+        // modules from the package wiring to determine if we need
+        // to filter the service reference.
+
+        // Case 1: Always include service reference.
+        if (requesterWire == null)
+        {
+            return allow;
+        }
+
+        // Get package wiring from service provider.
+        IModule providerModule = 
+            ((FelixBundle) m_bundle).getInfo().getCurrentModule();
+        IWire providerWire = Util.getWire(providerModule, pkgName);
+        
+        // Case 2: Only include service reference if the service
+        // object uses the same class as the requester.
+        if (providerWire == null)
+        {
+            // If the provider is not the exporter of the requester's package,
+            // then try to use the service registration to see if the requester's
+            // class is accessible.
+            if (!((FelixBundle) m_bundle).getInfo().hasModule(requesterWire.getExporter()))
+            {
+                try
+                {
+                    // Load the class from the requesting bundle.
+                    Class requestClass = requesterModule.getClass(className);
+                    // Get the service registration and ask it to check
+                    // if the service object is assignable to the requesting
+                    // bundle's class.
+                    allow = getServiceRegistration().isClassAccessible(requestClass);
+                }
+                catch (Exception ex)
+                {
+                    // This should not happen, filter to be safe.
+                    allow = false;
+                }
+            }
+            else
+            {
+                // O.k. the provider is the exporter of the requester's package, now check
+                // if the requester is wired to the latest version of the provider, if so
+                // then allow else don't (the provider has been updated but not refreshed).
+                allow = providerModule == requesterWire.getExporter();
+            }
+        }
+        // Case 3: Include service reference if the wires have the
+        // same source module.
+        else
+        {
+            allow = providerWire.getExporter().equals(requesterWire.getExporter());
+        }
+
+        return allow;
+    }
+}
\ No newline at end of file

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/ServiceReferenceImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/ServiceReferenceImpl.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java?rev=690991&view=auto
==============================================================================
--- cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java (added)
+++ cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java Mon Sep  1 08:08:01 2008
@@ -0,0 +1,322 @@
+/* 
+ * 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.framework;
+
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.felix.framework.util.StringMap;
+import org.apache.felix.framework.util.Util;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+
+class ServiceRegistrationImpl implements ServiceRegistration
+{
+    // Service registry.
+    private ServiceRegistry m_registry = null;
+    // Bundle implementing the service.
+    private Bundle m_bundle = null;
+    // Interfaces associated with the service object.
+    private String[] m_classes = null;
+    // Service Id associated with the service object.
+    private Long m_serviceId = null;
+    // Service object.
+    private Object m_svcObj = null;
+    // Service factory interface.
+    private ServiceFactory m_factory = null;
+    // Associated property dictionary.
+    private Map m_propMap =  new StringMap(false);
+    // Re-usable service reference.
+    private ServiceReferenceImpl m_ref = null;
+    // Flag indicating that we are unregistering.
+    private boolean m_isUnregistering = false;
+    
+    public ServiceRegistrationImpl(
+        ServiceRegistry registry, Bundle bundle,
+        String[] classes, Long serviceId,
+        Object svcObj, Dictionary dict)
+    {
+        m_registry = registry;
+        m_bundle = bundle;
+        m_classes = classes;
+        m_serviceId = serviceId;
+        m_svcObj = svcObj;
+        m_factory = (m_svcObj instanceof ServiceFactory)
+            ? (ServiceFactory) m_svcObj : null;
+
+        initializeProperties(dict);
+
+        // This reference is the "standard" reference for this
+        // service and will always be returned by getReference().
+        // Since all reference to this service are supposed to
+        // be equal, we use the hashcode of this reference for
+        // a references to this service in ServiceReference.
+        m_ref = new ServiceReferenceImpl(this, m_bundle);
+        
+    }
+
+    protected synchronized boolean isValid()
+    {
+        return (m_svcObj != null);
+    }
+
+    protected synchronized void invalidate()
+    {
+        m_svcObj = null;
+    }
+
+    public ServiceReference getReference()
+    {
+        return m_ref;
+    }
+
+    public void setProperties(Dictionary dict)
+    {
+        // Make sure registration is valid.
+        if (!isValid())
+        {
+            throw new IllegalStateException(
+                "The service registration is no longer valid.");
+        }
+        // Set the properties.
+        initializeProperties(dict);
+        
+        // Tell registry about it.
+        m_registry.servicePropertiesModified(this);
+    }
+
+    public void unregister()
+    {
+        synchronized (this)
+        {
+            if (!isValid() || m_isUnregistering)
+            {
+                throw new IllegalStateException("Service already unregistered.");
+            }
+            m_isUnregistering = true;
+        }
+        
+        removeHook();
+        m_registry.unregisterService(m_bundle, this);
+        
+        synchronized (this)
+        {
+            m_svcObj = null;
+            m_factory = null;
+        }
+    }
+
+    private void removeHook() {
+        m_registry.removeHook(m_svcObj);
+    }
+    
+    //
+    // Utility methods.
+    //
+
+    /**
+     * This method determines if the class loader of the service object
+     * has access to the specified class.
+     * @param clazz the class to test for reachability.
+     * @return <tt>true</tt> if the specified class is reachable from the
+     *         service object's class loader, <tt>false</tt> otherwise.
+    **/
+    protected boolean isClassAccessible(Class clazz)
+    {
+        try
+        {
+            // Try to load from the service object or service factory class.
+            Class sourceClass = (m_factory != null)
+                ? m_factory.getClass() : m_svcObj.getClass();
+            Class targetClass = Util.loadClassUsingClass(sourceClass, clazz.getName());
+            return (targetClass == clazz);
+        }
+        catch (Exception ex)
+        {
+            // Ignore this and return false.
+        }
+        return false;
+    }
+
+    protected Object getProperty(String key)
+    {
+        return m_propMap.get(key);
+    }
+
+    private transient ArrayList m_list = new ArrayList();
+
+    protected String[] getPropertyKeys()
+    {
+        synchronized (m_propMap)
+        {
+            m_list.clear();
+            Iterator i = m_propMap.entrySet().iterator();
+            while (i.hasNext())
+            {
+                Map.Entry entry = (Map.Entry) i.next();
+                m_list.add(entry.getKey());
+            }
+            return (String[]) m_list.toArray(new String[m_list.size()]);
+        }
+    }
+
+    protected Bundle[] getUsingBundles()
+    {
+        return m_registry.getUsingBundles(m_ref);
+    }
+
+    protected Object getService(Bundle acqBundle)
+    {
+        // If the service object is a service factory, then
+        // let it create the service object.
+        if (m_factory != null)
+        {
+            try
+            {
+                if (System.getSecurityManager() != null)
+                {
+                    return AccessController.doPrivileged(
+                        new ServiceFactoryPrivileged(acqBundle, null));
+                }
+                else
+                {
+                    return getFactoryUnchecked(acqBundle);
+                }
+            }
+            catch (Exception ex)
+            {
+                m_registry.getLogger().log(
+                    Logger.LOG_ERROR, "ServiceRegistrationImpl: Error getting service.", ex);
+                return null;
+            }
+        }
+        else
+        {
+            return m_svcObj;
+        }
+    }
+
+    protected void ungetService(Bundle relBundle, Object svcObj)
+    {
+        // If the service object is a service factory, then
+        // let it release the service object.
+        if (m_factory != null)
+        {
+            try
+            {
+                if (System.getSecurityManager() != null)
+                {
+                    AccessController.doPrivileged(
+                        new ServiceFactoryPrivileged(relBundle, svcObj));
+                }
+                else
+                {
+                    ungetFactoryUnchecked(relBundle, svcObj);
+                }
+            }
+            catch (Exception ex)
+            {
+                m_registry.getLogger().log(
+                    Logger.LOG_ERROR, "ServiceRegistrationImpl: Error ungetting service.", ex);
+            }
+        }
+    }
+
+    private void initializeProperties(Dictionary dict)
+    {
+        synchronized (m_propMap)
+        {
+            m_propMap.clear();
+    
+            if (dict != null)
+            {
+                Enumeration keys = dict.keys();
+                while (keys.hasMoreElements())
+                {
+                    Object key = keys.nextElement();
+                    m_propMap.put(key, dict.get(key));
+                }
+            }
+    
+            // Add the framework assigned properties.
+            m_propMap.put(Constants.OBJECTCLASS, m_classes);
+            m_propMap.put(Constants.SERVICE_ID, m_serviceId);
+        }
+    }
+
+    private Object getFactoryUnchecked(Bundle bundle)
+    {
+        Object svcObj = m_factory.getService(bundle, this);
+        if (svcObj != null)
+        {
+            for (int i = 0; i < m_classes.length; i++)
+            {
+                Class clazz = Util.loadClassUsingClass(svcObj.getClass(), m_classes[i]);
+                if ((clazz == null) || !clazz.isAssignableFrom(svcObj.getClass()))
+                {
+                    return null;
+                }
+            }
+        }
+        return svcObj;
+    }
+
+    private void ungetFactoryUnchecked(Bundle bundle, Object svcObj)
+    {
+        m_factory.ungetService(bundle, this, svcObj);
+    }
+
+    /**
+     * This simple class is used to ensure that when a service factory
+     * is called, that no other classes on the call stack interferes
+     * with the permissions of the factory itself.
+    **/
+    private class ServiceFactoryPrivileged implements PrivilegedExceptionAction
+    {
+        private Bundle m_bundle = null;
+        private Object m_svcObj = null;
+
+        public ServiceFactoryPrivileged(Bundle bundle, Object svcObj)
+        {
+            m_bundle = bundle;
+            m_svcObj = svcObj;
+        }
+
+        public Object run() throws Exception
+        {
+            if (m_svcObj == null)
+            {
+                return getFactoryUnchecked(m_bundle);
+            }
+            else
+            {
+                ungetFactoryUnchecked(m_bundle, m_svcObj);
+            }
+            return null;
+        }
+    }
+}
\ No newline at end of file

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date