Intellij plugin development, how to prevent an action from occuring, like closing a tab - intellij-idea

Is this possible?
I need to subscribe to the event somehow and possibly return false or similar, i am guessing. I have no idea how though.
What event is that?
Where do I register it?
Anyone?
EDIT:
I have tried this:
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.editor.impl.EditorComponentImpl;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.awt.event.AWTEventListener;
import java.awt.event.KeyEvent;
public class MyPlugin implements ApplicationComponent {
static {
/*MessageBus bus = ApplicationManager.getApplication().get
MessageBusConnection connection = bus.connect();
connection.subscribe(AppTopics.FILE_DOCUMENT_SYNC,
new FileDocumentManagerAdapter() {
#Override
public void beforeDocumentSaving(Document document) {
// create your custom logic here
}
});*/
}
private final AWTEventListener listener;
public MyPlugin() {
System.out.println("111111111111111111");
listener = new AWTEventListener() {
#Override
public void eventDispatched(AWTEvent event) {
if ( event instanceof KeyEvent ) {
KeyEvent kv = (KeyEvent) event;
Component component = kv.getComponent();
if ( component instanceof EditorComponentImpl) {
EditorComponentImpl cp = (EditorComponentImpl) component;
}
System.out.println("3333333" + component.getClass());
}
System.out.println("aaaaaaa" + event.getClass());
}
};
}
#Override
public void initComponent() {
System.out.println("bbbbbbbbbbbbbbbbbbbbbbbbbbb");
Toolkit.getDefaultToolkit().addAWTEventListener(listener, AWTEvent.KEY_EVENT_MASK);
}
#Override
public void disposeComponent() {
Toolkit.getDefaultToolkit().removeAWTEventListener(listener);
}
#NotNull
#Override
public String getComponentName() {
return "temp";
}
}
But it does not work. I get events but the wrong kind.

Two plugins were developed in the end to accomplish this:
https://plugins.jetbrains.com/space/index?pr=idea&lg=opensource%40momomo.com

Related

Add custom selection menu on Android in React Native WebView

I'm trying to show custom buttons for text selection in React-Native WebView on Android. I've created a custom component as described here. It works fine.
Following this answer, I'm trying to override ActionMode with custom ActionMode.Callback to display my custom menu. However it doesn't seem to work at all.
My code:
CustomWebViewManager.java
protected static class CustomWebView extends RNCWebView {
public Context context;
public CustomWebView(ThemedReactContext reactContext) {
super(reactContext);
this.context=context;
}
// setting custom action bar
private ActionMode mActionMode;
private ActionMode.Callback mSelectActionModeCallback;
private GestureDetector mDetector;
// this will over ride the default action bar on long press
#Override
public ActionMode startActionMode(Callback callback) {
ViewParent parent = getParent();
if (parent == null) {
return null;
}
String name = callback.getClass().toString();
if (name.contains("SelectActionModeCallback")) {
mSelectActionModeCallback = callback;
mDetector = new GestureDetector(context,
new CustomGestureListener());
}
CustomActionModeCallback mActionModeCallback = new CustomActionModeCallback();
return parent.startActionModeForChild(this, mActionModeCallback);
}
private class CustomActionModeCallback implements ActionMode.Callback {
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mActionMode = mode;
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
//overriding onPrepareActionMode, onActionItemClicked and onDestroyActionMode as usual
...
}
private class CustomGestureListener extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onSingleTapUp(MotionEvent e) {
if (mActionMode != null) {
mActionMode.finish();
return true;
}
return false;
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(mDetector !=null)
mDetector.onTouchEvent(event);
return super.onTouchEvent(event);
}
}
What I'm doing wrong here? Is that a correct approach?
Thanks.

In Eclipse WizardPage - Issues in Navigating between pages

I have written a small program which should navigate from one page to another. But I am unable to do that.
My requirement is
On PageOne, if the user Enters a value it should be validated i.e simple comparison in this case it is "123".
if it matches the proceed to the next page as shown below:
Page One
Page Two
else throw a dialogue box below:
Page One
Page One Code:
package testing.importWizards;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
public class PageOne extends WizardPage {
private Text text1;
private Composite container;
boolean isVisible=false;
public PageOne() {
super("Page One");
setTitle("Page One");
setDescription("Fake Wizard: Page One");
}
#Override
public void createControl(Composite parent) {
container = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
container.setLayout(layout);
layout.numColumns = 2;
Label label1 = new Label(container, SWT.NONE);
label1.setText("Put a value here.");
text1 = new Text(container, SWT.BORDER | SWT.SINGLE);
text1.setText("");
text1.addKeyListener(new KeyListener() {
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
if (!text1.getText().isEmpty()) {
setPageComplete(true);
}
}
});
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
text1.setLayoutData(gd);
setControl(container);
setPageComplete(false);
}
#Override
public IWizardPage getNextPage() {
// TODO Auto-generated method stub
Shell shell=getShell();
return super.getNextPage();
}
public String getText1() {
return text1.getText();
}
}
Page Two Code:
package testing.importWizards;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
public class PageTwo extends WizardPage {
private Text text1;
private Composite container;
public PageTwo() {
super("Page Two");
setTitle("Page Two");
setDescription("Fake Wizard: Page Two");
}
#Override
public void createControl(Composite parent) {
container = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
container.setLayout(layout);
layout.numColumns = 2;
Label label1 = new Label(container, SWT.NONE);
label1.setText("Success");
/*text1 = new Text(container, SWT.BORDER | SWT.SINGLE);
text1.setText("");
text1.addKeyListener(new KeyListener() {
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
if (!text1.getText().isEmpty()) {
setPageComplete(true);
}
}
});*/
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
//text1.setLayoutData(gd);
setControl(container);
//setPageComplete(false);
setPageComplete(true);
}
public String getText1() {
return text1.getText();
}
}
I have teid overriding setVisible and getNextPage Methods, but I am getting erroneous behaviour. Could someone please explaing me the logic for implementing the validation. Is my entire approach wrong?
Rather than displaying a dialog it is usual for a wizard page to display errors in the top area of the wizard using setErrorMessage or setError.
Usually it is convenient to do the validation every time data on the page is changed. For your example page one something like:
public class PageOne extends WizardPage
{
private Text text1;
public PageOne()
{
super("testWizardPage");
setTitle("Page One");
setDescription("Fake Wizard: Page One");
}
#Override
public void createControl(final Composite parent)
{
Composite container = new Composite(parent, SWT.NONE);
container.setLayout(new GridLayout(2, false));
Label label1 = new Label(container, SWT.NONE);
label1.setText("Put a value here.");
text1 = new Text(container, SWT.BORDER | SWT.SINGLE);
text1.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
text1.addModifyListener(this::modifyListener);
setControl(container);
setPageComplete(false);
}
private void modifyListener(final ModifyEvent event)
{
boolean empty = text1.getText().isEmpty();
if (empty)
setErrorMessage("Text must be entered");
else
setErrorMessage(null);
setPageComplete(!empty);
}
}
This is using a 'modify listener' on the text1 field and calling setErrorMessage and setPageComplete each time the field is changed.

How to manage the life cycle in react native

I know when we need a nativeUI component we need override function
getName()and
createViewInstance(ThemedReactContext context) But when I use a dependence about map. The API need me use the component like this
#Override
protected void onDestroy() {
super.onDestroy();
//在activity执行onDestroy时执行mMapView.onDestroy(),
mMapView.onDestroy();
}
#Override
protected void onResume() {
super.onResume();
//在activity执行onResume时执行mMapView. onResume (),
mMapView.onResume();
}
#Override
protected void onPause() {
super.onPause();
//在activity执行onPause时执行mMapView. onPause (),
mMapView.onPause();
}
}
I override the function getetName()and
createViewInstance(ThemedReactContext context) like this
#Override
public String getName() {
return REACT_CLASS;
}
#Override
public MapView createViewInstance(ThemedReactContext context) {
final ThemedReactContext mapContext = context;
bdMapViewInstance = new MapView(context);
bdMapViewInstance.getMap().setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker marker) {
ShopResponseInfo shopResponseInfo = (ShopResponseInfo) marker.getExtraInfo().getSerializable(INDENTIFY);
if(shopResponseInfo != null){
String id = shopResponseInfo.getShop_id() + "";
String shop_name = shopResponseInfo.getShop_name() + "";
onReceiveNativeEvent(mapContext,bdMapViewInstance,id,shop_name);
}
return true;
}
});
return bdMapViewInstance;
}
Finally There are some performance question in my app. I don't know whether it is affect on my app's performance. And I don't know how to meet the official suggestion. I don't know how to control the life cycle of nativeUI component for android. Very Thanks.
You can listen to activity life cycle like this in your createViewInstance. You probably want to keep track of listeners and remove them appropriately based on you keep track of your instances.
LifecycleEventListener lifecycleEventListener = new LifecycleEventListener() {
#Override
public void onHostResume() {
}
#Override
public void onHostPause() {
}
#Override
public void onHostDestroy() {
}
};
getReactApplicationContext().addLifecycleEventListener(lifecycleEventListener);
An example of TestModule as explained in the docs of RN. PS Don't forget to use implements LifecycleEventListener
package com.testpackage;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.LifecycleEventListener;
import java.util.Map;
import java.util.HashMap;
public class TestModule extends ReactContextBaseJavaModule implements LifecycleEventListener {
public TestModule(ReactApplicationContext reactContext) {
super(reactContext);
reactContext.addLifecycleEventListener(this);
}
#Override
public void onHostResume() {
}
#Override
public void onHostPause() {
}
#Override
public void onHostDestroy() {
}
}

#EventHandler events not working

I am trying to make a simple addition to my plugin so that when someone joins they receive a message that says "Heyyyyyyy". My plugin has a few commands also.
Here's my Main class:
package me.ben.test;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;
public class Main extends JavaPlugin implements Listener {
#Override
public void onEnable() {
this.getServer().getPluginManager().registerEvents(new Click(), this);
getLogger().info("The Plugin Has Been Enabled!");
}
#Override
public void onDisable() {
getLogger().info("The Plugin Has Been Disabled!");
}
public boolean onCommand(CommandSender sender, Command cmd, String label,
String[] args) {
if (cmd.getName().equalsIgnoreCase("hello") && sender instanceof Player) {
Player player = (Player) sender;
player.sendMessage("Hello, " + player.getName() + "!");
return true;
} else if (cmd.getName().equalsIgnoreCase("isonline")
&& args.length == 1) {
Player target = Bukkit.getServer().getPlayer(args[0]);
if (target == null) {
sender.sendMessage(ChatColor.AQUA + "Player " + args[0]
+ " is not online.");
return true;
} else if (target != null) {
sender.sendMessage(ChatColor.AQUA + "Player " + args[0]
+ " is online.");
return true;
} else {
return false;
}
}
return false;
}
}
and here is my Click class:
package me.ben.test;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.java.JavaPlugin;
public class Click extends JavaPlugin implements Listener {
#EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
event.getPlayer().sendMessage("Heyyyyyyy");
}
}
All of the #EventHandler things are not working so I quick made this simple one.
You can have only one class that extends JavaPlugin. Remove extends JavaPlugin from your Click Class - only your main class should extend JavaPlugin.
Check out Bukkit's official plugin tutorial for help on coding Bukkit Plugins.
You are using Listener in your Main class but you are not handling any event there, use it only when you want the class to be able to handler bukkit events.
You can use Listener with your Main class if you want, but you'll need to put the methods that handles events in your main class, but it'll become messy in big projects...
You also don't need to extend JavaPlugin everywhere, just in your main class.
If you want to use your main class:
public class Main extends JavaPlugin implements Listener {
#Override
public void onEnable() {
this.getServer().getPluginManager().registerEvents(this, this);
getLogger().info("The Plugin Has Been Enabled!");
}
#EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
event.getPlayer().sendMessage("Heyyyyyyy");
}
}
If you want to use a separated class to handle events:
public class Main extends JavaPlugin {
#Override
public void onEnable() {
this.getServer().getPluginManager().registerEvents(new Click(), this);
getLogger().info("The Plugin Has Been Enabled!");
}
}
public class Click implements Listener {
#EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
event.getPlayer().sendMessage("Heyyyyyyy");
}
}
Don't forget that you need to create a plugin.yml file correctly otherwise nothing will work.

USB/Serial communication with Netty

In our organisation, we implemented our own protocol over UDP and TCP to let external devices connected to the Internet exchange messages with a server that we developed using Netty (indeed!).
For testing purpose, we would like to connect those devices directly to our computers through USB/serial interface (we did not choose the serial communication library yet). We would also like to deploy/port the embedded software we developed for our devices on our computer to simulate the devices and to connect directly to our server using a named pipe for example (IPC).
In the Architecture Overview documentation of Netty, you claim that we could use Netty as well for such serial communication:
"Also, you are even able to take advantage of new transports which aren't yet written (such as serial port communication transport), again by replacing just a couple lines of constructor calls. Moreover, you can write your own transport by extending the core API."
Is anyone somewhere already developed such implementation in Netty or does someone else plan to do such implementation? I am also wondering if Netty is really well-suited for that since the Channel interface and many other ones use a SocketAddress to bind/connect to a peer?
Thank you for your suggestions, advices!
I wonder if you may be able to use the new iostream package for that. All you need here is an InputStream and Outputstream. See [1]
[1] https://github.com/netty/netty/tree/master/transport/src/main/java/io/netty/channel/iostream
It is possible to implement such a solutions. I have not meet problems with binding with SocketAddress.
I’m posting my implementation of USB connection with Netty.
Serial communication is quite simillar, I'm not posting it for brevity. However I am happy to add it as well if anyone needs it.
Here is base class for connection. A ChannelHandler shall be implemented according to communication needs.
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;
import java.net.SocketAddress;
public abstract class ConnectorImpl {
protected ChannelHandler handler;
protected Bootstrap bootstrap;
protected ChannelFuture channelFuture;
public ChannelFuture connect() throws Exception {
if (!isConnected()) {
channelFuture = bootstrap.connect(getSocketAddress()).sync();
}
return channelFuture.channel().closeFuture();
}
public boolean isConnected() {
try {
return channelFuture.channel().isOpen();
} catch (NullPointerException ex) {
return false;
}
}
public void close() {
if (!isConnected()) {
return;
}
try {
channelFuture.channel().close().sync();
} catch (InterruptedException e) {
}
}
protected ChannelOutboundHandlerAdapter createOutgoingErrorHandler() {
return new ChannelOutboundHandlerAdapter() {
#Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
final ChannelFutureListener channelFutureListener = future -> {
if (!future.isSuccess()) {
future.channel().close();
}
};
promise.addListener(channelFutureListener);
ctx.write(msg, promise);
}
};
}
public abstract SocketAddress getSocketAddress();
}
An extensions of that connector for needed type of connection together with Channel implementations is needed.
USB connector:
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.handler.timeout.ReadTimeoutHandler;
import javax.usb.UsbDevice;
import java.net.SocketAddress;
import java.util.concurrent.TimeUnit;
public class UsbConnectorImpl extends ConnectorImpl {
private static final int READ_TIMEOUT = 60;
private final UsbDevice usbDevice;
public UsbConnectorImpl(UsbChannelHandler handler, UsbDevice usbDevice) {
this.handler = handler;
this.usbDevice = usbDevice;
this.bootstrap = new Bootstrap()
.channel(getChannelClass())
.group(getLoop())
.handler(getChannelInitializer());
}
public EventLoopGroup getLoop() {
return new NioEventLoopGroup(1);
}
Class<UsbAsyncChannel> getChannelClass() {
return UsbAsyncChannel.class;
}
ChannelInitializer<Channel> getChannelInitializer() {
return new ChannelInitializer<Channel>() {
#Override
public void initChannel(#SuppressWarnings("NullableProblems") Channel ch) {
ch.pipeline()
.addLast("Generic encoder", new RequestEncoder())
.addLast("Decoder", new ResponseDecoder())
.addLast("Read timeout handler", new ReadTimeoutHandler(READ_TIMEOUT, TimeUnit.SECONDS))
.addLast("Outgoing Error Handler", createOutgoingErrorHandler())
.addLast("Card Reader handler", handler);
}
};
}
public SocketAddress getSocketAddress() {
return new UsbDeviceAddress(usbDevice);
}
}
USB Channel:
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.FileRegion;
import io.netty.channel.nio.AbstractNioByteChannel;
import org.usb4java.LibUsb;
import javax.usb.UsbConfiguration;
import javax.usb.UsbDevice;
import javax.usb.UsbEndpoint;
import javax.usb.UsbInterface;
import javax.usb.UsbPipe;
import javax.usb.event.UsbPipeDataEvent;
import javax.usb.event.UsbPipeErrorEvent;
import javax.usb.event.UsbPipeListener;
import java.io.IOException;
import java.net.SocketAddress;
import java.nio.channels.Pipe;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public abstract class UsbChannel extends AbstractNioByteChannel {
protected static final byte INTERFACE_BULK_PIPES = (byte) 1;
private static final AtomicInteger READ_TASK_COUNTER = new AtomicInteger();
private final UsbChannelConfig config;
protected UsbPipe outPipe = null;
protected UsbPipe inPipe = null;
private UsbDevice usbDevice;
private UsbDeviceAddress deviceAddress;
private UsbInterface usbInterface;
public UsbChannel() throws IOException {
super(null, Pipe.open().source());
config = new UsbChannelConfig(this);
}
#Override
public UsbChannelConfig config() {
return config;
}
#Override
public boolean isActive() {
return usbDevice != null;
}
#Override
protected ChannelFuture shutdownInput() {
try {
doClose();
} catch (Exception e) {
pipeline().fireExceptionCaught(e);
}
return null;
}
protected abstract ReadTask createReadTask();
protected void invokeRead() {
ReadTask task = createReadTask();
task.scheduledFuture = eventLoop().schedule(task, 0, TimeUnit.MILLISECONDS);
}
#Override
protected AbstractNioUnsafe newUnsafe() {
return new UsbUnsafe();
}
#Override
protected long doWriteFileRegion(FileRegion region) throws Exception {
throw new UnsupportedOperationException();
}
#Override
protected int doReadBytes(ByteBuf buf) throws Exception {
return 0;
}
#Override
protected Pipe.SourceChannel javaChannel() {
return (Pipe.SourceChannel) super.javaChannel();
}
#Override
protected boolean doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
UsbDeviceAddress remote = (UsbDeviceAddress) remoteAddress;
usbDevice = remote.value();
UsbConfiguration configuration = usbDevice.getActiveUsbConfiguration();
usbInterface = configuration.getUsbInterface(INTERFACE_BULK_PIPES);
usbInterface = usbInterface.getActiveSetting();
usbInterface.claim();
for (int i = 0; i < usbInterface.getUsbEndpoints().size(); i++) {
UsbEndpoint endpoint = (UsbEndpoint) usbInterface.getUsbEndpoints().get(i);
UsbPipe usbPipe = endpoint.getUsbPipe();
if (endpoint.getDirection() == LibUsb.ENDPOINT_IN) {
inPipe = usbPipe;
inPipe.open();
} else if (endpoint.getDirection() == LibUsb.ENDPOINT_OUT) {
outPipe = usbPipe;
outPipe.open();
}
if (inPipe != null && outPipe != null) {
break;
}
}
outPipe.addUsbPipeListener(new UsbPipeListener() {
#Override
public void errorEventOccurred(UsbPipeErrorEvent event) {
pipeline().fireExceptionCaught(event.getUsbException());
}
#Override
public void dataEventOccurred(UsbPipeDataEvent event) {
invokeRead();
}
});
inPipe.addUsbPipeListener(new UsbPipeListener() {
#Override
public void errorEventOccurred(UsbPipeErrorEvent event) {
pipeline().fireExceptionCaught(event.getUsbException());
}
#Override
public void dataEventOccurred(UsbPipeDataEvent event) {
pipeline().fireChannelRead(Unpooled.wrappedBuffer(event.getData(), 0, event.getData().length));
}
});
deviceAddress = remote;
return true;
}
#Override
protected void doFinishConnect() throws Exception {
}
#Override
public UsbDeviceAddress localAddress() {
return (UsbDeviceAddress) super.localAddress();
}
#Override
public UsbDeviceAddress remoteAddress() {
return (UsbDeviceAddress) super.remoteAddress();
}
#Override
protected UsbDeviceAddress localAddress0() {
return deviceAddress;
}
#Override
protected UsbDeviceAddress remoteAddress0() {
return deviceAddress;
}
#Override
protected void doBind(SocketAddress localAddress) throws Exception {
throw new UnsupportedOperationException();
}
#Override
protected void doDisconnect() throws Exception {
doClose();
}
#Override
protected void doClose() throws Exception {
try {
super.doClose();
javaChannel().close();
} finally {
if (inPipe != null) {
inPipe.close();
inPipe = null;
}
if (outPipe != null) {
outPipe.close();
outPipe = null;
}
if (usbInterface != null) {
usbInterface.release();
usbInterface = null;
}
if (usbDevice != null) {
usbDevice = null;
}
}
}
protected abstract static class ReadTask implements Runnable, ChannelFutureListener {
protected final int id;
protected ScheduledFuture<?> scheduledFuture;
public ReadTask() {
this.id = READ_TASK_COUNTER.incrementAndGet();
}
}
private final class UsbUnsafe extends AbstractNioUnsafe {
#Override
public void read() {
}
}
}