Package org.apache.felix.framework.security.condpermadmin

Source Code of org.apache.felix.framework.security.condpermadmin.ConditionalPermissionInfoImpl

/*
* 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.security.condpermadmin;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.StringTokenizer;

import org.apache.felix.framework.security.util.Permissions;
import org.osgi.service.condpermadmin.ConditionInfo;
import org.osgi.service.condpermadmin.ConditionalPermissionInfo;
import org.osgi.service.permissionadmin.PermissionInfo;

/**
* Simple storage class for condperminfos. Additionally, this class can be used
* to encode and decode infos.
*/
public final class ConditionalPermissionInfoImpl implements
    ConditionalPermissionInfo
{
    private static final Random RANDOM = new Random();
    static final ConditionInfo[] CONDITION_INFO = new ConditionInfo[0];
    static final PermissionInfo[] PERMISSION_INFO = new PermissionInfo[0];
    private final Object m_lock = new Object();
    private final String m_name;
    private final boolean m_allow;
    private volatile ConditionalPermissionAdminImpl m_cpai;
    private ConditionInfo[] m_conditions;
    private PermissionInfo[] m_permissions;
   
    private int parseConditionInfo(char[] encoded, int idx, List conditions) {
        String type;
        String[] args;
        try {
            int pos = idx;

            /* skip whitespace */
            while (Character.isWhitespace(encoded[pos])) {
                    pos++;
            }

            /* the first character must be '[' */
            if (encoded[pos] != '[') {
                    throw new IllegalArgumentException("expecting open bracket");
            }
            pos++;

            /* skip whitespace */
            while (Character.isWhitespace(encoded[pos])) {
                    pos++;
            }

            /* type is not quoted or encoded */
            int begin = pos;
            while (!Character.isWhitespace(encoded[pos])
                            && (encoded[pos] != ']')) {
                    pos++;
            }
            if (pos == begin || encoded[begin] == '"') {
                    throw new IllegalArgumentException("expecting type");
            }
            type = new String(encoded, begin, pos - begin);

            /* skip whitespace */
            while (Character.isWhitespace(encoded[pos])) {
                    pos++;
            }

            /* type may be followed by args which are quoted and encoded */
            ArrayList argsList = new ArrayList();
            while (encoded[pos] == '"') {
                    pos++;
                    begin = pos;
                    while (encoded[pos] != '"') {
                            if (encoded[pos] == '\\') {
                                    pos++;
                            }
                            pos++;
                    }
                    argsList.add(unescapeString(encoded, begin, pos));
                    pos++;

                    if (Character.isWhitespace(encoded[pos])) {
                            /* skip whitespace */
                            while (Character.isWhitespace(encoded[pos])) {
                                    pos++;
                            }
                    }
            }
            args = (String[]) argsList
                            .toArray(new String[argsList.size()]);

            /* the final character must be ']' */
            char c = encoded[pos++];
            if (c != ']') {
                    throw new IllegalArgumentException("expecting close bracket");
            }
            conditions.add(new ConditionInfo(type, args));
            return pos;
    }
    catch (ArrayIndexOutOfBoundsException e) {
            throw new IllegalArgumentException("parsing terminated abruptly");
    }
    }
   
    private int parsePermissionInfo(char[] encoded, int idx, List permissions)
    {
        String parsedType = null;
        String parsedName = null;
        String parsedActions = null;
        try {
                int pos = idx;

                /* skip whitespace */
                while (Character.isWhitespace(encoded[pos])) {
                        pos++;
                }

                /* the first character must be '(' */
                if (encoded[pos] != '(') {
                        throw new IllegalArgumentException("expecting open parenthesis");
                }
                pos++;

                /* skip whitespace */
                while (Character.isWhitespace(encoded[pos])) {
                        pos++;
                }

                /* type is not quoted or encoded */
                int begin = pos;
                while (!Character.isWhitespace(encoded[pos])
                                && (encoded[pos] != ')')) {
                        pos++;
                }
                if (pos == begin || encoded[begin] == '"') {
                        throw new IllegalArgumentException("expecting type");
                }
                parsedType = new String(encoded, begin, pos - begin);

                /* skip whitespace */
                while (Character.isWhitespace(encoded[pos])) {
                        pos++;
                }

                /* type may be followed by name which is quoted and encoded */
                if (encoded[pos] == '"') {
                        pos++;
                        begin = pos;
                        while (encoded[pos] != '"') {
                                if (encoded[pos] == '\\') {
                                        pos++;
                                }
                                pos++;
                        }
                        parsedName = unescapeString(encoded, begin, pos);
                        pos++;

                        if (Character.isWhitespace(encoded[pos])) {
                                /* skip whitespace */
                                while (Character.isWhitespace(encoded[pos])) {
                                        pos++;
                                }

                                /*
                                 * name may be followed by actions which is quoted and
                                 * encoded
                                 */
                                if (encoded[pos] == '"') {
                                        pos++;
                                        begin = pos;
                                        while (encoded[pos] != '"') {
                                                if (encoded[pos] == '\\') {
                                                        pos++;
                                                }
                                                pos++;
                                        }
                                        parsedActions = unescapeString(encoded, begin, pos);
                                        pos++;

                                        /* skip whitespace */
                                        while (Character.isWhitespace(encoded[pos])) {
                                                pos++;
                                        }
                                }
                        }
                }

                /* the final character must be ')' */
                char c = encoded[pos++];
                if (c != ')') {
                        throw new IllegalArgumentException(
                                        "expecting close parenthesis");
                }
                permissions.add(new PermissionInfo(parsedType,parsedName, parsedActions));
                return pos;
        }
        catch (ArrayIndexOutOfBoundsException e) {
                throw new IllegalArgumentException("parsing terminated abruptly");
        }
    }
    /**
     * Takes an encoded character array and decodes it into a new String.
     */
    private static String unescapeString(char[] str, int begin, int end) {
            StringBuffer output = new StringBuffer(end - begin);
            for (int i = begin; i < end; i++) {
                    char c = str[i];
                    if (c == '\\') {
                            i++;
                            if (i < end) {
                                    c = str[i];
                                    switch (c) {
                                            case '"' :
                                            case '\\' :
                                                    break;
                                            case 'r' :
                                                    c = '\r';
                                                    break;
                                            case 'n' :
                                                    c = '\n';
                                                    break;
                                            default :
                                                    c = '\\';
                                                    i--;
                                                    break;
                                    }
                            }
                    }
                    output.append(c);
            }

            return output.toString();
    }

    public ConditionalPermissionInfoImpl(String encoded)
    {
        encoded = encoded.trim();
        String toUpper = encoded.toUpperCase();
        if (!(toUpper.startsWith("ALLOW {") || toUpper.startsWith("DENY {")))
        {
            throw new IllegalArgumentException();
        }
        m_allow = toUpper.startsWith("ALLOW {");
        m_cpai = null;
        List conditions = new ArrayList();
        List permissions = new ArrayList();
        try {
        char[] chars = encoded.substring((m_allow ? "ALLOW {".length() : "DENY {".length())).toCharArray();
        int idx = 0;
        while (idx <  chars.length)
        {
            if (Character.isWhitespace(chars[idx])) {
                idx++;
            }
            else if (chars[idx] == '[')
            {
                idx = parseConditionInfo(chars, idx, conditions);
            }
            else if (chars[idx] == '(')
            {
                idx = parsePermissionInfo(chars, idx, permissions);
            }
            else
            {
                if (chars[idx] != '}')
                {
                    throw new IllegalArgumentException("Expected } but was: " + chars[idx]);
                }
                idx++;
                break;
            }
        }
        while (Character.isWhitespace(chars[idx])) {
            idx++;
        }
        if (chars[idx] == '"') {
            idx++;
            int begin = idx;
            while (chars[idx] != '"') {
                    if (chars[idx] == '\\') {
                            idx++;
                    }
                    idx++;
            }
            m_name = unescapeString(chars, begin, idx);
        }
        else {
            m_name = Long.toString(RANDOM.nextLong() ^ System.currentTimeMillis());
        }
        } catch (ArrayIndexOutOfBoundsException ex) {
            ex.printStackTrace();
            throw new IllegalArgumentException("Unable to parse conditional permission info: " + ex.getMessage());
        }
        m_conditions = conditions.isEmpty() ? CONDITION_INFO
            : (ConditionInfo[]) conditions.toArray(new ConditionInfo[conditions
                .size()]);
        m_permissions = permissions.isEmpty() ? PERMISSION_INFO
            : (PermissionInfo[]) permissions
                .toArray(new PermissionInfo[permissions.size()]);
    }

    public ConditionalPermissionInfoImpl(ConditionalPermissionAdminImpl cpai,
        String name, boolean access)
    {
        m_allow = access;
        m_name = name;
        m_cpai = cpai;
        m_conditions = CONDITION_INFO;
        m_permissions = PERMISSION_INFO;
    }

    public ConditionalPermissionInfoImpl(ConditionInfo[] conditions,
        PermissionInfo[] permisions, ConditionalPermissionAdminImpl cpai,
        boolean access)
    {
        m_allow = access;
        m_name = Long.toString(RANDOM.nextLong() ^ System.currentTimeMillis());
        m_cpai = cpai;
        m_conditions = conditions == null ? CONDITION_INFO : conditions;
        m_permissions = permisions == null ? PERMISSION_INFO : permisions;
    }

    public ConditionalPermissionInfoImpl(String name,
        ConditionInfo[] conditions, PermissionInfo[] permisions,
        ConditionalPermissionAdminImpl cpai, boolean access)
    {
        m_allow = access;
        m_name = (name != null) ? name : Long.toString(RANDOM.nextLong()
            ^ System.currentTimeMillis());
        m_conditions = conditions == null ? CONDITION_INFO : conditions;
        m_permissions = permisions == null ? PERMISSION_INFO : permisions;
        m_cpai = cpai;
    }

    public void delete()
    {
        Object sm = System.getSecurityManager();
        if (sm != null)
        {
            ((SecurityManager) sm).checkPermission(Permissions.ALL_PERMISSION);
        }

        synchronized (m_lock)
        {
            m_cpai.write(m_name, null);
            m_conditions = CONDITION_INFO;
            m_permissions = PERMISSION_INFO;
        }
    }

    public ConditionInfo[] getConditionInfos()
    {
        synchronized (m_lock)
        {
            return (ConditionInfo[]) m_conditions.clone();
        }
    }

    ConditionInfo[] _getConditionInfos()
    {
        synchronized (m_lock)
        {
            return m_conditions;
        }
    }

    void setConditionsAndPermissions(ConditionInfo[] conditions,
        PermissionInfo[] permissions)
    {
        synchronized (m_lock)
        {
            m_conditions = conditions;
            m_permissions = permissions;
        }
    }

    public String getName()
    {
        return m_name;
    }

    public PermissionInfo[] getPermissionInfos()
    {
        synchronized (m_lock)
        {
            return (PermissionInfo[]) m_permissions.clone();
        }
    }

    PermissionInfo[] _getPermissionInfos()
    {
        synchronized (m_lock)
        {
            return m_permissions;
        }
    }

    public String getEncoded()
    {
        StringBuffer buffer = new StringBuffer();
        buffer.append(m_allow ? "ALLOW " : "DENY ");
        buffer.append('{');
        buffer.append(' ');
        synchronized (m_lock)
        {
            writeTo(m_conditions, buffer);
            writeTo(m_permissions, buffer);
        }
        buffer.append('}');
        buffer.append(' ');
        buffer.append('"');
        escapeString(m_name, buffer);
        buffer.append('"');
        return buffer.toString();
    }
   
    /**
     * This escapes the quotes, backslashes, \n, and \r in the string using a
     * backslash and appends the newly escaped string to a StringBuffer.
     */
    private static void escapeString(String str, StringBuffer output) {
            int len = str.length();
            for (int i = 0; i < len; i++) {
                    char c = str.charAt(i);
                    switch (c) {
                            case '"' :
                            case '\\' :
                                    output.append('\\');
                                    output.append(c);
                                    break;
                            case '\r' :
                                    output.append("\\r");
                                    break;
                            case '\n' :
                                    output.append("\\n");
                                    break;
                            default :
                                    output.append(c);
                                    break;
                    }
            }
    }

    private void writeTo(Object[] elements, StringBuffer buffer)
    {
        for (int i = 0; i < elements.length; i++)
        {
            buffer.append(elements[i]);
            buffer.append(' ');
        }
    }

    public String toString()
    {
        return getEncoded();
    }

    public String getAccessDecision()
    {
        return m_allow ? ConditionalPermissionInfo.ALLOW
            : ConditionalPermissionInfo.DENY;
    }

    public boolean isAllow()
    {
        return m_allow;
    }
}
TOP

Related Classes of org.apache.felix.framework.security.condpermadmin.ConditionalPermissionInfoImpl

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.