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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
See Svata's comments above.
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 --->
---> CLOSED