001/* 002 * Copyright 2013 Christopher Pheby 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.jadira.reflection.access.unsafe; 017 018import java.lang.reflect.Field; 019 020import org.jadira.reflection.access.api.FieldAccess; 021 022/** 023 * FieldAccess implementation based on sun.misc.Unsafe 024 * @param <C> The Class containing the Field to be accessed 025 */ 026public class UnsafeFieldAccess<C> implements FieldAccess<C> { 027 028 private static final UnsafeOperations UNSAFE_OPERATIONS = UnsafeOperations.getUnsafeOperations(); 029 030 private Field field; 031 private Class<C> declaringClass; 032 private Class<?> type; 033 private long fieldOffset; 034 035 @SuppressWarnings("unchecked") 036 private UnsafeFieldAccess(Field f) { 037 this.field = f; 038 this.declaringClass = (Class<C>) f.getDeclaringClass(); 039 this.type = (Class<?>) f.getType(); 040 this.fieldOffset = UNSAFE_OPERATIONS.getObjectFieldOffset(f); 041 } 042 043 @Override 044 public Class<C> declaringClass() { 045 return declaringClass; 046 } 047 048 @Override 049 public Class<?> fieldClass() { 050 return type; 051 } 052 053 @Override 054 public Field field() { 055 return field; 056 } 057 058 /** 059 * Get the offset position (in bytes) for this field 060 * @return Offset as a long 061 */ 062 public long fieldOffset() { 063 return fieldOffset; 064 } 065 066 @Override 067 public Object getValue(C parent) { 068 return UNSAFE_OPERATIONS.getObject(parent, fieldOffset); 069 } 070 071 @Override 072 public boolean getBooleanValue(C parent) { 073 throw new UnsupportedOperationException("Not supported for this field type"); 074 } 075 076 @Override 077 public byte getByteValue(C parent) { 078 throw new UnsupportedOperationException("Not supported for this field type"); 079 } 080 081 @Override 082 public char getCharValue(C parent) { 083 throw new UnsupportedOperationException("Not supported for this field type"); 084 } 085 086 @Override 087 public short getShortValue(C parent) { 088 throw new UnsupportedOperationException("Not supported for this field type"); 089 } 090 091 @Override 092 public int getIntValue(C parent) { 093 throw new UnsupportedOperationException("Not supported for this field type"); 094 } 095 096 @Override 097 public long getLongValue(C parent) { 098 throw new UnsupportedOperationException("Not supported for this field type"); 099 } 100 101 @Override 102 public float getFloatValue(C parent) { 103 throw new UnsupportedOperationException("Not supported for this field type"); 104 } 105 106 @Override 107 public double getDoubleValue(C parent) { 108 throw new UnsupportedOperationException("Not supported for this field type"); 109 } 110 111 @Override 112 public void putValue(C parent, Object newFieldValue) { 113 if (newFieldValue == null) { 114 UNSAFE_OPERATIONS.putNullObject(parent, fieldOffset); 115 } else { 116 UNSAFE_OPERATIONS.putObject(parent, fieldOffset, newFieldValue); 117 } 118 } 119 120 @Override 121 public void putBooleanValue(C parent, boolean newFieldValue) { 122 throw new UnsupportedOperationException("Not supported for this field type"); 123 } 124 125 @Override 126 public void putByteValue(C parent, byte newFieldValue) { 127 throw new UnsupportedOperationException("Not supported for this field type"); 128 } 129 130 @Override 131 public void putCharValue(C parent, char newFieldValue) { 132 throw new UnsupportedOperationException("Not supported for this field type"); 133 } 134 135 @Override 136 public void putShortValue(C parent, short newFieldValue) { 137 throw new UnsupportedOperationException("Not supported for this field type"); 138 } 139 140 @Override 141 public void putIntValue(C parent, int newFieldValue) { 142 throw new UnsupportedOperationException("Not supported for this field type"); 143 } 144 145 @Override 146 public void putLongValue(C parent, long newFieldValue) { 147 throw new UnsupportedOperationException("Not supported for this field type"); 148 } 149 150 @Override 151 public void putFloatValue(C parent, float newFieldValue) { 152 throw new UnsupportedOperationException("Not supported for this field type"); 153 } 154 155 @Override 156 public void putDoubleValue(C parent, double newFieldValue) { 157 throw new UnsupportedOperationException("Not supported for this field type"); 158 } 159 160 /** 161 * Get a new instance that can access the given Field 162 * @param f Field to be accessed 163 * @param <C> The type of class containing the field to be accessed 164 * @return New UnsafeFieldAccess instance 165 */ 166 public static <C> UnsafeFieldAccess<C> get(Field f) { 167 168 Class<?> type = f.getType(); 169 170 if (type.isPrimitive()) { 171 if (java.lang.Boolean.TYPE == type) { 172 return new UnsafeBooleanFieldAccess<C>(f); 173 } else if (java.lang.Byte.TYPE == type) { 174 return new UnsafeByteFieldAccess<C>(f); 175 } else if (java.lang.Character.TYPE == type) { 176 return new UnsafeCharFieldAccess<C>(f); 177 } else if (java.lang.Short.TYPE == type) { 178 return new UnsafeShortFieldAccess<C>(f); 179 } else if (java.lang.Integer.TYPE == type) { 180 return new UnsafeIntFieldAccess<C>(f); 181 } else if (java.lang.Long.TYPE == type) { 182 return new UnsafeLongFieldAccess<C>(f); 183 } else if (java.lang.Float.TYPE == type) { 184 return new UnsafeFloatFieldAccess<C>(f); 185 } else if (java.lang.Double.TYPE == type) { 186 return new UnsafeDoubleFieldAccess<C>(f); 187 } 188 } 189 return new UnsafeFieldAccess<C>(f); 190 } 191 192 /** 193 * UnsafeFieldAccess implementation suitable for accessing boolean fields 194 * @param <C> The Class containing the Field to be accessed 195 */ 196 public static class UnsafeBooleanFieldAccess<C> extends UnsafeFieldAccess<C> { 197 198 /** 199 * Construct a new instance for the given Field 200 * @param f The Field to be accessed 201 */ 202 public UnsafeBooleanFieldAccess(Field f) { 203 super(f); 204 } 205 206 @Override 207 public Boolean getValue(C parent) { 208 return Boolean.valueOf(getBooleanValue(parent)); 209 } 210 211 @Override 212 public boolean getBooleanValue(C parent) { 213 return UNSAFE_OPERATIONS.getBoolean(parent, super.fieldOffset); 214 } 215 216 @Override 217 public void putValue(C parent, Object newFieldValue) { 218 if (newFieldValue instanceof Boolean) { 219 putBooleanValue(parent, ((Boolean)newFieldValue).booleanValue()); 220 } else { 221 throw new IllegalArgumentException("Only a boolean value can be supplied to a boolean field"); 222 } 223 } 224 225 @Override 226 public void putBooleanValue(C parent, boolean newFieldValue) { 227 UNSAFE_OPERATIONS.putBoolean(parent, super.fieldOffset, newFieldValue); 228 } 229 } 230 231 /** 232 * UnsafeFieldAccess implementation suitable for accessing byte fields 233 * @param <C> The Class containing the Field to be accessed 234 */ 235 public static class UnsafeByteFieldAccess<C> extends UnsafeFieldAccess<C> { 236 237 /** 238 * Construct a new instance for the given Field 239 * @param f The Field to be accessed 240 */ 241 public UnsafeByteFieldAccess(Field f) { 242 super(f); 243 } 244 245 @Override 246 public Byte getValue(C parent) { 247 return Byte.valueOf(getByteValue(parent)); 248 } 249 250 @Override 251 public byte getByteValue(C parent) { 252 return UNSAFE_OPERATIONS.getByte(parent, super.fieldOffset); 253 } 254 255 @Override 256 public void putValue(C parent, Object newFieldValue) { 257 if (newFieldValue instanceof Byte) { 258 putByteValue(parent, ((Byte)newFieldValue).byteValue()); 259 } else { 260 throw new IllegalArgumentException("Only a byte value can be supplied to a byte field"); 261 } 262 } 263 264 @Override 265 public void putByteValue(C parent, byte newFieldValue) { 266 UNSAFE_OPERATIONS.putByte(parent, super.fieldOffset, newFieldValue); 267 } 268 } 269 270 /** 271 * UnsafeFieldAccess implementation suitable for accessing char fields 272 * @param <C> The Class containing the Field to be accessed 273 */ 274 public static class UnsafeCharFieldAccess<C> extends UnsafeFieldAccess<C> { 275 276 /** 277 * Construct a new instance for the given Field 278 * @param f The Field to be accessed 279 */ 280 public UnsafeCharFieldAccess(Field f) { 281 super(f); 282 } 283 284 @Override 285 public Character getValue(C parent) { 286 return Character.valueOf(getCharValue(parent)); 287 } 288 289 @Override 290 public char getCharValue(C parent) { 291 return UNSAFE_OPERATIONS.getChar(parent, super.fieldOffset); 292 } 293 294 @Override 295 public void putValue(C parent, Object newFieldValue) { 296 if (newFieldValue instanceof Character) { 297 putCharValue(parent, ((Character)newFieldValue).charValue()); 298 } else { 299 throw new IllegalArgumentException("Only a character value can be supplied to a char field"); 300 } 301 } 302 303 @Override 304 public void putCharValue(C parent, char newFieldValue) { 305 UNSAFE_OPERATIONS.putChar(parent, super.fieldOffset, newFieldValue); 306 } 307 } 308 309 /** 310 * UnsafeFieldAccess implementation suitable for accessing short fields 311 * @param <C> The Class containing the Field to be accessed 312 */ 313 public static class UnsafeShortFieldAccess<C> extends UnsafeFieldAccess<C> { 314 315 /** 316 * Construct a new instance for the given Field 317 * @param f The Field to be accessed 318 */ 319 public UnsafeShortFieldAccess(Field f) { 320 super(f); 321 } 322 323 @Override 324 public Short getValue(C parent) { 325 return Short.valueOf(getShortValue(parent)); 326 } 327 328 @Override 329 public short getShortValue(C parent) { 330 return UNSAFE_OPERATIONS.getShort(parent, super.fieldOffset); 331 } 332 333 @Override 334 public void putValue(C parent, Object newFieldValue) { 335 if (newFieldValue instanceof Short) { 336 putShortValue(parent, ((Short)newFieldValue).shortValue()); 337 } else if (newFieldValue instanceof Byte) { 338 putShortValue(parent, ((Byte)newFieldValue).shortValue()); 339 } else { 340 throw new IllegalArgumentException("Only a short, or byte value can be supplied to a short field"); 341 } 342 } 343 344 @Override 345 public void putShortValue(C parent, short newFieldValue) { 346 UNSAFE_OPERATIONS.putShort(parent, super.fieldOffset, newFieldValue); 347 } 348 } 349 350 /** 351 * UnsafeFieldAccess implementation suitable for accessing int fields 352 * @param <C> The Class containing the Field to be accessed 353 */ 354 public static class UnsafeIntFieldAccess<C> extends UnsafeFieldAccess<C> { 355 356 /** 357 * Construct a new instance for the given Field 358 * @param f The Field to be accessed 359 */ 360 public UnsafeIntFieldAccess(Field f) { 361 super(f); 362 } 363 364 @Override 365 public Integer getValue(C parent) { 366 return Integer.valueOf(getIntValue(parent)); 367 } 368 369 @Override 370 public int getIntValue(C parent) { 371 return UNSAFE_OPERATIONS.getInt(parent, super.fieldOffset); 372 } 373 374 @Override 375 public void putValue(C parent, Object newFieldValue) { 376 if (newFieldValue instanceof Integer) { 377 putIntValue(parent, ((Integer)newFieldValue).intValue()); 378 } else if (newFieldValue instanceof Short) { 379 putIntValue(parent, ((Short)newFieldValue).intValue()); 380 } else if (newFieldValue instanceof Byte) { 381 putIntValue(parent, ((Byte)newFieldValue).intValue()); 382 } else { 383 throw new IllegalArgumentException("Only an integer, short, or byte value can be supplied to an int field"); 384 } 385 } 386 387 @Override 388 public void putIntValue(C parent, int newFieldValue) { 389 UNSAFE_OPERATIONS.putInt(parent, super.fieldOffset, newFieldValue); 390 } 391 } 392 393 /** 394 * UnsafeFieldAccess implementation suitable for accessing long fields 395 * @param <C> The Class containing the Field to be accessed 396 */ 397 public static class UnsafeLongFieldAccess<C> extends UnsafeFieldAccess<C> { 398 399 /** 400 * Construct a new instance for the given Field 401 * @param f The Field to be accessed 402 */ 403 public UnsafeLongFieldAccess(Field f) { 404 super(f); 405 } 406 407 @Override 408 public Long getValue(C parent) { 409 return Long.valueOf(getLongValue(parent)); 410 } 411 412 @Override 413 public long getLongValue(C parent) { 414 return UNSAFE_OPERATIONS.getLong(parent, super.fieldOffset); 415 } 416 417 @Override 418 public void putValue(C parent, Object newFieldValue) { 419 if (newFieldValue instanceof Long) { 420 putLongValue(parent, ((Long)newFieldValue).longValue()); 421 } else if (newFieldValue instanceof Integer) { 422 putLongValue(parent, ((Integer)newFieldValue).longValue()); 423 } else if (newFieldValue instanceof Short) { 424 putLongValue(parent, ((Short)newFieldValue).longValue()); 425 } else if (newFieldValue instanceof Byte) { 426 putLongValue(parent, ((Byte)newFieldValue).longValue()); 427 } else { 428 throw new IllegalArgumentException("Only a long, integer, short, or byte value can be supplied to a long field"); 429 } 430 } 431 432 @Override 433 public void putLongValue(C parent, long newFieldValue) { 434 UNSAFE_OPERATIONS.putLong(parent, super.fieldOffset, newFieldValue); 435 } 436 } 437 438 /** 439 * UnsafeFieldAccess implementation suitable for accessing float fields 440 * @param <C> The Class containing the Field to be accessed 441 */ 442 public static class UnsafeFloatFieldAccess<C> extends UnsafeFieldAccess<C> { 443 444 /** 445 * Construct a new instance for the given Field 446 * @param f The Field to be accessed 447 */ 448 public UnsafeFloatFieldAccess(Field f) { 449 super(f); 450 } 451 452 @Override 453 public Float getValue(C parent) { 454 return Float.valueOf(getFloatValue(parent)); 455 } 456 457 @Override 458 public float getFloatValue(C parent) { 459 return UNSAFE_OPERATIONS.getFloat(parent, super.fieldOffset); 460 } 461 462 @Override 463 public void putValue(C parent, Object newFieldValue) { 464 if (newFieldValue instanceof Float) { 465 putFloatValue(parent, ((Float)newFieldValue).floatValue()); 466 } else { 467 throw new IllegalArgumentException("Only a float value can be supplied to a float field"); 468 } 469 } 470 471 @Override 472 public void putFloatValue(C parent, float newFieldValue) { 473 UNSAFE_OPERATIONS.putFloat(parent, super.fieldOffset, newFieldValue); 474 } 475 } 476 477 /** 478 * UnsafeFieldAccess implementation suitable for accessing double fields 479 * @param <C> The Class containing the Field to be accessed 480 */ 481 public static class UnsafeDoubleFieldAccess<C> extends UnsafeFieldAccess<C> { 482 483 /** 484 * Construct a new instance for the given Field 485 * @param f The Field to be accessed 486 */ 487 public UnsafeDoubleFieldAccess(Field f) { 488 super(f); 489 } 490 491 @Override 492 public Double getValue(C parent) { 493 return Double.valueOf(getDoubleValue(parent)); 494 } 495 496 @Override 497 public double getDoubleValue(C parent) { 498 return UNSAFE_OPERATIONS.getDouble(parent, super.fieldOffset); 499 } 500 501 @Override 502 public void putValue(C parent, Object newFieldValue) { 503 if (newFieldValue instanceof Double) { 504 putDoubleValue(parent, ((Double)newFieldValue).doubleValue()); 505 } else { 506 throw new IllegalArgumentException("Only a double value can be supplied to a double field"); 507 } 508 } 509 510 @Override 511 public void putDoubleValue(C parent, double newFieldValue) { 512 UNSAFE_OPERATIONS.putDouble(parent, super.fieldOffset, newFieldValue); 513 } 514 } 515}