~ubuntu-branches/ubuntu/quantal/netbeans/quantal

« back to all changes in this revision

Viewing changes to java/j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/J2SELibrarySourceLevelQueryImpl.java

  • Committer: Bazaar Package Importer
  • Author(s): Marek Slama
  • Date: 2008-01-29 14:11:22 UTC
  • Revision ID: james.westby@ubuntu.com-20080129141122-fnzjbo11ntghxfu7
Tags: upstream-6.0.1
ImportĀ upstreamĀ versionĀ 6.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 
3
 *
 
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 
5
 *
 
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]"
 
23
 *
 
24
 * Contributor(s):
 
25
 *
 
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.
 
29
 *
 
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.
 
40
 */
 
41
 
 
42
package org.netbeans.modules.java.j2seplatform.libraries;
 
43
 
 
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;
 
49
import java.net.URL;
 
50
import java.util.Iterator;
 
51
import java.util.List;
 
52
import java.util.Map;
 
53
import java.util.WeakHashMap;
 
54
 
 
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;
 
63
 
 
64
/**
 
65
 *
 
66
 * @author  tom
 
67
 */
 
68
public class J2SELibrarySourceLevelQueryImpl implements SourceLevelQueryImplementation {
 
69
    
 
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;
 
83
    
 
84
    //Cache for source level
 
85
    private Map/*<Library, sourceLevel>*/ sourceLevelCache = new WeakHashMap ();
 
86
    
 
87
    //Cache for last used library, helps since queries are sequential
 
88
    private /*Soft*/Reference lastUsedRoot;
 
89
    private /*Weak*/Reference lastUsedLibrary;
 
90
    
 
91
    /** Creates a new instance of J2SELibrarySourceLevelQueryImpl */
 
92
    public J2SELibrarySourceLevelQueryImpl() {
 
93
    }
 
94
    
 
95
    public String getSourceLevel(org.openide.filesystems.FileObject javaFile) {        
 
96
        Library ll = this.isLastUsed (javaFile);
 
97
        if (ll != null) {
 
98
            return getSourceLevel (ll);
 
99
        }
 
100
        Library[] libraries = LibraryManager.getDefault().getLibraries();
 
101
        for (int i=0; i< libraries.length; i++) {
 
102
            if (!J2SELibraryTypeProvider.LIBRARY_TYPE.equalsIgnoreCase(libraries[i].getType())) { 
 
103
                continue;
 
104
            }
 
105
            List sourceRoots = libraries[i].getContent(J2SELibraryTypeProvider.VOLUME_TYPE_SRC);   //NOI18N
 
106
            if (sourceRoots.size() == 0) {
 
107
                continue;
 
108
            }            
 
109
            ClassPath cp = ClassPathSupport.createClassPath((URL[])sourceRoots.toArray(new URL[sourceRoots.size()]));
 
110
            FileObject root;
 
111
            if ((root = cp.findOwnerRoot(javaFile)) != null) {
 
112
                setLastUsedRoot (root, libraries[i]);
 
113
                return getSourceLevel(libraries[i]);
 
114
            }
 
115
        }
 
116
        return null;
 
117
    }    
 
118
    
 
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);
 
124
        }
 
125
        return slevel == JDK_UNKNOWN ? null : slevel;                
 
126
    }
 
127
    
 
128
    private String getSourceLevel (List cpRoots) {
 
129
        FileObject classFile = getClassFile (cpRoots);
 
130
        if (classFile == null) {
 
131
            return JDK_UNKNOWN;
 
132
        }
 
133
        int version = getClassFileMajorVersion (classFile);
 
134
        if (version == CF_11 || version == CF_12) {
 
135
            return JDK_12;
 
136
        }
 
137
        else if (version == CF_13) {
 
138
            return JDK_13;
 
139
        }
 
140
        else if (version == CF_14) {
 
141
            return JDK_14;
 
142
        }
 
143
        else if (version >= CF_15) {
 
144
            return JDK_15;
 
145
        }        
 
146
        return JDK_UNKNOWN;
 
147
    }
 
148
    
 
149
    private FileObject getClassFile (List cpRoots) {
 
150
        for (Iterator it = cpRoots.iterator(); it.hasNext();) {
 
151
            FileObject root = URLMapper.findFileObject((URL)it.next());
 
152
            if (root == null) {
 
153
                continue;
 
154
            }
 
155
            FileObject cf = findClassFile (root);
 
156
            if (cf != null) {
 
157
                return cf;
 
158
            }
 
159
        }
 
160
        return null;
 
161
    }
 
162
    
 
163
    private FileObject findClassFile (FileObject root) {
 
164
        if (root.isData()) {
 
165
            if (CLASS.equals(root.getExt())) {
 
166
                return root;
 
167
            }
 
168
            else {
 
169
                return null;
 
170
            }
 
171
        }
 
172
        else {
 
173
            FileObject[] children = root.getChildren();
 
174
            for (int i=0; i<children.length; i++) {
 
175
                FileObject result = findClassFile(children[i]);
 
176
                if (result != null) {
 
177
                    return result;
 
178
                }
 
179
            }
 
180
            return null;
 
181
        }
 
182
    }
 
183
    
 
184
    private int getClassFileMajorVersion (FileObject classFile) {
 
185
        DataInputStream in = null;
 
186
        try {
 
187
            in = new DataInputStream (classFile.getInputStream());
 
188
            int magic = in.readInt();   
 
189
            if (CF_MAGIC != magic) {
 
190
                return CF_INVALID;
 
191
            }
 
192
            short minor = in.readShort(); //Ignore it
 
193
            short major = in.readShort();
 
194
            return major;
 
195
        } catch (IOException e) {
 
196
            return CF_INVALID;
 
197
        } finally {
 
198
            if (in != null) {
 
199
                try {
 
200
                    in.close ();
 
201
                } catch (IOException e) {
 
202
                    //Ignore it, can not recover
 
203
                }
 
204
            }
 
205
        }
 
206
    }
 
207
    
 
208
    private synchronized void setLastUsedRoot (FileObject root, Library lib) {
 
209
        this.lastUsedRoot = new SoftReference (root);
 
210
        this.lastUsedLibrary = new WeakReference (lib);
 
211
    }
 
212
    
 
213
    private synchronized Library isLastUsed (FileObject javaFile) {
 
214
        if (lastUsedRoot == null) {
 
215
            return null;
 
216
        }
 
217
        
 
218
        FileObject root = (FileObject) lastUsedRoot.get ();
 
219
        if (root == null) {
 
220
            return null;
 
221
        }
 
222
        
 
223
        if (root.equals(javaFile) || FileUtil.isParentOf(root,javaFile)) {
 
224
            return (Library) lastUsedLibrary.get ();
 
225
        }
 
226
        return null;
 
227
    }
 
228
    
 
229
}