1

For a Java / OSGi project I need to communicate with a smartcard plugged to my computer. I do this using the package javax.smartcardio.

When I first imported this package and wanted to use it, Eclipse anounced an error "Access restriction: The type 'CommandAPDU' is not API". As proposed on https://www.javacardos.com/javacardforum/viewtopic.php?t=918, I added an Accessibility Rule Pattern to the Build Path. After that, everything worked fine and I could use the package in my local environment.

But now I wanted to pass the project to our continous integration system, which is Jenkins with Maven. I also committed the .classpath file. And there I get the same error:

[ERROR] import javax.smartcardio.CommandAPDU;

[ERROR] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

[ERROR] Access restriction: The type 'CommandAPDU' is not API (restriction on classpath entry '/disc2/lunifera/server/jenkins/workspace/tools/hudson.model.JDK/JDK-8/jre/lib/rt.jar')

For some reason, the access rule does not seem to work on Jenkins. Does anybody know how to solve this problem? Thanks alot.

Bilbo
  • 63
  • 1
  • 7

1 Answers1

1

Not exactly the kind of answer I hoped for, but in the end, I overcame the problem by using reflection. I wrote wrapper classes for the classes from javax.smartcardio that I needed. These wrapper classes hold instances of the original classes and operate on them purely by reflection. For example, the CardTerminal class wrapper may look like this:

public class CardTerminal {

   private Object originalCardTerminal;

   public CardTerminal(Object originalCardTerminal)
   {
       this.originalCardTerminal = originalCardTerminal;
   }

   public Card connect(String protocol)
   {
       try
       {
           Class originalCardTerminalClass   = Class.forName("javax.smartcardio.CardTerminal");
           Method connectMethod              = originalCardTerminalClass.getMethod("connect", String.class);
           Object originalCard               = connectMethod.invoke(originalCardTerminal, protocol);
        
           if (originalCard == null)
           {
               return null;
           }
           else
           {
               return new Card(originalCard);  // "Card" is another wrapper type, of course
           }
       }
       catch (ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
       {
           return null;
       }  
   }}

Of course, this is not a good solution because all the objects are just of type "object" and you lose type safety. But it's the best solution I found so far, and it's working, because you don't need to import anything from javax.smartcardio.

Bilbo
  • 63
  • 1
  • 7