2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
42
package org.netbeans.modules.java.j2seplatform.libraries;
44
import java.io.DataInputStream;
45
import java.io.IOException;
46
import java.lang.ref.Reference;
47
import java.lang.ref.SoftReference;
48
import java.lang.ref.WeakReference;
50
import java.util.Iterator;
51
import java.util.List;
53
import java.util.WeakHashMap;
55
import org.netbeans.api.java.classpath.ClassPath;
56
import org.netbeans.api.project.libraries.Library;
57
import org.netbeans.api.project.libraries.LibraryManager;
58
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
59
import org.netbeans.spi.java.queries.SourceLevelQueryImplementation;
60
import org.openide.filesystems.FileObject;
61
import org.openide.filesystems.FileUtil;
62
import org.openide.filesystems.URLMapper;
68
public class J2SELibrarySourceLevelQueryImpl implements SourceLevelQueryImplementation {
70
private static final String JDK_12 = "1.2"; //NOI18N
71
private static final String JDK_13 = "1.3"; //NOI18N
72
private static final String JDK_14 = "1.4"; //NOI18N
73
private static final String JDK_15 = "1.5"; //NOI18N
74
private static final String JDK_UNKNOWN = ""; //NOI18N
75
private static final String CLASS = "class"; //NOI18N
76
private static final int CF_MAGIC = 0xCAFEBABE;
77
private static final int CF_INVALID = -1;
78
private static final int CF_11 = 0x2d;
79
private static final int CF_12 = 0x2e;
80
private static final int CF_13 = 0x2f;
81
private static final int CF_14 = 0x30;
82
private static final int CF_15 = 0x31;
84
//Cache for source level
85
private Map/*<Library, sourceLevel>*/ sourceLevelCache = new WeakHashMap ();
87
//Cache for last used library, helps since queries are sequential
88
private /*Soft*/Reference lastUsedRoot;
89
private /*Weak*/Reference lastUsedLibrary;
91
/** Creates a new instance of J2SELibrarySourceLevelQueryImpl */
92
public J2SELibrarySourceLevelQueryImpl() {
95
public String getSourceLevel(org.openide.filesystems.FileObject javaFile) {
96
Library ll = this.isLastUsed (javaFile);
98
return getSourceLevel (ll);
100
Library[] libraries = LibraryManager.getDefault().getLibraries();
101
for (int i=0; i< libraries.length; i++) {
102
if (!J2SELibraryTypeProvider.LIBRARY_TYPE.equalsIgnoreCase(libraries[i].getType())) {
105
List sourceRoots = libraries[i].getContent(J2SELibraryTypeProvider.VOLUME_TYPE_SRC); //NOI18N
106
if (sourceRoots.size() == 0) {
109
ClassPath cp = ClassPathSupport.createClassPath((URL[])sourceRoots.toArray(new URL[sourceRoots.size()]));
111
if ((root = cp.findOwnerRoot(javaFile)) != null) {
112
setLastUsedRoot (root, libraries[i]);
113
return getSourceLevel(libraries[i]);
119
private String getSourceLevel (Library lib) {
120
String slevel = (String)this.sourceLevelCache.get (lib);
121
if (slevel == null) {
122
slevel = getSourceLevel (lib.getContent(J2SELibraryTypeProvider.VOLUME_TYPE_CLASSPATH));
123
this.sourceLevelCache.put (lib,slevel);
125
return slevel == JDK_UNKNOWN ? null : slevel;
128
private String getSourceLevel (List cpRoots) {
129
FileObject classFile = getClassFile (cpRoots);
130
if (classFile == null) {
133
int version = getClassFileMajorVersion (classFile);
134
if (version == CF_11 || version == CF_12) {
137
else if (version == CF_13) {
140
else if (version == CF_14) {
143
else if (version >= CF_15) {
149
private FileObject getClassFile (List cpRoots) {
150
for (Iterator it = cpRoots.iterator(); it.hasNext();) {
151
FileObject root = URLMapper.findFileObject((URL)it.next());
155
FileObject cf = findClassFile (root);
163
private FileObject findClassFile (FileObject root) {
165
if (CLASS.equals(root.getExt())) {
173
FileObject[] children = root.getChildren();
174
for (int i=0; i<children.length; i++) {
175
FileObject result = findClassFile(children[i]);
176
if (result != null) {
184
private int getClassFileMajorVersion (FileObject classFile) {
185
DataInputStream in = null;
187
in = new DataInputStream (classFile.getInputStream());
188
int magic = in.readInt();
189
if (CF_MAGIC != magic) {
192
short minor = in.readShort(); //Ignore it
193
short major = in.readShort();
195
} catch (IOException e) {
201
} catch (IOException e) {
202
//Ignore it, can not recover
208
private synchronized void setLastUsedRoot (FileObject root, Library lib) {
209
this.lastUsedRoot = new SoftReference (root);
210
this.lastUsedLibrary = new WeakReference (lib);
213
private synchronized Library isLastUsed (FileObject javaFile) {
214
if (lastUsedRoot == null) {
218
FileObject root = (FileObject) lastUsedRoot.get ();
223
if (root.equals(javaFile) || FileUtil.isParentOf(root,javaFile)) {
224
return (Library) lastUsedLibrary.get ();