This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 31104 - Regression in ClassPath functionality
Summary: Regression in ClassPath functionality
Status: CLOSED INVALID
Alias: None
Product: java
Classification: Unclassified
Component: Unsupported (show other bugs)
Version: 3.x
Hardware: Sun Solaris
: P3 blocker (vote)
Assignee: issues@java
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2003-02-16 17:56 UTC by Chris Webster
Modified: 2007-09-26 09:14 UTC (History)
0 users

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Chris Webster 2003-02-16 17:56:17 UTC
I developed a build target that used the results
of compiled classes similar to the following code
slice. After updating my source the
ClassPath.getClassPath method invocation returns 
null, even though the results are from compiled
classes. 

FileSet fs = compiledClasses.getContent(config);
Iterator it =       
FileSets.createFileObjectSet(fs,false).iterator();
  ..
FileObject fo = (FileObject) it.next();
String fName = ClassPath.getClassPath(fo,
ClassPath.COMPILE).getResourceName(fo);

I see that this method has been deprecated;
however, I don't think this is a good alternative
as I am just interested in extracting the fully
qualified name of the class. I marked this as P1
since this code worked before I updated the
source.
Comment 1 Tomas Zezula 2003-02-17 18:35:49 UTC
This is not the best way, how to obtain the set of compiled classes.
The right way is to use JavaProject and CompilationUnit. This code
depends on the Java Module classes which are not declared to be an
API, and may be made module private.
The code is correct, but instead of FileSet fs =
compiledClasses.getContent(config);
use 
JavaProject.getCompilationUnits() and use CompilationUnit to return
the FileSet.

Comment 2 Svata Dedic 2003-02-17 18:43:54 UTC
BTW using ClassPath.getClassPath(FileObject, String) was *deprecated*
because it must use Project.findAll() and decide which Project (and in
turn which Project's settings) it should use to construct the
ClassPath. The method obviously returns only an *approximation* when
the context file/folder is a part of 2 or more projects.
Comment 3 Chris Webster 2003-02-17 18:58:18 UTC
In my opinion there should be a way to use the ContentDescriptor
mechanism to obtain the java files produce by compiled classes.
Providing a special api defeats the purpose of the content descriptor
which allows generic linking of build targets.  
Comment 4 Chris Webster 2003-02-17 19:13:33 UTC
What about just changing the signature of the method to contain the
Project and configuration or just extrating the name from the class
file. My concern with using the java specific api's is that bytecode
to bytecode transformation steps wil not be possible.
Comment 5 Svata Dedic 2003-02-18 08:13:47 UTC
Chris, I am not sure I follow your comments. If you want to extract a
fully qualified name from a .class FileObject, the ClassPath API is
not the right way to do it. ClassPath concept has only a little in
common with .class file format - you should use "classfile" module (by
Tom Ball) for that. Or, you may use regular org.openide.src on the
.class file's DataObject.
Of course, that approach is not very performant (opening .class file,
reading/analysing etc).
ClassPath API provides translation between FileObjects and [java]
resource names; nothing more nothing less.

A note to Tomas' comment from 02/17: getContent is a regular BTD
method - you can of course use it; it is a part of general BT public
contract. Can you tell us how your code gets to that
BuildTargetDescriptor instance ? If you use ContainerList-based
search, how can you be sure that it describes "javac" build target and
not some other BT type ?

ClassPath concept has also only little common with project management.
I specifically I think we should not permit mixing any Project-related
stuff into ClassPath interface; ClassPath is pure data structure and
can well exist even without a project - it is not a proper location
for Project-aware factory methods, unless we are after a high number
of inter-package dependencies.

The last sentence makes me curious: do you want to transform java
bytecode without using java services ? It is possible, but you will be
limited to transformations done file by file without context and
access to any environmental information as it is (intentionally)
reachable only through nature-specific API.
Comment 6 Chris Webster 2003-02-20 19:16:12 UTC
The basic architecture is that I have a build target which will have
either a mandatory  or user configurable dependency on class file
producing build targets. Currently the only way to determine which of
the project's build targets produces class files must use the java api
(see #29713 for what I proposed). I would like to not use the java
module specific api's so that other build targets producing class
files could be used as input for this target (I could have a
obfuscator which worked on the output from compiled classes and still
specifies class files as the output; however with the java project
specific api's I am not sure how this would be achieved). Once the
build target I am creating executes I need to obtain the class files
produced by the targets I depend on, so I would like to just use the
getContents method of the BuildTargetDescriptor. This is what I
originally used and this worked until the latest cvs update. I need to
be able to get the fully qualified java name of the class file. The
CompilationUnit api referenced in this bug report does not seem to be
a good replacement for the getContent method of the build target
mostly because of the convolution involved in obtaining the class
files. The compilation unit api's require that the source be used to
obtain the class files; however, the referencing build target only
cares about obtain the results of the build. I have some code like
this which does not work because I am not clear how this api should be
used. 

JavaProject jp = 
               
JavaProject.getJavaProject(btd.getProjectMember().getProject());
            Iterator compUnits = jp.getCompilationUnits().iterator();
	    while(compUnits.hasNext()) {
                CompilationUnit cu = (CompilationUnit)
compUnits.next();
                if (!cu.containsSource(cu.getSourceOwner())) {
                    continue;
                }
	        Set fs = cu.findCompiledFiles(cu.getSourceOwner(),
getConfiguration());
	        

The hacked project impl is generating illegal argument exceptions in
some cases and special case handling needs to be performed for the
null compilation unit. If the api is not going to changed a code slice
demonstrating how to obtain the classes given only a build target
should be included in the javadoc.
Comment 7 Svata Dedic 2003-03-18 15:44:35 UTC
I wonder how will you obtain the class' name from a generic
BuildTargetDescriptor.getContents() contract, which is able to
enumerate produced files, but is not powerful enough to give you root
folder where those classes are.

In the case of 29713 (which is going to be implemented, BTW), the
ContentDescriptor does not even declare getContents() method -- so you
will probably have to rely on that the returned type will be
BuildTargetDescriptor.

I will keep this issue open until the possibility to define ClassPath
for files produced by the project build is evaluated. There will be no
hacks into (deprecated and obsolete) method ClassPath.getClassPath().

For example code:
> Set fs = cu.findCompiledFiles(cu.getSourceOwner(), getConfiguration());

seems somewhat misguided. In the javadoc, there's a sentence "Only
sources contained in the CompilationUnit's sources are permitted". You
are passing in a non-source object - an organizational project artifact.
If some parts of the doc seem unclear in any way, please ask on
dev@projects before filing a refression class bugs.

Code 

> if (!cu.containsSource(cu.getSourceOwner())) { ... }

should not work well -- at least I think it should evaluate to false
at all times: a project artifact can not be among [java] sources
managed by the project.

Comment 8 Chris Webster 2003-03-18 23:09:01 UTC
The question about how the class name will be obtained from a FileSet
is what was originally solved using the Classpath api (a previous
implementation of a build target obtained the set of class files and
used the classpath api to obtain the normalized class name).  When
this stopped functioning as it had in the past was what triggered this
regression. 

One of the problems I see with requiring that source be used to obtain
the fully qualified class name does not seem like a good solution for
a build target whose function is to obtain the set of class produced
by a build target and package them. An API which requires information
about how these files were derived seems to be the responsibility of
the build target generating the project artifacts (the java build
target).  A more reasonable api (IMHO) would be an api requiring a
BuildTargetDescriptor which returns the class files and the fully
qualified names. This would allow an optimized solution in most cases
for build targets provided via the java nature, while still providing
the ability of fully qualified class name extraction (from class
files) for other class files. 
Comment 9 Svata Dedic 2003-03-19 08:40:25 UTC
a) in the case that you really want to perform class file content
analysis (such as FQN extraction), please use classfile module. Such
API will not be provided by java module. As this seems as a thing
specific for your use cases, so you should implement it rather than
ask us to implement it for you (given that the classfile module is
ready to use).

I really do not think that packagers, or non-compiling providers that
produce .class files, will be willing to implement "api requiring a
BuildTargetDescriptor which returns the class files and the fully
qualified names" as it puts extra burden on implementation to extract
fully qualified names, while the fqn extraction can be done in other
way (through the classfile module, or heuristically from the file's
position within the generated output).

b) if you need that a BuildTargetDescriptor serve you the base folder
(so you can retain/reuse the output strucutre when e.g. packaging),
request a more precise contract from project core, *not* java. There's
nothing java-specific on a request to have access to the generated
file structure, not just individual files. After defined, build
targets whose output is structured (e.g. java's one is structured
according to packages) can implement the broader contract and provide
you with information.

c) please keep THIS defect focused on the fact that ClassPath
instances are not served for .class files generated from java
compilation. Since you filed it as a DEFECT, I suppose you want us to
evaluate and possibly fix the defect. Use dev@projects mailing list to
request "how-to" documents if you are not sure how to code a feature
with the current APIs.

d) when you find something that need, but the current APIs do not
cover it, please try to use the other issue types, like FEATURE or
ENHANCEMENT.
Comment 10 Tomas Zezula 2003-06-17 15:00:46 UTC
See Svata's comments above.
Comment 11 Jan Becicka 2003-11-25 13:59:57 UTC
As described in
http://www.netbeans.org/servlets/ReadMsg?msgId=619519&listName=nbdiscuss the
current work on projects prototype has been stopped.

Marking issue as VERIFIED --->
Comment 12 Jan Becicka 2003-11-25 14:08:47 UTC
---> CLOSED