java.lang.NoClassDefFoundError: JVideoOCR - java

public class JVideoOCR extends Observable
{
public static final int STATUS_DOCUMENT_REMOVED = 1;
public native boolean init();
public native boolean terminate();
public native boolean startRead();
public native boolean stopRead();
static {
System.loadLibrary("JVideoOCR"); }
IOCRDataHandler dataHandler = null;
public void setOCRDataHandler(IOCRDataHandler handler)
{
dataHandler = handler;
}
public void MRZDataCallback(MRZData data)
{
if (dataHandler != null)
dataHandler.handleOCRData(data);
}
private void returnStatus(int status)
{
switch (status)
{
case STATUS_DOCUMENT_REMOVED:
setChanged() ;
notifyObservers(new Integer(2)) ;
break;
}
}
}
This code is working fine whent plced that java file to default package but if i am shifting this java file to package it's not working.

Related

AWS SDK v2 SdkAsyncHttpClient implementation Using Java 11 java.net.http HttpClient sendAsync

I am trying to implement a SdkAsyncHttpClient that uses Java 11's java.net.http.HttpClient (specifically sendAsync). SdkAsyncHttpClient has one method to implement CompletableFuture<Void> execute(AsyncExecuteRequest asyncExecuteRequest). The AsyncExecuteRequest provides a way to get details about the HTTP request and, crucially, a SdkHttpContentPublisher. This goes into the paradigm of a reactive Publisher/Subscribe model - which HttpClient.sendAsync seems to have builtin support for. I seem to be close to an implementation but (at least) one crucial step is missing as I can't seem to get the returned future to ever be completed.
I think that I am probably missing something fundamental to link the two together in a straight-forward way but so far it eludes me.
Here is my attempt at a naive (and very simple) implementation:
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import software.amazon.awssdk.http.Protocol;
import software.amazon.awssdk.http.SdkHttpConfigurationOption;
import software.amazon.awssdk.http.SdkHttpRequest;
import software.amazon.awssdk.http.async.AsyncExecuteRequest;
import software.amazon.awssdk.http.async.SdkAsyncHttpClient;
import software.amazon.awssdk.http.async.SdkHttpContentPublisher;
import software.amazon.awssdk.utils.AttributeMap;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Flow;
import static java.net.http.HttpClient.Version.HTTP_1_1;
import static java.net.http.HttpClient.Version.HTTP_2;
import static software.amazon.awssdk.http.Protocol.HTTP2;
import static software.amazon.awssdk.http.SdkHttpConfigurationOption.CONNECTION_TIMEOUT;
import static software.amazon.awssdk.http.SdkHttpConfigurationOption.PROTOCOL;
import static software.amazon.awssdk.http.SdkHttpConfigurationOption.READ_TIMEOUT;
public class JavaAsyncHttpClient implements SdkAsyncHttpClient {
private final HttpClient httpClient;
public JavaAsyncHttpClient(AttributeMap options) {
this.httpClient = HttpClient.newBuilder()
.connectTimeout(options.get(CONNECTION_TIMEOUT))
.version(options.get(PROTOCOL) == HTTP2 ? HTTP_2 : HTTP_1_1)
.build();
}
#Override
public CompletableFuture<Void> execute(AsyncExecuteRequest asyncExecuteRequest) {
SdkHttpRequest request = asyncExecuteRequest.request();
HttpRequest.Builder requestBuilder = HttpRequest.newBuilder().uri(request.getUri());
for (Map.Entry<String, List<String>> header : request.headers().entrySet()) {
// avoid java.lang.IllegalArgumentException: restricted header name: "Content-Length"
if (!header.getKey().equalsIgnoreCase("Content-Length") && !header.getKey().equalsIgnoreCase("Host")) {
for (String headerVal : header.getValue()) {
requestBuilder = requestBuilder.header(header.getKey(), headerVal);
}
}
}
switch (request.method()) {
case POST:
requestBuilder = requestBuilder.POST(HttpRequest.BodyPublishers.fromPublisher(
toFlowPublisher(asyncExecuteRequest.requestContentPublisher())));
break;
case PUT:
requestBuilder = requestBuilder.PUT(HttpRequest.BodyPublishers.fromPublisher(
toFlowPublisher(asyncExecuteRequest.requestContentPublisher())));
break;
case DELETE:
requestBuilder = requestBuilder.DELETE();
break;
case HEAD:
requestBuilder = requestBuilder.method("HEAD", HttpRequest.BodyPublishers.noBody());
break;
case PATCH:
throw new UnsupportedOperationException("PATCH not supported");
case OPTIONS:
requestBuilder = requestBuilder.method("OPTIONS", HttpRequest.BodyPublishers.noBody());
break;
}
// Need to use BodyHandlers.ofPublisher() or is that a dead end? How can link up the AWS Publisher/Subscribers
Subscriber<ByteBuffer> subscriber = new BaosSubscriber(new CompletableFuture<>());
asyncExecuteRequest.requestContentPublisher().subscribe(subscriber);
HttpRequest httpRequest = requestBuilder.build();
return httpClient.sendAsync(httpRequest, HttpResponse.BodyHandlers.fromSubscriber(toFlowSubscriber(subscriber)))
.thenApply(voidHttpResponse -> null);
}
private Flow.Subscriber<? super List<ByteBuffer>> toFlowSubscriber(Subscriber<ByteBuffer> subscriber) {
return new Flow.Subscriber<>() {
#Override
public void onSubscribe(Flow.Subscription subscription) {
subscriber.onSubscribe(toAwsSubscription(subscription));
}
#Override
public void onNext(List<ByteBuffer> item) {
subscriber.onNext(item.get(0));
}
#Override
public void onError(Throwable throwable) {
subscriber.onError(throwable);
}
#Override
public void onComplete() {
subscriber.onComplete();
}
};
}
private Subscription toAwsSubscription(Flow.Subscription subscription) {
return new Subscription() {
#Override
public void request(long n) {
subscription.request(n);
}
#Override
public void cancel() {
subscription.cancel();
}
};
}
private Flow.Publisher<ByteBuffer> toFlowPublisher(SdkHttpContentPublisher requestContentPublisher) {
return subscriber -> requestContentPublisher.subscribe(toAwsSubscriber(subscriber));
}
private Subscriber<? super ByteBuffer> toAwsSubscriber(Flow.Subscriber<? super ByteBuffer> subscriber) {
return new Subscriber<>() {
#Override
public void onSubscribe(Subscription s) {
subscriber.onSubscribe(toFlowSubscription(s));
}
#Override
public void onNext(ByteBuffer byteBuffer) {
subscriber.onNext(byteBuffer);
}
#Override
public void onError(Throwable t) {
subscriber.onError(t);
}
#Override
public void onComplete() {
subscriber.onComplete();
}
};
}
private Flow.Subscription toFlowSubscription(Subscription subscription) {
return new Flow.Subscription() {
#Override
public void request(long n) {
subscription.request(n);
}
#Override
public void cancel() {
subscription.cancel();
}
};
}
#Override
public void close() {}
private static class BaosSubscriber implements Subscriber<ByteBuffer> {
private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
private final CompletableFuture<ByteArrayOutputStream> streamFuture;
private Subscription subscription;
private BaosSubscriber(CompletableFuture<ByteArrayOutputStream> streamFuture) {
this.streamFuture = streamFuture;
}
#Override
public void onSubscribe(Subscription subscription) {
this.subscription = subscription;
subscription.request(Long.MAX_VALUE);
}
#Override
public void onNext(ByteBuffer byteBuffer) {
try {
baos.write(BinaryUtils.copyBytesFrom(byteBuffer));
this.subscription.request(Long.MAX_VALUE);
} catch (IOException e) {
// Should never happen
streamFuture.completeExceptionally(e);
}
}
#Override
public void onError(Throwable t) {
streamFuture.completeExceptionally(t);
}
#Override
public void onComplete() {
streamFuture.complete(baos);
}
}
What am I missing here? Returning a future that completes with null is following the spec of SdkAsyncHttpClient so clearly the HTTP response needs to somehow be sent to a subscriber on the AWS side of things - but that's where I get lost.
Edit: Just found this via Googling: https://github.com/rmcsoft/j11_aws_http_client/blob/63f05326990317c59f1863be55942054769b437e/src/main/java/com/rmcsoft/aws/http/proxy/BodyHandlerProxy.java - going to see if the answers lie within.
Unbeknownst to me when I asked this question - this ground has already been tread upon. Nikita Skornyakov (#rmcsoft on Github) implemented this exact thing (a SdkAsyncHttpClient implementation that uses Java 11's HTTP client (java.net.http). It can be found here: https://github.com/rmcsoft/j11_aws_http_client (MIT licensed).
For completion's sake here is a self-contained (which you should probably never use) Java implementation:
package com.dow.as2;
import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import software.amazon.awssdk.http.AbortableInputStream;
import software.amazon.awssdk.http.Protocol;
import software.amazon.awssdk.http.SdkHttpConfigurationOption;
import software.amazon.awssdk.http.SdkHttpFullResponse;
import software.amazon.awssdk.http.SdkHttpRequest;
import software.amazon.awssdk.http.SdkHttpResponse;
import software.amazon.awssdk.http.async.AsyncExecuteRequest;
import software.amazon.awssdk.http.async.SdkAsyncHttpClient;
import software.amazon.awssdk.http.async.SdkAsyncHttpResponseHandler;
import software.amazon.awssdk.http.async.SdkHttpContentPublisher;
import software.amazon.awssdk.utils.AttributeMap;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Flow;
import java.util.concurrent.atomic.AtomicReference;
import static java.net.http.HttpClient.Version.HTTP_1_1;
import static java.net.http.HttpClient.Version.HTTP_2;
import static software.amazon.awssdk.http.Protocol.HTTP2;
import static software.amazon.awssdk.http.SdkHttpConfigurationOption.CONNECTION_TIMEOUT;
import static software.amazon.awssdk.http.SdkHttpConfigurationOption.PROTOCOL;
import static software.amazon.awssdk.http.SdkHttpConfigurationOption.READ_TIMEOUT;
public class JavaAsyncHttpClient implements SdkAsyncHttpClient {
private static final String CLIENT_NAME = "JavaNetAsyncHttpClient";
private final HttpClient httpClient;
private JavaAsyncHttpClient(AttributeMap options) {
this.httpClient = HttpClient.newBuilder()
.connectTimeout(options.get(CONNECTION_TIMEOUT))
.version(options.get(PROTOCOL) == HTTP2 ? HTTP_2 : HTTP_1_1)
.build();
}
public static Builder builder() {
return new DefaultBuilder();
}
/**
* Create a {#link HttpClient} client with the default properties
*
* #return a {#link JavaHttpClient}
*/
public static SdkAsyncHttpClient create() {
return new DefaultBuilder().build();
}
#Override
public CompletableFuture<Void> execute(AsyncExecuteRequest asyncExecuteRequest) {
SdkHttpRequest request = asyncExecuteRequest.request();
HttpRequest.Builder requestBuilder = HttpRequest.newBuilder().uri(request.getUri());
for (Map.Entry<String, List<String>> header : request.headers().entrySet()) {
// avoid java.lang.IllegalArgumentException: restricted header name: "Content-Length"
if (!header.getKey().equalsIgnoreCase("Content-Length") && !header.getKey().equalsIgnoreCase("Host")) {
for (String headerVal : header.getValue()) {
requestBuilder = requestBuilder.header(header.getKey(), headerVal);
}
}
}
switch (request.method()) {
case POST:
requestBuilder = requestBuilder.POST(new BodyPublisherProxy(asyncExecuteRequest.requestContentPublisher()));
break;
case PUT:
requestBuilder = requestBuilder.PUT(new BodyPublisherProxy(asyncExecuteRequest.requestContentPublisher()));
break;
case DELETE:
requestBuilder = requestBuilder.DELETE();
break;
case HEAD:
requestBuilder = requestBuilder.method("HEAD", HttpRequest.BodyPublishers.noBody());
break;
case PATCH:
throw new UnsupportedOperationException("PATCH not supported");
case OPTIONS:
requestBuilder = requestBuilder.method("OPTIONS", HttpRequest.BodyPublishers.noBody());
break;
}
// Need to use BodyHandlers.ofPublisher() or is that a dead end? How can link up the AWS Publisher/Subscribers
// with HttpClient sendAsync Flow.Publishers/Flow.Subscriber?
var responseHandler = asyncExecuteRequest.responseHandler();
var bodyHandler = new BodyHandlerProxy(asyncExecuteRequest.responseHandler());
return httpClient
.sendAsync(requestBuilder.build(), bodyHandler)
.thenApply(HttpResponse::body)
.thenApply(this::toAwsPublisher)
.thenAccept(responseHandler::onStream)
.exceptionally(t -> {
responseHandler.onError(t);
return null;
});
}
private Subscription toAwsSubscription(Flow.Subscription subscription) {
return new Subscription() {
#Override
public void request(long n) {
subscription.request(n);
}
#Override
public void cancel() {
subscription.cancel();
}
};
}
private Flow.Subscriber<? super ByteBuffer> toFlowSubscriber(Subscriber<? super ByteBuffer> subscriber) {
return new Flow.Subscriber<>() {
#Override
public void onSubscribe(Flow.Subscription subscription) {
subscriber.onSubscribe(toAwsSubscription(subscription));
}
#Override
public void onNext(ByteBuffer item) {
subscriber.onNext(item);
}
#Override
public void onError(Throwable throwable) {
subscriber.onError(throwable);
}
#Override
public void onComplete() {
subscriber.onComplete();
}
};
}
private Publisher<ByteBuffer> toAwsPublisher(Flow.Publisher<ByteBuffer> publisher) {
return new Publisher<>() {
#Override
public void subscribe(Subscriber<? super ByteBuffer> s) {
publisher.subscribe(toFlowSubscriber(s));
}
};
}
#Override
public void close() {
}
#Override
public String clientName() {
return CLIENT_NAME;
}
private static final class DefaultBuilder implements Builder {
private final AttributeMap.Builder standardOptions = AttributeMap.builder();
private DefaultBuilder() {
}
/**
* Sets the read timeout to a specified timeout. A timeout of zero is interpreted as an infinite timeout.
*
* #param socketTimeout the timeout as a {#link Duration}
* #return this object for method chaining
*/
public Builder socketTimeout(Duration socketTimeout) {
standardOptions.put(READ_TIMEOUT, socketTimeout);
return this;
}
public void setSocketTimeout(Duration socketTimeout) {
socketTimeout(socketTimeout);
}
/**
* Sets the connect timeout to a specified timeout. A timeout of zero is interpreted as an infinite timeout.
*
* #param connectionTimeout the timeout as a {#link Duration}
* #return this object for method chaining
*/
public Builder connectionTimeout(Duration connectionTimeout) {
standardOptions.put(CONNECTION_TIMEOUT, connectionTimeout);
return this;
}
public void setConnectionTimeout(Duration connectionTimeout) {
connectionTimeout(connectionTimeout);
}
public Builder protocol(Protocol protocol) {
standardOptions.put(PROTOCOL, protocol);
return this;
}
/**
* Used by the SDK to create a {#link SdkAsyncHttpClient} with service-default values if no other values have been configured
*
* #param serviceDefaults Service specific defaults. Keys will be one of the constants defined in
* {#link SdkHttpConfigurationOption}.
* #return an instance of {#link SdkAsyncHttpClient}
*/
#Override
public SdkAsyncHttpClient buildWithDefaults(AttributeMap serviceDefaults) {
return new JavaAsyncHttpClient(standardOptions.build()
.merge(serviceDefaults)
.merge(SdkHttpConfigurationOption.GLOBAL_HTTP_DEFAULTS));
}
}
private static class BodyHandlerProxy implements HttpResponse.BodyHandler<Flow.Publisher<ByteBuffer>> {
private final SdkAsyncHttpResponseHandler handler;
private BodyHandlerProxy(SdkAsyncHttpResponseHandler responseHandler) {
Objects.requireNonNull(responseHandler);
handler = responseHandler;
}
#Override
public HttpResponse.BodySubscriber<Flow.Publisher<ByteBuffer>> apply(HttpResponse.ResponseInfo responseInfo) {
handler.onHeaders(new SdkHttpHeadersProxy(responseInfo));
return new BodySubscriberProxy();
}
}
static final class SubscriberRef {
Flow.Subscriber<? super ByteBuffer> ref;
SubscriberRef(Flow.Subscriber<? super ByteBuffer> subscriber) {
ref = subscriber;
}
Flow.Subscriber<? super ByteBuffer> get() {
return ref;
}
Flow.Subscriber<? super ByteBuffer> clear() {
Flow.Subscriber<? super ByteBuffer> res = ref;
ref = null;
return res;
}
}
static final class SubscriptionRef implements Flow.Subscription {
final Flow.Subscription subscription;
final SubscriberRef subscriberRef;
SubscriptionRef(Flow.Subscription subscription,
SubscriberRef subscriberRef) {
this.subscription = subscription;
this.subscriberRef = subscriberRef;
}
#Override
public void request(long n) {
if (subscriberRef.get() != null) {
subscription.request(n);
}
}
#Override
public void cancel() {
subscription.cancel();
subscriberRef.clear();
}
void subscribe() {
Flow.Subscriber<?> subscriber = subscriberRef.get();
if (subscriber != null) {
subscriber.onSubscribe(this);
}
}
#Override
public String toString() {
return String
.format("SubscriptionRef/%s#%s", subscription.getClass().getName(), System.identityHashCode(subscription));
}
}
// Adapted from jdk.internal.net.http.ResponseSubscribers.PublishingBodySubscriber
private static class BodySubscriberProxy implements HttpResponse.BodySubscriber<Flow.Publisher<ByteBuffer>> {
private final CompletableFuture<Flow.Subscription>
subscriptionCF = new CompletableFuture<>();
private final CompletableFuture<SubscriberRef>
subscribedCF = new CompletableFuture<>();
private AtomicReference<SubscriberRef>
subscriberRef = new AtomicReference<>();
private final CompletableFuture<Flow.Publisher<ByteBuffer>> body =
subscriptionCF.thenCompose(
(s) -> CompletableFuture.completedFuture(this::subscribe));
private final CompletableFuture<Void> completionCF;
BodySubscriberProxy() {
completionCF = new CompletableFuture<>();
completionCF.whenComplete(
(r, t) -> subscribedCF.thenAccept(s -> complete(s, t)));
}
public CompletionStage<Flow.Publisher<ByteBuffer>> getBody() {
return body;
}
// This is a callback for the subscribedCF.
// Do not call directly!
private void complete(SubscriberRef ref, Throwable t) {
Flow.Subscriber<?> s = ref.clear();
// maybe null if subscription was cancelled
if (s == null) {
return;
}
if (t != null) {
s.onError(t);
return;
}
try {
s.onComplete();
} catch (Throwable x) {
s.onError(x);
}
}
private void signalError(Throwable err) {
completionCF.completeExceptionally(err != null ? err : new IllegalArgumentException("null throwable"));
}
private void signalComplete() {
completionCF.complete(null);
}
private void subscribe(Flow.Subscriber<? super ByteBuffer> subscriber) {
if (subscriber == null) {
throw new IllegalArgumentException("subscriber must not be null");
}
SubscriberRef ref = new SubscriberRef(subscriber);
if (subscriberRef.compareAndSet(null, ref)) {
subscriptionCF.thenAccept((s) -> {
SubscriptionRef subscription = new SubscriptionRef(s, ref);
try {
subscription.subscribe();
subscribedCF.complete(ref);
} catch (Throwable t) {
subscription.cancel();
}
});
} else {
subscriber.onSubscribe(new Flow.Subscription() {
#Override
public void request(long n) {
}
#Override
public void cancel() {
}
});
subscriber.onError(new IllegalStateException("This publisher has already one subscriber"));
}
}
#Override
public void onSubscribe(Flow.Subscription subscription) {
subscriptionCF.complete(subscription);
}
#Override
public void onNext(List<ByteBuffer> item) {
try {
SubscriberRef ref = subscriberRef.get();
Flow.Subscriber<? super ByteBuffer> subscriber = ref.get();
if (subscriber != null) { // may be null if subscription was cancelled.
item.forEach(subscriber::onNext);
}
} catch (Throwable err) {
signalError(err);
subscriptionCF.thenAccept(Flow.Subscription::cancel);
}
}
#Override
public void onError(Throwable throwable) {
// onError can be called before request(1), and therefore can
// be called before subscriberRef is set.
signalError(throwable);
}
#Override
public void onComplete() {
// cannot be called before onSubscribe()
if (!subscriptionCF.isDone()) {
signalError(new InternalError("onComplete called before onSubscribed"));
} else {
// onComplete can be called before request(1),
// and therefore can be called before subscriberRef
// is set.
signalComplete();
}
}
}
private static class SdkHttpHeadersProxy implements SdkHttpFullResponse {
private final HttpResponse.ResponseInfo responseInfo;
private SdkHttpHeadersProxy(HttpResponse.ResponseInfo responseInfo) {
Objects.requireNonNull(responseInfo);
this.responseInfo = responseInfo;
}
#Override
public Optional<String> statusText() {
return Optional.empty();
}
#Override
public int statusCode() {
return responseInfo.statusCode();
}
#Override
public Map<String, List<String>> headers() {
return responseInfo.headers().map();
}
#Override
public Builder toBuilder() {
return SdkHttpResponse
.builder()
.headers(headers())
.statusCode(statusCode());
}
#Override
public Optional<AbortableInputStream> content() {
return Optional.empty(); // will be available at later stage
}
}
private class BodyPublisherProxy implements HttpRequest.BodyPublisher {
private final SdkHttpContentPublisher publisher;
private BodyPublisherProxy(SdkHttpContentPublisher publisher) {
Objects.requireNonNull(publisher);
this.publisher = publisher;
}
#Override
public long contentLength() {
return publisher.contentLength().orElse(-1L);
}
#Override
public void subscribe(Flow.Subscriber<? super ByteBuffer> subscriber) {
publisher.subscribe(toAwsSubscriber(subscriber));
}
}
private Flow.Subscription toFlowSubscription(Subscription subscription) {
return new Flow.Subscription() {
#Override
public void request(long n) {
subscription.request(n);
}
#Override
public void cancel() {
subscription.cancel();
}
};
}
private Subscriber<? super ByteBuffer> toAwsSubscriber(Flow.Subscriber<? super ByteBuffer> subscriber) {
return new Subscriber<>() {
#Override
public void onSubscribe(Subscription s) {
subscriber.onSubscribe(toFlowSubscription(s));
}
#Override
public void onNext(ByteBuffer byteBuffer) {
subscriber.onNext(byteBuffer);
}
#Override
public void onError(Throwable t) {
subscriber.onError(t);
}
#Override
public void onComplete() {
subscriber.onComplete();
}
};
}
}
I recommend using the j11_aws_http_client linked previously over this monstrosity (it only handles a fraction of the restricted headers, for example). The above code is almost completely copy and pasted from that Github project.
The implementation could be simplified drastically if there was a way to use java.net.http.BodySubscribers.ofPublisher (which is a Flow.Publisher<List<ByteBuffer>>>).

How to implement and fire an event when a change occurs in a property of `T` in `List<T>` within the owning class in Java

Any clue if it is possible to convert code below to Java (Android) from C#?
It is based on my prev.question
How to implement and fire an event when a change occurs in a property of `T` in `List<T>` within the owning class
public class ItemPropertyChangedNotifyingList<T> : IList<T>, INotifyPropertyChanged where T : INotifyPropertyChanged
{
private List<T> _listImplementation = new List<T>();
public void Add(T item)
{
item.PropertyChanged += ItemOnPropertyChanged;
_listImplementation.Add(item);
}
private void ItemOnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
PropertyChanged?.Invoke(sender, e);
}
public IEnumerator<T> GetEnumerator()
{
return _listImplementation.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)_listImplementation).GetEnumerator();
}
public void Clear()
{
_listImplementation.ForEach(x => x.PropertyChanged -= ItemOnPropertyChanged);
_listImplementation.Clear();
}
public bool Contains(T item)
{
return _listImplementation.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
_listImplementation.CopyTo(array, arrayIndex);
}
public bool Remove(T item)
{
item.PropertyChanged -= ItemOnPropertyChanged;
return _listImplementation.Remove(item);
}
public int Count => _listImplementation.Count;
public bool IsReadOnly => false;
public int IndexOf(T item)
{
return _listImplementation.IndexOf(item);
}
public void Insert(int index, T item)
{
item.PropertyChanged += ItemOnPropertyChanged;
_listImplementation.Insert(index, item);
}
public void RemoveAt(int index)
{
_listImplementation.RemoveAt(index);
}
public T this[int index]
{
get => _listImplementation[index];
set => _listImplementation[index] = value;
}
public event PropertyChangedEventHandler PropertyChanged;
}
Have we use PropertyChangeListener for this task? Like it is shown here.
public FocusManagerListener implements PropertyChangeListener {
public void propertyChange(PropertyChangeEvent e) {
String propertyName = e.getPropertyName();
if ("focusOwner".equals(propertyName) {
...
} else if ("focusedWindow".equals(propertyName) {
...
}
}
...
}
I just ported ItemPropertyChangedNotifyingList to ItemChangeList.
In code, I changed this part.
Used 'ArrayList' to hold elements instead of 'List` in C#
In copyTo, I used Java 8 Stream. Since you tag 'android', I used Lightweight-Stream-API to achieve same feature of copyTo.
Java doesn't support get, set syntax, i divide to two methods.
import com.annimon.stream.Stream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ItemChangedList<T> {
private List<T> _listImplementation = new ArrayList<>();
private List<OnPropertyChangedObserver<T>> _changedObserverList = new ArrayList<>();
public static final String ITEM_ADDED = "bbed36af-0b7b-4e53-abc9-02d6a14d7f34";
public static final String ITEM_REMOVED = "7390116e-586d-4e62-9343-5b82b0a8c6c5";
public void add(T item) {
sendPropertyChanged(item, ITEM_ADDED);
_listImplementation.add(item);
}
public Iterator<T> iterator() {
return _listImplementation.iterator();
}
public void clear() {
for (T item : _listImplementation) {
sendPropertyChanged(item, ITEM_REMOVED);
}
_listImplementation.clear();
}
public boolean contains(T item) {
return _listImplementation.contains(item);
}
public void copyTo(T[] array, int arrayIndex) {
// Using https://github.com/aNNiMON/Lightweight-Stream-API
_listImplementation.addAll(Stream.of(array).skip(arrayIndex).toList());
// Traditional Java way
// _listImplementation.addAll(Arrays.stream(array).skip(arrayIndex).collect(Collectors.toList()));
}
public boolean remove(T item) {
sendPropertyChanged(item, ITEM_REMOVED);
return _listImplementation.remove(item);
}
public int count() {
return _listImplementation.size();
}
public boolean isReadOnly() {
return false;
}
public int indexOf(T item) {
return _listImplementation.indexOf(item);
}
public void insert(int index, T item) {
sendPropertyChanged(item, ITEM_ADDED);
_listImplementation.add(index, item);
}
public void removeAt(int index) {
_listImplementation.remove(index);
}
public T get(int index) {
return _listImplementation.get(index);
}
public void set(int index, T item) {
_listImplementation.set(index, item);
}
public void addObserver(OnPropertyChangedObserver<T> observer) {
_changedObserverList.add(observer);
}
public void removeObserver(OnPropertyChangedObserver<T> observer) {
_changedObserverList.remove(observer);
}
public void clearObserver() {
_changedObserverList.clear();
}
private void sendPropertyChanged(T item, String args) {
for (OnPropertyChangedObserver<T> observer : _changedObserverList) {
observer.onChanged(item, args);
}
}
public interface OnPropertyChangedObserver<T> {
void onChanged(T item, String args);
}
}
Other way is extends ArrayList instead _listImplementation. it can be provide more functionally. Personally, I prefer this way. Gist
Edit-1) Oh, i forget add args in OnPropertyChangeObserver.
Edit-2) Let Kotlin optimize this! Gist

Trouble calling a non-static method from an abstract class

I'm trying to call getSetting() from SettingsItem.java in SingleChoiceViewHolder.java. Is there a way to call getSetting() while keeping SettingsItem a non-static abstract class? Here's what I tried to add to SingleChoiceViewHolder.java, however Android Studio says that 'SettingsItem' is abstract; cannot be instantiated.:
SettingsItem instance = new SettingsItem();
instance.getSetting();
IntSetting setting = (IntSetting) getSetting();
mTextSettingDescription.setText(setting.getValue());
I also tried I tried converting SettingsItem to an interface and implementing it alongside SingleChoiceViewHolder extends SettingViewHolder but the original problem still remained.
The files are attached below.
SingleChoiceViewHolder.java:
public final class SingleChoiceViewHolder extends SettingViewHolder
{
private SingleChoiceSetting mItem;
private TextView mTextSettingName;
private TextView mTextSettingDescription;
public SingleChoiceViewHolder(View itemView, SettingsAdapter adapter)
{
super(itemView, adapter);
}
#Override
protected void findViews(View root)
{
mTextSettingName = (TextView) root.findViewById(R.id.text_setting_name);
mTextSettingDescription = (TextView) root.findViewById(R.id.text_setting_description);
}
#Override
public void bind(SettingsItem item)
{
mItem = (SingleChoiceSetting) item;
mTextSettingName.setText(item.getNameId());
if (item.getDescriptionId() == R.string.dynamic_descriptionId)
{
SettingsItem instance = new SettingsItem();
instance.getSetting();
IntSetting setting = (IntSetting) getSetting();
mTextSettingDescription.setText(setting.getValue());
}
if (item.getDescriptionId() > 0 && item.getDescriptionId() != R.string.dynamic_descriptionId)
{
mTextSettingDescription.setText(item.getDescriptionId());
}
}
#Override
public void onClick(View clicked)
{
getAdapter().onSingleChoiceClick(mItem);
}
SettingsItem.java:
public abstract class SettingsItem
{
public static final int TYPE_HEADER = 0;
public static final int TYPE_CHECKBOX = 1;
public static final int TYPE_SINGLE_CHOICE = 2;
public static final int TYPE_SLIDER = 3;
public static final int TYPE_SUBMENU = 4;
public static final int TYPE_INPUT_BINDING = 5;
public static final int TYPE_RADIO_BUTTON = 6;
private String mKey;
private String mSection;
private int mFile;
private Setting mSetting;
private int mNameId;
private int mDescriptionId;
public SettingsItem(String key, String section, int file, Setting setting, int nameId, int descriptionId)
{
mKey = key;
mSection = section;
mFile = file;
mSetting = setting;
mNameId = nameId;
mDescriptionId = descriptionId;
}
public String getKey()
{
return mKey;
}
public String getSection()
{
return mSection;
}
public int getFile()
{
return mFile;
}
public Setting getSetting()
{
return mSetting;
}
public void setSetting(Setting setting)
{
mSetting = setting;
}
public int getNameId()
{
return mNameId;
}
public int getDescriptionId()
{
return mDescriptionId;
}
public abstract int getType();
}
Since getSetting() is not a static method, you need to invoke it on an instance of some concrete class that extends the abstract class SettingsItem.
Think about it. If you have two instances of such a class, and the mSetting variable is different for the two instances, which one should be returned from a static-like call to getSetting()?
By definition abstract class means it is not instantiated but you can inherit from it. If you want to create many different objects with the same values but different names you can just extend SettingsItem.
Also, if you want more abstraction for future use you can create an interface with the same methods as the abstract methods in case you need to make customize methods for a different settings item.
Example:
interface SettingsInterface {
void doSomething();
}
class abstract SettingsItem implements SettingsInterface {
public void doSomething() {
System.out.println("Hello");
}
}
class RegularSettings extends SettingsItem {}
class CustomSettings implements SettingsInterface {
public void doSomething() {
System.out.println("Goodbye");
}
}
class TestClass {
public static void testAbstract(SettingsItem extendedAbstract) {
extendedAbstract.doSomething();
}
public static void testInterface(SettingsInterface interface) {
interface.doSomething();
}
public static void main(String[] args) {
SettingsItem abstractExtended = new RegularSettings();
// also could be CustomSettings instead of SettingsInterface
SettingsInterface customClass = new CustomSettings();
testInterface(abstractExtended);
testInterface(customClass);
testAbstract(abstractExtended);
// will throw errors since it doesn't extend SettingsItem
testAbstract(customClass);
}
}

Translate C struct of function pointers to JNA code

// original c code
struct callback {
void (*recv_msg_)(const char * msg, int type, unsigned int len);
void (*connected_)(void *cs);
void (*disconnected_)(void *cs);
};
void recv_msg(const char *msg, int type, unsigned int len)
{
// some code
//......
}
void connected(void *s)
{
// some code
//......
}
void disconnected(void *s)
{
// some code
//......
}
struct callback cb;
cb.recv_msg_ = recv_msg;
cb.connected_ = connected;
cb.disconnected = disconnected;
init("127.0.0.1", 5672, &cb);
// C code end
////////////////////////////////////////////////////////////////////////
// THE JNA code
interface RecvMsg extends Callback {
void invoke(String msg, int type, int con_len);
}
interface CbConnected extends Callback {
void invoke(Pointer ctx);
}
interface CbDisconnected extends Callback {
void invoke(Pointer ctx);
}
class RecvMsgImpl implements RecvMsg {
#Override
public void invoke(String msg, int type, int len) {
System.out.println("recv msg: " + msg);
}
}
class CbConnectedImpl implements CbConnected {
#Override
public void invoke(Pointer ctx) {
System.out.println("connected.");
}
}
class CbDisconnectedImpl implements CbDisconnected {
#Override
public void invoke(Pointer ctx) {
System.out.println("diconnected.");
}
}
public class MyCallBack extends Structure {
public RecvMsg recv_msg_;
public CbConnected cb_connected_;
public CbDisconnected cb_disconnected_;
#Override
protected List getFieldOrder() {
return Arrays.asList(new String[] {"recv_msg_", "cb_connected_", "cb_disconnected_"});
}
}
MyCallBack cb = new MyCallBack();
cb.recv_msg_ = new RecvMsgImpl();
cb.cb_connected_ = new CbConnectedImpl();
cb.cb_disconnected_ = new CbDisconnectedImpl();
Xxx xxx = (Xxx) Native.loadLibrary("***", Xxx.class);
xxx.init("127.0.0.1", 5672, cb);
// Java code end
////////////////////////////////////////////////////////////////////
I run the java code, got exception like this:
Exception in thread "main" java.lang.IllegalArgumentException: Structure field "cb_connected_" was declared as interface DLLTest.CbConnected, which is not supported within a Structure
at com.sun.jna.Structure.writeField(Structure.java:808)
at com.sun.jna.Structure.write(Structure.java:718)
at com.sun.jna.Structure.autoWrite(Structure.java:1923)
at com.sun.jna.Function.convertArgument(Function.java:505)
at com.sun.jna.Function.invoke(Function.java:297)
at com.sun.jna.Library$Handler.invoke(Library.java:212)
at com.sun.proxy.$Proxy1.init(Unknown Source)
at DLLTest.Tester.main(Tester.java:55)
Please tell me how to translate it to java with JNA.
This is my test for this with jna library.
I think you have to find some difference with mine.
I made my own code because you didn't show me the full source code.
My environment of development are a mingw64 with msys2 and a eclipse(oxygen) with the java(1.8)
Here are some more details.
Gcc version
Using built-in specs.
COLLECT_GCC=C:\DEV\COMP\msys32\mingw64\bin\gcc.exe
COLLECT_LTO_WRAPPER=C:/DEV/COMP/msys32/mingw64/bin/../lib/gcc/x86_64-w64-
mingw32/6.3.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: .....skip
Thread model: posix
gcc version 6.3.0 (Rev1, Built by MSYS2 project)
Java information
java.class.version::52.0
sun.management.compiler::HotSpot 64-Bit Tiered Compilers
sun.arch.data.model::64
sun.desktop::windows
sun.cpu.isalist::amd64
First, A complete code of a JnaTest class from yours.
package stackoverflow;
import java.util.Arrays;
import java.util.List;
import com.sun.jna.Callback;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
public class JnaTest {
public interface JnaInf extends Library {
public void init(String val, int port, MyCallBack cb);
}
public static void main(String[] args) {
MyCallBack cb = new MyCallBack();
cb.recv_msg_ = new RecvMsgImpl();
cb.cb_connected_ = new CbConnectedImpl();
cb.cb_disconnected_ = new CbDisconnectedImpl();
System.load("C:\\DEV\\COMP\\msys32\\home\\stackoverflow\\jna_inf.dll");
JnaInf xxx = (JnaInf) Native.loadLibrary("jna_inf", JnaInf.class);
xxx.init("127.0.0.1", 5672, cb);
}
interface RecvMsg extends Callback {
void invoke(String msg, int type, int con_len);
}
interface CbConnected extends Callback {
void invoke(Pointer ctx);
}
interface CbDisconnected extends Callback {
void invoke(Pointer ctx);
}
static class RecvMsgImpl implements RecvMsg {
#Override
public void invoke(String msg, int type, int len) {
System.out.println("recv msg: " + msg);
System.out.println("type: " + type);
System.out.println("len: " + len);
}
}
static class CbConnectedImpl implements CbConnected {
#Override
public void invoke(Pointer ctx) {
System.out.println("connected.");
}
}
static class CbDisconnectedImpl implements CbDisconnected {
#Override
public void invoke(Pointer ctx) {
System.out.println("diconnected.");
}
}
public static class MyCallBack extends Structure {
public RecvMsg recv_msg_;
public CbConnected cb_connected_;
public CbDisconnected cb_disconnected_;
#Override
protected List getFieldOrder() {
return Arrays.asList(new String[] { "recv_msg_", "cb_connected_", "cb_disconnected_" });
}
}
}
Then, the c source code name, jna_info.c is as follows,
struct callback {
void (*recv_msg_)(const char * msg, int type, unsigned int len);
void (*connected_)(void *cs);
void (*disconnected_)(void *cs);
};
void recv_msg(const char *msg, int type, unsigned int len)
{
// some code
//......
}
void connected(void *s)
{
// some code
//......
return;
}
void disconnected(void *s)
{
// some code
//......
return;
}
void init(const char *msg, int type, struct callback *mycallback)
{
mycallback->recv_msg_("123", 22, 3);
mycallback->connected_("123");
return;
}
Compile the c source code
gcc -c jna_inf.c
gcc -shared -o jna_inf.dll jna_inf.o
The output looks like what i am expecting..
I sincerely hope this helps you.

Catch Win32 Event with Java JNA

I am solving this issue:
In my Java application (installed on Windows OS machine) I have to catch Win32 Event which is created by another application on same machine. This app is written in C++ and there is no way to change it. I have information that I have to use OpenEvent function. I started as is metioned in:
Calling OpenEvent fails through JNA
Here is my code:
public class WinEventListener {
private Logger logger = LoggerFactory.getLogger(WinEventListener.class);
static {
Native.register("kernel32");
}
public static native HANDLE OpenEventW(int access, boolean inheritHandle, WString name);
public static native int WaitForSingleObject(HANDLE hHandle, int dwMilliseconds);
public static native boolean CloseHandle(HANDLE hObject);
public static class HANDLE extends PointerType {
public Object fromNative(Object nativeValue, FromNativeContext context) {
Object o = super.fromNative(nativeValue, context);
if (INVALID_HANDLE_VALUE.equals(o))
return INVALID_HANDLE_VALUE;
return o;
}
}
static HANDLE INVALID_HANDLE_VALUE = new HANDLE() {
{
super.setPointer(Pointer.createConstant(-1));
}
public void setPointer(Pointer p) {
throw new UnsupportedOperationException("Immutable reference");
}
};
public void listen() throws Exception {
HANDLE handle = null;
do {
//logger.debug("Wainting for handle");
handle = OpenEventW(2, false, new WString("VLIT_SERVER_DATA"));
logger.debug("Handle:" + handle.toString());
Thread.sleep(1000);
} while (handle == null);
logger.debug("Handle obtained");
while(true){
int result = WaitForSingleObject(handle,Integer.MAX_VALUE);
if(result == 0){
logger.debug("Handle signalized");
VLITProcceserThread thread = new VLITProcceserThread();
thread.start();
CloseHandle(handle);
}
}
}
}
Basiclly I want in listen() method wait for HANDLE create by other program and if its created then wait for its signalized state, do some action and release handle.
BUt I have no success. Can anybody point me to right way?
Thans a lot!
If it is the opening of the handle that is failing it is most likely an issue with privileges. Is your program running as a service? I was trying to do something similar and was able to get this program running and working when i called it via a system call inside a program that was running as a service.
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.PointerType;
import com.sun.jna.WString;
import com.sun.jna.FromNativeContext;
public class WinEventListener {
static {
Native.register("kernel32");
}
public static native HANDLE OpenEventW(int access, boolean inheritHandle, WString name);
public static native int WaitForSingleObject(HANDLE hHandle, int dwMilliseconds);
public static native boolean CloseHandle(HANDLE hObject);
public static class HANDLE extends PointerType {
public Object fromNative(Object nativeValue, FromNativeContext context) {
Object o = super.fromNative(nativeValue, context);
if (INVALID_HANDLE_VALUE.equals(o))
return INVALID_HANDLE_VALUE;
return o;
}
}
static HANDLE INVALID_HANDLE_VALUE = new HANDLE() {
{
super.setPointer(Pointer.createConstant(-1));
}
public void setPointer(Pointer p) {
throw new UnsupportedOperationException("Immutable reference");
}
};
public void listen() {
try {
HANDLE handle = null;
do {
handle = OpenEventW(2031619, false, new WString("event_name"));
if(handle == null) {
System.out.print("Handle is null\n");
}
Thread.sleep(500);
} while (handle == null);
while(true){
// 50 second timeout
int result = WaitForSingleObject(handle, 50000);
if(result == 0){
System.out.print("Handle signaled\n");
}
else if (result == 258){
System.out.print("Timed out\n");
}
else{
System.out.print("Handle not signaled\n");
System.out.print(result);
}
System.out.print(result);
//System.out.print(handle);
Thread.sleep(100);
}
}
catch (Exception exc)
{
System.out.print(exc);
//Thread.sleep(10000);
//writer.writeln(exc);
}
}
public static void main(String[] args) {
WinEventListener listener = new WinEventListener();
listener.listen();
}
}

Categories