Bitwise Operators and Bit Masks
作者:anotherbug 日期:2007-09-12 10:36:18
Bitwise Operators
- Although the examples here use 8-bit integers, Java integers are 32 bits. The highest bit is reserved for plus or minus sign. So you can set/unset 31 one-bit flags and a whole bunch of combination masks derived from the one-bit flag masks.
- It is not recommended to use bitwise operations in routine application programming because the resulting code is not very easy to understand. The flow of logic is not obvious. Save bitwise operations for systems programming or where memory savings may be desired such as in a JavaCards.
- One hexadecimal digit represents four binary digits. Some math:
Binary Math
0 + 0 = 0
0 + 1 = 1
1 + 1 = 10
Binary to Decimal Conversion
00010011 = 0*2**7 + 0*2**6 + 0*2**5 + 1*2**4 +
0*2**3 + 0*2**2 + 1*2**1 + 1*2**0
= 0 + 0 + 0 + 16 + 0 + 0 + 2 + 1
= 19
Hexadecimal to Decimal Conversion
3F = 3*16**1 + 15*16**0
= 63 (01111111 in binary)
Logical Bitwise Operations
bit 1
bit 2
OR ( |)
AND ( &)
XOR ( ^)
0
0
0
0
0
1
0
1
0
1
0
1
1
0
1
1
1
1
1
0
| <script type="text/javascript"><!-- google_ad_client = "pub-4447351096301747"; google_ad_width = 300; google_ad_height = 250; google_ad_format = "300x250_as"; google_color_border = "DDB7BA"; google_color_bg = "FFF5F6"; google_color_link = "0000CC"; google_color_url = "008000"; google_color_text = "6F6F6F"; //--></script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script> |
^(Bitwise XOR or exclusive OR) sets the bit to1where the corresponding bits in its operands are different, and to0if they are the same. Even1 ^ 1evaluates to0unlike the regular Bitwise OR. A bit pattern XORed with itself returns zero (because same bit values return zero). The Bitwise XOR is used to toggle the flag bits of aMASKin yourflagsvariable. It means that, if a flag bit was set inflags, XORing with itsMASKwill unset it. If it was not set, XORing will set it. This is different from turning a flag bit on or off, regardless of its prior state (which is accomplished using|and& ~).
// To toggle a flag bit(s) (on if it was off, off if it was on)
flags = flags ^ MASK;
// or, more succintly
flags ^= MASK;
~(Bitwise NOT) takes only one parameter and inverts each bit in the operand, changing all the ones to zeros and zeros to ones. This is useful when "unsetting" or "turning off" a flag.
// To unset or turn off a flag bit(s)
flags = flags & ~MASK;
// or, more succintly
flags &= ~MASK;
Here,
~MASKturns all zeros to ones and all ones to zeros inMASK.flags & ~MASKleaves all the bits offlagsas they are (one bit in the now-invertedMASKANDed with anyflagsbit is thatflagsbit) except for the now-zeroedMASKbits. ZeroedMASKbits ANDed with anyflagsbit return zero, thereby unsetting the flag, regardless of its original value.
Typical Bit Mask Operations
Operation
Code
Set a flag or overlay multiple values
flags | flagbitN
Unset a flag (zero-out a bit or set a bit to zero)
flags & ~flagbitN
Check if a bit is set
(flags & flagbitN) == flagbitN
Invert a pattern of bits
~flags
- Bit flags and bit masks use bitwise operators. A Java integer has 32 bits out of which 31 bits can be turned off or on to act as flag bits. (The highest order bit is reserved for plus or minus sign). A bit mask is simply a integer with one or more bits sets to
1. If you assign the integer any power of 2, it will set only one bit as 1 in the integer. Therefore, you initialize one-bit masks to powers of 2. Java integers can go from 2^^0 through 2^^30.
// Constants to hold bit masks for desired flags
static final int flagAllOff = 0; // 000...00000000 (empty mask)
static final int flagbit1 = 1; // 2^^0 000...00000001
static final int flagbit2 = 2; // 2^^1 000...00000010
static final int flagbit3 = 4; // 2^^2 000...00000100
static final int flagbit4 = 8; // 2^^3 000...00001000
static final int flagbit5 = 16; // 2^^4 000...00010000
static final int flagbit6 = 32; // 2^^5 000...00100000
static final int flagbit7 = 64; // 2^^6 000...01000000
static final int flagbit8 = 128; // 2^^7 000...10000000
//...
static final int flagbit31 = (int) Math.pow(2, 30); // 2^^30
//...
// Variable to hold the status of all flags
int flags = 0;
- Traditionally, you will use boolean-type variables to act as a flag:
boolean VISIBLE = true;
If you want to use a bit mask as a flag:
int VISIBLE = 4; // 0000 0100 in binary
which sets the third bit from the right as the flag for VISIBLE, thus becoming a bit mask for the VISIBLE flag. Then you do bitwise operations to apply this mask on some
flags(oroptionsorstatus) variable to set, unset, check or toggle the VISIBLE flag bit in yourflagsvariable.
- You can combine individual masks to obtain combo masks:
int maskReadAllowed = 4; // 00001000
int maskWriteAllowed = 16; // 00010000
// 00001000 | 00010000 = 00011000 represents both read and write permissions
int maskReadAndWriteAllowed = maskReadAllowed | maskWriteAllowed;
// Start out with no permissions
int user1Permissions = 0; // 00000000
int user2Permissions = 0; // 00000000
// Allow user 1 to read
// 00000000 | 00001000 = 00001000
user1Permissions |= maskReadAllowed;
// Allow user 2 to read as well as write in one shot
// 00000000 | 00011000 = 00011000
user2Permissions |= maskReadAndWriteAllowed;
// Later, allow user 1 to write also
// 00001000 | 00010000 = 00011000
user1Permissions |= maskWriteAllowed;
// Or, to make sure that user 1 has read permission as well, just in case
// 00001000 | 00011000 = 00011000 (same as before)
user1Permissions |= maskReadAndWriteAllowed;
Why the name Bit Mask?
- When a
bitwise ANDis performed, the zeros in theMASKconstant hide the corresponding bits in the yourflagsvariable (because the result contains only the bits that are ones in both operands). You can think of the zeros in theMASKconstant as being opaque and the ones as being transparent. Thus the expressionflags & MASKis like covering the bit pattern offlagswith the bit pattern ofMASKso that only the bits under the ones of MASK are visible.
0 0 0 0 0 0 1 0 (MASK constant)
AND 1 0 0 1 0 1 1 0 (your flags variable)
---------------
0 0 0 0 0 0 1 0 (result of operation)
Uses of Bit Masks
^can swap two variables without using an intermediate, temporary variable which is useful if you are short on available RAM or want that sliver of extra speed.
Usually, when not using
^, you will do:
temp = a;
a = b;
b = temp;
Using
^, no "temp" is needed:
a ^= b;
b ^= a;
a ^= b;
This will swap "a" and "b" integers. Both must be integers.
- A common C language usage of masks is:
ch &= 0377
where octal value 0377 is:
11111111 in binary
FF in Hexadecimal
255 in Decimal
This mask leaves the final (low or right end) eight bits of the variable
chalone and sets the rest to zero. Thus, regardless of whether the originalchis 8, 16, 32 or more bits, the final value is trimmed down to fit into a single byte. This is useful:
- For cross-platform development where the sizes of the primitive data types may vary between platforms.
- When the operands to the binary bitwise operators are of different-sized data types.
- For cross-platform development where the sizes of the primitive data types may vary between platforms.
- The most common application of the bitwise operators is to set, clear, test and toggle individual bit flags using bit masks. One 32 bit Java integer can hold 31 individual flags (about 2**31 - 1 total combinations). The last bit on the left (the highest or most significant bit) is reserved for the + or - sign of the integer.
- Bit masks can be used to store all the permissions granted to a database user as an integer in the permissions table.
Let's say that a user can be granted four types of permissions (in practice, there can be numerous types of permissions) - View, Add, Edit and Delete.
Desired User Permissions
User ID
View
Add
Edit
Delete
tom
Yes
No
No
No
dick
Yes
Yes
Yes
No
harry
Yes
Yes
Yes
Yes
It doesn't make sense to allow a user to add, edit or delete tables or rows if the user cannot view them. What we need are sets of valid permissions that a user may be granted.
- No permission to do anything
- View Only
- View and Add
- View and Edit
- View, Add and Edit
- All permissions (View, Add, Edit and Delete)
Using bit flags and masks, Each user's permission set can be stored as an integer in a simple key-value file or database. For very large systems or very small systems, this can significantly reduce the disk space needed.
User ID Permission Set
------- --------------
User1 1
User2 9
User3 15
How do we make sure that a user can only be assigned one of these permission sets? And how can we store permissions for numerous users for later access. We will investigate two ways of doing it - the application programming way and the system programming way.
- No permission to do anything
Code Examples Using Bitwise Operators
- There are two main Java code files below -
BitwisePermissions.javaandBooleanPermissions.java. The first one shows how to use bitwise Operators to set and unset various permission flags for database users.BooleanPermissions.javaaccomplishes exactly the same thing except that it uses Java booleans to represent flags.
- On an average over 100's of tests, boolean version took about 50 percent longer to achieve same results.
Memory used by the boolean version was about 150 percent more than the memory used by the bitwise version.
Average time taken for testBitwiseOperations() = 1.62 millisecs
Free memory change for testBitwiseOperations() = -13656 bytes
Average time taken for testBooleanOperations() = 2.44 millisecs
Free memory change for testBooleanOperations() = -34024 bytes
- Instead of using Java's
System.out.println()method, the examples on this page use Apache Log4j'scat.info()methods to display output. To run the example code, you will need to putlog4j.jarin Java's classpath. Alternatively, you may want to download the latest Log4j software (about 2.3MB as of log4j 1.1.3) and extractlog4j.jar(about 156KB) out of it.
You will also need to save the following statements in a file named
log4j.propertiesand place that file in a directory which is in Java's classpath so that Log4j can find this file and configure itself.
#### ROOT category will log INFO and higher
log4j.rootCategory=info, dest1
#log4j.rootCategory=error, dest1
#### Individual categories, if different from root. Usually unnecessary.
#log4j.category.assign_permissions=DEBUG
#log4j.category.assign_permissions=DEBUG, dest1
#### Write logs to console stdout
log4j.appender.dest1=org.apache.log4j.ConsoleAppender
#### Layout for writing each log message
log4j.appender.dest1.layout=org.apache.log4j.PatternLayout
#log4j.appender.dest1.layout.ConversionPattern=%-5p %m%n
#log4j.appender.dest1.layout.ConversionPattern=%C.%M(): %m%n
#log4j.appender.dest1.layout.ConversionPattern=%5.5r %-25.25c.%-25.25M(): %m%n
To measure performance of the code examples below, you will need to disable logging for every statement below the
erroras shown in the commented-out line above. Otherwise, the logging action itself takes too much time.
To not use Log4j, replace
cat.info(withSystem.out.println(and deleteimport org.apache.log4j.*;
- First of all, we will need DBSecurityException.java class to throw custom exceptions when the requested permissions do not make sense.
public class DBSecurityException extends Exception {
DBSecurityException() { super(); }
DBSecurityException(String s) { super(s); }
}
- BitwisePermissions.java is the primary file which exercises bitwise operators. What we are doing here is trying to represent valid sets of database permissions as bit masks. This coding practice is used in systems level programming where speed and memory usage matters. A user can then be granted one of these valid permission sets. It needs Java 2 or higher because it uses the
Arrays.
import org.apache.log4j.*;
import java.util.Arrays;
class BitwisePermissions {
// Log4j logging category
static Category cat =
Category.getInstance(BitwisePermissions.class.getName());
// Define masks for lowest level permissions as constants which
// are powers of 2. This ensures that only one bit in an integer
// is set to 1. Make these private because combinations will be
// used to publically access valid permission sets.
public static final int VIEW = 4;
public static final int ADD = 16;
public static final int EDIT = 32;
public static final int DELETE = 256;
/* Valid permission sets
- No permission to do anything
- View Only
- View and Add
- View and Edit
- View, Add and Edit
- All permissions (View, Add, Edit and Delete)
*/
// Obtain valid permission sets by Bitwise ORing lower level permissions
public static final int NOTHING_ALLOWED = 0;
public static final int VIEW_ALLOWED = VIEW;
public static final int VIEW_ADD_ALLOWED = VIEW | ADD;
public static final int VIEW_EDIT_ALLOWED = VIEW | EDIT;
public static final int VIEW_ADD_EDIT_ALLOWED = VIEW | ADD | EDIT;
public static final int ALL_ALLOWED = VIEW | ADD | EDIT | DELETE;
// Or, alternately
//public static final int ALL_ALLOWED = VIEW_ADD_EDIT_ALLOWED | DELETE;
public static final int [] validPermissions = {
NOTHING_ALLOWED,
VIEW_ALLOWED,
VIEW_ADD_ALLOWED,
VIEW_EDIT_ALLOWED,
VIEW_ADD_EDIT_ALLOWED,
ALL_ALLOWED,
};
static {
// Sort needed to later use binarySearch() method
Arrays.sort(validPermissions);
for (int i = 0; i < validPermissions.length; i++) {
if(cat.isInfoEnabled()) {
cat.info("Valid permission:" +
printAsBinary(validPermissions[i]) );
}
}
}
// Check permission(s)
public static boolean isPermitted(
int myPermissions,
int permissionToCheck
) {
return ((myPermissions & permissionToCheck) == permissionToCheck);
}
/* Public setter methods to make sure that only valid
* permission sets can be assigned */
public static int addPermission(int myPermissions, int permissionToAdd)
throws DBSecurityException {
return addPermissions(myPermissions,
new int[] { permissionToAdd } );
}
public static int addPermissions(int myPermissions, int[] permissionsToAdd)
throws DBSecurityException {
if(cat.isInfoEnabled()) {
cat.info("BEFORE Permissions:" + printAsBinary(myPermissions) );
}
for (int i = 0; i < permissionsToAdd.length; i++) {
if(cat.isInfoEnabled()) {
cat.info("Add permission:" +
printAsBinary(permissionsToAdd[i]));
}
myPermissions |= permissionsToAdd[i];
}
if (Arrays.binarySearch(validPermissions, myPermissions) < 0) {
throw new DBSecurityException(
"Resulting permission set will be invalid. Aborted.");
}
else {
if(cat.isInfoEnabled()) {
cat.info("AFTER Permissions:" +
printAsBinary(myPermissions) + "\n");
}
return myPermissions;
}
}
public static int deletePermission(
int myPermissions,
int permissionToDelete
) throws DBSecurityException {
return deletePermissions(myPermissions,
new int[] { permissionToDelete } );
}
public static int deletePermissions(
int myPermissions,
int[] permissionsToDelete
) throws DBSecurityException {
if(cat.isInfoEnabled()) {
cat.info("BEFORE Permissions:" + printAsBinary(myPermissions));
}
for (int i = 0; i < permissionsToDelete.length; i++) {
if(cat.isInfoEnabled()) {
cat.info("Delete permission:" +
printAsBinary(permissionsToDelete[i]));
}
myPermissions &= ~permissionsToDelete[i];
}
if (Arrays.binarySearch(validPermissions, myPermissions) < 0) {
throw new DBSecurityException(
"Resulting permission set will be invalid. Aborted.");
}
else {
if(cat.isInfoEnabled()) {
cat.info("AFTER Permissions:" +
printAsBinary(myPermissions) + "\n");
}
return myPermissions;
}
}
// Toggle permission(s) - off if on, on if off - RARELY USED
public static int togglePermission(
int myPermissions,
int permissionToToggle
) throws DBSecurityException {
myPermissions ^= permissionToToggle;
if (Arrays.binarySearch(validPermissions, myPermissions) < 0) {
throw new DBSecurityException(
"Resulting permission set will be invalid. Aborted.");
}
else {
return myPermissions;
}
}
// Convert an int to a string displaying int as binary
private static String printAsBinary(int i) {
if(cat.isDebugEnabled()) cat.debug("incoming = " + i);
StringBuffer sb = new StringBuffer();
if ( isPermitted(i, VIEW) ) sb.append('V');
else sb.append(' ');
if ( isPermitted(i, ADD) ) sb.append('A');
else sb.append(' ');
if ( isPermitted(i, EDIT) ) sb.append('E');
else sb.append(' ');
if ( isPermitted(i, DELETE) ) sb.append('D');
else sb.append(' ');
String s = Integer.toString(i, 2);
String pattern = "................................";
if(cat.isDebugEnabled()) cat.debug("pattern = " + pattern);
String temp1 = pattern.substring(0, pattern.length() - s.length());
String temp2 = temp1 + s;
if(cat.isDebugEnabled()) cat.debug("converted = " + temp2);
temp2 = temp2.replace('0', '.');
sb.append("=" + temp2);
if(cat.isDebugEnabled()) cat.debug("returned = " + sb.toString());
return sb.toString();
}
} // End of class
- BooleanPermissions.java is a replica of the bitwise class above, except that it uses booleans as flags instead of bitmasks as flags. This coding practice is used in application level programming.
import org.apache.log4j.*;
import java.util.Arrays;
class BooleanPermissions implements Cloneable, Comparable {
// Log4j logging category
static Category cat =
Category.getInstance(BooleanPermissions.class.getName());
/* Public constants */
public static final int VIEW = 1;
public static final int ADD = 2;
public static final int EDIT = 3;
public static final int DELETE = 4;
/* Private permission variables */
// Nothing is allowed by default
private boolean bViewAllowed = false;
private boolean bAddAllowed = false;
private boolean bEditAllowed = false;
private boolean bDeleteAllowed = false;
/* Valid permission sets
- No permission to do anything
- View Only
- View and Add
- View and Edit
- View, Add and Edit
- All permissions (View, Add, Edit and Delete)
*/
public static final BooleanPermissions
NOTHING_ALLOWED = new BooleanPermissions();
public static final BooleanPermissions
VIEW_ALLOWED = new BooleanPermissions();
public static final BooleanPermissions
VIEW_ADD_ALLOWED = new BooleanPermissions();
public static final BooleanPermissions
VIEW_EDIT_ALLOWED = new BooleanPermissions();
public static final BooleanPermissions
VIEW_ADD_EDIT_ALLOWED = new BooleanPermissions();
public static final BooleanPermissions
ALL_ALLOWED = new BooleanPermissions();
public static final BooleanPermissions [] validPermissions = {
NOTHING_ALLOWED,
VIEW_ALLOWED,
VIEW_ADD_ALLOWED,
VIEW_EDIT_ALLOWED,
VIEW_ADD_EDIT_ALLOWED,
ALL_ALLOWED,
};
static {
VIEW_ALLOWED.bViewAllowed = true;
VIEW_ADD_ALLOWED.bViewAllowed = true;
VIEW_ADD_ALLOWED.bAddAllowed = true;
VIEW_EDIT_ALLOWED.bViewAllowed = true;
VIEW_EDIT_ALLOWED.bEditAllowed = true;
VIEW_ADD_EDIT_ALLOWED.bViewAllowed = true;
VIEW_ADD_EDIT_ALLOWED.bAddAllowed = true;
VIEW_ADD_EDIT_ALLOWED.bEditAllowed = true;
ALL_ALLOWED.bViewAllowed = true;
ALL_ALLOWED.bAddAllowed = true;
ALL_ALLOWED.bEditAllowed = true;
ALL_ALLOWED.bDeleteAllowed = true;
Arrays.sort(validPermissions);
for (int i = 0; i < validPermissions.length; i++) {
if(cat.isInfoEnabled()) {
cat.info("Valid permission:" + validPermissions[i]);
}
}
}
public String toString() {
StringBuffer sb = new StringBuffer();
if (bViewAllowed) sb.append('V');
else sb.append(' ');
if (bAddAllowed) sb.append('A');
else sb.append(' ');
if (bEditAllowed) sb.append('E');
else sb.append(' ');
if (bDeleteAllowed) sb.append('D');
else sb.append(' ');
sb.append("=" + hashCode());
return sb.toString();
}
public boolean equals(Object o) {
if ((o instanceof BooleanPermissions) &&
(o.hashCode() != this.hashCode())
) {
return true;
}
else {
return false;
}
}
public int hashCode() {
StringBuffer sb = new StringBuffer();
if (bViewAllowed) sb.append('1');
else sb.append('0');
if (bAddAllowed) sb.append('1');
else sb.append('0');
if (bEditAllowed) sb.append('1');
else sb.append('0');
if (bDeleteAllowed) sb.append('1');
else sb.append('0');
return Integer.parseInt(sb.toString());
}
public int compareTo(Object o) {
return this.hashCode() - o.hashCode();
}
private void copyFields(BooleanPermissions bp) {
if (bp != null) {
this.bViewAllowed = bp.bViewAllowed;
this.bAddAllowed = bp.bAddAllowed;
this.bEditAllowed = bp.bEditAllowed;
this.bDeleteAllowed = bp.bDeleteAllowed;
}
}
private void setPermission(int permission, boolean value)
throws DBSecurityException {
switch(permission) {
case VIEW:
if(cat.isInfoEnabled()) cat.info("Set VIEW = " + value);
bViewAllowed = value;
break;
case ADD:
if(cat.isInfoEnabled()) cat.info("Set ADD = " + value);
bAddAllowed = value;
break;
case EDIT:
if(cat.isInfoEnabled()) cat.info("Set EDIT = " + value);
bEditAllowed = value;
break;
case DELETE:
if(cat.isInfoEnabled()) cat.info("Set DELETE = " + value);
bDeleteAllowed = value;
break;
default:
throw new DBSecurityException("Invalid permission");
}
}
public boolean isPermitted(int permission) {
switch(permission) {
case VIEW:
if(cat.isInfoEnabled()) {
cat.info("Checking permission " + permission +
" VIEW = " + bViewAllowed);
}
return bViewAllowed;
case ADD:
if(cat.isInfoEnabled()) {
cat.info("Checking permission " + permission +
" ADD = " + bAddAllowed);
}
return bAddAllowed;
case EDIT:
if(cat.isInfoEnabled()) {
cat.info("Checking permission " + permission +
" EDIT = " + bEditAllowed);
}
return bEditAllowed;
case DELETE:
if(cat.isInfoEnabled()) {
cat.info("Checking permission " + permission +
" DELETE = " + bDeleteAllowed);
}
return bDeleteAllowed;
default:
if(cat.isInfoEnabled()) {
cat.info("Checking permission " + permission +
" NOT FOUND. Returning false");
}
return false;
}
}
public void addPermission(int permissionToAdd) throws DBSecurityException {
addPermissions(new int[] { permissionToAdd } );
}
public void addPermissions(int[] permissionsToAdd)
throws DBSecurityException {
if(cat.isInfoEnabled()) cat.info("BEFORE Permissions:" + this);
BooleanPermissions temp = null;
try {
temp = (BooleanPermissions) this.clone();
}
catch (CloneNotSupportedException cns) {
// Should not happen. Ignore.
if(cat.isDebugEnabled()) cat.debug( cns, cns);
}
for (int i = 0; i < permissionsToAdd.length; i++) {
setPermission(permissionsToAdd[i], true);
}
if (Arrays.binarySearch(validPermissions, this) < 0) {
copyFields(temp);
throw new DBSecurityException(
"Resulting permission set will be invalid. Aborted.");
}
if(cat.isInfoEnabled()) cat.info("AFTER Permissions:" + this + "\n");
}
public void deletePermission(int permissionToDelete)
throws DBSecurityException {
deletePermissions(new int[] { permissionToDelete } );
}
public void deletePermissions(int[] permissionsToDelete)
throws DBSecurityException {
if(cat.isInfoEnabled()) cat.info("BEFORE Permissions:" + this);
BooleanPermissions temp = null;
try {
temp = (BooleanPermissions) this.clone();
}
catch (CloneNotSupportedException cns) {
// Should not happen. Ignore.
if(cat.isDebugEnabled()) cat.debug( cns, cns);
}
for (int i = 0; i < permissionsToDelete.length; i++) {
setPermission(permissionsToDelete[i], false);
}
if (Arrays.binarySearch(validPermissions, this) < 0) {
copyFields(temp);
throw new DBSecurityException(
"Resulting permission set will be invalid. Aborted.");
}
if(cat.isInfoEnabled()) cat.info("AFTER Permissions:" + this + "\n");
}
} // End of class
- Okay, this one is a bit tricky. assign_permissions.java uses JUnit package to implement a testing class which exercises the two classes above. Basically, it extends JUnit's
TestCaseclass, defines two methods -testBitwiseOperations()andtestBooleanOperations()and runs these two methods repeatedlyn2number of times. You can changen2value, recompile and run it. You may want to run withn2 = 1and Log4j root category set toinfo. Then, you may want to run atn2 = 100or something like that, but make sure that you set the Log4j root category toerror, otherwise the tests will generate heaps of output and take forever to run. You, of course, needjunit.jarin Java's classpath.
import org.apache.log4j.*;
import junit.framework.*;
import junit.extensions.*;
import java.util.*;
public class assign_permissions extends TestCase {
// Log4j logging category
static Category cat =
Category.getInstance(assign_permissions.class.getName());
// Fixtures - Class fields to allow access from anywhere in class
HashMap bitwiseUsers;
HashMap booleanUsers;
// Some free memory info
Runtime rt = Runtime.getRuntime();
long tm, tm2;
long free4, free5;
// Test statistics
static int n2 = 0;
static long timetaken1 = 0;
static long timetaken2 = 0;
static long freechange1 = 0;
static long freechange2 = 0;
// Required constructor - takes method name to test as parameter
public assign_permissions(String name) {
super(name);
}
// Add tests to run in order of running into the suite
public static Test suite() {
// Shortcut to automatically add all testXXX methods
//return new TestSuite(assign_permissions.class);
// Number of repetitions per test
n2 = 1;
TestSuite suite1 = new TestSuite();
suite1.addTest(
new RepeatedTest(
new assign_permissions("testBitwiseOperations"), n2));
TestSuite suite2 = new TestSuite();
suite2.addTest(
new RepeatedTest(
new assign_permissions("testBooleanOperations"), n2));
TestSuite suite = new TestSuite();
//suite.addTest(new assign_permissions("testBitwiseOperations"));
//suite.addTest(new assign_permissions("testBooleanOperations"));
suite.addTest(suite1);
suite.addTest(suite2);
//TestResult result = suite.run();
return suite;
}
public static void main (String[] args) {
// Initialize static fields
timetaken1 = 0;
timetaken2 = 0;
freechange1 = 0;
freechange2 = 0;
// Run the tests
junit.textui.TestRunner.run( suite() );
// Print the results
// No sense in averaging less than 10 tests
if (n2 > 9) {
cat.error(
"Average time taken for testBitwiseOperations() = " +
((0.0 + (timetaken1*100.0/n2))/100.0) + " millisecs" );
cat.error(
"Average time taken for testBooleanOperations() = " +
((0.0 + (timetaken2*100.0/n2))/100.0) + " millisecs" );
if (timetaken1 != 0) {
cat.error(
"testBooleanOperations() takes " +
((timetaken2-timetaken1)*100/timetaken1) +
"% more time than testBitwiseOperations()");
}
}
// Because of automatic garbage collection, no sense in measuring
// memory usage for more than 1 tests
if (n2 == 1) {
cat.error(
"Memory used for testBitwiseOperations() = " +
freechange1 + " bytes" );
cat.error(
"Memory used for testBooleanOperations() = " +
freechange2 + " bytes" );
if (freechange1 != 0) {
cat.error("testBooleanOperations() uses " +
((freechange2-freechange1)*100/freechange1) +
"% more memory than testBitwiseOperations()");
}
}
}
// This method is called before running each test
protected void setUp() {
if(cat.isInfoEnabled()) cat.info("setUp(): Started\n");
//System.gc();
}
// Test method
public void testBitwiseOperations() {
if(cat.isInfoEnabled()) cat.info("testBitwiseOperations(): Started\n");
tm = System.currentTimeMillis();
free4 = rt.freeMemory();
bitwiseUsers = new HashMap();
bitwiseUsers.put("user1",
new Integer(BitwisePermissions.NOTHING_ALLOWED));
bitwiseUsers.put("user2",
new Integer(BitwisePermissions.VIEW_ALLOWED));
bitwiseUsers.put("user3",
new Integer(BitwisePermissions.VIEW_ADD_ALLOWED));
bitwiseUsers.put("user4",
new Integer(BitwisePermissions.VIEW_EDIT_ALLOWED));
bitwiseUsers.put("user5",
new Integer(BitwisePermissions.VIEW_ADD_EDIT_ALLOWED));
bitwiseUsers.put("user6",
new Integer(BitwisePermissions.ALL_ALLOWED));
Set keys = bitwiseUsers.keySet();
Iterator i = keys.iterator();
while (i.hasNext()) {
Object o = i.next();
if(cat.isInfoEnabled()) cat.info("User ID = " + o + "\n");
int currentPermissions =
((Integer) bitwiseUsers.get(o)).intValue();
try {
currentPermissions =
BitwisePermissions.addPermissions(
currentPermissions,
new int[] {
BitwisePermissions.DELETE,
BitwisePermissions.ADD,
BitwisePermissions.EDIT,
BitwisePermissions.VIEW,
}
);
}
catch (DBSecurityException dbse) {
if(cat.isEnabledFor(Priority.WARN)) cat.warn(dbse, dbse);
}
try {
currentPermissions =
BitwisePermissions.deletePermissions(
currentPermissions,
new int[] {
BitwisePermissions.ADD,
BitwisePermissions.EDIT,
BitwisePermissions.VIEW,
}
);
}
catch (DBSecurityException dbse) {
if(cat.isEnabledFor(Priority.WARN)) cat.warn(dbse, dbse);
}
try {
currentPermissions =
BitwisePermissions.addPermissions(
currentPermissions,
new int[] {
BitwisePermissions.VIEW,
}
);
}
catch (DBSecurityException dbse) {
if(cat.isEnabledFor(Priority.WARN)) cat.warn(dbse, dbse);
}
try {
currentPermissions =
BitwisePermissions.addPermissions(
currentPermissions,
new int[] {
BitwisePermissions.DELETE,
BitwisePermissions.VIEW,
}
);
}
catch (DBSecurityException dbse) {
if(cat.isEnabledFor(Priority.WARN)) cat.warn(dbse, dbse);
}
try {
currentPermissions =
BitwisePermissions.deletePermissions(
currentPermissions,
new int[] {
BitwisePermissions.DELETE,
}
);
}
catch (DBSecurityException dbse) {
if(cat.isEnabledFor(Priority.WARN)) cat.warn(dbse, dbse);
}
try {
currentPermissions =
BitwisePermissions.addPermissions(
currentPermissions,
new int[] {
BitwisePermissions.DELETE,
BitwisePermissions.EDIT,
BitwisePermissions.VIEW,
}
);
}
catch (DBSecurityException dbse) {
if(cat.isEnabledFor(Priority.WARN)) cat.warn(dbse, dbse);
}
try {
currentPermissions =
BitwisePermissions.deletePermissions(
currentPermissions,
new int[] {
BitwisePermissions.DELETE,
BitwisePermissions.ADD,
BitwisePermissions.EDIT,
BitwisePermissions.VIEW,
}
);
}
catch (DBSecurityException dbse) {
if(cat.isEnabledFor(Priority.WARN)) cat.warn(dbse, dbse);
}
}
tm2 = System.currentTimeMillis();
free5 = rt.freeMemory();
timetaken1 += (tm2-tm);
freechange1 += (free5-free4);
assertTrue(true);
}
// Test method
public void testBooleanOperations() {
if(cat.isInfoEnabled()) cat.info("testBooleanOperations(): Started\n");
tm = System.currentTimeMillis();
free4 = rt.freeMemory();
booleanUsers = new HashMap();
booleanUsers.put("user1", BooleanPermissions.NOTHING_ALLOWED);
booleanUsers.put("user2", BooleanPermissions.VIEW_ALLOWED);
booleanUsers.put("user3", BooleanPermissions.VIEW_ADD_ALLOWED);
booleanUsers.put("user4", BooleanPermissions.VIEW_EDIT_ALLOWED);
booleanUsers.put("user5", BooleanPermissions.VIEW_ADD_EDIT_ALLOWED);
booleanUsers.put("user6", BooleanPermissions.ALL_ALLOWED);
Set keys = booleanUsers.keySet();
Iterator i = keys.iterator();
while (i.hasNext()) {
Object o = i.next();
if(cat.isInfoEnabled()) cat.info("User ID = " + o + "\n");
BooleanPermissions currentPermissions =
(BooleanPermissions) booleanUsers.get(o);
try {
currentPermissions.addPermissions(
new int[] {
BooleanPermissions.DELETE,
BooleanPermissions.ADD,
BooleanPermissions.EDIT,
BooleanPermissions.VIEW,
}
);
}
catch (DBSecurityException dbse) {
if(cat.isEnabledFor(Priority.WARN)) cat.warn(dbse, dbse);
}
try {
currentPermissions.deletePermissions(
new int[] {
BooleanPermissions.ADD,
BooleanPermissions.EDIT,
BooleanPermissions.VIEW,
}
);
}
catch (DBSecurityException dbse) {
if(cat.isEnabledFor(Priority.WARN)) cat.warn(dbse, dbse);
}
try {
currentPermissions.addPermissions(
new int[] {
BooleanPermissions.VIEW,
}
);
}
catch (DBSecurityException dbse) {
if(cat.isEnabledFor(Priority.WARN)) cat.warn(dbse, dbse);
}
try {
currentPermissions.addPermissions(
new int[] {
BooleanPermissions.DELETE,
BooleanPermissions.VIEW,
}
);
}
catch (DBSecurityException dbse) {
if(cat.isEnabledFor(Priority.WARN)) cat.warn(dbse, dbse);
}
try {
currentPermissions.deletePermissions(
new int[] {
BooleanPermissions.DELETE,
}
);
}
catch (DBSecurityException dbse) {
if(cat.isEnabledFor(Priority.WARN)) cat.warn(dbse, dbse);
}
try {
currentPermissions.addPermissions(
new int[] {
BooleanPermissions.DELETE,
BooleanPermissions.EDIT,
BooleanPermissions.VIEW,
}
);
}
catch (DBSecurityException dbse) {
if(cat.isEnabledFor(Priority.WARN)) cat.warn(dbse, dbse);
}
try {
currentPermissions.addPermissions(
new int[] {
BooleanPermissions.DELETE,
BooleanPermissions.ADD,
BooleanPermissions.EDIT,
BooleanPermissions.VIEW,
}
);
}
catch (DBSecurityException dbse) {
if(cat.isEnabledFor(Priority.WARN)) cat.warn(dbse, dbse);
}
}
tm2 = System.currentTimeMillis();
free5 = rt.freeMemory();
timetaken2 += (tm2-tm);
freechange2 += (free5-free4);
assertTrue(true);
}
} // End of class
References
平均得分(0 次评分)
- 共有 9 条评论
- 共有 9 条评论
订阅
上一篇
|

文章来自:
标签:
计米器
插标机
调节表
喷粉设备
多层信号灯
测长传感器
声光报警器
电流继电器
静电消除器
时间继电器
累加计数器
润滑控制器
预置计数器
电压表电流表
免费电影
防伪
seo
三通球阀
防伪标签
防伪商标
防伪标识
防伪标志
防伪标贴
数码防伪
防伪技术
激光防伪
防伪公司
防伪系统
防伪印刷
佛像雕刻机
饰品雕刻机
打标机
鞋模雕刻机
模具雕刻机
真空吸附雕刻机
雕刻机
雕铣机
打胶机
钥匙扣
温州设计公司
温州企划公司
温州样本设计
丽水房地产策划公司
台州房地产策划公司
台州vi设计
温州品牌设计公司
温州广告设计公司
温州平面广告设计
温州广告公司
温州样本设计
温州海报设计
温州商标设计
温州标志设计
温州包装设计
Ceramic tile
Ceramic floor tile
Border tile
Rustic tile
Carpet tile
Skirting tile
Polished tile
Glazed tile
Skirting tile
Rustie tile
Border tile
Ceramic tile
Warhammer Gold
Warhammer Online Gold
Warhammer Accounts
Warhammer Power Leveling
Warhammer Online Key
Warhammer Gold
Warhammer Online Gold
Warhammer Time Card
Warhammer CD Key
WAR gold
warhammer online gold
Buy WAR gold
Buy warhammer gold
Buy warhammer online gold
warhammer gold
WAR Accounts
warhammer Accounts
warhammer online Accounts
Buy WAR Accounts
warhammer Accounts for sale
Warhammer Power Leveling
Warhammer Online Power Leveling
War Power Leveling
Buy Warhammer Power Leveling
Warhammer PowerLeveling
Cheap Warhammer Power Leveling
Cheap Warhammer Online Power Leveling
Buy War Power Leveling
Warhammer EU Power Leveling
Cheap Warhammer Gold
Cheap Warhammer online gold
Buy Cheap Warhammer Gold
Buy WAR Gold
Warhammer EU Gold
Warhammer EU Power Leveling
Warhammer EU CD Key
Warhammer EU Accounts
Warhammer CD Key
Warhammer online CD Key
Warhammer Timecard
Buy Warhammer Time Card
Warhammer 60 days Time Card
Cheap WAR Accounts
Cheap warhammer Accounts
Cheap warhammer online Accounts
Buy Cheap WAR Accounts
buy Warhammer CD Key
buy Warhammer online CD Key
cheap Warhammer CD key
warhammer time card
Warhammer prepaid time card
Lord of the Rings Online Gold
Buy Lotro Gold
Sell LoTRO Gold
LoTRO CD Key
LoTRO Europe Gold
Cheap LoTRO Accounts
Lord of the Rings Online Power Leveling
Lord of the Rings online CD Key
Cheap Lotro Gold
Buy Lotro Gold | Lord Of The Rings Online Gold
Lotro Accounts
| Buy Lotro Accounts
Lord Of The Rings Online Power Leveling | Lord Of The Rings Online PowerLeveling
Lotro Cd Key | Lord Time Card
Lotro Gold | Lotro Gold Instant Delivery
lord of the rings online accounts | lord of the rings online accounts for sale
Lotro Power Leveling | Lotro Powerleveling
Lord Of The Rings Online Cd Key | Lord Of The Rings Online Time Card
窃听器
手机监听器
监听器
手机窃听器
窃听器
手机监听器
监听器
手机窃听器
窃听器
手机窃听器
窃听器
手机监听器
监听器
手机窃听器│窃听器
手机窃听器│窃听器
手机窃听器│窃听器
手机窃听器│窃听器
手机窃听器│窃听器
手机窃听器│窃听器
手机窃听器│窃听器
手机窃听器│窃听器
手机窃听器│窃听器
手机窃听器│窃听器
手机窃听器│窃听器
手机窃听器│窃听器
Warhammer Online Gold
Warhammer gold
cheap Warhammer gold
Warhammer Online gold
Warhammer gold
Buy WAR gold
Cheap Warhammer Gold
Buy warhammer online gold
cheap warhammer online gold
Buy warhammer gold
buy warhammer online gold
buy cheap warhammer gold
War Gold
Buy Warhammer Gold
Warhammer Online Gold
Warhammer Gold for sale
Cheap Warhammer Gold
Warhammer Accounts
Buy Warhammer Accounts
Cheap Warhammer Accounts
Warhammer Power leveling
War Power leveling
Warhammer Online Power Leveling
heap Warhammer Power Leveling
Warhammer CD Key
War CD Key
Warhammer Online CD Key
Warhammer Game Time Card
Warhammer Game Card
Buy Warhammer Online CD Key
Buy War Gold
Sell Warhammer Gold
Warhammer EU Gold
Warhammer Online EU Gold
Sell Warhammer Gold
Warhammer EU Gold
Buy War Gold
Warhammer Online EU Gold
Buy Cheap Warhammer Gold
Cheap warhammer EU gold
Cheap War Gold
Cheapest Warhammer Gold
Buy Cheap Warhammer Gold
Buy Warhammer Online Accounts
Buy WAR Accounts
Buy Warhammer Power Leveling
Warhammer Powerleveling
Buy WAR Power Leveling
Buy Cheap Warhammer Power Leveling
Buy Warhammer CD Key
Warhammer EU CD key
Buy Warhammer Online key
Warhammer Time Card
Buy Warhammer Time Card
LoTRO Gold
Lord of the Rings Online Gold
Buy Lotro Gold
Sell LoTRO Gold
LoTRO CD Key
LoTRO Europe Gold
Cheap LoTRO Accounts
Lord of the Rings Online Power Leveling
Lord of the Rings online CD Key
Cheap Lotro Gold
Buy Lotro Gold | Lord Of The Rings Online Gold
Lotro Accounts
| Buy Lotro Accounts
Lord Of The Rings Online Power Leveling | Lord Of The Rings Online PowerLeveling
Lotro Cd Key | Lord Time Card
Lotro Gold | Lotro Gold Instant Delivery
lord of the rings online accounts | lord of the rings online accounts for sale
Lotro Power Leveling | Lotro Powerleveling
Lord Of The Rings Online Cd Key | Lord Of The Rings Online Time Card
Lotro Accounts
| Buy Lotro Accounts
Lord Of The Rings Online Power Leveling | Lord Of The Rings Online PowerLeveling
Lotro Cd Key | Lord Time Card
Lotro Gold | Lotro Gold Instant Delivery
lord of the rings online accounts | lord of the rings online accounts for sale
Lotro Power Leveling | Lotro Powerleveling
Lord Of The Rings Online Cd Key | Lord Of The Rings Online Time Card
LoTRO Gold
Lord of the Rings Online Gold
Buy Lotro Gold
Sell LoTRO Gold
LoTRO CD Key
LoTRO Europe Gold
Cheap LoTRO Accounts
Lord of the Rings Online Power Leveling
Lord of the Rings online CD Key
Cheap Lotro Gold
Warhammer gold
Warhammer Online Gold
Warhammer Accounts
Warhammer Power Leveling
Warhammer CD Key
WAR gold
warhammer gold
warhammer online gold
Buy WAR gold
Buy warhammer gold
Buy warhammer online gold
WAR Accounts
warhammer Accounts
warhammer online Accounts
Buy WAR Accounts
warhammer Accounts for sale
WAR Power leveling
WAR Powerleveling
warhammer Power leveling
warhammer online Power leveling
Buy WAR Powerleveling
Buy warhammer Powerleveling
Buy warhammer online Powerleveling
warhammer game card
warhammer cd key
warhammer online game card
warhammer online cd key
warhammer cdkey
warhammer online cdkey
Warhammer Gold
Warhammer Online Gold
Warhammer Accounts
Warhammer Power Leveling
Warhammer CD Key
Cheap Warhammer Gold
Cheap Warhammer online gold
Buy Cheap Warhammer Gold
Buy WAR Gold
Cheap WAR Accounts
Cheap warhammer Accounts
Cheap warhammer online Accounts
Buy Cheap WAR Accounts
Cheap Warhammer Power Leveling
Cheap Warhammer Online Power Leveling
Cheap WAR Power Leveling
buy warhammer cd key
buy warhammer online cd key
cheap warhammer online cd key
warhammer time card
Lotro Accounts
| Buy Lotro Accounts
Lord Of The Rings Online Power Leveling | Lord Of The Rings Online PowerLeveling
Lotro Cd Key | Lord Time Card
Lotro Gold | Lotro Gold Instant Delivery
lord of the rings online accounts | lord of the rings online accounts for sale
Lotro Power Leveling | Lotro Powerleveling
Lord Of The Rings Online Cd Key | Lord Of The Rings Online Time Card
LoTRO Gold
Lord of the Rings Online Gold
Buy Lotro Gold
Sell LoTRO Gold
LoTRO CD Key
LoTRO Europe Gold
Cheap LoTRO Accounts
Lord of the Rings Online Power Leveling
Lord of the Rings online CD Key
Cheap Lotro Gold
Lord of the Rings Online Gold
Buy Lotro Gold
Sell LoTRO Gold
LoTRO CD Key
LoTRO Europe Gold
Cheap LoTRO Accounts
Lord of the Rings Online Power Leveling
Lord of the Rings online CD Key
Cheap Lotro Gold
Buy Lotro Gold | Lord Of The Rings Online Gold
Lotro Accounts
| Buy Lotro Accounts
Lord Of The Rings Online Power Leveling | Lord Of The Rings Online PowerLeveling
Lotro Cd Key | Lord Time Card
Lotro Gold | Lotro Gold Instant Delivery
lord of the rings online accounts | lord of the rings online accounts for sale
Lotro Power Leveling | Lotro Powerleveling
Lord Of The Rings Online Cd Key | Lord Of The Rings Online Time Card
Lotro Accounts
| Buy Lotro Accounts
Lord Of The Rings Online Power Leveling | Lord Of The Rings Online PowerLeveling
Lotro Cd Key | Lord Time Card
Lotro Gold | Lotro Gold Instant Delivery
lord of the rings online accounts | lord of the rings online accounts for sale
Lotro Power Leveling | Lotro Powerleveling
Lord Of The Rings Online Cd Key | Lord Of The Rings Online Time Card
LoTRO Gold
Lord of the Rings Online Gold
Buy Lotro Gold
Sell LoTRO Gold
LoTRO CD Key
LoTRO Europe Gold
Cheap LoTRO Accounts
Lord of the Rings Online Power Leveling
Lord of the Rings online CD Key
Cheap Lotro Gold
Cheap Warhammer gold
Warhammer Online gold
WAR Gold
Buy Warhammer Gold
Warhammer Online Gold
Warhammer Gold for sale
Warhammer Accounts
Buy Warhammer Accounts
Cheap Warhammer Accounts
Warhammer Power leveling
WAR Power leveling
Warhammer Online Power Leveling
Warhammer CD Key
WAR CD Key
Warhammer Online CD Key
Warhammer Game Time Card