JavaCardLibraries

Java Card Library Management Conundrums

Libraries are a complicated issue for Java Card projects. Below are the issues involved and some outlines of the necessary architecture both in the IDE and Ant scripts. Items requiring input from the Java Card team or others are in boldface.

The main issue here is the complexity caused by the combinatorics of needing to generate different pieces of build script for number of dependencies * number of deployment strategies * 6 different kinds of dependencies that need different XML * number of targets that interact with dependencies (compile, deploy, run, ???). Doing this correctly will not be easy.

Summary

Java Card handles libraries very differently than other NetBeans project types because of the nature of the platform. This means two things

  1. We probably cannot reuse any existing NB Java library support
  2. We need to carefully model what scenarios can be supported and also accept that some may be impossible to support

Libraries must be deployed to the device or emulator before any code that depends on them is deployed.

For debugging, a debug classpath must be passed to a debug proxy executable. This classpath must include all classes that need to be debuggable - i.e. the complete transitive closure of all code that should be debuggable


Kinds of Library Projects

Java Card support allows you to build two kinds of "library" project:

  1. Classic Library - Java Card 2.x compatible library with same restrictions - library may only contain one Java package
  2. Extension Library - Java Card 3.x compatible library w/o the above restrictions


Kinds of Libraries a Java Card Project may depend on

There are more kinds of libraries a Java Card project can depend on

  1. Classic Library Project / Extension Library Project - the project being run/debugged can invoke the deploy target for those projects before deploying itself. In doing so, it must
    1. Pass the target platform and device (the project may be set up to deploy someplace different than the one depending on it is to be deployed - they need to end up on the same device)
    2. For debugging, somehow return a Path representing the library project's dependency closure
    3. Not allow cyclic dependencies
    4. Perform the same operation on any library projects it depends on, performing all the steps above and including the closure of all sub-dependencies for the debug classpath
  2. Plain JAR file - there are several possible operations depending on user input
    1. Is there an "export path" (.exp) file associated with it? Is this the same as deploying a classic library, does that something different deployment code? IF YES: this goes into Legacy support to convert an application into CAP (Classic Application) format. Classic applications are converted from class files into CAP format. CAP format is different set of bytecodes in different structure. Just like compiler needs class files in the classpath, converter needs export files of other libraries in .exp file format. They are similar to header files for the library. If an exp file is present, the build script needs to handle it differently. IF NO: there are two possible ways of handling it, which probably require user input in the Project Properties | Libraries tab:
      1. Use on compilation classpath only - assume the JAR represents a proprietary API that already exists on the target device
      2. UnJAR the contents into build.classes.dir before building the project
  • This will break on classic application projects if the JAR file does not contain exactly one package with the same name as the single package in the project
  1. Raw Classic Library (.???) JAR file - is this the same as JAR w/ .exp file?
  2. Raw Extension Library (.???) JAR file - anything special needed for this?
  3. Raw Classic Applet (.cap) JAR file - anything special needed for this?
  4. Raw Extended Applet (.eap) JAR file - anything special needed for this?

Implications of these different library types:

The build.xsl is going to have to insert one chunk of deployment code into the deploy target for each type of library (except if the deployment strategy is ALREADY_ON_CARD); build and other targets are probably similar. There probably needs to be a different XSL sub-template for each library-type:target:type. To say this is non-trivial for build script generation is an understatement.

Deployment Strategies

There are several known and two questionable different possible strategies that could be used, to decide how to handle a library at deploy-time. Not all library kinds support all deployment strategies (see DependencyKind.supportedDeploymentStrategies). Items in bold are the questionable ones. The build-impl.xsl should generate different contents for the relevant targets, depending on the type of dependency and deployment strategy. The deployment strategies available are:

  • ALREADY_ON_CARD - just use on compile time classpath, do not try to deploy anything for this library
  • UNBUNDLE - UnJAR the JAR into build.classes.dir before compilation, so it is simply included in the final project artifact (will not work for Classic projects if this creates additional packages)
  • DEPLOY_TO_CARD - if a project or a CAP, EAP, EXTLIB, CLSLIB JAR file, always deploy/redeploy the dependency when deploying the target project
  • DEPLOY_TO_CARD_IF_NOT_PRESENT - if a project or a CAP, EAP, EXTLIB, CLSLIB JAR file, deploy the dependency when deploying the target project if it is not already on the card (using cardmanagerurl/xlist to determine presence?)
  • DEPLOY_TO_CARD_IF_NEWER - only viable if we can get a file date or build info out of xlist and figure out if the local copy of the lib is newer than the one on the card

Possible blocking issues

Managing Dependencies

1. The dependency tree of a project is a tree. But in the end, libraries will be deployed serially to the target device culminating with the target application the deploy. The tree will, in practice, be collapsed to a list. This presents a problem. Consider the following dependency tree:


http://wiki.netbeans.org/attach/JavaCardLibraries/MultipleDependencies_JavaCardLibraries.png

In the simplest possible scenario

  • A will deploy C
  • C will deploy D
  • A will deploy D again

Ideally, C's build process would communicate the D had been deployed, so A would not undeploy and redeploy it. Whether we can realistically extract any information from a foreign Ant task (perhaps some log file or passed in file parameter to append to?) is TBD.

But in the case of multiple deployments, this means overwriting existing properties which is against Ant rules. May be solvable if all code to handle this is generated directly into the build-impl.xml based on the project.xml.

2. A and C may be set up to deploy D with different deployment parameters/arguments. If every project could have only one dependency, this could be handled by parameters passed in to the Ant call to the dependency's build script. With multiple parameters, it is probably impossible. D being deployed twice may be the best solution, since A will deploy D with its desired parameters after C has deployed it; however, it also may break C's ability to call D.

Also, deployment is via http, is not fast, and undeploying and redeploying the same thing multiple times in one build cycle will slow the process considerably.

This issue needs further investigation and may be unsolvable

Aggregating information from a subtree of calls into foreign projects' build scripts

A can pass information into B's build script when invoking it without a problem. Getting information back from B's build script is another question entirely. This causes some potential blocking issues;

  • For debugging, we need a Path, in Ant parlance, containing paths to all of the JAR files that could be debugged into (presumably the IDE has the sources to make this actually useful, in the case of JAR files). This must be passed to the debug proxy that shuttles data between the VM and the IDE. If A depends on B depends on C depends on D, then when the call that deploys A needs to be returned (bearing in mind that Ant has no concept of returning a value from an invocation of another Ant process) a :-delimited list of JAR files representing the entire closure of A's dependency tree
  • This list may need to be pruned of duplicates

One conceivable way of doing this would be to pass in an empty temp file as a parameter to the invocation of each dependency's deploy target, and set up the deploy targets to append their classpath to that file.

Determining if a dependency is deployed in debug mode

A dependent library may already be on the device. There is minimal support for determining what is running on a device by using calling the emulator/deployer's $CARDMANAGER_URL/xlist

What this does not tell us is

  • If the library contains debug information
  • If the library was deployed in debug mode (i.e. debugger proxy knows about it)
  • If something currently running is being debugged
  • This issue may be moot if the debugger proxy needs restarting for a new debug session
  • NetBeans debugger supports multiple concurrent sessions. What is the behavior of invoking a second debug session on a project when one is already running?

Dealing with raw JAR files

  • How does the IDE know where to find sources for debugging?
  • __What do we do if the JAR includes Class-Path: entries in its manifest?
  • How would we even parse and deploy them? What about .exp files?

.exp files

  • Who generates them, when and how? The Ant task? The IDE?
  • How do we handle the case of a missing .exp file?

Modelling Java Card Dependencies for configuration in NetBeans UI

We appear to have several flavors of library with very different sets of attributes

  • Classic Library - easy to handle, since the IDE has complete information. Some issues with crossover dependencies with conflicting deployment instructions. Attributes:
  • Project location
  • Should deploy on run/debug/deploy?
  • Extension Library - same as above. Attributes:
  • Project location
  • Should deploy on run/debug/deploy?
  • JAR file representing an API built into the device
  • JAR location
  • Source JAR/folder location for debugging
  • JAR file with .exp header file
  • JAR location
  • Should deploy on run/debug/deploy?
  • .exp file location
  • Source JAR/folder location for debugging
  • Raw JAR file with no .exp file
  • JAR location
  • Deployment strategy - unbundle? Something else?
  • Raw Classic Library / Classic Applet / Extended Applet / Extension Library files (i.e. no associated project, just the, e.g., .cap file)
  • Is there other metadata we need to deploy these correctly?
  • In the case of applets, are there cases where
  • We need to instantiate an instance of an applet the target project depends on
  • Do we need a specific instance AID for that applet, and how will the build script find this info?

Handling different versions of dependencies

Say that A depends on B and C. B depends on X.jar with X.exp. C depends on X'.jar with X'.exp representing a different version of library X with different signatures or incompatible changes or just different source line debug info. How do we handle such a scenario?

Open questions:

  1. Can the debug proxy which needs the debug classpath handle duplicate classpath entries? There is no way to weed them out w/o a custom Ant task, which should be avoided if possible.

Design

The customizer and tools for modeling dependencies in Java Card projects will need to built custom to the needs of Java Card projects. Below is a sketch of UML for the basic design - comments or corrections appreciated.

Amendment: There is only one dependency class; added ArtifactKind for origin, sources, etc. So the UML below is no longer accurate. Will update at some point - Tim

http://wiki.netbeans.org/attach/JavaCardLibraries/DepsUML_JavaCardLibraries.png

Information the IDE and/or Ant tasks need from the emulator/deployment executable

Right now we can list what is on the card. This is insufficient to create a working system for deployment. Ideally the build script should be able to quickly determine if a dependency is already in place with appropriate configuration on the target device, if a dependent applet has a running instance with the expected AID, and so forth.

The minimum following information is required:

  • For each library or applet
  • AID or other unique identifier that can be mapped back to a dependency or project
  • Has debug information?
  • Is already deployed in debug mode?
  • If applet
  • List of instances by AID
  • If possible, original file date of a deployed library, for up-to-dateness check
Not logged in. Log in, Register

By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo