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

com.hcl.domino.jna.internal.gc.handles.ReadUtil Maven / Gradle / Ivy

There is a newer version: 1.41.0
Show newest version
/*
 * ==========================================================================
 * Copyright (C) 2019-2022 HCL America, Inc. ( http://www.hcl.com/ )
 *                            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 .
 *
 * 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 com.hcl.domino.jna.internal.gc.handles;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import com.hcl.domino.commons.util.NotesErrorUtils;
import com.hcl.domino.data.DominoDateRange;
import com.hcl.domino.jna.internal.ItemDecoder;
import com.hcl.domino.jna.internal.Mem;
import com.sun.jna.Pointer;

/**
 * Utility methods to access memory associated with a handle.
 * 
 * @author Tammo Riedinger
 */
public class ReadUtil {

	/**
	 * Method to lock the given handle and retrieve the memory pointer to access the data.
	 * The pointer will be handed to the callback which can then extract the data safely.
	 *  
	 * @param 		the type of result to be generated by the callback
	 * @param handle	the memory-handle
	 * @param autoFree	true, if the memory held by the handle should be freed after this operation
	 * @param callback		the callback to read the data
	 * @return			the data as created by the callback
	 */
	public static  R accessMemory(DHANDLE handle, boolean autoFree, final MemoryAccess callback) {
		return LockUtil.lockHandle(handle, (hMemoryByVal) -> {
			if (!hMemoryByVal.isNull()) {
				Pointer ptr = Mem.OSLockObject(hMemoryByVal);
				try {
					return callback.access(ptr);
				}
				finally {
					Mem.OSUnlockObject(hMemoryByVal);
					
					if (autoFree) {
						NotesErrorUtils.checkResult(
							Mem.OSMemFree(hMemoryByVal)
						);
					}
				}
			}
			return callback.handleIsNull();
		});
	}
	
	/**
	 * Callback interface to ensure exclusive handle access across threads.
	 * 
	 * @author Tammo Riedinger
	 *
	 * @param  result type
	 */
	public interface MemoryAccess {

		/**
		 * Implement this method with code reading data from the memory pointer
		 * 
		 * @param ptr 	the memory pointer
		 * @return result
		 */
		R access(Pointer ptr);
		
		/**
		 * This method is called, when the given handle contained a null value.
		 * Defaults to null
		 * 
		 * @return		the result
		 */
		default R handleIsNull() {
			return null;
		}
	}

	/**
	 * Method to read all {@link DominoDateRange}-instances from the list-values of the given range
	 * 
	 * @param hRange		the handle to the range
	 * @param freeMemory	true to free the memory used by the range-handle
	 * @return				the list of found {@link DominoDateRange}
	 */
	public static List readDateRange(DHANDLE hRange, boolean freeMemory) {
		return accessMemory(hRange, freeMemory, new MemoryAccess>() {
			@Override
			public List access(Pointer ptr) {
				List range = ItemDecoder.decodeTimeDateListAsNotesTimeDate(ptr);
				
				return range.stream().filter((currObj) -> {
					return (currObj instanceof DominoDateRange);
				}).map(DominoDateRange.class::cast).collect(Collectors.toList());
			}
			
			@Override
			public List handleIsNull() {
				return Collections.emptyList();
			}
		});
	}
}