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.

View | Details | Raw Unified | Return to bug 200698
Collapse All | Expand All

(-)a/api.java/apichanges.xml (+19 lines)
Lines 76-81 Link Here
76
<!-- ACTUAL CHANGES BEGIN HERE: -->
76
<!-- ACTUAL CHANGES BEGIN HERE: -->
77
77
78
<changes>
78
<changes>
79
        <change id="source-javadoc-attacher">
80
            <api name="queries"/>
81
            <summary>Added SourceJavadocAttacher to allow clients to attach source (javadoc) roots to binary root</summary>
82
            <version major="1" minor="35"/>
83
            <date day="11" month="8" year="2011"/>
84
            <author login="tzezula"/>
85
            <compatibility addition="yes" semantic="compatible" source="compatible" binary="compatible"/>
86
            <description>
87
                <p>
88
                    Added an API to allow clients to attach source roots and javadoc roots to binary roots.
89
                    The API delegates to SPI implementations which provide specific behavior depending on
90
                    type of binary root (platform, library, maven artifact). There is also fallback implementation
91
                    handling unknown binary roots by storing the bindings into IDE's userdir.
92
                </p>
93
            </description>
94
            <class package="org.netbeans.api.java.queries" name="SourceJavadocAttacher" />
95
            <class package="org.netbeans.spi.java.queries" name="SourceJavadocAttacherImplementation" />
96
            <issue number="47498"/>
97
        </change>
79
        <change id="source-level-changes">
98
        <change id="source-level-changes">
80
            <api name="queries"/>
99
            <api name="queries"/>
81
            <summary>Added notifications about source level changes into SourceLevelQuery</summary>
100
            <summary>Added notifications about source level changes into SourceLevelQuery</summary>
(-)a/api.java/manifest.mf (-1 / +1 lines)
Lines 1-6 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.netbeans.api.java/1
2
OpenIDE-Module: org.netbeans.api.java/1
3
OpenIDE-Module-Specification-Version: 1.34
3
OpenIDE-Module-Specification-Version: 1.35
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/api/java/queries/Bundle.properties
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/api/java/queries/Bundle.properties
5
AutoUpdate-Show-In-Client: false
5
AutoUpdate-Show-In-Client: false
6
6
(-)a/api.java/src/org/netbeans/api/java/queries/SourceJavadocAttacher.java (+106 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.api.java.queries;
43
44
import java.io.IOException;
45
import java.net.URL;
46
import javax.swing.SwingUtilities;
47
import org.netbeans.api.annotations.common.NonNull;
48
import org.netbeans.spi.java.queries.SourceJavadocAttacherImplementation;
49
import org.openide.util.Exceptions;
50
import org.openide.util.Lookup;
51
52
/**
53
 * A support for attaching source roots and javadoc roots to binary roots.
54
 * @author Tomas Zezula
55
 * @since 1.35
56
 */
57
public final class SourceJavadocAttacher {
58
59
    private SourceJavadocAttacher() {}
60
61
    /**
62
     * Attaches a source root provided by the SPI {@link SourceJavadocAttacherImplementation}
63
     * to given binary root.
64
     * Has to be called by event dispatch thread as the SPI implementation may need to show
65
     * an UI to select source root(s).
66
     * @param root the binary root to attach sources to
67
     * @return true if the source root was successfully attached
68
     */
69
    public static boolean attachSources(@NonNull final URL root) {
70
        return attach(root,0);
71
    }
72
73
    /**
74
     * Attaches a javadoc root provided by the SPI {@link SourceJavadocAttacherImplementation}
75
     * to given binary root.
76
     * Has to be called by event dispatch thread as the SPI implementation may need to show
77
     * an UI to select javadoc root(s).
78
     * @param root the binary root to attach javadoc to
79
     * @return true if the javadoc root was successfully attached
80
     */
81
    public static boolean attachJavadoc(@NonNull final URL root) {
82
        return attach(root,1);
83
    }
84
85
    private static boolean attach(final URL root, final int mode) {
86
        if (!SwingUtilities.isEventDispatchThread()) {
87
            throw new IllegalStateException("Has to be called by EDT.");    //NOI18N
88
        }
89
        try {
90
            for (SourceJavadocAttacherImplementation attacher : Lookup.getDefault().lookupAll(SourceJavadocAttacherImplementation.class)) {
91
                final SourceJavadocAttacherImplementation.Result res =
92
                        mode == 0 ?
93
                            attacher.attachSources(root) :
94
                            attacher.attachJavadoc(root);
95
                if (res == SourceJavadocAttacherImplementation.Result.ATTACHED) {
96
                    return true;
97
                } else if (res == SourceJavadocAttacherImplementation.Result.CANCELED) {
98
                    return false;
99
                }
100
            }
101
        } catch (IOException ioe) {
102
            Exceptions.printStackTrace(ioe);
103
        }
104
        return false;
105
    }
106
}
(-)a/api.java/src/org/netbeans/spi/java/queries/SourceJavadocAttacherImplementation.java (+106 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.spi.java.queries;
43
44
import java.io.IOException;
45
import java.net.URL;
46
import org.netbeans.api.annotations.common.NonNull;
47
import org.netbeans.api.java.queries.SourceJavadocAttacher;
48
import org.openide.util.Lookup;
49
import org.openide.util.lookup.ServiceProvider;
50
51
52
/**
53
 * A SPI for attaching source roots and javadoc roots to binary roots.
54
 * The implementations of this interface are registered in global {@link Lookup}
55
 * @see ServiceProvider
56
 * @since 1.35
57
 * @author Tomas Zezula
58
 * @since 1.35
59
 */
60
public interface SourceJavadocAttacherImplementation {
61
62
    /**
63
     * Result of the attaching sources (javadoc) to binary root.
64
     */
65
    enum Result {
66
        /**
67
         * The source (javadoc) root was successfully attached to
68
         * the binary root.
69
         */
70
        ATTACHED,
71
72
        /**
73
         * User canceled the attaching, no other SPI provider
74
         * is called and {@link SourceJavadocAttacher} returns false.
75
         */
76
        CANCELED,
77
78
        /**
79
         * The SPI is not able to attach sources (javadoc) to given
80
         * binary root (it does not handle it), next SPI provider is
81
         * called.
82
         */
83
        UNSUPPORTED
84
    }
85
86
87
    /**
88
     * Attaches a source root provided by this SPI to given binary root.
89
     * Called by event dispatch thread, it's safe to show an UI to select source root(s).
90
     * @param root the binary root to attach sources to
91
     * @return {@link SourceJavadocAttacherImplementation.Result} the result of
92
     * attach operation.
93
     */
94
    @NonNull
95
    Result attachSources(@NonNull URL root) throws IOException;
96
97
    /**
98
     * Attaches a javadoc root provided by this SPI to given binary root.
99
     * Called by event dispatch thread, it's safe to show an UI to select javadoc root(s).
100
     * @param root the binary root to attach javadoc to
101
     * @return {@link SourceJavadocAttacherImplementation.Result} the result of
102
     * attach operation.
103
     */
104
    @NonNull
105
    Result attachJavadoc(@NonNull URL root) throws IOException;
106
}
(-)a/java.j2seplatform/nbproject/project.xml (-1 / +10 lines)
Lines 59-70 Link Here
59
                    </run-dependency>
59
                    </run-dependency>
60
                </dependency>
60
                </dependency>
61
                <dependency>
61
                <dependency>
62
                    <code-name-base>org.netbeans.api.annotations.common</code-name-base>
63
                    <build-prerequisite/>
64
                    <compile-dependency/>
65
                    <run-dependency>
66
                        <release-version>1</release-version>
67
                        <specification-version>1.10</specification-version>
68
                    </run-dependency>
69
                </dependency>
70
                <dependency>
62
                    <code-name-base>org.netbeans.api.java</code-name-base>
71
                    <code-name-base>org.netbeans.api.java</code-name-base>
63
                    <build-prerequisite/>
72
                    <build-prerequisite/>
64
                    <compile-dependency/>
73
                    <compile-dependency/>
65
                    <run-dependency>
74
                    <run-dependency>
66
                        <release-version>1</release-version>
75
                        <release-version>1</release-version>
67
                        <specification-version>1.18</specification-version>
76
                        <specification-version>1.35</specification-version>
68
                    </run-dependency>
77
                    </run-dependency>
69
                </dependency>
78
                </dependency>
70
                <dependency>
79
                <dependency>
(-)a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/J2SELibrarySourceJavadocAttacher.java (+159 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.java.j2seplatform.libraries;
43
44
import java.io.File;
45
import java.io.IOException;
46
import java.net.URI;
47
import java.net.URISyntaxException;
48
import java.net.URL;
49
import java.util.ArrayList;
50
import java.util.Arrays;
51
import java.util.HashMap;
52
import java.util.List;
53
import java.util.Map;
54
import org.netbeans.api.annotations.common.NonNull;
55
import org.netbeans.api.project.libraries.Library;
56
import org.netbeans.api.project.libraries.LibraryManager;
57
import org.netbeans.spi.java.queries.SourceJavadocAttacherImplementation;
58
import org.openide.util.Exceptions;
59
import org.openide.util.lookup.ServiceProvider;
60
61
/**
62
 *
63
 * @author Tomas Zezula
64
 */
65
@ServiceProvider(service=SourceJavadocAttacherImplementation.class, position=151)
66
public class J2SELibrarySourceJavadocAttacher implements SourceJavadocAttacherImplementation {
67
68
    @Override
69
    public Result attachSources(@NonNull final URL root) throws IOException {
70
        return attach(root, J2SELibraryTypeProvider.VOLUME_TYPE_SRC);
71
    }
72
73
    @Override
74
    public Result attachJavadoc(@NonNull final URL root) throws IOException {
75
        return attach(root, J2SELibraryTypeProvider.VOLUME_TYPE_JAVADOC);
76
    }
77
78
    private Result attach(
79
            @NonNull final URL root,
80
            final String volume) {
81
        final Pair<LibraryManager,Library> pair = findOwner(root);
82
        if (pair == null) {
83
            return Result.UNSUPPORTED;
84
        }
85
        final LibraryManager lm = pair.first;
86
        final Library lib = pair.second;
87
        assert lm != null;
88
        assert lib != null;
89
        try {
90
            final URL areaLocation = lm.getLocation();
91
            final File baseFolder = areaLocation == null ? null : new File(areaLocation.toURI()).getParentFile();
92
            final URI[] uris = J2SEVolumeCustomizer.select(
93
                volume,
94
                lib.getName(),
95
                new File[1],
96
                null,
97
                baseFolder);
98
            if (uris != null) {
99
                final String name = lib.getName();
100
                final String displayName = lib.getDisplayName();
101
                final String desc = lib.getDescription();
102
                final Map<String,List<URI>> volumes = new HashMap<String, List<URI>>();
103
                for (String currentVolume : J2SELibraryTypeProvider.VOLUME_TYPES) {
104
                    List<URI> content = lib.getURIContent(currentVolume);
105
                    if (volume == currentVolume) {
106
                        final List<URI> newContent = new ArrayList<URI>(content.size()+uris.length);
107
                        newContent.addAll(content);
108
                        newContent.addAll(Arrays.asList(uris));
109
                        content = newContent;
110
                    }
111
                    volumes.put(currentVolume,content);
112
                }
113
                lm.removeLibrary(lib);
114
                lm.createURILibrary(
115
                    J2SELibraryTypeProvider.LIBRARY_TYPE,
116
                    name,
117
                    displayName,
118
                    desc,
119
                    volumes);
120
                return Result.ATTACHED;
121
            }
122
        } catch (IOException ioe) {
123
            Exceptions.printStackTrace(ioe);
124
        } catch (URISyntaxException use) {
125
            Exceptions.printStackTrace(use);
126
        }
127
        return Result.CANCELED;
128
    }
129
130
    private Pair<LibraryManager,Library> findOwner(final URL root) {
131
        for (LibraryManager lm : LibraryManager.getOpenManagers()) {
132
            for (Library l : lm.getLibraries()) {
133
                if (!J2SELibraryTypeProvider.LIBRARY_TYPE.equals(l.getType())) {
134
                    continue;
135
                }
136
                final List<URL> cp = l.getContent(J2SELibraryTypeProvider.VOLUME_TYPE_CLASSPATH);
137
                if (cp.contains(root)) {
138
                    return Pair.<LibraryManager,Library>of(lm, l);
139
                }
140
            }
141
        }
142
        return null;
143
    }
144
145
    private static class Pair<F,S> {
146
        public final F first;
147
        public final S second;
148
149
        private Pair(F first, S second) {
150
            this.first = first;
151
            this.second = second;
152
        }
153
154
        public static <F,S> Pair<F,S> of(F first, S second) {
155
            return new Pair<F,S>(first,second);
156
        }
157
    }
158
159
}
(-)a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/J2SEVolumeCustomizer.java (-89 / +134 lines)
Lines 55-63 Link Here
55
import java.net.MalformedURLException;
55
import java.net.MalformedURLException;
56
import java.net.URI;
56
import java.net.URI;
57
import java.net.URISyntaxException;
57
import java.net.URISyntaxException;
58
import java.util.ArrayList;
58
import java.util.Collection;
59
import java.util.Collection;
59
import java.util.Arrays;
60
import java.util.Arrays;
60
import java.util.Collections;
61
import java.util.Collections;
62
import java.util.List;
61
import javax.swing.AbstractAction;
63
import javax.swing.AbstractAction;
62
import javax.swing.DefaultListCellRenderer;
64
import javax.swing.DefaultListCellRenderer;
63
import javax.swing.JComponent;
65
import javax.swing.JComponent;
Lines 67-72 Link Here
67
import javax.swing.event.ListSelectionEvent;
69
import javax.swing.event.ListSelectionEvent;
68
import javax.swing.event.ListSelectionListener;
70
import javax.swing.event.ListSelectionListener;
69
import javax.swing.filechooser.FileFilter;
71
import javax.swing.filechooser.FileFilter;
72
import org.netbeans.api.annotations.common.CheckForNull;
73
import org.netbeans.api.annotations.common.NonNull;
74
import org.netbeans.api.annotations.common.NullAllowed;
70
import org.netbeans.api.project.ant.FileChooser;
75
import org.netbeans.api.project.ant.FileChooser;
71
import org.netbeans.spi.java.project.support.JavadocAndSourceRootDetection;
76
import org.netbeans.spi.java.project.support.JavadocAndSourceRootDetection;
72
import org.netbeans.spi.project.libraries.LibraryCustomizerContext;
77
import org.netbeans.spi.project.libraries.LibraryCustomizerContext;
Lines 116-121 Link Here
116
        this.upButton.setEnabled(enabled && indices.length>0 && indices[0]>0);
121
        this.upButton.setEnabled(enabled && indices.length>0 && indices[0]>0);
117
    }
122
    }
118
123
124
    @CheckForNull
125
    static URI[] select(
126
            @NonNull final String volumeType,
127
            @NonNull final String libName,
128
            @NonNull final File[] lastFolder,
129
            @NullAllowed final Component owner,
130
            @NullAllowed final File baseFolder) {
131
        assert volumeType != null;
132
        assert lastFolder != null;
133
        assert lastFolder.length == 1;
134
        final File libFolder = baseFolder == null ?
135
            null:
136
            FileUtil.normalizeFile(new File(baseFolder, libName));
137
        FileChooser chooser = new FileChooser(baseFolder, libFolder);
138
        // for now variable based paths are disabled in library definition
139
        // can be revisit if it is needed
140
        chooser.setFileHidingEnabled(false);
141
        chooser.setAcceptAllFileFilterUsed(false);
142
        if (volumeType.equals(J2SELibraryTypeProvider.VOLUME_TYPE_CLASSPATH)) {
143
            chooser.setMultiSelectionEnabled (true);
144
            chooser.setDialogTitle(NbBundle.getMessage(J2SEVolumeCustomizer.class,"TXT_OpenClasses"));
145
            chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
146
            chooser.setFileFilter (new ArchiveFileFilter(NbBundle.getMessage(
147
                    J2SEVolumeCustomizer.class,"TXT_Classpath"),new String[] {"ZIP","JAR"}));   //NOI18N
148
            chooser.setApproveButtonText(NbBundle.getMessage(J2SEVolumeCustomizer.class,"CTL_SelectCP"));
149
            chooser.setApproveButtonMnemonic(NbBundle.getMessage(J2SEVolumeCustomizer.class,"MNE_SelectCP").charAt(0));
150
        } else if (volumeType.equals(J2SELibraryTypeProvider.VOLUME_TYPE_JAVADOC)) {
151
            chooser.setMultiSelectionEnabled (true);
152
            chooser.setDialogTitle(NbBundle.getMessage(J2SEVolumeCustomizer.class,"TXT_OpenJavadoc"));
153
            chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
154
            chooser.setFileFilter (new ArchiveFileFilter(NbBundle.getMessage(
155
                    J2SEVolumeCustomizer.class,"TXT_Javadoc"),new String[] {"ZIP","JAR"}));     //NOI18N
156
            chooser.setApproveButtonText(NbBundle.getMessage(J2SEVolumeCustomizer.class,"CTL_SelectJD"));
157
            chooser.setApproveButtonMnemonic(NbBundle.getMessage(J2SEVolumeCustomizer.class,"MNE_SelectJD").charAt(0));
158
        } else if (volumeType.equals(J2SELibraryTypeProvider.VOLUME_TYPE_SRC)) {
159
            chooser.setMultiSelectionEnabled (true);
160
            chooser.setDialogTitle(NbBundle.getMessage(J2SEVolumeCustomizer.class,"TXT_OpenSources"));
161
            chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
162
            chooser.setFileFilter (new ArchiveFileFilter(NbBundle.getMessage(
163
                    J2SEVolumeCustomizer.class,"TXT_Sources"),new String[] {"ZIP","JAR"}));     //NOI18N
164
            chooser.setApproveButtonText(NbBundle.getMessage(J2SEVolumeCustomizer.class,"CTL_SelectSRC"));
165
            chooser.setApproveButtonMnemonic(NbBundle.getMessage(J2SEVolumeCustomizer.class,"MNE_SelectSRC").charAt(0));
166
        }
167
        if (lastFolder[0] != null) {
168
            chooser.setCurrentDirectory (lastFolder[0]);
169
        } else if (baseFolder != null) {
170
            chooser.setCurrentDirectory (baseFolder);
171
        }
172
        if (chooser.showOpenDialog(owner) == JFileChooser.APPROVE_OPTION) {
173
            try {
174
                lastFolder[0] = chooser.getCurrentDirectory();
175
                return pathsToURIs (
176
                        chooser.getSelectedPaths(),
177
                        volumeType,
178
                        baseFolder);
179
            } catch (MalformedURLException mue) {
180
                Exceptions.printStackTrace(mue);
181
            } catch (URISyntaxException ue) {
182
                Exceptions.printStackTrace(ue);
183
            } catch (IOException ex) {
184
                Exceptions.printStackTrace(ex);
185
            }
186
        }
187
        return null;
188
    }
189
119
190
120
    private void postInitComponents () {
191
    private void postInitComponents () {
121
        this.content.setCellRenderer(new ContentRenderer());
192
        this.content.setCellRenderer(new ContentRenderer());
Lines 346-399 Link Here
346
    }//GEN-LAST:event_removeResource
417
    }//GEN-LAST:event_removeResource
347
418
348
    private void addResource(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addResource
419
    private void addResource(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addResource
349
        File baseFolder = null;
420
        final boolean arp = allowRelativePaths != null && allowRelativePaths.booleanValue();
350
        File libFolder = null;
421
        final File baseFolder = arp ?
351
        if (allowRelativePaths != null && allowRelativePaths.booleanValue()) {
422
            FileUtil.normalizeFile(new File(URI.create(area.getLocation().toExternalForm())).getParentFile()):
352
            baseFolder = FileUtil.normalizeFile(new File(URI.create(area.getLocation().toExternalForm())).getParentFile());
423
            null;
353
            libFolder = FileUtil.normalizeFile(new File(baseFolder, impl.getName()));
424
        final File[] cwd = new File[]{lastFolder};
354
        }
425
        final URI[] res = select(volumeType, impl.getName(), cwd, this, baseFolder);
355
        FileChooser chooser = new FileChooser(baseFolder, libFolder);
426
        if (res != null) {
356
        FileUtil.preventFileChooserSymlinkTraversal(chooser, null);
357
        // for now variable based paths are disabled in library definition
358
        // can be revisit if it is needed
359
        chooser.setFileHidingEnabled(false);
360
        chooser.setAcceptAllFileFilterUsed(false);
361
        if (this.volumeType.equals(J2SELibraryTypeProvider.VOLUME_TYPE_CLASSPATH)) {
362
            chooser.setMultiSelectionEnabled (true);
363
            chooser.setDialogTitle(NbBundle.getMessage(J2SEVolumeCustomizer.class,"TXT_OpenClasses"));
364
            chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
365
            chooser.setFileFilter (new ArchiveFileFilter(NbBundle.getMessage(
366
                    J2SEVolumeCustomizer.class,"TXT_Classpath"),new String[] {"ZIP","JAR"}));   //NOI18N
367
            chooser.setApproveButtonText(NbBundle.getMessage(J2SEVolumeCustomizer.class,"CTL_SelectCP"));
368
            chooser.setApproveButtonMnemonic(NbBundle.getMessage(J2SEVolumeCustomizer.class,"MNE_SelectCP").charAt(0));
369
        }
370
        else if (this.volumeType.equals(J2SELibraryTypeProvider.VOLUME_TYPE_JAVADOC)) {
371
            chooser.setMultiSelectionEnabled (true);
372
            chooser.setDialogTitle(NbBundle.getMessage(J2SEVolumeCustomizer.class,"TXT_OpenJavadoc"));
373
            chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
374
            chooser.setFileFilter (new ArchiveFileFilter(NbBundle.getMessage(
375
                    J2SEVolumeCustomizer.class,"TXT_Javadoc"),new String[] {"ZIP","JAR"}));     //NOI18N
376
            chooser.setApproveButtonText(NbBundle.getMessage(J2SEVolumeCustomizer.class,"CTL_SelectJD"));
377
            chooser.setApproveButtonMnemonic(NbBundle.getMessage(J2SEVolumeCustomizer.class,"MNE_SelectJD").charAt(0));
378
        }
379
        else if (this.volumeType.equals(J2SELibraryTypeProvider.VOLUME_TYPE_SRC)) {
380
            chooser.setMultiSelectionEnabled (true);
381
            chooser.setDialogTitle(NbBundle.getMessage(J2SEVolumeCustomizer.class,"TXT_OpenSources"));
382
            chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
383
            chooser.setFileFilter (new ArchiveFileFilter(NbBundle.getMessage(
384
                    J2SEVolumeCustomizer.class,"TXT_Sources"),new String[] {"ZIP","JAR"}));     //NOI18N
385
            chooser.setApproveButtonText(NbBundle.getMessage(J2SEVolumeCustomizer.class,"CTL_SelectSRC"));
386
            chooser.setApproveButtonMnemonic(NbBundle.getMessage(J2SEVolumeCustomizer.class,"MNE_SelectSRC").charAt(0));
387
        }
388
        if (lastFolder != null) {
389
            chooser.setCurrentDirectory (lastFolder);
390
        } else if (baseFolder != null) {
391
            chooser.setCurrentDirectory (baseFolder);
392
        }
393
        if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
394
            try {
427
            try {
395
                lastFolder = chooser.getCurrentDirectory();
428
                lastFolder = cwd[0];
396
                addFiles (chooser.getSelectedPaths(), area != null ? area.getLocation() : null, this.volumeType);
429
                addFiles (res, arp);
397
            } catch (MalformedURLException mue) {
430
            } catch (MalformedURLException mue) {
398
                Exceptions.printStackTrace(mue);
431
                Exceptions.printStackTrace(mue);
399
            } catch (URISyntaxException ue) {
432
            } catch (URISyntaxException ue) {
Lines 435-485 Link Here
435
        }
468
        }
436
    }//GEN-LAST:event_addURLButtonActionPerformed
469
    }//GEN-LAST:event_addURLButtonActionPerformed
437
470
438
    private void addFiles (String[] fileNames, URL libraryLocation, String volume) throws MalformedURLException, URISyntaxException {
471
    private void addFiles (URI[] toAdd, boolean  allowRelativePaths) throws MalformedURLException, URISyntaxException {
439
        int firstIndex = this.model.getSize();
472
        int firstIndex = this.model.getSize();
440
        for (int i = 0; i < fileNames.length; i++) {
473
        for (URI uri : toAdd) {
441
            File f = new File(fileNames[i]);
474
            if (allowRelativePaths) {
442
            URI uri = LibrariesSupport.convertFilePathToURI(fileNames[i]);
443
            if (allowRelativePaths != null && allowRelativePaths.booleanValue()) {
444
                File realFile = f;
445
                if (!f.isAbsolute()) {
446
                    assert area != null;
447
                    if (area != null) {
448
                        realFile = FileUtil.normalizeFile(new File(
449
                            new File(URI.create(area.getLocation().toExternalForm())).getParentFile(), f.getPath()));
450
                    }
451
                }
452
                String jarPath = checkFile(realFile, volume);
453
                if (FileUtil.isArchiveFile(realFile.toURI().toURL())) {
454
                    uri = LibrariesSupport.getArchiveRoot(uri);
455
                    if (jarPath != null) {
456
                        assert uri.toString().endsWith("!/") : uri.toString(); //NOI18N
457
                        uri = URI.create(uri.toString() + encodePath(jarPath));
458
                    }
459
                } else if (!uri.toString().endsWith("/")){ //NOI18N
460
                    try {
461
                        uri = new URI(uri.toString()+"/"); //NOI18N
462
                    } catch (URISyntaxException ex) {
463
                        throw new AssertionError(ex);
464
                    }
465
                }
466
                model.addResource(uri);
475
                model.addResource(uri);
467
            } else {
476
            } else {
468
                assert f.isAbsolute() : f.getPath(); 
469
                f = FileUtil.normalizeFile (f);
470
                String jarPath = checkFile(f, volume);
471
                uri = f.toURI();
472
                if (FileUtil.isArchiveFile(uri.toURL())) {
473
                    uri = LibrariesSupport.getArchiveRoot(uri);
474
                    if (jarPath != null) {
475
                        assert uri.toString().endsWith("!/") : uri.toString(); //NOI18N
476
                        uri = URI.create(uri.toString() + encodePath(jarPath));
477
                    }
478
                } else if (!uri.toString().endsWith("/")){ //NOI18N
479
                    uri = URI.create(uri.toString()+"/"); //NOI18N
480
                }
481
                model.addResource(uri.toURL()); //Has to be added as URL, model asserts it
477
                model.addResource(uri.toURL()); //Has to be added as URL, model asserts it
482
483
            }
478
            }
484
        }
479
        }
485
        int lastIndex = this.model.getSize()-1;
480
        int lastIndex = this.model.getSize()-1;
Lines 501-507 Link Here
501
        return new URI(null, null, path, null).getRawPath();
496
        return new URI(null, null, path, null).getRawPath();
502
    }
497
    }
503
498
504
    private String checkFile(File f, String volume) {
499
    @NonNull
500
    private static URI[] pathsToURIs(
501
            @NonNull final String[] fileNames,
502
            @NonNull final String volume,
503
            @NullAllowed final File baseFolder) throws MalformedURLException, URISyntaxException {
504
        final List<URI> result = new ArrayList<URI>(fileNames.length);
505
        for (int i = 0; i < fileNames.length; i++) {
506
            File f = new File(fileNames[i]);
507
            URI uri = LibrariesSupport.convertFilePathToURI(fileNames[i]);
508
            if (baseFolder != null) {
509
                File realFile = f;
510
                if (!f.isAbsolute()) {
511
                        realFile = FileUtil.normalizeFile(new File(
512
                            baseFolder, f.getPath()));
513
                }
514
                String jarPath = checkFile(realFile, volume);
515
                if (FileUtil.isArchiveFile(realFile.toURI().toURL())) {
516
                    uri = LibrariesSupport.getArchiveRoot(uri);
517
                    if (jarPath != null) {
518
                        assert uri.toString().endsWith("!/") : uri.toString(); //NOI18N
519
                        uri = URI.create(uri.toString() + encodePath(jarPath));
520
                    }
521
                } else if (!uri.toString().endsWith("/")){ //NOI18N
522
                    try {
523
                        uri = new URI(uri.toString()+"/"); //NOI18N
524
                    } catch (URISyntaxException ex) {
525
                        throw new AssertionError(ex);
526
                    }
527
                }
528
                result.add(uri);
529
            } else {
530
                assert f.isAbsolute() : f.getPath();
531
                f = FileUtil.normalizeFile (f);
532
                String jarPath = checkFile(f, volume);
533
                uri = f.toURI();
534
                if (FileUtil.isArchiveFile(uri.toURL())) {
535
                    uri = LibrariesSupport.getArchiveRoot(uri);
536
                    if (jarPath != null) {
537
                        assert uri.toString().endsWith("!/") : uri.toString(); //NOI18N
538
                        uri = URI.create(uri.toString() + encodePath(jarPath));
539
                    }
540
                } else if (!uri.toString().endsWith("/")){ //NOI18N
541
                    uri = URI.create(uri.toString()+"/"); //NOI18N
542
                }
543
                result.add(uri);
544
            }
545
        }
546
        return result.toArray(new URI[result.size()]);
547
    }
548
549
    private static String checkFile(File f, String volume) {
505
        FileObject fo = FileUtil.toFileObject(f);
550
        FileObject fo = FileUtil.toFileObject(f);
506
        if (volume.equals(J2SELibraryTypeProvider.VOLUME_TYPE_JAVADOC)) {
551
        if (volume.equals(J2SELibraryTypeProvider.VOLUME_TYPE_JAVADOC)) {
507
            if (fo != null) {
552
            if (fo != null) {
(-)a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/platformdefinition/J2SEPlatformCustomizer.java (-62 / +71 lines)
Lines 94-102 Link Here
94
    private static final String CUSTOMIZERS_PATH =
94
    private static final String CUSTOMIZERS_PATH =
95
        "org-netbeans-api-java/platform/j2seplatform/customizers/";  //NOI18N
95
        "org-netbeans-api-java/platform/j2seplatform/customizers/";  //NOI18N
96
96
97
    private static final int CLASSPATH = 0;
97
    static final int CLASSPATH = 0;
98
    private static final int SOURCES = 1;
98
    static final int SOURCES = 1;
99
    private static final int JAVADOC = 2;
99
    static final int JAVADOC = 2;
100
100
101
    private J2SEPlatformImpl platform;    
101
    private J2SEPlatformImpl platform;    
102
102
Lines 106-111 Link Here
106
    }
106
    }
107
107
108
108
109
    static boolean select(
110
            final PathModel model,
111
            final File[] currentDir,
112
            final Component parentComponent) {
113
        final JFileChooser chooser = new JFileChooser ();
114
        chooser.setMultiSelectionEnabled (true);
115
        String title = null;
116
        String message = null;
117
        String approveButtonName = null;
118
        String approveButtonNameMne = null;
119
        if (model.type == SOURCES) {
120
            title = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_OpenSources");
121
            message = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_Sources");
122
            approveButtonName = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_OpenSources");
123
            approveButtonNameMne = NbBundle.getMessage (J2SEPlatformCustomizer.class,"MNE_OpenSources");
124
        } else if (model.type == JAVADOC) {
125
            title = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_OpenJavadoc");
126
            message = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_Javadoc");
127
            approveButtonName = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_OpenJavadoc");
128
            approveButtonNameMne = NbBundle.getMessage (J2SEPlatformCustomizer.class,"MNE_OpenJavadoc");
129
        }
130
        chooser.setDialogTitle(title);
131
        chooser.setApproveButtonText(approveButtonName);
132
        chooser.setApproveButtonMnemonic (approveButtonNameMne.charAt(0));
133
        chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
134
        if (Utilities.isMac()) {
135
            //New JDKs and JREs are bundled into package, allow JFileChooser to navigate in
136
            chooser.putClientProperty("JFileChooser.packageIsTraversable", "always");   //NOI18N
137
        }
138
        //#61789 on old macosx (jdk 1.4.1) these two method need to be called in this order.
139
        chooser.setAcceptAllFileFilterUsed( false );
140
        chooser.setFileFilter (new ArchiveFileFilter(message,new String[] {"ZIP","JAR"}));   //NOI18N
141
        if (currentDir[0] != null) {
142
            chooser.setCurrentDirectory(currentDir[0]);
143
        }
144
        if (chooser.showOpenDialog(parentComponent) == JFileChooser.APPROVE_OPTION) {
145
            File[] fs = chooser.getSelectedFiles();
146
            boolean addingFailed = false;
147
            for (File f : fs) {
148
                //XXX: JFileChooser workaround (JDK bug #5075580), double click on folder returns wrong file
149
                // E.g. for /foo/src it returns /foo/src/src
150
                // Try to convert it back by removing last invalid name component
151
                if (!f.exists()) {
152
                    File parent = f.getParentFile();
153
                    if (parent != null && f.getName().equals(parent.getName()) && parent.exists()) {
154
                        f = parent;
155
                    }
156
                }
157
                if (f.exists()) {
158
                    addingFailed|=!model.addPath (f);
159
                }
160
            }
161
            if (addingFailed) {
162
                new NotifyDescriptor.Message (NbBundle.getMessage(J2SEPlatformCustomizer.class,"TXT_CanNotAddResolve"),
163
                        NotifyDescriptor.ERROR_MESSAGE);
164
            }
165
            currentDir[0] = FileUtil.normalizeFile(chooser.getCurrentDirectory());
166
            return true;
167
        }
168
        return false;
169
    }
170
109
    private void initComponents () {
171
    private void initComponents () {
110
        this.getAccessibleContext().setAccessibleName (NbBundle.getMessage(J2SEPlatformCustomizer.class,"AN_J2SEPlatformCustomizer"));
172
        this.getAccessibleContext().setAccessibleName (NbBundle.getMessage(J2SEPlatformCustomizer.class,"AN_J2SEPlatformCustomizer"));
111
        this.getAccessibleContext().setAccessibleDescription (NbBundle.getMessage(J2SEPlatformCustomizer.class,"AD_J2SEPlatformCustomizer"));
173
        this.getAccessibleContext().setAccessibleDescription (NbBundle.getMessage(J2SEPlatformCustomizer.class,"AD_J2SEPlatformCustomizer"));
Lines 369-431 Link Here
369
        }
431
        }
370
432
371
        private void addPathElement () {
433
        private void addPathElement () {
372
            JFileChooser chooser = new JFileChooser ();
434
            final int firstIndex = this.resources.getModel().getSize();
373
            FileUtil.preventFileChooserSymlinkTraversal(chooser, null);
435
            final File[] cwd = new File[]{currentDir};
374
            chooser.setMultiSelectionEnabled (true);
436
            if (select((PathModel)this.resources.getModel(),cwd, this)) {
375
            String title = null;
437
                final int lastIndex = this.resources.getModel().getSize()-1;
376
            String message = null;
377
            String approveButtonName = null;
378
            String approveButtonNameMne = null;
379
            if (this.type == SOURCES) {
380
                title = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_OpenSources");
381
                message = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_Sources");
382
                approveButtonName = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_OpenSources");
383
                approveButtonNameMne = NbBundle.getMessage (J2SEPlatformCustomizer.class,"MNE_OpenSources");
384
            }
385
            else if (this.type == JAVADOC) {
386
                title = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_OpenJavadoc");
387
                message = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_Javadoc");
388
                approveButtonName = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_OpenJavadoc");
389
                approveButtonNameMne = NbBundle.getMessage (J2SEPlatformCustomizer.class,"MNE_OpenJavadoc");
390
            }
391
            chooser.setDialogTitle(title);
392
            chooser.setApproveButtonText(approveButtonName);
393
            chooser.setApproveButtonMnemonic (approveButtonNameMne.charAt(0));
394
            chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
395
            if (Utilities.isMac()) {
396
                //New JDKs and JREs are bundled into package, allow JFileChooser to navigate in
397
                chooser.putClientProperty("JFileChooser.packageIsTraversable", "always");   //NOI18N
398
            }
399
            //#61789 on old macosx (jdk 1.4.1) these two method need to be called in this order.
400
            chooser.setAcceptAllFileFilterUsed( false );
401
            chooser.setFileFilter (new ArchiveFileFilter(message,new String[] {"ZIP","JAR"}));   //NOI18N
402
            if (this.currentDir != null) {
403
                chooser.setCurrentDirectory(this.currentDir);
404
            }
405
            if (chooser.showOpenDialog(this)==JFileChooser.APPROVE_OPTION) {
406
                File[] fs = chooser.getSelectedFiles();
407
                PathModel model = (PathModel) this.resources.getModel();
408
                boolean addingFailed = false;
409
                int firstIndex = this.resources.getModel().getSize();
410
                for (File f : fs) {
411
                    //XXX: JFileChooser workaround (JDK bug #5075580), double click on folder returns wrong file
412
                    // E.g. for /foo/src it returns /foo/src/src
413
                    // Try to convert it back by removing last invalid name component
414
                    if (!f.exists()) {
415
                        File parent = f.getParentFile();
416
                        if (parent != null && f.getName().equals(parent.getName()) && parent.exists()) {
417
                            f = parent;
418
                        }
419
                    }
420
                    if (f.exists()) {
421
                        addingFailed|=!model.addPath (f);
422
                    }
423
                }
424
                if (addingFailed) {
425
                    new NotifyDescriptor.Message (NbBundle.getMessage(J2SEPlatformCustomizer.class,"TXT_CanNotAddResolve"),
426
                            NotifyDescriptor.ERROR_MESSAGE);
427
                }
428
                int lastIndex = this.resources.getModel().getSize()-1;
429
                if (firstIndex<=lastIndex) {
438
                if (firstIndex<=lastIndex) {
430
                    int[] toSelect = new int[lastIndex-firstIndex+1];
439
                    int[] toSelect = new int[lastIndex-firstIndex+1];
431
                    for (int i = 0; i < toSelect.length; i++) {
440
                    for (int i = 0; i < toSelect.length; i++) {
Lines 433-439 Link Here
433
                    }
442
                    }
434
                    this.resources.setSelectedIndices(toSelect);
443
                    this.resources.setSelectedIndices(toSelect);
435
                }
444
                }
436
                this.currentDir = FileUtil.normalizeFile(chooser.getCurrentDirectory());
445
                this.currentDir = cwd[0];
437
            }
446
            }
438
        }
447
        }
439
448
Lines 491-497 Link Here
491
    }
500
    }
492
501
493
502
494
    private static class PathModel extends AbstractListModel/*<String>*/ {
503
    static class PathModel extends AbstractListModel/*<String>*/ {
495
504
496
        private J2SEPlatformImpl platform;
505
        private J2SEPlatformImpl platform;
497
        private int type;
506
        private int type;
(-)a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/platformdefinition/J2SEPlatformImpl.java (+13 lines)
Lines 476-481 Link Here
476
        }
476
        }
477
        return Collections.emptyList();
477
        return Collections.emptyList();
478
    }
478
    }
479
480
    boolean isBroken () {
481
        if (getInstallFolders().isEmpty()) {
482
            return true;
483
        }
484
        for (String tool : PlatformConvertor.IMPORTANT_TOOLS) {
485
            if (findTool(tool) == null) {
486
                return true;
487
            }
488
        }
489
        return false;
490
    }
491
479
    private static final Map<String,String> OFFICIAL_JAVADOC = new HashMap<String,String>();
492
    private static final Map<String,String> OFFICIAL_JAVADOC = new HashMap<String,String>();
480
    static {
493
    static {
481
        OFFICIAL_JAVADOC.put("1.0", null); // NOI18N
494
        OFFICIAL_JAVADOC.put("1.0", null); // NOI18N
(-)a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/platformdefinition/J2SEPlatformNode.java (-14 / +2 lines)
Lines 67-73 Link Here
67
    }
67
    }
68
68
69
    public String getHtmlDisplayName() {
69
    public String getHtmlDisplayName() {
70
        if (isBroken()) {
70
        if (platform.isBroken()) {
71
            return "<font color=\"#A40000\">"+this.platform.getDisplayName()+"</font>";
71
            return "<font color=\"#A40000\">"+this.platform.getDisplayName()+"</font>";
72
        }
72
        }
73
        else {
73
        else {
Lines 103-109 Link Here
103
    }
103
    }
104
104
105
    public java.awt.Component getCustomizer () {
105
    public java.awt.Component getCustomizer () {
106
        if (isBroken()) {
106
        if (platform.isBroken()) {
107
            return new BrokenPlatformCustomizer (this.platform);
107
            return new BrokenPlatformCustomizer (this.platform);
108
        }
108
        }
109
        else {
109
        else {
Lines 111-126 Link Here
111
        }
111
        }
112
    }
112
    }
113
113
114
    private boolean isBroken () {
115
        if (this.platform.getInstallFolders().size()==0) {
116
            return true;
117
        }
118
        for (String tool : PlatformConvertor.IMPORTANT_TOOLS) {
119
            if (platform.findTool(tool) == null) {
120
                return true;
121
            }
122
        }
123
        return false;
124
    }
125
126
}
114
}
(-)a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/platformdefinition/J2SEPlatformSourceJavadocAttacher.java (+102 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.java.j2seplatform.platformdefinition;
43
44
import java.io.File;
45
import java.io.IOException;
46
import java.net.URL;
47
import org.netbeans.api.java.classpath.ClassPath;
48
import org.netbeans.api.java.platform.JavaPlatform;
49
import org.netbeans.api.java.platform.JavaPlatformManager;
50
import org.netbeans.api.java.platform.Specification;
51
import org.netbeans.spi.java.queries.SourceJavadocAttacherImplementation;
52
import org.openide.util.lookup.ServiceProvider;
53
54
/**
55
 *
56
 * @author Tomas Zezula
57
 */
58
@ServiceProvider(service=SourceJavadocAttacherImplementation.class,position=150)
59
public class J2SEPlatformSourceJavadocAttacher implements SourceJavadocAttacherImplementation {
60
61
    @Override
62
    public Result attachSources(final URL root) throws IOException {
63
        return attach(root, J2SEPlatformCustomizer.SOURCES);
64
    }
65
66
    @Override
67
    public Result attachJavadoc(final URL root) throws IOException {
68
        return attach(root, J2SEPlatformCustomizer.JAVADOC);
69
    }
70
71
    private Result attach(final URL root, int mode) {
72
        final J2SEPlatformImpl platform = findOwner(root);
73
        if (platform == null) {
74
            return Result.UNSUPPORTED;
75
        }
76
        final J2SEPlatformCustomizer.PathModel model = new J2SEPlatformCustomizer.PathModel(platform, mode);
77
        if (J2SEPlatformCustomizer.select(model,new File[1],null)) {
78
            return Result.ATTACHED;
79
        }
80
        return Result.CANCELED;
81
    }
82
83
    private J2SEPlatformImpl findOwner(final URL root) {
84
        for (JavaPlatform p : JavaPlatformManager.getDefault().getPlatforms(null, new Specification(J2SEPlatformImpl.PLATFORM_J2SE, null))) {
85
            if (!(p instanceof J2SEPlatformImpl)) {
86
                //Cannot handle unknown platform
87
                continue;
88
            }
89
            final J2SEPlatformImpl j2sep = (J2SEPlatformImpl) p;
90
            if (j2sep.isBroken()) {
91
                continue;
92
            }
93
            for (ClassPath.Entry entry : j2sep.getBootstrapLibraries().entries()) {
94
                if (root.equals(entry.getURL())) {
95
                    return j2sep;
96
                }
97
            }
98
        }
99
        return null;
100
    }
101
102
}
(-)a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/queries/DefaultJavadocForBinaryQuery.java (+64 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.java.j2seplatform.queries;
43
44
import java.net.URL;
45
import java.util.Map;
46
import org.netbeans.api.annotations.common.NonNull;
47
import org.netbeans.api.java.queries.JavadocForBinaryQuery;
48
import org.netbeans.api.java.queries.JavadocForBinaryQuery.Result;
49
import org.netbeans.spi.java.queries.JavadocForBinaryQueryImplementation;
50
import org.openide.util.lookup.ServiceProvider;
51
52
/**
53
 *
54
 * @author Tomas Zezula
55
 */
56
@ServiceProvider(service=JavadocForBinaryQueryImplementation.class) //position = last
57
public class DefaultJavadocForBinaryQuery implements JavadocForBinaryQueryImplementation {
58
59
    @Override
60
    public Result findJavadoc(@NonNull final URL binaryRoot) {
61
        final Map<URL,? extends JavadocForBinaryQuery.Result> mapping = QueriesCache.getJavadoc().getRoots();
62
        return mapping.get(binaryRoot);
63
    }
64
}
(-)a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/queries/DefaultSourceForBinaryQuery.java (+69 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.java.j2seplatform.queries;
43
44
import java.net.URL;
45
import java.util.Map;
46
import org.netbeans.api.annotations.common.NonNull;
47
import org.netbeans.api.java.queries.SourceForBinaryQuery;
48
import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation2;
49
import org.openide.util.lookup.ServiceProvider;
50
51
/**
52
 *
53
 * @author Tomas Zezula
54
 */
55
@ServiceProvider(service=SourceForBinaryQueryImplementation2.class) //position = last
56
public class DefaultSourceForBinaryQuery implements SourceForBinaryQueryImplementation2 {
57
58
    @Override
59
    public Result findSourceRoots2(@NonNull final URL binaryRoot) {
60
        final Map<URL,? extends Result> mapping = QueriesCache.getSources().getRoots();
61
        return mapping.get(binaryRoot);
62
    }
63
64
    @Override
65
    public SourceForBinaryQuery.Result findSourceRoots(URL binaryRoot) {
66
        return findSourceRoots2(binaryRoot);
67
    }
68
69
}
(-)a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/queries/DefaultSourceJavadocAttacher.java (+140 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.java.j2seplatform.queries;
43
44
import java.io.File;
45
import java.io.IOException;
46
import java.net.MalformedURLException;
47
import java.net.URL;
48
import java.util.ArrayList;
49
import java.util.List;
50
import javax.swing.JFileChooser;
51
import javax.swing.filechooser.FileFilter;
52
import org.netbeans.spi.java.project.support.JavadocAndSourceRootDetection;
53
import org.netbeans.spi.java.queries.SourceJavadocAttacherImplementation;
54
import org.openide.filesystems.FileObject;
55
import org.openide.filesystems.FileStateInvalidException;
56
import org.openide.filesystems.FileUtil;
57
import org.openide.util.NbBundle;
58
import org.openide.util.lookup.ServiceProvider;
59
60
/**
61
 *
62
 * @author Tomas Zezula
63
 */
64
@ServiceProvider(service=SourceJavadocAttacherImplementation.class) //position=last
65
public class DefaultSourceJavadocAttacher implements SourceJavadocAttacherImplementation {
66
67
    @Override
68
    public Result attachSources(URL root) throws IOException {
69
        final URL[] sources = selectRoots(0);
70
        if (sources != null) {
71
            QueriesCache.getSources().updateRoot(root, sources);
72
            return Result.ATTACHED;
73
        }
74
        return Result.CANCELED;
75
    }
76
77
    @Override
78
    public Result attachJavadoc(URL root) throws IOException {
79
        final URL[] javadoc = selectRoots(1);
80
        if (javadoc != null) {
81
            QueriesCache.getSources().updateRoot(root, javadoc);
82
            return Result.ATTACHED;
83
        }
84
        return Result.CANCELED;
85
    }
86
87
    @NbBundle.Messages({
88
        "TXT_Title=Browse ZIP/Folder",
89
        "TXT_Javadoc=Library Javadoc (folder, ZIP or JAR file)",
90
        "TXT_Sources=Library Sources (folder, ZIP or JAR file)",
91
        "TXT_Select=Add ZIP/Folder",
92
        "MNE_Select=A"
93
    })
94
    private static URL[] selectRoots(final int mode) throws MalformedURLException, FileStateInvalidException {
95
        final JFileChooser chooser = new JFileChooser();
96
        chooser.setMultiSelectionEnabled (true);
97
        chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
98
        chooser.setDialogTitle(Bundle.TXT_Title());
99
        chooser.setFileFilter (new FileFilter() {
100
            @Override
101
            public boolean accept(File f) {
102
                try {
103
                    return f.isDirectory() ||
104
                        FileUtil.isArchiveFile(f.toURI().toURL());
105
                } catch (MalformedURLException ex) {
106
                    return false;
107
                }
108
            }
109
110
            @Override
111
            public String getDescription() {
112
                return mode == 0 ? Bundle.TXT_Sources() : Bundle.TXT_Javadoc();
113
            }
114
        });
115
        chooser.setApproveButtonText(Bundle.TXT_Select());
116
        chooser.setApproveButtonMnemonic(Bundle.MNE_Select().charAt(0));
117
        if (currentFolder != null) {
118
            chooser.setCurrentDirectory(currentFolder);
119
        }
120
        if (chooser.showOpenDialog(null) == chooser.APPROVE_OPTION) {
121
            currentFolder = chooser.getCurrentDirectory();
122
            final File[] files = chooser.getSelectedFiles();
123
            final List<URL> result = new ArrayList<URL>(files.length);
124
            for (File f : files) {
125
                FileObject fo = FileUtil.toFileObject(f);
126
                if (fo.isData()) {
127
                    fo = FileUtil.getArchiveRoot(fo);
128
                }
129
                fo = mode == 0 ?
130
                    JavadocAndSourceRootDetection.findSourceRoot(fo) :
131
                    JavadocAndSourceRootDetection.findJavadocRoot(fo);
132
                result.add(fo.getURL());
133
            }
134
            return result.toArray(new URL[result.size()]);
135
        }
136
        return null;
137
    }
138
139
    private static File currentFolder;
140
}
(-)a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/queries/QueriesCache.java (+268 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.java.j2seplatform.queries;
43
44
import java.net.MalformedURLException;
45
import java.net.URL;
46
import java.util.ArrayList;
47
import java.util.Arrays;
48
import java.util.Collection;
49
import java.util.Collections;
50
import java.util.HashMap;
51
import java.util.List;
52
import java.util.Map;
53
import java.util.prefs.BackingStoreException;
54
import java.util.prefs.Preferences;
55
import javax.swing.event.ChangeListener;
56
import org.netbeans.api.annotations.common.NonNull;
57
import org.netbeans.api.java.queries.JavadocForBinaryQuery;
58
import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation2;
59
import org.openide.filesystems.FileObject;
60
import org.openide.filesystems.URLMapper;
61
import org.openide.util.ChangeSupport;
62
import org.openide.util.Exceptions;
63
import org.openide.util.NbPreferences;
64
65
/**
66
 *
67
 * @author Tomas Zezula
68
 */
69
final class QueriesCache<T extends QueriesCache.ResultBase> {
70
71
    private static QueriesCache<Javadoc> javadoc;
72
    private static QueriesCache<Sources> sources;
73
    private static final char SEP = '-';  //NOI18N
74
75
    private final Object lck = new Object();
76
    private final Class<T> clazz;
77
    //@GuardedBy("lck")
78
    private Map<URL,T> cache;
79
80
    private QueriesCache(@NonNull final Class<T> clazz){
81
        assert clazz != null;
82
        this.clazz = clazz;
83
    }
84
85
    @NonNull
86
    Map<URL,? extends T> getRoots() {
87
        return Collections.unmodifiableMap(loadRoots());
88
    }
89
90
    void updateRoot(final URL binaryRoot, final URL... rootsToAttach) {
91
        T currentMapping = null;
92
        synchronized (lck) {
93
            final Map<URL,T> currentRoots = loadRoots();
94
            currentMapping = currentRoots.get(binaryRoot);
95
            final Preferences root = NbPreferences.forModule(QueriesCache.class);
96
            final Preferences node = root.node(clazz.getSimpleName());
97
            final String binaryRootStr = binaryRoot.toExternalForm();
98
            try {
99
                for (String key : filterKeys(node.keys(),binaryRootStr)) {
100
                    node.remove(key);
101
                }
102
                for (int i=0; i < rootsToAttach.length; i++) {
103
                    node.put(String.format("%s-%d",binaryRootStr,i), rootsToAttach[i].toExternalForm());
104
                }
105
                node.flush();
106
            } catch (BackingStoreException bse) {
107
                Exceptions.printStackTrace(bse);
108
            }
109
            if (currentMapping == null) {
110
                try {
111
                    currentMapping = clazz.newInstance();
112
                    currentRoots.put(binaryRoot, currentMapping);
113
                } catch (InstantiationException ie) {
114
                    Exceptions.printStackTrace(ie);
115
                } catch (IllegalAccessException iae) {
116
                    Exceptions.printStackTrace(iae);
117
                }
118
            }
119
        }
120
        if (currentMapping != null) {
121
            currentMapping.update(Arrays.asList(rootsToAttach));
122
        }
123
    }
124
125
    @NonNull
126
    private Map<URL,T> loadRoots() {
127
        synchronized(lck) {
128
           if (cache == null) {
129
               Map<URL,T> result = new HashMap<URL, T>();
130
               final Preferences root = NbPreferences.forModule(QueriesCache.class);
131
               final String folder = clazz.getSimpleName();
132
               try {
133
                   if (root.nodeExists(folder)) {
134
                       final Preferences node = root.node(folder);
135
                       Map<URL,List<URL>> bindings = new HashMap<URL, List<URL>>();
136
                       for (String key : node.keys()) {
137
                           final String value = node.get(key, null);
138
                           if (value != null) {
139
                               final URL binUrl = getURL(key);
140
                               List<URL> binding = bindings.get(binUrl);
141
                               if(binding == null) {
142
                                   binding = new ArrayList<URL>();
143
                                   bindings.put(binUrl,binding);
144
                               }
145
                               binding.add(new URL(value));
146
                           }
147
                       }
148
                       for (Map.Entry<URL,List<URL>> e : bindings.entrySet()) {
149
                           final T instance = clazz.newInstance();
150
                           instance.update(e.getValue());
151
                           result.put(e.getKey(), instance);
152
                       }
153
                   }
154
               } catch (BackingStoreException bse) {
155
                   Exceptions.printStackTrace(bse);
156
               } catch (MalformedURLException mue) {
157
                   Exceptions.printStackTrace(mue);
158
               } catch (InstantiationException ie) {
159
                   Exceptions.printStackTrace(ie);
160
               } catch (IllegalAccessException iae) {
161
                   Exceptions.printStackTrace(iae);
162
               }
163
               cache = result;
164
           }
165
           return cache;
166
        }
167
    }
168
169
    private URL getURL(@NonNull final String pattern) throws MalformedURLException {
170
        final int index = pattern.lastIndexOf(SEP); //NOI18N
171
        assert index > 0;
172
        return new URL(pattern.substring(0, index));
173
    }
174
175
    private Iterable<? extends String> filterKeys(
176
            final String[] keys,
177
            final String binaryRoot) {
178
        final List<String> result = new ArrayList<String>();
179
        for (int i=0; i<keys.length; i++) {
180
            final int index = keys[i].lastIndexOf(SEP); //NOI18N
181
            if (index <=0) {
182
                continue;
183
            }
184
            final String root = keys[i].substring(0, index);
185
            if (root.equals(binaryRoot)) {
186
                result.add(keys[i]);
187
            }
188
        }
189
        return result;
190
    }
191
192
    @NonNull
193
    static synchronized QueriesCache<Javadoc> getJavadoc() {
194
        if (javadoc == null) {
195
            javadoc = new QueriesCache<Javadoc>(Javadoc.class);
196
        }
197
        return javadoc;
198
    }
199
200
    @NonNull
201
    static synchronized QueriesCache<Sources> getSources() {
202
        if (sources == null) {
203
            sources = new QueriesCache<Sources>(Sources.class);
204
        }
205
        return sources;
206
    }
207
208
    static abstract class ResultBase {
209
        private final ChangeSupport cs = new ChangeSupport(this);
210
211
        public void addChangeListener(@NonNull final ChangeListener l) {
212
            cs.addChangeListener(l);
213
        }
214
215
        public void removeChangeListener(@NonNull final ChangeListener l) {
216
            cs.removeChangeListener(l);
217
        }
218
219
        public final void update(final Collection<? extends URL> roots) {
220
            updateImpl(roots);
221
            cs.fireChange();
222
        }
223
224
        protected abstract void updateImpl(final Collection<? extends URL> roots);
225
    }
226
227
    static class Javadoc extends ResultBase implements JavadocForBinaryQuery.Result {
228
        private volatile URL[] roots;
229
230
        public URL[] getRoots() {
231
            final URL[] tmp = roots;
232
            return tmp == null ? new URL[0] : Arrays.copyOf(tmp, tmp.length);
233
        }
234
235
        @Override
236
        protected void updateImpl(final Collection<? extends URL> roots) {
237
            this.roots = roots.toArray(new URL[roots.size()]);
238
        }
239
    }
240
241
    static class Sources extends ResultBase implements SourceForBinaryQueryImplementation2.Result {
242
        private volatile FileObject[] roots;
243
244
        @Override
245
        public boolean preferSources() {
246
            return false;
247
        }
248
249
        @Override
250
        public FileObject[] getRoots() {
251
            final FileObject[] tmp = roots;
252
            return tmp == null ? new FileObject[0]: Arrays.copyOf(tmp, tmp.length);
253
        }
254
255
        @Override
256
        protected void updateImpl(final Collection<? extends URL> roots) {
257
            //Todo: replace by classpath to handle fo listening
258
            final List<FileObject> fos = new ArrayList<FileObject>(roots.size());
259
            for (URL url : roots) {
260
                final FileObject fo = URLMapper.findFileObject(url);
261
                if (fo != null) {
262
                    fos.add(fo);
263
                }
264
            }
265
            this.roots = fos.toArray(new FileObject[fos.size()]);
266
        }
267
    }
268
}
(-)a/java.source/nbproject/project.xml (-1 / +1 lines)
Lines 64-70 Link Here
64
                    <compile-dependency/>
64
                    <compile-dependency/>
65
                    <run-dependency>
65
                    <run-dependency>
66
                        <release-version>1</release-version>
66
                        <release-version>1</release-version>
67
                        <specification-version>1.28</specification-version>
67
                        <specification-version>1.35</specification-version>
68
                    </run-dependency>
68
                    </run-dependency>
69
                </dependency>
69
                </dependency>
70
                <dependency>
70
                <dependency>
(-)a/java.source/src/org/netbeans/modules/java/classfile/AttachSourcePanel.form (+66 lines)
Line 0 Link Here
1
<?xml version="1.1" encoding="UTF-8" ?>
2
3
<Form version="1.5" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
4
  <AuxValues>
5
    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
6
    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
7
    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
8
    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
9
    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
10
    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
11
    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
12
    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
13
    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
14
  </AuxValues>
15
16
  <Layout>
17
    <DimensionLayout dim="0">
18
      <Group type="103" groupAlignment="0" attributes="0">
19
          <Group type="102" alignment="0" attributes="0">
20
              <EmptySpace min="-2" pref="20" max="-2" attributes="0"/>
21
              <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
22
              <EmptySpace max="-2" attributes="0"/>
23
              <Component id="jLabel2" pref="430" max="32767" attributes="0"/>
24
              <EmptySpace max="-2" attributes="0"/>
25
              <Component id="jButton1" min="-2" max="-2" attributes="0"/>
26
              <EmptySpace min="-2" pref="17" max="-2" attributes="0"/>
27
          </Group>
28
      </Group>
29
    </DimensionLayout>
30
    <DimensionLayout dim="1">
31
      <Group type="103" groupAlignment="0" attributes="0">
32
          <Group type="103" groupAlignment="3" attributes="0">
33
              <Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
34
              <Component id="jLabel2" alignment="3" min="-2" max="-2" attributes="0"/>
35
              <Component id="jButton1" alignment="3" min="-2" pref="25" max="-2" attributes="0"/>
36
          </Group>
37
      </Group>
38
    </DimensionLayout>
39
  </Layout>
40
  <SubComponents>
41
    <Component class="javax.swing.JLabel" name="jLabel1">
42
      <Properties>
43
        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
44
          <ResourceString bundle="org/netbeans/modules/java/classfile/Bundle.properties" key="AttachSourcePanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
45
        </Property>
46
      </Properties>
47
    </Component>
48
    <Component class="javax.swing.JButton" name="jButton1">
49
      <Properties>
50
        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
51
          <ResourceString bundle="org/netbeans/modules/java/classfile/Bundle.properties" key="AttachSourcePanel.jButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
52
        </Property>
53
      </Properties>
54
      <Events>
55
        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="attachSources"/>
56
      </Events>
57
    </Component>
58
    <Component class="javax.swing.JLabel" name="jLabel2">
59
      <Properties>
60
        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
61
          <Connection code="getFileDisplayName()" type="code"/>
62
        </Property>
63
      </Properties>
64
    </Component>
65
  </SubComponents>
66
</Form>
(-)a/java.source/src/org/netbeans/modules/java/classfile/AttachSourcePanel.java (+167 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common Development and
11
 * Distribution License("CDDL") (collectively, the "License"). You may not use
12
 * this file except in compliance with the License. You can obtain a copy of
13
 * the License at http://www.netbeans.org/cddl-gplv2.html or
14
 * nbbuild/licenses/CDDL-GPL-2-CP. See the License for the specific language
15
 * governing permissions and limitations under the License. When distributing
16
 * the software, include this License Header Notice in each file and include
17
 * the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
18
 * particular file as subject to the "Classpath" exception as provided by
19
 * Oracle in the GPL Version 2 section of the License file that accompanied
20
 * this code. If applicable, add the following below the License Header, with
21
 * the fields enclosed by brackets [] replaced by your own identifying
22
 * information: "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL or
25
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
26
 * elects to include this software in this distribution under the [CDDL or GPL
27
 * Version 2] license." If you do not indicate a single choice of license, a
28
 * recipient has the option to distribute your version of this file under
29
 * either the CDDL, the GPL Version 2 or to extend the choice of license to its
30
 * licensees as provided above. However, if you add GPL Version 2 code and
31
 * therefore, elected the GPL Version 2 license, then the option applies only
32
 * if the new code is made subject to such option by the copyright holder.
33
 *
34
 * Contributor(s):
35
 *
36
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
37
 */
38
39
/*
40
 * AttachSourcePanel.java
41
 *
42
 * Created on Aug 1, 2011, 4:54:38 PM
43
 */
44
package org.netbeans.modules.java.classfile;
45
46
import java.net.URL;
47
import org.netbeans.api.actions.Openable;
48
import org.netbeans.api.annotations.common.NonNull;
49
import org.netbeans.api.java.classpath.ClassPath;
50
import org.netbeans.api.java.queries.SourceForBinaryQuery;
51
import org.netbeans.api.java.queries.SourceJavadocAttacher;
52
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
53
import org.openide.cookies.EditorCookie;
54
import org.openide.filesystems.FileObject;
55
import org.openide.filesystems.FileUtil;
56
import org.openide.filesystems.URLMapper;
57
import org.openide.loaders.DataObject;
58
import org.openide.loaders.DataObjectNotFoundException;
59
import org.openide.util.Exceptions;
60
import org.openide.util.NbBundle;
61
62
63
public class AttachSourcePanel extends javax.swing.JPanel {
64
65
    private final URL root;
66
    private final URL file;
67
    private final String binaryName;
68
69
    public AttachSourcePanel(
70
            @NonNull final URL root,
71
            @NonNull final URL file,
72
            @NonNull final String binaryName) {
73
        assert root != null;
74
        assert file != null;
75
        assert binaryName != null;
76
        this.root = root;
77
        this.file = file;
78
        this.binaryName = binaryName;
79
        initComponents();
80
    }
81
82
    @NbBundle.Messages({
83
        "TXT_UnknownRoot=<unknown-root>"
84
    })
85
    private String getFileDisplayName() {
86
        final FileObject rootFo = URLMapper.findFileObject(root);
87
        return rootFo == null ? Bundle.TXT_UnknownRoot() : FileUtil.getFileDisplayName(rootFo);
88
    }
89
90
    /** This method is called from within the constructor to
91
     * initialize the form.
92
     * WARNING: Do NOT modify this code. The content of this method is
93
     * always regenerated by the Form Editor.
94
     */
95
    @SuppressWarnings("unchecked")
96
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
97
    private void initComponents() {
98
99
        jLabel1 = new javax.swing.JLabel();
100
        jButton1 = new javax.swing.JButton();
101
        jLabel2 = new javax.swing.JLabel();
102
103
        jLabel1.setText(org.openide.util.NbBundle.getMessage(AttachSourcePanel.class, "AttachSourcePanel.jLabel1.text")); // NOI18N
104
105
        jButton1.setText(org.openide.util.NbBundle.getMessage(AttachSourcePanel.class, "AttachSourcePanel.jButton1.text")); // NOI18N
106
        jButton1.addActionListener(new java.awt.event.ActionListener() {
107
            public void actionPerformed(java.awt.event.ActionEvent evt) {
108
                attachSources(evt);
109
            }
110
        });
111
112
        jLabel2.setText(getFileDisplayName());
113
114
        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
115
        this.setLayout(layout);
116
        layout.setHorizontalGroup(
117
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
118
            .addGroup(layout.createSequentialGroup()
119
                .addGap(20, 20, 20)
120
                .addComponent(jLabel1)
121
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
122
                .addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, 430, Short.MAX_VALUE)
123
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
124
                .addComponent(jButton1)
125
                .addGap(17, 17, 17))
126
        );
127
        layout.setVerticalGroup(
128
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
129
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
130
                .addComponent(jLabel1)
131
                .addComponent(jLabel2)
132
                .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE))
133
        );
134
    }// </editor-fold>//GEN-END:initComponents
135
136
private void attachSources(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_attachSources
137
        if (SourceJavadocAttacher.attachSources(root)) {
138
            final FileObject rootFo = URLMapper.findFileObject(root);
139
            final FileObject fileFo = URLMapper.findFileObject(file);
140
            if (rootFo != null && fileFo != null) {
141
                final FileObject[] fos = SourceForBinaryQuery.findSourceRoots(root).getRoots();
142
                if (fos.length > 0) {
143
                    final ClassPath cp = ClassPathSupport.createClassPath(fos);
144
                    final FileObject newFileFo = cp.findResource(binaryName + ".java"); //NOI18N
145
                    if (newFileFo != null) {
146
                        try {
147
                            final EditorCookie ec = DataObject.find(fileFo).getLookup().lookup(EditorCookie.class);
148
                            final Openable open = DataObject.find(newFileFo).getLookup().lookup(Openable.class);
149
                            if (ec != null && open != null) {
150
                                ec.close();
151
                                open.open();
152
                            }
153
                        } catch (DataObjectNotFoundException ex) {
154
                            Exceptions.printStackTrace(ex);
155
                        }
156
                    }
157
                }
158
            }
159
        }
160
}//GEN-LAST:event_attachSources
161
162
    // Variables declaration - do not modify//GEN-BEGIN:variables
163
    private javax.swing.JButton jButton1;
164
    private javax.swing.JLabel jLabel1;
165
    private javax.swing.JLabel jLabel2;
166
    // End of variables declaration//GEN-END:variables
167
}
(-)a/java.source/src/org/netbeans/modules/java/classfile/Bundle.properties (+2 lines)
Line 0 Link Here
1
AttachSourcePanel.jLabel1.text=No source associated with:
2
AttachSourcePanel.jButton1.text=Associate Source...
(-)a/java.source/src/org/netbeans/modules/java/classfile/CodeGenerator.java (-4 / +16 lines)
Lines 44-49 Link Here
44
import java.io.File;
44
import java.io.File;
45
import java.io.IOException;
45
import java.io.IOException;
46
import java.io.OutputStream;
46
import java.io.OutputStream;
47
import java.net.URL;
47
import java.security.MessageDigest;
48
import java.security.MessageDigest;
48
import java.util.Arrays;
49
import java.util.Arrays;
49
import java.util.Collections;
50
import java.util.Collections;
Lines 96-103 Link Here
96
97
97
    private static final Logger LOG = Logger.getLogger(CodeGenerator.class.getName());
98
    private static final Logger LOG = Logger.getLogger(CodeGenerator.class.getName());
98
    private static final Set<ElementKind> UNUSABLE_KINDS = EnumSet.of(ElementKind.PACKAGE);
99
    private static final Set<ElementKind> UNUSABLE_KINDS = EnumSet.of(ElementKind.PACKAGE);
99
    private static final String HASH_ATTRIBUTE_NAME = "origin-hash";
100
    private static final byte VERSION = 2;
100
    private static final String DISABLE_ERRORS = "disable-java-errors";
101
    private static final String HASH_ATTRIBUTE_NAME = "origin-hash";    //NOI18N
102
    private static final String DISABLE_ERRORS = "disable-java-errors"; //NOI18N
103
    static final String CLASSFILE_ROOT = "classfile-root";              //NOI18N
104
    static final String CLASSFILE_BINNAME = "classfile-binaryName";     //NOI18N
101
105
102
    public static FileObject generateCode(final ClasspathInfo cpInfo, final ElementHandle<? extends Element> toOpenHandle) {
106
    public static FileObject generateCode(final ClasspathInfo cpInfo, final ElementHandle<? extends Element> toOpenHandle) {
103
	if (UNUSABLE_KINDS.contains(toOpenHandle.getKind())) {
107
	if (UNUSABLE_KINDS.contains(toOpenHandle.getKind())) {
Lines 117-122 Link Here
117
            JavaSource js = JavaSource.create(cpInfo, file);
121
            JavaSource js = JavaSource.create(cpInfo, file);
118
            final FileObject[] result = new FileObject[1];
122
            final FileObject[] result = new FileObject[1];
119
            final boolean[] sourceGenerated = new boolean[1];
123
            final boolean[] sourceGenerated = new boolean[1];
124
            final URL[] classfileRoot = new URL[1];
125
            final String[] binaryName = new String[1];
120
126
121
            ModificationResult r = js.runModificationTask(new Task<WorkingCopy>() {
127
            ModificationResult r = js.runModificationTask(new Task<WorkingCopy>() {
122
                @Override
128
                @Override
Lines 135-141 Link Here
135
                        return;
141
                        return;
136
                    }
142
                    }
137
143
138
                    final String resourceName = te.getQualifiedName().toString().replace('.', '/') + ".class";  //NOI18N
144
                    final String binName = te.getQualifiedName().toString().replace('.', '/');  //NOI18N
145
                    final String resourceName = binName + ".class";  //NOI18N
139
                    final FileObject resource = cp.findResource(resourceName);
146
                    final FileObject resource = cp.findResource(resourceName);
140
                    if (resource == null) {
147
                    if (resource == null) {
141
                        LOG.info("Cannot find resource: " + resourceName +" on classpath: " + cp.toString()); //NOI18N
148
                        LOG.info("Cannot find resource: " + resourceName +" on classpath: " + cp.toString()); //NOI18N
Lines 148-153 Link Here
148
                        return ;
155
                        return ;
149
                    }
156
                    }
150
157
158
                    classfileRoot[0] = root.getURL();
159
                    binaryName[0] = binName;
151
                    final File  sourceRoot = new File (JavaIndex.getIndex(root.getURL()),"gensrc");     //NOI18N
160
                    final File  sourceRoot = new File (JavaIndex.getIndex(root.getURL()),"gensrc");     //NOI18N
152
                    final FileObject sourceRootFO = FileUtil.createFolder(sourceRoot);
161
                    final FileObject sourceRootFO = FileUtil.createFolder(sourceRoot);
153
                    if (sourceRootFO == null) {
162
                    if (sourceRootFO == null) {
Lines 155-164 Link Here
155
                        return ;
164
                        return ;
156
                    }
165
                    }
157
166
158
                    final String path = te.getQualifiedName().toString().replace('.', '/') + ".java";   //NOI18N
167
                    final String path = binName + ".java";   //NOI18N
159
                    final FileObject source = sourceRootFO.getFileObject(path);
168
                    final FileObject source = sourceRootFO.getFileObject(path);
160
169
161
                    MessageDigest md = MessageDigest.getInstance("MD5");
170
                    MessageDigest md = MessageDigest.getInstance("MD5");
171
                    md.update(VERSION);
162
                    byte[] hashBytes = md.digest(resource.asBytes());
172
                    byte[] hashBytes = md.digest(resource.asBytes());
163
                    StringBuilder hashBuilder = new StringBuilder();
173
                    StringBuilder hashBuilder = new StringBuilder();
164
174
Lines 207-212 Link Here
207
                if (resultFile != null) {
217
                if (resultFile != null) {
208
                    resultFile.setReadOnly();
218
                    resultFile.setReadOnly();
209
                    result[0].setAttribute(DISABLE_ERRORS, true);
219
                    result[0].setAttribute(DISABLE_ERRORS, true);
220
                    result[0].setAttribute(CLASSFILE_ROOT, classfileRoot[0]);
221
                    result[0].setAttribute(CLASSFILE_BINNAME, binaryName[0]);
210
                }
222
                }
211
            }
223
            }
212
224
(-)a/java.source/src/org/netbeans/modules/java/classfile/SideBarFactoryImpl.java (+92 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common Development and
11
 * Distribution License("CDDL") (collectively, the "License"). You may not use
12
 * this file except in compliance with the License. You can obtain a copy of
13
 * the License at http://www.netbeans.org/cddl-gplv2.html or
14
 * nbbuild/licenses/CDDL-GPL-2-CP. See the License for the specific language
15
 * governing permissions and limitations under the License. When distributing
16
 * the software, include this License Header Notice in each file and include
17
 * the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
18
 * particular file as subject to the "Classpath" exception as provided by
19
 * Oracle in the GPL Version 2 section of the License file that accompanied
20
 * this code. If applicable, add the following below the License Header, with
21
 * the fields enclosed by brackets [] replaced by your own identifying
22
 * information: "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL or
25
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
26
 * elects to include this software in this distribution under the [CDDL or GPL
27
 * Version 2] license." If you do not indicate a single choice of license, a
28
 * recipient has the option to distribute your version of this file under
29
 * either the CDDL, the GPL Version 2 or to extend the choice of license to its
30
 * licensees as provided above. However, if you add GPL Version 2 code and
31
 * therefore, elected the GPL Version 2 license, then the option applies only
32
 * if the new code is made subject to such option by the copyright holder.
33
 *
34
 * Contributor(s):
35
 *
36
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
37
 */
38
package org.netbeans.modules.java.classfile;
39
40
import java.net.URL;
41
import javax.swing.JComponent;
42
import javax.swing.text.Document;
43
import javax.swing.text.JTextComponent;
44
import org.netbeans.editor.SideBarFactory;
45
import org.openide.filesystems.FileObject;
46
import org.openide.filesystems.FileStateInvalidException;
47
import org.openide.loaders.DataObject;
48
import org.openide.util.Exceptions;
49
50
/**
51
 *
52
 * @author lahvac
53
 */
54
public class SideBarFactoryImpl implements SideBarFactory {
55
56
    @Override
57
    public JComponent createSideBar(JTextComponent target) {
58
        Document doc = target.getDocument();
59
        FileObject originFile;
60
        Object origin = doc.getProperty(Document.StreamDescriptionProperty);
61
62
        if (origin instanceof DataObject) {
63
            originFile = ((DataObject) origin).getPrimaryFile();
64
        } else if (origin instanceof FileObject) {
65
            originFile = (FileObject) origin;
66
        } else {
67
            originFile = null;
68
        }
69
70
        Object classFileRoot;
71
        Object binaryName;
72
        if (originFile != null) {
73
            classFileRoot = originFile.getAttribute(CodeGenerator.CLASSFILE_ROOT);
74
            binaryName = originFile.getAttribute(CodeGenerator.CLASSFILE_BINNAME);
75
        } else {
76
            classFileRoot = binaryName = null;
77
        }
78
79
        if (classFileRoot instanceof URL && binaryName instanceof String) {
80
            try {
81
                return new AttachSourcePanel(
82
                    (URL) classFileRoot,
83
                    originFile.getURL(),
84
                    (String) binaryName);
85
            } catch (FileStateInvalidException ex) {
86
                Exceptions.printStackTrace(ex);
87
            }
88
        }
89
        return null;
90
    }
91
92
}
(-)a/java.source/src/org/netbeans/modules/java/source/resources/layer.xml (+7 lines)
Lines 285-290 Link Here
285
                    <attr name="regex5" stringvalue="\s*else[\s\{]"/>
285
                    <attr name="regex5" stringvalue="\s*else[\s\{]"/>
286
                    <attr name="regex6" stringvalue="\s*\w*\s*:"/>
286
                    <attr name="regex6" stringvalue="\s*\w*\s*:"/>
287
                </file>
287
                </file>
288
                <folder name="SideBar">
289
                    <file name="org-netbeans-modules-java-classfile-SideBarFactoryImpl.instance">
290
                        <attr name="location" stringvalue="North" />
291
                        <attr name="scrollable" boolvalue="false" />
292
                        <attr name="position" intvalue="7000"/>
293
                    </file>
294
                </folder>
288
            </folder>
295
            </folder>
289
        </folder>
296
        </folder>
290
        <folder name="application">
297
        <folder name="application">
(-)a/java.sourceui/nbproject/project.xml (-1 / +1 lines)
Lines 11-17 Link Here
11
                    <compile-dependency/>
11
                    <compile-dependency/>
12
                    <run-dependency>
12
                    <run-dependency>
13
                        <release-version>1</release-version>
13
                        <release-version>1</release-version>
14
                        <specification-version>1.18</specification-version>
14
                        <specification-version>1.35</specification-version>
15
                    </run-dependency>
15
                    </run-dependency>
16
                </dependency>
16
                </dependency>
17
                <dependency>
17
                <dependency>
(-)a/java.sourceui/src/org/netbeans/api/java/source/ui/Bundle.properties (+2 lines)
Lines 54-59 Link Here
54
array_length_field_javadoc=Length of array.
54
array_length_field_javadoc=Length of array.
55
class_constant_javadoc=java.lang.Class constant.
55
class_constant_javadoc=java.lang.Class constant.
56
javadoc_content_not_found=<font color=\"#7c0000\">Javadoc not found.</font> Either Javadoc documentation for this item does not exist or you have not added specified Javadoc in the Java Platform Manager or the Library Manager.
56
javadoc_content_not_found=<font color=\"#7c0000\">Javadoc not found.</font> Either Javadoc documentation for this item does not exist or you have not added specified Javadoc in the Java Platform Manager or the Library Manager.
57
javadoc_content_not_found_attach=<font color=\"#7c0000\">Javadoc not found.</font> Either Javadoc documentation for this item does not exist or you have not added specified Javadoc in the Java Platform Manager or the Library Manager.<p/>\
58
 <a href="associate-javadoc:{0}">Associate Javadoc to {1}</a>
57
LBL_HTTPJavadocDownload=Downloading HTTP Javadoc
59
LBL_HTTPJavadocDownload=Downloading HTTP Javadoc
58
60
59
LBL_CancelAction=Cancel {0}
61
LBL_CancelAction=Cancel {0}
(-)a/java.sourceui/src/org/netbeans/api/java/source/ui/ElementJavadoc.java (-9 / +62 lines)
Lines 59-64 Link Here
59
import java.util.ArrayList;
59
import java.util.ArrayList;
60
import java.util.concurrent.Callable;
60
import java.util.concurrent.Callable;
61
import java.util.concurrent.FutureTask;
61
import java.util.concurrent.FutureTask;
62
import org.netbeans.api.java.classpath.ClassPath;
63
import org.netbeans.api.java.queries.JavadocForBinaryQuery;
64
import org.netbeans.api.java.queries.SourceJavadocAttacher;
62
import org.netbeans.api.java.source.ClasspathInfo;
65
import org.netbeans.api.java.source.ClasspathInfo;
63
import org.netbeans.api.java.source.CompilationController;
66
import org.netbeans.api.java.source.CompilationController;
64
import org.netbeans.api.java.source.CompilationInfo;
67
import org.netbeans.api.java.source.CompilationInfo;
Lines 73-80 Link Here
73
import org.netbeans.modules.java.preprocessorbridge.api.JavaSourceUtil;
76
import org.netbeans.modules.java.preprocessorbridge.api.JavaSourceUtil;
74
import org.netbeans.modules.java.source.JavadocHelper;
77
import org.netbeans.modules.java.source.JavadocHelper;
75
import org.netbeans.modules.java.source.usages.Pair;
78
import org.netbeans.modules.java.source.usages.Pair;
79
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
76
import org.openide.filesystems.FileObject;
80
import org.openide.filesystems.FileObject;
77
import org.openide.filesystems.FileStateInvalidException;
81
import org.openide.filesystems.FileStateInvalidException;
82
import org.openide.filesystems.FileUtil;
78
import org.openide.util.Exceptions;
83
import org.openide.util.Exceptions;
79
import org.openide.util.NbBundle;
84
import org.openide.util.NbBundle;
80
import org.openide.util.RequestProcessor;
85
import org.openide.util.RequestProcessor;
Lines 85-91 Link Here
85
 * @author Dusan Balek, Petr Hrebejk
90
 * @author Dusan Balek, Petr Hrebejk
86
 */
91
 */
87
public class ElementJavadoc {
92
public class ElementJavadoc {
88
    
93
94
    private static final String ASSOCIATE_JDOC = "associate-javadoc:";          //NOI18N
89
    private static final String API = "/api";                                   //NOI18N
95
    private static final String API = "/api";                                   //NOI18N
90
    private static final Set<String> LANGS;
96
    private static final Set<String> LANGS;
91
97
Lines 100-109 Link Here
100
        LANGS = Collections.unmodifiableSet(locNames);
106
        LANGS = Collections.unmodifiableSet(locNames);
101
    }
107
    }
102
    
108
    
103
    private ElementJavadoc() {
104
    }
105
109
106
    private ClasspathInfo cpInfo;
110
    private final ClasspathInfo cpInfo;
111
    private final ElementHandle<? extends Element> handle;
107
    //private Doc doc;
112
    //private Doc doc;
108
    private volatile Future<String> content;
113
    private volatile Future<String> content;
109
    private Hashtable<String, ElementHandle<? extends Element>> links = new Hashtable<String, ElementHandle<? extends Element>>();
114
    private Hashtable<String, ElementHandle<? extends Element>> links = new Hashtable<String, ElementHandle<? extends Element>>();
Lines 184-189 Link Here
184
     * @return ElementJavadoc describing the javadoc of liked element
189
     * @return ElementJavadoc describing the javadoc of liked element
185
     */
190
     */
186
    public ElementJavadoc resolveLink(final String link) {
191
    public ElementJavadoc resolveLink(final String link) {
192
        if (link.startsWith(ASSOCIATE_JDOC)) {
193
            final String root = link.substring(ASSOCIATE_JDOC.length());
194
            try {
195
                SourceJavadocAttacher.attachJavadoc(new URL(root));
196
            } catch (MalformedURLException ex) {
197
                Exceptions.printStackTrace(ex);
198
            }
199
            return null;
200
        }
187
        final ElementJavadoc[] ret = new ElementJavadoc[1];
201
        final ElementJavadoc[] ret = new ElementJavadoc[1];
188
        try {
202
        try {
189
            final ElementHandle<? extends Element> linkDoc = links.get(link);
203
            final ElementHandle<? extends Element> linkDoc = links.get(link);
Lines 273-278 Link Here
273
    private ElementJavadoc(CompilationInfo compilationInfo, Element element, URL url, final Callable<Boolean> cancel) {
287
    private ElementJavadoc(CompilationInfo compilationInfo, Element element, URL url, final Callable<Boolean> cancel) {
274
        Pair<Trees,ElementUtilities> context = Pair.of(compilationInfo.getTrees(), compilationInfo.getElementUtilities());
288
        Pair<Trees,ElementUtilities> context = Pair.of(compilationInfo.getTrees(), compilationInfo.getElementUtilities());
275
        this.cpInfo = compilationInfo.getClasspathInfo();
289
        this.cpInfo = compilationInfo.getClasspathInfo();
290
        this.handle = element == null ? null : ElementHandle.create(element);
276
        Doc doc = context.second.javaDocFor(element);
291
        Doc doc = context.second.javaDocFor(element);
277
        boolean localized = false;
292
        boolean localized = false;
278
        StringBuilder content = new StringBuilder();
293
        StringBuilder content = new StringBuilder();
Lines 287-293 Link Here
287
            if (!localized) {
302
            if (!localized) {
288
                final FileObject fo = SourceUtils.getFile(element, compilationInfo.getClasspathInfo());
303
                final FileObject fo = SourceUtils.getFile(element, compilationInfo.getClasspathInfo());
289
                if (fo != null) {
304
                if (fo != null) {
290
                    final ElementHandle<? extends Element> handle = ElementHandle.create(element);
291
                    goToSource = new AbstractAction() {
305
                    goToSource = new AbstractAction() {
292
                        public void actionPerformed(ActionEvent evt) {
306
                        public void actionPerformed(ActionEvent evt) {
293
                            ElementOpen.open(fo, handle);
307
                            ElementOpen.open(fo, handle);
Lines 311-317 Link Here
311
            this.content = prepareContent(content, doc,localized, page, cancel, true, context);
325
            this.content = prepareContent(content, doc,localized, page, cancel, true, context);
312
        } catch (RemoteJavadocException re) {
326
        } catch (RemoteJavadocException re) {
313
            final FileObject fo = compilationInfo.getFileObject();
327
            final FileObject fo = compilationInfo.getFileObject();
314
            final ElementHandle<? extends Element> handle = ElementHandle.create(element);
315
            final StringBuilder contentFin = content;
328
            final StringBuilder contentFin = content;
316
            final boolean localizedFin = localized;
329
            final boolean localizedFin = localized;
317
            this.content = new FutureTask<String>(new Callable<String>(){
330
            this.content = new FutureTask<String>(new Callable<String>(){
Lines 346-351 Link Here
346
        assert url != null;
359
        assert url != null;
347
        this.content = null;
360
        this.content = null;
348
        this.docURL = url;
361
        this.docURL = url;
362
        this.handle = null;
363
        this.cpInfo = null;
349
    }
364
    }
350
365
351
    // Private section ---------------------------------------------------------
366
    // Private section ---------------------------------------------------------
Lines 635-641 Link Here
635
                        if (jdText != null)
650
                        if (jdText != null)
636
                            sb.append(jdText);
651
                            sb.append(jdText);
637
                        else
652
                        else
638
                            sb.append(NbBundle.getMessage(ElementJavadoc.class, "javadoc_content_not_found")); //NOI18N
653
                            sb.append(noJavadocFound()); //NOI18N
639
                        sb.append("</p>"); //NOI18N
654
                        sb.append("</p>"); //NOI18N
640
                        return sb.toString();
655
                        return sb.toString();
641
                    }
656
                    }
Lines 648-661 Link Here
648
                }
663
                }
649
                return task;
664
                return task;
650
            }
665
            }
651
            sb.append(NbBundle.getMessage(ElementJavadoc.class, "javadoc_content_not_found")); //NOI18N
666
            sb.append(noJavadocFound()); //NOI18N
652
            return new Now (sb.toString());
667
            return new Now (sb.toString());
653
        } finally {
668
        } finally {
654
            if (page != null)
669
            if (page != null)
655
                page.close();
670
                page.close();
656
        }
671
        }
657
    }
672
    }
658
    
673
674
    private String noJavadocFound() {
675
        final List<ClassPath> cps = new ArrayList<ClassPath>(2);
676
        ClassPath cp = cpInfo.getClassPath(ClasspathInfo.PathKind.BOOT);
677
        if (cp != null) {
678
            cps.add(cp);
679
        }
680
        cp = cpInfo.getClassPath(ClasspathInfo.PathKind.COMPILE);
681
        if (cp != null) {
682
            cps.add(cp);
683
        }
684
        cp = ClassPathSupport.createProxyClassPath(cps.toArray(new ClassPath[cps.size()]));
685
        String toSearch = SourceUtils.getJVMSignature(handle)[0].replace('.', '/');
686
        if (handle.getKind() != ElementKind.PACKAGE) {
687
            toSearch = toSearch + ".class"; //NOI18N
688
        }
689
        final FileObject resource = cp.findResource(toSearch);
690
        if (resource != null) {
691
            final FileObject root = cp.findOwnerRoot(resource);
692
            try {
693
                final URL rootURL = root.getURL();
694
                if (JavadocForBinaryQuery.findJavadoc(rootURL).getRoots().length == 0) {
695
                    FileObject userRoot = FileUtil.getArchiveFile(root);
696
                    if (userRoot == null) {
697
                        userRoot = root;
698
                    }
699
                    return NbBundle.getMessage(
700
                            ElementJavadoc.class,
701
                            "javadoc_content_not_found_attach",
702
                            rootURL.toExternalForm(),
703
                            FileUtil.getFileDisplayName(userRoot));
704
                }
705
            } catch (FileStateInvalidException ex) {
706
                Exceptions.printStackTrace(ex);
707
            }
708
        }
709
        return NbBundle.getMessage(ElementJavadoc.class, "javadoc_content_not_found");
710
    }
711
659
    private CharSequence getContainingClassOrPackageHeader(ProgramElementDoc peDoc, Pair<Trees,ElementUtilities> ctx) {
712
    private CharSequence getContainingClassOrPackageHeader(ProgramElementDoc peDoc, Pair<Trees,ElementUtilities> ctx) {
660
        StringBuilder sb = new StringBuilder();
713
        StringBuilder sb = new StringBuilder();
661
        ClassDoc cls = peDoc.containingClass();
714
        ClassDoc cls = peDoc.containingClass();
(-)a/maven.embedder/src/org/netbeans/modules/maven/embedder/EmbedderFactory.java (-11 / +6 lines)
Lines 52-58 Link Here
52
import java.util.logging.Level;
52
import java.util.logging.Level;
53
import java.util.logging.Logger;
53
import java.util.logging.Logger;
54
import org.apache.maven.artifact.Artifact;
54
import org.apache.maven.artifact.Artifact;
55
import org.apache.maven.artifact.UnknownRepositoryLayoutException;
56
import org.apache.maven.artifact.repository.ArtifactRepository;
55
import org.apache.maven.artifact.repository.ArtifactRepository;
57
import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
56
import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
58
import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
57
import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
Lines 61-66 Link Here
61
import org.codehaus.plexus.classworlds.ClassWorld;
60
import org.codehaus.plexus.classworlds.ClassWorld;
62
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
61
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
63
import java.util.prefs.Preferences;
62
import java.util.prefs.Preferences;
63
import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
64
import org.apache.maven.model.Model;
64
import org.apache.maven.model.Model;
65
import org.apache.maven.model.building.DefaultModelBuildingRequest;
65
import org.apache.maven.model.building.DefaultModelBuildingRequest;
66
import org.apache.maven.model.building.ModelBuilder;
66
import org.apache.maven.model.building.ModelBuilder;
Lines 346-361 Link Here
346
    }
346
    }
347
347
348
    public static ArtifactRepository createRemoteRepository(MavenEmbedder embedder, String url, String id) {
348
    public static ArtifactRepository createRemoteRepository(MavenEmbedder embedder, String url, String id) {
349
        try {
349
        ArtifactRepositoryFactory fact = embedder.lookupComponent(ArtifactRepositoryFactory.class);
350
            ArtifactRepositoryFactory fact = embedder.lookupComponent(ArtifactRepositoryFactory.class);
350
        assert fact!=null : "ArtifactRepositoryFactory component not found in maven";
351
            assert fact!=null : "ArtifactRepositoryFactory component not found in maven";
351
        ArtifactRepositoryPolicy snapshotsPolicy = new ArtifactRepositoryPolicy(true, ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN);
352
            ArtifactRepositoryPolicy snapshotsPolicy = new ArtifactRepositoryPolicy(true, ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN);
352
        ArtifactRepositoryPolicy releasesPolicy = new ArtifactRepositoryPolicy(true, ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN);
353
            ArtifactRepositoryPolicy releasesPolicy = new ArtifactRepositoryPolicy(true, ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN);
353
        return fact.createArtifactRepository(id, url, new DefaultRepositoryLayout(), snapshotsPolicy, releasesPolicy);
354
            return fact.createArtifactRepository(id, url, ArtifactRepositoryFactory.DEFAULT_LAYOUT_ID, snapshotsPolicy, releasesPolicy);
355
        } catch (UnknownRepositoryLayoutException ex) {
356
            Exceptions.printStackTrace(ex);
357
        }
358
        return null;
359
    }
354
    }
360
355
361
    /**
356
    /**
(-)a/maven/nbproject/project.xml (-1 / +1 lines)
Lines 82-88 Link Here
82
                    <compile-dependency/>
82
                    <compile-dependency/>
83
                    <run-dependency>
83
                    <run-dependency>
84
                        <release-version>1</release-version>
84
                        <release-version>1</release-version>
85
                        <specification-version>1.25</specification-version>
85
                        <specification-version>1.35</specification-version>
86
                    </run-dependency>
86
                    </run-dependency>
87
                </dependency>
87
                </dependency>
88
                <dependency>
88
                <dependency>
(-)a/maven/src/org/netbeans/modules/maven/queries/MavenFileOwnerQueryImpl.java (-41 / +55 lines)
Lines 54-59 Link Here
54
import java.util.prefs.Preferences;
54
import java.util.prefs.Preferences;
55
import javax.swing.event.ChangeListener;
55
import javax.swing.event.ChangeListener;
56
import org.apache.maven.project.MavenProject;
56
import org.apache.maven.project.MavenProject;
57
import org.netbeans.api.annotations.common.CheckForNull;
57
import org.netbeans.api.project.Project;
58
import org.netbeans.api.project.Project;
58
import org.netbeans.api.project.ProjectManager;
59
import org.netbeans.api.project.ProjectManager;
59
import org.netbeans.modules.maven.NbMavenProjectImpl;
60
import org.netbeans.modules.maven.NbMavenProjectImpl;
Lines 149-157 Link Here
149
        }
150
        }
150
        return null;
151
        return null;
151
    }
152
    }
152
    
153
153
    private Project getOwner(File file) {
154
    /**
154
        LOG.log(Level.FINER, "Looking for owner of {0}", file);
155
     * Utility method to identify a file which might be an artifact in the local repository.
156
     * @param file a putative artifact
157
     * @return its coordinates (groupId/artifactId/version), or null if it cannot be identified
158
     */
159
    static @CheckForNull String[] findCoordinates(File file) {
155
        String nm = file.getName(); // commons-math-2.1.jar
160
        String nm = file.getName(); // commons-math-2.1.jar
156
        File parentVer = file.getParentFile(); // ~/.m2/repository/org/apache/commons/commons-math/2.1
161
        File parentVer = file.getParentFile(); // ~/.m2/repository/org/apache/commons/commons-math/2.1
157
        if (parentVer != null) {
162
        if (parentVer != null) {
Lines 163-178 Link Here
163
                    File parentGroup = parentArt.getParentFile(); // ~/.m2/repository/org/apache/commons
168
                    File parentGroup = parentArt.getParentFile(); // ~/.m2/repository/org/apache/commons
164
                    if (parentGroup != null) {
169
                    if (parentGroup != null) {
165
                        // Split rest into separate method, to avoid linking EmbedderFactory unless and until needed.
170
                        // Split rest into separate method, to avoid linking EmbedderFactory unless and until needed.
166
                        return getArtifactOwner(parentGroup, artifactID, version);
171
                        return findCoordinates(parentGroup, artifactID, version);
167
                    }
172
                    }
168
                }
173
                }
169
            }
174
            }
170
        }
175
        }
171
        return null;
176
        return null;
172
    }
177
    }
173
178
    private static @CheckForNull String[] findCoordinates(File parentGroup, String artifactID, String version) {
174
    private Project getArtifactOwner(File parentGroup, String artifactID, String version) {
175
        LOG.log(Level.FINER, "Checking {0} / {1} / {2}", new Object[] {parentGroup, artifactID, version});
176
        File repo = new File(EmbedderFactory.getProjectEmbedder().getLocalRepository().getBasedir()); // ~/.m2/repository
179
        File repo = new File(EmbedderFactory.getProjectEmbedder().getLocalRepository().getBasedir()); // ~/.m2/repository
177
        String repoS = repo.getAbsolutePath();
180
        String repoS = repo.getAbsolutePath();
178
        if (!repoS.endsWith(File.separator)) {
181
        if (!repoS.endsWith(File.separator)) {
Lines 184-234 Link Here
184
        }
187
        }
185
        if (parentGroupS.startsWith(repoS)) {
188
        if (parentGroupS.startsWith(repoS)) {
186
            String groupID = parentGroupS.substring(repoS.length()).replace(File.separatorChar, '.'); // org.apache.commons
189
            String groupID = parentGroupS.substring(repoS.length()).replace(File.separatorChar, '.'); // org.apache.commons
187
            String key = groupID + ':' + artifactID; // org.apache.commons:commons-math
190
            return new String[] {groupID, artifactID, version};
188
            String ownerURI = prefs().get(key, null);
191
        } else {
189
            if (ownerURI != null) {
192
            return null;
190
                boolean stale = true;
193
        }
191
                try {
194
    }
192
                    FileObject projectDir = URLMapper.findFileObject(new URI(ownerURI).toURL());
195
    
193
                    if (projectDir != null && projectDir.isFolder()) {
196
    private Project getOwner(File file) {
194
                        Project p = ProjectManager.getDefault().findProject(projectDir);
197
        LOG.log(Level.FINER, "Looking for owner of {0}", file);
195
                        if (p != null) {
198
        String[] coordinates = findCoordinates(file);
196
                            NbMavenProjectImpl mp = p.getLookup().lookup(NbMavenProjectImpl.class);
199
        if (coordinates == null) {
197
                            if (mp != null) {
200
            LOG.log(Level.FINE, "{0} not an artifact in local repo", file);
198
                                MavenProject model = mp.getOriginalMavenProject();
201
            return null;
199
                                if (model.getGroupId().equals(groupID) && model.getArtifactId().equals(artifactID)) {
202
        }
200
                                    if (model.getVersion().equals(version)) {
203
        LOG.log(Level.FINER, "Checking {0} / {1} / {2}", coordinates);
201
                                        LOG.log(Level.FINE, "Found match {0}", p);
204
        String key = coordinates[0] + ':' + coordinates[1]; // org.apache.commons:commons-math
202
                                        return p;
205
        String ownerURI = prefs().get(key, null);
203
                                    } else {
206
        if (ownerURI != null) {
204
                                        LOG.log(Level.FINE, "Mismatch on version {0} in {1}", new Object[] {model.getVersion(), ownerURI});
207
            boolean stale = true;
205
                                        stale = false; // we merely remembered another version
208
            try {
206
                                    }
209
                FileObject projectDir = URLMapper.findFileObject(new URI(ownerURI).toURL());
210
                if (projectDir != null && projectDir.isFolder()) {
211
                    Project p = ProjectManager.getDefault().findProject(projectDir);
212
                    if (p != null) {
213
                        NbMavenProjectImpl mp = p.getLookup().lookup(NbMavenProjectImpl.class);
214
                        if (mp != null) {
215
                            MavenProject model = mp.getOriginalMavenProject();
216
                            if (model.getGroupId().equals(coordinates[0]) && model.getArtifactId().equals(coordinates[1])) {
217
                                if (model.getVersion().equals(coordinates[2])) {
218
                                    LOG.log(Level.FINE, "Found match {0}", p);
219
                                    return p;
207
                                } else {
220
                                } else {
208
                                    LOG.log(Level.FINE, "Mismatch on group and/or artifact ID in {0}", ownerURI);
221
                                    LOG.log(Level.FINE, "Mismatch on version {0} in {1}", new Object[] {model.getVersion(), ownerURI});
222
                                    stale = false; // we merely remembered another version
209
                                }
223
                                }
210
                            } else {
224
                            } else {
211
                                LOG.log(Level.FINE, "Not a Maven project {0} in {1}", new Object[] {p, ownerURI});
225
                                LOG.log(Level.FINE, "Mismatch on group and/or artifact ID in {0}", ownerURI);
212
                            }
226
                            }
213
                        } else {
227
                        } else {
214
                            LOG.log(Level.FINE, "No such project in {0}", ownerURI);
228
                            LOG.log(Level.FINE, "Not a Maven project {0} in {1}", new Object[] {p, ownerURI});
215
                        }
229
                        }
216
                    } else {
230
                    } else {
217
                        LOG.log(Level.FINE, "No such folder {0}", ownerURI);
231
                        LOG.log(Level.FINE, "No such project in {0}", ownerURI);
218
                    }
232
                    }
219
                } catch (IOException x) {
233
                } else {
220
                    LOG.log(Level.FINE, "Could not load project in " + ownerURI, x);
234
                    LOG.log(Level.FINE, "No such folder {0}", ownerURI);
221
                } catch (URISyntaxException x) {
222
                    LOG.log(Level.INFO, null, x);
223
                }
235
                }
224
                if (stale) {
236
            } catch (IOException x) {
225
                    prefs().remove(key); // stale
237
                LOG.log(Level.FINE, "Could not load project in " + ownerURI, x);
226
                }
238
            } catch (URISyntaxException x) {
227
            } else {
239
                LOG.log(Level.INFO, null, x);
228
                LOG.log(Level.FINE, "No known owner for {0}", key);
240
            }
241
            if (stale) {
242
                prefs().remove(key); // stale
229
            }
243
            }
230
        } else {
244
        } else {
231
            LOG.log(Level.FINE, "Not in local repo {0}", repoS);
245
            LOG.log(Level.FINE, "No known owner for {0}", key);
232
        }
246
        }
233
        return null;
247
        return null;
234
    }
248
    }
(-)a/maven/src/org/netbeans/modules/maven/queries/MavenSourceJavadocAttacher.java (+114 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common Development and
11
 * Distribution License("CDDL") (collectively, the "License"). You may not use
12
 * this file except in compliance with the License. You can obtain a copy of
13
 * the License at http://www.netbeans.org/cddl-gplv2.html or
14
 * nbbuild/licenses/CDDL-GPL-2-CP. See the License for the specific language
15
 * governing permissions and limitations under the License. When distributing
16
 * the software, include this License Header Notice in each file and include
17
 * the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
18
 * particular file as subject to the "Classpath" exception as provided by
19
 * Oracle in the GPL Version 2 section of the License file that accompanied
20
 * this code. If applicable, add the following below the License Header, with
21
 * the fields enclosed by brackets [] replaced by your own identifying
22
 * information: "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL or
25
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
26
 * elects to include this software in this distribution under the [CDDL or GPL
27
 * Version 2] license." If you do not indicate a single choice of license, a
28
 * recipient has the option to distribute your version of this file under
29
 * either the CDDL, the GPL Version 2 or to extend the choice of license to its
30
 * licensees as provided above. However, if you add GPL Version 2 code and
31
 * therefore, elected the GPL Version 2 license, then the option applies only
32
 * if the new code is made subject to such option by the copyright holder.
33
 *
34
 * Contributor(s):
35
 *
36
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
37
 */
38
39
package org.netbeans.modules.maven.queries;
40
41
import java.io.File;
42
import java.io.IOException;
43
import java.net.URL;
44
import java.util.ArrayList;
45
import java.util.List;
46
import org.apache.maven.artifact.Artifact;
47
import org.apache.maven.artifact.repository.ArtifactRepository;
48
import org.apache.maven.artifact.resolver.AbstractArtifactResolutionException;
49
import org.netbeans.api.progress.aggregate.AggregateProgressFactory;
50
import org.netbeans.api.progress.aggregate.AggregateProgressHandle;
51
import org.netbeans.api.progress.aggregate.ProgressContributor;
52
import org.netbeans.modules.maven.embedder.EmbedderFactory;
53
import org.netbeans.modules.maven.embedder.MavenEmbedder;
54
import org.netbeans.modules.maven.embedder.exec.ProgressTransferListener;
55
import org.netbeans.modules.maven.indexer.api.RepositoryInfo;
56
import org.netbeans.modules.maven.indexer.api.RepositoryPreferences;
57
import org.netbeans.spi.java.queries.SourceJavadocAttacherImplementation;
58
import org.openide.filesystems.FileUtil;
59
import org.openide.util.NbBundle.Messages;
60
import org.openide.util.lookup.ServiceProvider;
61
62
@ServiceProvider(service=SourceJavadocAttacherImplementation.class, position=200)
63
public class MavenSourceJavadocAttacher implements SourceJavadocAttacherImplementation {
64
65
    @Override public Result attachSources(URL root) throws IOException {
66
        return attach(root, false);
67
    }
68
69
    @Override public Result attachJavadoc(URL root) throws IOException {
70
        return attach(root, true);
71
    }
72
73
    @Messages({"# {0} - artifact ID", "attaching=Attaching {0}"})
74
    private Result attach(URL root, boolean javadoc) throws IOException {
75
        File file = FileUtil.archiveOrDirForURL(root);
76
        if (file == null) {
77
            return Result.UNSUPPORTED;
78
        }
79
        String[] coordinates = MavenFileOwnerQueryImpl.findCoordinates(file);
80
        if (coordinates == null) {
81
            return Result.UNSUPPORTED;
82
        }
83
        MavenEmbedder online = EmbedderFactory.getOnlineEmbedder();
84
        Artifact art = online.createArtifactWithClassifier(coordinates[0], coordinates[1], coordinates[2], "jar", javadoc ? "javadoc" : "sources");
85
        AggregateProgressHandle hndl = AggregateProgressFactory.createHandle(Bundle.attaching(art.getId()),
86
                new ProgressContributor[] {AggregateProgressFactory.createProgressContributor("attach")},
87
                ProgressTransferListener.cancellable(), null);
88
        ProgressTransferListener.setAggregateHandle(hndl);
89
        try {
90
            hndl.start();
91
            List<ArtifactRepository> repos = new ArrayList<ArtifactRepository>();
92
            // XXX is there some way to determine from local metadata which remote repo it is from? (i.e. API to read _maven.repositories)
93
            for (RepositoryInfo info : RepositoryPreferences.getInstance().getRepositoryInfos()) {
94
                if (info.isRemoteDownloadable()) {
95
                    repos.add(EmbedderFactory.createRemoteRepository(online, info.getRepositoryUrl(), info.getId()));
96
                }
97
            }
98
            online.resolve(art, repos, online.getLocalRepository());
99
            if (art.getFile().isFile()) {
100
                return Result.ATTACHED;
101
            } else {
102
                return Result.CANCELED;
103
            }
104
        } catch (ThreadDeath d) {
105
            return Result.CANCELED;
106
        } catch (AbstractArtifactResolutionException x) {
107
            return Result.CANCELED;
108
        } finally {
109
            hndl.finish();
110
            ProgressTransferListener.clearAggregateHandle();
111
        }
112
    }
113
114
}
(-)a/maven/test/unit/src/org/netbeans/modules/maven/queries/MavenFileOwnerQueryImplTest.java (-2 / +7 lines)
Lines 43-48 Link Here
43
package org.netbeans.modules.maven.queries;
43
package org.netbeans.modules.maven.queries;
44
44
45
import java.io.File;
45
import java.io.File;
46
import java.util.Arrays;
46
import org.netbeans.api.project.ProjectManager;
47
import org.netbeans.api.project.ProjectManager;
47
import org.netbeans.junit.NbTestCase;
48
import org.netbeans.junit.NbTestCase;
48
import org.netbeans.modules.maven.NbMavenProjectImpl;
49
import org.netbeans.modules.maven.NbMavenProjectImpl;
Lines 60-67 Link Here
60
        clearWorkDir();
61
        clearWorkDir();
61
    }
62
    }
62
63
63
    protected @Override int timeOut() {
64
    public void testFindCoordinates() throws Exception {
64
        return 300000;
65
        File repo = new File(EmbedderFactory.getProjectEmbedder().getLocalRepository().getBasedir());
66
        assertEquals("[test, prj, 1.0]", Arrays.toString(MavenFileOwnerQueryImpl.findCoordinates(new File(repo, "test/prj/1.0/prj-1.0.jar"))));
67
        assertEquals("[my.test, prj, 1.0-SNAPSHOT]", Arrays.toString(MavenFileOwnerQueryImpl.findCoordinates(new File(repo, "my/test/prj/1.0-SNAPSHOT/prj-1.0-SNAPSHOT.pom"))));
68
        assertEquals("null", Arrays.toString(MavenFileOwnerQueryImpl.findCoordinates(new File(repo, "test/prj/1.0"))));
69
        assertEquals("null", Arrays.toString(MavenFileOwnerQueryImpl.findCoordinates(getWorkDir())));
65
    }
70
    }
66
71
67
    public void testMultipleVersions() throws Exception {
72
    public void testMultipleVersions() throws Exception {

Return to bug 200698