changeset 207:6a6eda574d4e

8132777: spi/typeChecks/index.html#SPI and spi/se/index.html#DenyRGrantO fail due to "Unexpected IOE" Summary: Correct DeviceProvider is recorded during config checking procedure. The fix is not complete for OpenJDK DIO Reviewed-by: alkonsta
author snazarki
date Fri, 31 Jul 2015 14:03:09 +0300
parents 197db5731b92
children a00757ecbb33
files src/se/classes/com/oracle/dio/registry/RegistryImpl.java src/share/classes/com/oracle/dio/impl/PeripheralDescriptorImpl.java src/share/classes/com/oracle/dio/registry/Registry.java src/share/classes/jdk/dio/DeviceManager.java
diffstat 4 files changed, 76 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/src/se/classes/com/oracle/dio/registry/RegistryImpl.java	Wed Jul 29 18:08:43 2015 +0300
+++ b/src/se/classes/com/oracle/dio/registry/RegistryImpl.java	Fri Jul 31 14:03:09 2015 +0300
@@ -76,18 +76,14 @@
     }
 
     @Override
-    public synchronized void register(int id, Class<T> intf,
-                                      DeviceConfig<? super T> config,
-                                      String name,
-                                      String... properties)
+    public synchronized void register(DeviceDescriptor<? super T> descriptor)
                                       throws UnsupportedOperationException, IOException {
         Properties registry = loadRegistry();
         RegistryContent content = readRegistryContent(registry);
-        String factory = DeviceRegistryFactory.registryFactoryName(intf);
+        String factory = DeviceRegistryFactory.registryFactoryName(descriptor.getInterface());
         if (factory == null) {
             throw new UnsupportedDeviceTypeException("Unsupported type: " + intf.getName());
         }
-        DeviceDescriptor<? super T> descriptor = new PeripheralDescriptorImpl(id, name, config, intf, properties);
 
         Registry.checkPermission(descriptor, DeviceMgmtPermission.REGISTER);
 
--- a/src/share/classes/com/oracle/dio/impl/PeripheralDescriptorImpl.java	Wed Jul 29 18:08:43 2015 +0300
+++ b/src/share/classes/com/oracle/dio/impl/PeripheralDescriptorImpl.java	Fri Jul 31 14:03:09 2015 +0300
@@ -24,15 +24,20 @@
  */
 
 package com.oracle.dio.impl;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.util.Objects;
 import java.util.Set;
 
 import com.oracle.dio.utils.Constants;
 import com.oracle.dio.utils.Logging;
+import com.oracle.jme.serializer.SerializeManager;
 
 import jdk.dio.Device;
 import jdk.dio.DeviceConfig;
 import jdk.dio.DeviceDescriptor;
+import jdk.dio.spi.DeviceProvider;
 
 import romizer.*;
 
@@ -44,19 +49,20 @@
  */
 @SerializeMe
 @DontRenameClass
-public final class PeripheralDescriptorImpl<C extends DeviceConfig<T>, T extends Device<? super T>> implements DeviceDescriptor<T> {
+public final class PeripheralDescriptorImpl<T extends Device<? super T>> implements DeviceDescriptor<T> {
 
-    private C config;
+    private Object config;
     private String clazz;
     private int id = DeviceDescriptor.UNDEFINED_ID;
     private String name;
     private String[] props;
+    private String providerClazz;
 
     // need for serializator
     public PeripheralDescriptorImpl() {
     }
 
-    public PeripheralDescriptorImpl(int id, String name, C config, Class<T> intf, String[] props) {
+    public PeripheralDescriptorImpl(int id, String name, DeviceConfig config, Class<T> intf, String[] props) {
         Objects.requireNonNull(config);
         this.config = config;
         // see DeviceManager.openWithConfig where intf may be null
@@ -71,8 +77,11 @@
     }
 
     @Override
-    public C getConfiguration() {
-        return config;
+    public <C extends DeviceConfig<? super T>> C getConfiguration() {
+        if (config instanceof DeviceConfig) {
+            return (C)config;
+        }
+        return null;
     }
 
     @Override
@@ -101,5 +110,41 @@
     public String[] getProperties() {
         return (props == null) ? props : props.clone();
     }
+
+    public void setDeviceProvider(DeviceProvider provider) {
+        providerClazz = provider.getClass().getName();
+    }
+
+    public void prepareForSerilization() throws IOException {
+        if (! (config instanceof byte[]) ) {
+            if (null != providerClazz) {
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                ((DeviceConfig)config).serialize(baos);
+                baos.close();
+                config = baos.toByteArray();
+            } else {
+                SerializeManager.serialize(config);
+            }
+        }
+    }
+
+    public void recoverFromSerialization() {
+        if (config instanceof byte[]) {
+            ByteArrayInputStream bais = new ByteArrayInputStream((byte[])config);
+            try {
+                config = Platform.deserialize(bais);
+            } catch (IOException e1) {
+                Logging.reportInformation("Config is custom DeviceConfig child");
+                try {
+                    bais.reset();
+                    DeviceProvider<T> provider = (DeviceProvider)Class.forName(providerClazz).newInstance();
+                    config = provider.deserialize(bais);
+                } catch (Exception e2) {
+                    Logging.reportError("Can't restore config object");
+                }
+            }
+        }
+    }
+
 }
 
--- a/src/share/classes/com/oracle/dio/registry/Registry.java	Wed Jul 29 18:08:43 2015 +0300
+++ b/src/share/classes/com/oracle/dio/registry/Registry.java	Fri Jul 31 14:03:09 2015 +0300
@@ -93,10 +93,7 @@
      * @see jdk.dio.DeviceManager#register(int,
      *      Class, DeviceConfig, String, String...)
      */
-    public abstract void register(int id, Class<T> intf,
-                                                        DeviceConfig<? super T> config,
-                                                        String name,
-                                                        String... properties)
+    public abstract void register(DeviceDescriptor<? super T> d)
     throws UnsupportedOperationException, IOException;
 
     /**
--- a/src/share/classes/jdk/dio/DeviceManager.java	Wed Jul 29 18:08:43 2015 +0300
+++ b/src/share/classes/jdk/dio/DeviceManager.java	Fri Jul 31 14:03:09 2015 +0300
@@ -305,7 +305,7 @@
             );
         }
         checkMode(mode);
-        PeripheralDescriptorImpl<DeviceConfig<P>, P> descr = new PeripheralDescriptorImpl(UNSPECIFIED_ID, null, config, intf, null);
+        PeripheralDescriptorImpl<P> descr = new PeripheralDescriptorImpl(UNSPECIFIED_ID, null, config, intf, null);
         if (null != intf) {
             try {
                 return ((PeripheralFactory<P>)getFactory(intf)).create(descr, mode);
@@ -476,7 +476,7 @@
                 ExceptionMessage.format(ExceptionMessage.DEVICE_NULL_INTF)
             );
         }
-        DeviceDescriptor<P> descr = Registry.getInstance().get(id);
+        PeripheralDescriptorImpl<P> descr = (PeripheralDescriptorImpl<P>)Registry.getInstance().get(id);
         if (null == descr) {
             throw new DeviceNotFoundException(
                 ExceptionMessage.format(ExceptionMessage.DEVICE_NOT_FOUND, String.valueOf(id))
@@ -737,9 +737,9 @@
             checkWithProviders(intf);
         }
 
-        Iterator<DeviceDescriptor<P>> iter = Registry.getInstance().get(name, intf, properties);
+        Iterator<PeripheralDescriptorImpl<P>> iter = Registry.getInstance().get(name, intf, properties);
         while (iter.hasNext()) {
-            DeviceDescriptor<P> descr = iter.next();
+            PeripheralDescriptorImpl<P> descr = iter.next();
             try {
                 final PeripheralFactory<P> f =  getFactory(descr.getInterface());
 
@@ -919,10 +919,18 @@
 
         int new_id = checkConfig(id, intf, config, name, properties);
 
-        Registry.getInstance().register(new_id, intf, config, name, properties);
+        // quick fix: need info about custom DeviceConfig factory (if any)
+        PeripheralDescriptorImpl<P> dscr = new PeripheralDescriptorImpl(new_id, name, config, intf, properties);
+        // this fills dscr with correct provider
+        try (Device d = loadFromDriver(dscr, EXCLUSIVE)) {
+        } catch (Exception e) {
+            // intentionally ignored
+        }
+
+        Registry.getInstance().register(dscr);
 
         // send notification in non-priveleged mode
-        RegistrationEventSender.notifyRegistered(null, new PeripheralDescriptorImpl(new_id, name, config, intf, properties));
+        RegistrationEventSender.notifyRegistered(null, dscr);
 
         return new_id;
     }
@@ -1108,7 +1116,7 @@
     @Local(DontRenameNonAbstractSubtypes = {"com.oracle.dio.impl.PeripheralFactory"})
     private static PeripheralFactory getFactory(Class clazz) throws UnsupportedDeviceTypeException {
         // get package name of com.oracle.dio.PACAKAGE_NAME.PERIPHERAL_IFACE
-        // following code is correct for precompiled peripheral driver that following DAAPI name convention.
+        // following code is correct for precompiled peripheral driver that follows DAAPI name convention.
         String fullName = clazz.getName();
 
         // check for name correctness from current spec point of view.
@@ -1133,7 +1141,7 @@
     }
 
     // is called in response to UDTE and DNFE
-    private static <P extends Device<? super P>> P loadFromDriver(DeviceDescriptor<P> descr, int mode) throws
+    private static <P extends Device<? super P>> P loadFromDriver(PeripheralDescriptorImpl<P> descr, int mode) throws
         DeviceNotFoundException, UnavailableDeviceException, InvalidDeviceConfigException,
         UnsupportedAccessModeException, IOException {
         ServiceLoader<DeviceProvider> loader = ServiceLoader.load(DeviceProvider.class);
@@ -1155,11 +1163,16 @@
                         found = true;
                         if (provider.matches(descr.getProperties())) {
                             // properties was checked by Registry when descriptor was loaded up
-                            return (P)provider.open(config,descr.getProperties(),mode);
+                            P dev = (P)provider.open(config,descr.getProperties(),mode);
+                            // hack for config registration: save info about factory that may restore config from serialized data
+                            descr.setDeviceProvider(provider);
+                            return dev;
                         }
                     }
                 } catch (UnavailableDeviceException | InvalidDeviceConfigException | UnsupportedAccessModeException | SecurityException e) {
-                    // driver was found but it rejects provided data or device is busy or application has no rights to use the driver
+                    // driver was found but it rejects provided data or device is busy or application has no rights to use the driver.
+                    // the driver is suitable for config class deserialization as well
+                    descr.setDeviceProvider(provider);
                     throw e;
                 } catch (Throwable  e3) {
                     Logging.reportError("Provider " + provider + " throws " + e3);