General Information
Question (arch-what):
What is this project good for?
Answer:
The Java Language API is good for providing a uniform way of accessing/modifying Java metadata from the IDE modules. Instead
of implementing code that extracts information from Java code/class files directly (by parsing the sources/reading classfiles)
in every single module that needs to access the information, the whole parsing and code generation functionality is encapsulated
in the language API implementation. Modules then use the API (instead of doing their own textual manipulations and parsing) to
do the work they need.
Question (arch-overall):
Describe the overall architecture.
Answer:
The module provides JavaLanguageModelAPI
- API for accessing Java language metadata for projects opened in the IDE. The whole API is generated
from a MOF metamodel of Java language according
to the JMI specification.
The metamodel can be downloaded here. It can be opened using
MagicDraw 7.5 Community Edition (and higher) available for free at www.magicdraw.com.
Question (arch-usecases):
Describe the main
use cases of the new API. Who will use it under
what circumstances? What kind of code would typically need to be written
to use the module?
Answer:
The API can be used for exploration of the metadata (extracting information from the Java sources/class files) or for generating Java
source code (i.e. the API allows read-write access to the metadata).
The entry-point to the metadata should be provided by a set of support (non-JMI) APIs that provide utility methods for finding
metadata representation for a given FileObject or DataObject and similar helper operations. Such utility classes are already present
in the JavaCore module, however they are not a public API, yet.
To demonstrate the work with the API, the following piece of code iterates through all features of a Java class and prints their
names to the console:
public void printFeatures(JavaClass cls) {
for (Iterator it = cls.getFeatures().iterator(); it.hasNext();) {
Feature feature = (Feature) it.next();
System.out.println(feature.getName());
}
}
The following piece of code adds "return null;" statement to the end of the body of a method passed as a parameter:
public void addReturnNull(Method method) {
// get the root of the method codebase
JavaModelPackage pkg = (JavaModelPackage) method.refImmediatePackage();
// get return statement factory
ReturnStatementClass rsc = pkg.getReturnStatement();
// get null literal factory
NullLiteralClass nlc = pkg.getNullLiteral();
// create a new return statement returning a new null literal
ReturnStatement rs = rsc.createReturnStatement(nlc.createNullLiteral());
// add the return statement to the end of the method body statement block
method.getBody().getStatements().add(rs);
}
Obtaining element from lookup.
Some modules (e.g. Java module) may expose metadata elements via nodes - i.e. various nodes presenting a java file structure may offer
org.netbeans.jmi.javamodel.Element
or its subclasses in their lookup.
In this case clients need to check validity of the provided
element inside of an MDR transaction before any of the element's method
is used, since node supplying the element cannot guarantee the element
stays valid. Here is an example code:
public void performAction(Node node) {
// try to get an implementation of Element from the lookup
Element el = (Element) node.getLookup().lookup(Element.class);
if (el == null) return;
try {
// start a transaction
JavaMetamodel.getDefaultRepository().beginTrans(false);
try {
// it is important to check validity of the element first
if (element.isValid()) {
// do the work
...
}
} finally {
// stop the transaction
JavaMetamodel.getDefaultRepository().endTrans();
}
} catch (JmiException e) {
ErrorManager.getDefault().notify(e);
}
}
Question (arch-time):
What are the time estimates of the work?
Answer:
We will be feature complete by June 14. The functionality is planned to be released in promoD.
Question (arch-quality):
How will the quality
of your code be tested and
how are future regressions going to be prevented?
Answer:
We have a set of unit tests (right now about 75) which will grow over time. The functionality is also tested by higher-level
tests in modules that use the API (refactoring, java, editor - code completion).
Project and platform dependencies
Question (dep-nb):
What other NetBeans projects and modules does this one depend on?
Answer:
Theoretically the API itself depends just on the JMI.
Practically the module depends on MDRAPI and the related modules (javax.jmi.model/1,
org.netbeans.api.mdr/1, org.netbeans.modules.jmiutils/1) since the metadata described by the metamodel need to be managed by MDR.
Question (dep-non-nb):
What other projects outside NetBeans does this one depend on?
Answer:
Java Metadata Interface (JMI) and
Meta-Object Facility (MOF) standards.
Question (dep-platform):
On which platforms does your module run? Does it run in the same
way on each?
Answer:
The module does not contain any platform-specific code.
Question (dep-jre):
Which version of JRE do you need (1.2, 1.3, 1.4, etc.)?
Answer:
The code makes use of some methods/features introduced in JDK 1.4 (e.g. assertions). Thus it is the earliest version it can run with.
Question (dep-jrejdk):
Do you require the JDK or is the JRE enough?
Answer:
JRE is enough.
Deployment
Question (deploy-jar):
Do you deploy just module JAR file(s) or other files as well?
Answer:
Just the module's jar file.
Question (deploy-nbm):
Can you deploy an NBM via the Update Center?
Answer:
Sure.
Question (deploy-shared):
Do you need to be installed in the shared location only, or in the user directory only,
or can your module be installed anywhere?
Answer:
Anywhere.
Question (deploy-packages):
Are packages of your module made inaccessible by not declaring them
public?
Answer:
Yes.
Question (deploy-dependencies):
What do other modules need to do to declare a dependency on this one?
Answer:
Currently they need to declare an implementation dependency since the API is not stable yet.
Compatibility with environment
Question (compat-i18n):
Is your module correctly internationalized?
Answer:
Internationalization is not applicable to the language API.
Question (compat-standards):
Does the module implement or define any standards? Is the
implementation exact or does it deviate somehow?
Answer:
The Java language metamodel provided by the module can be considered being and informal standard.
Question (compat-version):
Can your module coexist with earlier and future
versions of itself? Can you correctly read all old settings? Will future
versions be able to read your current settings? Can you read
or politely ignore settings stored by a future version?
Answer:
The module is able to handle versioning - version number is stored with the metamodel. Older versions of the stored metadata
are ignored, since all the metadata can be recreated from scratch.
Access to resources
Question (resources-file):
Does your module use java.io.File
directly?
Answer:
No.
Question (resources-layer):
Does your module provide own layer? Does it create any files or
folders in it? What it is trying to communicate by that and with which
components?
Answer:
No.
Question (resources-read):
Does your module read any resources from layers? For what purpose?
Answer:
No.
Question (resources-mask):
Does your module mask/hide/override any resources provided by other modules in
their layers?
Answer:
No.
Lookup of components
Execution Environment
Question (exec-property):
Is execution of your code influenced by any environment or
Java system (System.getProperty
) property?
Answer:
No.
Question (exec-component):
Is execution of your code influenced by any (string) property
of any of your components?
Answer:
No.
Question (exec-classloader):
Does your code create its own class loader(s)?
Answer:
No.
Question (exec-reflection):
Does your code use Java Reflection to execute other code?
Answer:
No.
Question (exec-privateaccess):
Are you aware of any other parts of the system calling some of
your methods by reflection?
Answer:
No.
Question (exec-process):
Do you execute an external process from your module? How do you ensure
that the result is the same on different platforms? Do you parse output?
Do you depend on result code?
Answer:
No.
Question (exec-introspection):
Does your module use any kind of runtime type information (instanceof
,
work with java.lang.Class
, etc.)?
Answer:
No.
Question (exec-threading):
What threading models, if any, does your module adhere to?
Answer:
All methods from the API involve implicit transactions. The transaction entry is controlled by an "exclusive" mutex, which means
that there is only one thread allowed to execute a code in a transaction at a given time.
This means that clients need to be careful when accessing the API since the API calls may block the client for a while (if a long running
operation blocks the transaction) since it is discouraged to make calls to this API from the AWT thread.
To help clients to deal with this more easily a helper API for asynchronous access will be provided in the future releases.
Question (security-policy):
Does your functionality require modifications to the standard policy file?
Answer:
No.
Question (security-grant):
Does your code grant additional rights to some other code?
Answer:
No.
Format of files and protocols
Question (format-types):
Which protocols and file formats (if any) does your module read or write on disk,
or transmit or receive over the network?
Answer:
None.
Question (format-dnd):
Which protocols (if any) does your code understand during Drag & Drop?
Answer:
None.
Question (format-clipboard):
Which data flavors (if any) does your code read from or insert to
the clipboard (by access to clipboard on means calling methods on java.awt.datatransfer.Transferable
?
Answer:
None.
Performance and Scalability
Question (perf-startup):
Does your module run any code on startup?
Answer:
No.
Question (perf-exit):
Does your module run any code on exit?
Answer:
No.
Question (perf-scale):
Which external criteria influence the performance of your
program (size of file in editor, number of files in menu,
in source directory, etc.) and how well your code scales?
Answer:
Not applicable.
Question (perf-limit):
Are there any hard-coded or practical limits in the number or size of
elements your code can handle?
Answer:
No.
Question (perf-mem):
How much memory does your component consume? Estimate
with a relation to the number of windows, etc.
Answer:
Not applicable.
Question (perf-wakeup):
Does any piece of your code wake up periodically and do something
even when the system is otherwise idle (no user interaction)?
Answer:
No.
Question (perf-progress):
Does your module execute any long-running tasks?
Answer:
No.
Question (perf-huge_dialogs):
Does your module contain any dialogs or wizards with a large number of
GUI controls such as combo boxes, lists, trees, or text areas?
Answer:
No.
Question (perf-menus):
Does your module use dynamically updated context menus, or
context-sensitive actions with complicated enablement logic?
Answer:
No.
Question (perf-spi):
How the performance of the plugged in code will be enforced?
Answer:
Not applicable.