All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.osgi.service.condpermadmin.ConditionInfo Maven / Gradle / Ivy

There is a newer version: 1.9.22.1
Show newest version
/*
 * Copyright (c) OSGi Alliance (2004, 2016). All Rights Reserved.
 * 
 * Licensed 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.osgi.service.condpermadmin;

import java.util.ArrayList;
import java.util.List;

/**
 * Condition representation used by the Conditional Permission Admin service.
 * 
 * 

* This class encapsulates two pieces of information: a Condition type * (class name), which must implement {@code Condition}, and the arguments * passed to its constructor. * *

* In order for a Condition represented by a {@code ConditionInfo} to be * instantiated and considered during a permission check, its Condition class * must be available from the system classpath. * *

* The Condition class must either: *

    *
  • Declare a public static {@code getCondition} method that takes a * {@code Bundle} object and a {@code ConditionInfo} object as arguments. That * method must return an object that implements the {@code Condition} interface. *
  • *
  • Implement the {@code Condition} interface and define a public constructor * that takes a {@code Bundle} object and a {@code ConditionInfo} object as * arguments.
  • *
* * @Immutable * @author $Id: f96821be9ea49552285ed5eb699b05371f7f9ba8 $ */ public class ConditionInfo { private final String type; private final String[] args; /** * Constructs a {@code ConditionInfo} from the specified type and args. * * @param type The fully qualified class name of the Condition represented * by this {@code ConditionInfo}. * @param args The arguments for the Condition. These arguments are * available to the newly created Condition by calling the * {@link #getArgs()} method. * @throws NullPointerException If {@code type} is {@code null}. */ public ConditionInfo(String type, String[] args) { this.type = type; this.args = (args != null) ? args.clone() : new String[0]; if (type == null) { throw new NullPointerException("type is null"); } } /** * Constructs a {@code ConditionInfo} object from the specified encoded * {@code ConditionInfo} string. White space in the encoded * {@code ConditionInfo} string is ignored. * * @param encodedCondition The encoded {@code ConditionInfo}. * @see #getEncoded() * @throws IllegalArgumentException If the specified * {@code encodedCondition} is not properly formatted. */ public ConditionInfo(String encodedCondition) { if (encodedCondition == null) { throw new NullPointerException("missing encoded condition"); } if (encodedCondition.length() == 0) { throw new IllegalArgumentException("empty encoded condition"); } try { char[] encoded = encodedCondition.toCharArray(); int length = encoded.length; int pos = 0; /* 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"); } this.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 */ List 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++; } } } this.args = argsList.toArray(new String[0]); /* the final character must be ']' */ char c = encoded[pos]; pos++; while ((pos < length) && Character.isWhitespace(encoded[pos])) { pos++; } if ((c != ']') || (pos != length)) { throw new IllegalArgumentException("expecting close bracket"); } } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException("parsing terminated abruptly"); } } /** * Returns the string encoding of this {@code ConditionInfo} in a form * suitable for restoring this {@code ConditionInfo}. * *

* The encoded format is: * *

	 *   [type "arg0" "arg1" ...]
	 * 
* * where argN are strings that must be encoded for proper parsing. * Specifically, the {@code "}, {@code \}, carriage return, and line feed * characters must be escaped using {@code \"}, {@code \\}, {@code \r}, and * {@code \n}, respectively. * *

* The encoded string contains no leading or trailing whitespace characters. * A single space character is used between type and "arg0" * and between the arguments. * * @return The string encoding of this {@code ConditionInfo}. */ public final String getEncoded() { StringBuilder output = new StringBuilder(); output.append('['); output.append(type); for (int i = 0; i < args.length; i++) { output.append(" \""); escapeString(args[i], output); output.append('\"'); } output.append(']'); return output.toString(); } /** * Returns the string representation of this {@code ConditionInfo}. The * string is created by calling the {@code getEncoded} method on this * {@code ConditionInfo}. * * @return The string representation of this {@code ConditionInfo}. */ @Override public String toString() { return getEncoded(); } /** * Returns the fully qualified class name of the condition represented by * this {@code ConditionInfo}. * * @return The fully qualified class name of the condition represented by * this {@code ConditionInfo}. */ public final String getType() { return type; } /** * Returns arguments of this {@code ConditionInfo}. * * @return The arguments of this {@code ConditionInfo}. An empty array is * returned if the {@code ConditionInfo} has no arguments. */ public final String[] getArgs() { return args.clone(); } /** * Determines the equality of two {@code ConditionInfo} objects. * * This method checks that specified object has the same type and args as * this {@code ConditionInfo} object. * * @param obj The object to test for equality with this * {@code ConditionInfo} object. * @return {@code true} if {@code obj} is a {@code ConditionInfo}, and has * the same type and args as this {@code ConditionInfo} object; * {@code false} otherwise. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof ConditionInfo)) { return false; } ConditionInfo other = (ConditionInfo) obj; if (!type.equals(other.type) || args.length != other.args.length) return false; for (int i = 0; i < args.length; i++) { if (!args[i].equals(other.args[i])) return false; } return true; } /** * Returns the hash code value for this object. * * @return A hash code value for this object. */ @Override public int hashCode() { int h = 31 * 17 + type.hashCode(); for (int i = 0; i < args.length; i++) { h = 31 * h + args[i].hashCode(); } return h; } /** * This escapes the quotes, backslashes, \n, and \r in the string using a * backslash and appends the newly escaped string to a StringBuilder. */ private static void escapeString(String str, StringBuilder 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; } } } /** * Takes an encoded character array and decodes it into a new String. */ private static String unescapeString(char[] str, int begin, int end) { StringBuilder output = new StringBuilder(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(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy