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 (+124 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 org.netbeans.api.annotations.common.NonNull;
47
import org.netbeans.api.annotations.common.NullAllowed;
48
import org.netbeans.spi.java.queries.SourceJavadocAttacherImplementation;
49
import org.openide.util.Exceptions;
50
import org.openide.util.Lookup;
51
import org.openide.util.Parameters;
52
53
/**
54
 * A support for attaching source roots and javadoc roots to binary roots.
55
 * @author Tomas Zezula
56
 * @since 1.35
57
 */
58
public final class SourceJavadocAttacher {
59
60
    private SourceJavadocAttacher() {}
61
62
    /**
63
     * Attaches a source root provided by the SPI {@link SourceJavadocAttacherImplementation}
64
     * to given binary root.
65
     * @param root the binary root to attach sources to
66
     * @param a listener notified about result when attaching is done
67
     */
68
    public static void attachSources(
69
            @NonNull final URL root,
70
            @NullAllowed final AttachmentListener listener) {
71
            attach(root, listener, 0);
72
    }
73
74
    /**
75
     * Attaches a javadoc root provided by the SPI {@link SourceJavadocAttacherImplementation}
76
     * to given binary root.
77
     * @param root the binary root to attach javadoc to
78
     * @param a listener notified about result  when attaching is done
79
     */
80
    public static void attachJavadoc(
81
            @NonNull final URL root,
82
            @NullAllowed final AttachmentListener listener) {
83
            attach(root, listener, 1);
84
    }
85
86
    /**
87
     * Listener notified by {@link SourceJavadocAttacher} about a result
88
     * of attaching source (javadoc) to binary root.
89
     */
90
    public interface AttachmentListener {
91
        /**
92
         * Invoked when the source (javadoc) was successfully attached to
93
         * binary root.
94
         */
95
        void attachmentSucceeded();
96
        /**
97
         * Invoked when the source (javadoc) was not attached to
98
         * binary root. The attaching either failed or was canceled by user.
99
         */
100
        void attachmentFailed();
101
    }
102
103
    private static void attach(
104
            final URL root,
105
            final AttachmentListener listener,
106
            final int mode) {
107
        Parameters.notNull("root", root);   //NOI18N
108
        try {
109
            for (SourceJavadocAttacherImplementation attacher : Lookup.getDefault().lookupAll(SourceJavadocAttacherImplementation.class)) {
110
                final boolean handles  = mode == 0 ?
111
                    attacher.attachSources(root, listener) :
112
                    attacher.attachJavadoc(root, listener);
113
                if (handles) {
114
                    return;
115
                }
116
            }
117
        } catch (IOException ioe) {
118
            Exceptions.printStackTrace(ioe);
119
        }
120
        if (listener != null) {
121
            listener.attachmentFailed();
122
        }
123
    }
124
}
(-)a/api.java/src/org/netbeans/spi/java/queries/SourceJavadocAttacherImplementation.java (+81 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.annotations.common.NullAllowed;
48
import org.netbeans.api.java.queries.SourceJavadocAttacher;
49
import org.openide.util.Lookup;
50
import org.openide.util.lookup.ServiceProvider;
51
52
53
/**
54
 * A SPI for attaching source roots and javadoc roots to binary roots.
55
 * The implementations of this interface are registered in global {@link Lookup}
56
 * @see ServiceProvider
57
 * @author Tomas Zezula
58
 * @since 1.35
59
 */
60
public interface SourceJavadocAttacherImplementation {
61
62
    /**
63
     * Attaches a source root provided by this SPI to given binary root.
64
     * @param root the binary root to attach sources to
65
     * @param a listener notified about result when attaching is done
66
     * @throws IOException in case of error
67
     */
68
    boolean attachSources(
69
            @NonNull URL root,
70
            @NullAllowed SourceJavadocAttacher.AttachmentListener listener) throws IOException;
71
72
    /**
73
     * Attaches a javadoc root provided by this SPI to given binary root.
74
     * @param root the binary root to attach javadoc to
75
     * @param a listener notified about result when attaching is done
76
     * @throws IOException in case of error
77
     */
78
    boolean attachJavadoc(
79
            @NonNull URL root,
80
            @NullAllowed SourceJavadocAttacher.AttachmentListener listener) throws IOException;
81
}
(-)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 (+232 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 java.util.concurrent.Callable;
55
import java.util.concurrent.Future;
56
import org.netbeans.api.annotations.common.NonNull;
57
import org.netbeans.api.annotations.common.NullAllowed;
58
import org.netbeans.api.java.queries.SourceJavadocAttacher.AttachmentListener;
59
import org.netbeans.api.project.libraries.Library;
60
import org.netbeans.api.project.libraries.LibraryManager;
61
import org.netbeans.modules.java.j2seplatform.queries.SourceJavadocAttacherUtil;
62
import org.netbeans.spi.java.queries.SourceJavadocAttacherImplementation;
63
import org.openide.util.Exceptions;
64
import org.openide.util.lookup.ServiceProvider;
65
66
/**
67
 *
68
 * @author Tomas Zezula
69
 */
70
@ServiceProvider(service=SourceJavadocAttacherImplementation.class, position=151)
71
public class J2SELibrarySourceJavadocAttacher implements SourceJavadocAttacherImplementation {
72
73
    @Override
74
    public boolean attachSources(
75
            @NonNull final URL root,
76
            @NullAllowed final AttachmentListener listener) throws IOException {
77
        return attach(root, listener, J2SELibraryTypeProvider.VOLUME_TYPE_SRC);
78
    }
79
80
    @Override
81
    public boolean attachJavadoc(
82
            @NonNull final URL root,
83
            @NullAllowed final AttachmentListener listener) throws IOException {
84
        return attach(root, listener, J2SELibraryTypeProvider.VOLUME_TYPE_JAVADOC);
85
    }
86
87
    private boolean attach(
88
            @NonNull final URL root,
89
            @NullAllowed final AttachmentListener listener,
90
            @NonNull final String volume) {
91
        final Pair<LibraryManager,Library> pair = findOwner(root);
92
        if (pair == null) {
93
            return false;
94
        }
95
        final Runnable call = new Runnable() {
96
            @Override
97
            public void run() {
98
                final LibraryManager lm = pair.first;
99
                final Library lib = pair.second;
100
                assert lm != null;
101
                assert lib != null;
102
                boolean success = false;
103
                try {
104
                    final URL areaLocation = lm.getLocation();
105
                    final File baseFolder = areaLocation == null ? null : new File(areaLocation.toURI()).getParentFile();
106
                    final List<? extends URI> selected;
107
                    if (volume == J2SELibraryTypeProvider.VOLUME_TYPE_SRC) {
108
                        selected = SourceJavadocAttacherUtil.selectSources(
109
                            root,
110
                            new SelectFolder(volume, lib.getName(), baseFolder),
111
                            new Convertor(volume, baseFolder));
112
                    } else if (volume == J2SELibraryTypeProvider.VOLUME_TYPE_JAVADOC) {
113
                        selected = SourceJavadocAttacherUtil.selectJavadoc(
114
                            root,
115
                            new SelectFolder(volume, lib.getName(), baseFolder),
116
                            new Convertor(volume, baseFolder));
117
                    } else {
118
                        throw new IllegalStateException();
119
                    }
120
                    if (selected != null) {
121
                        final String name = lib.getName();
122
                        final String displayName = lib.getDisplayName();
123
                        final String desc = lib.getDescription();
124
                        final Map<String,List<URI>> volumes = new HashMap<String, List<URI>>();
125
                        for (String currentVolume : J2SELibraryTypeProvider.VOLUME_TYPES) {
126
                            List<URI> content = lib.getURIContent(currentVolume);
127
                            if (volume == currentVolume) {
128
                                final List<URI> newContent = new ArrayList<URI>(content.size()+selected.size());
129
                                newContent.addAll(content);
130
                                newContent.addAll(selected);
131
                                content = newContent;
132
                            }
133
                            volumes.put(currentVolume,content);
134
                        }
135
                        lm.removeLibrary(lib);
136
                        lm.createURILibrary(
137
                            J2SELibraryTypeProvider.LIBRARY_TYPE,
138
                            name,
139
                            displayName,
140
                            desc,
141
                            volumes);
142
                        success = true;
143
                    }
144
                } catch (IOException ioe) {
145
                    Exceptions.printStackTrace(ioe);
146
                } catch (URISyntaxException use) {
147
                    Exceptions.printStackTrace(use);
148
                } finally {
149
                    SourceJavadocAttacherUtil.callListener(listener, success);
150
                }
151
            }
152
        };
153
        SourceJavadocAttacherUtil.scheduleInEDT(call);
154
        return true;
155
    }
156
157
    private Pair<LibraryManager,Library> findOwner(final URL root) {
158
        for (LibraryManager lm : LibraryManager.getOpenManagers()) {
159
            for (Library l : lm.getLibraries()) {
160
                if (!J2SELibraryTypeProvider.LIBRARY_TYPE.equals(l.getType())) {
161
                    continue;
162
                }
163
                final List<URL> cp = l.getContent(J2SELibraryTypeProvider.VOLUME_TYPE_CLASSPATH);
164
                if (cp.contains(root)) {
165
                    return Pair.<LibraryManager,Library>of(lm, l);
166
                }
167
            }
168
        }
169
        return null;
170
    }
171
172
    private static class Pair<F,S> {
173
        public final F first;
174
        public final S second;
175
176
        private Pair(F first, S second) {
177
            this.first = first;
178
            this.second = second;
179
        }
180
181
        public static <F,S> Pair<F,S> of(F first, S second) {
182
            return new Pair<F,S>(first,second);
183
        }
184
    }
185
186
    private static class SelectFolder implements Callable<List<? extends String>> {
187
188
        private final String volume;
189
        private final String libName;
190
        private final File baseFolder;
191
192
        private SelectFolder(
193
                @NonNull final String volume,
194
                @NonNull final String libName,
195
                @NullAllowed final File baseFolder) {
196
            this.volume = volume;
197
            this.libName = libName;
198
            this.baseFolder = baseFolder;
199
        }
200
201
        @Override
202
        public List<? extends String> call() throws Exception {
203
            final String[] paths = J2SEVolumeCustomizer.select(
204
                volume,
205
                libName,
206
                new File[1],
207
                null,
208
                baseFolder);
209
            return paths == null ? null : Arrays.<String>asList(paths);
210
        }
211
    }
212
213
    private static class Convertor implements SourceJavadocAttacherUtil.Function<String, URI> {
214
215
        private final String volume;
216
        private final File baseFolder;
217
218
        private Convertor(
219
                @NonNull final String volume,
220
                @NullAllowed final File baseFolder) {
221
            this.volume = volume;
222
            this.baseFolder = baseFolder;
223
        }
224
225
        @Override
226
        public URI call(String param) throws Exception {
227
            return J2SEVolumeCustomizer.pathToURI(baseFolder, param, volume);
228
        }
229
230
    }
231
232
}
(-)a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/J2SEVolumeCustomizer.java (-89 / +141 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 String[] 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 chooser.getSelectedPaths();
176
            } catch (MalformedURLException mue) {
177
                Exceptions.printStackTrace(mue);
178
            } catch (IOException ex) {
179
                Exceptions.printStackTrace(ex);
180
            }
181
        }
182
        return null;
183
    }
184
185
    static URI pathToURI(
186
            final File baseFolder,
187
            final String fileName,
188
            final String volume) throws MalformedURLException, URISyntaxException {
189
        File f = new File(fileName);
190
        URI uri = LibrariesSupport.convertFilePathToURI(fileName);
191
        if (baseFolder != null) {
192
            File realFile = f;
193
            if (!f.isAbsolute()) {
194
                    realFile = FileUtil.normalizeFile(new File(
195
                        baseFolder, f.getPath()));
196
            }
197
            String jarPath = checkFile(realFile, volume);
198
            if (FileUtil.isArchiveFile(realFile.toURI().toURL())) {
199
                uri = LibrariesSupport.getArchiveRoot(uri);
200
                if (jarPath != null) {
201
                    assert uri.toString().endsWith("!/") : uri.toString(); //NOI18N
202
                    uri = URI.create(uri.toString() + encodePath(jarPath));
203
                }
204
            } else if (!uri.toString().endsWith("/")){ //NOI18N
205
                try {
206
                    uri = new URI(uri.toString()+"/"); //NOI18N
207
                } catch (URISyntaxException ex) {
208
                    throw new AssertionError(ex);
209
                }
210
            }
211
            return uri;
212
        } else {
213
            assert f.isAbsolute() : f.getPath();
214
            f = FileUtil.normalizeFile (f);
215
            String jarPath = checkFile(f, volume);
216
            uri = f.toURI();
217
            if (FileUtil.isArchiveFile(uri.toURL())) {
218
                uri = LibrariesSupport.getArchiveRoot(uri);
219
                if (jarPath != null) {
220
                    assert uri.toString().endsWith("!/") : uri.toString(); //NOI18N
221
                    uri = URI.create(uri.toString() + encodePath(jarPath));
222
                }
223
            } else if (!uri.toString().endsWith("/")){ //NOI18N
224
                uri = URI.create(uri.toString()+"/"); //NOI18N
225
            }
226
            return uri;
227
        }
228
    }
229
119
230
120
    private void postInitComponents () {
231
    private void postInitComponents () {
121
        this.content.setCellRenderer(new ContentRenderer());
232
        this.content.setCellRenderer(new ContentRenderer());
Lines 346-399 Link Here
346
    }//GEN-LAST:event_removeResource
457
    }//GEN-LAST:event_removeResource
347
458
348
    private void addResource(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addResource
459
    private void addResource(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addResource
349
        File baseFolder = null;
460
        final boolean arp = allowRelativePaths != null && allowRelativePaths.booleanValue();
350
        File libFolder = null;
461
        final File baseFolder = arp ?
351
        if (allowRelativePaths != null && allowRelativePaths.booleanValue()) {
462
            FileUtil.normalizeFile(new File(URI.create(area.getLocation().toExternalForm())).getParentFile()):
352
            baseFolder = FileUtil.normalizeFile(new File(URI.create(area.getLocation().toExternalForm())).getParentFile());
463
            null;
353
            libFolder = FileUtil.normalizeFile(new File(baseFolder, impl.getName()));
464
        final File[] cwd = new File[]{lastFolder};
354
        }
465
        final String[] paths = select(volumeType, impl.getName(), cwd, this, baseFolder);
355
        FileChooser chooser = new FileChooser(baseFolder, libFolder);
466
        if (paths != 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 {
467
            try {
395
                lastFolder = chooser.getCurrentDirectory();
468
                lastFolder = cwd[0];
396
                addFiles (chooser.getSelectedPaths(), area != null ? area.getLocation() : null, this.volumeType);
469
                addFiles (
470
                    pathsToURIs (
471
                        paths,
472
                        volumeType,
473
                        baseFolder),
474
                    arp);
397
            } catch (MalformedURLException mue) {
475
            } catch (MalformedURLException mue) {
398
                Exceptions.printStackTrace(mue);
476
                Exceptions.printStackTrace(mue);
399
            } catch (URISyntaxException ue) {
477
            } catch (URISyntaxException ue) {
Lines 435-485 Link Here
435
        }
513
        }
436
    }//GEN-LAST:event_addURLButtonActionPerformed
514
    }//GEN-LAST:event_addURLButtonActionPerformed
437
515
438
    private void addFiles (String[] fileNames, URL libraryLocation, String volume) throws MalformedURLException, URISyntaxException {
516
    private void addFiles (URI[] toAdd, boolean  allowRelativePaths) throws MalformedURLException, URISyntaxException {
439
        int firstIndex = this.model.getSize();
517
        int firstIndex = this.model.getSize();
440
        for (int i = 0; i < fileNames.length; i++) {
518
        for (URI uri : toAdd) {
441
            File f = new File(fileNames[i]);
519
            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);
520
                model.addResource(uri);
467
            } else {
521
            } 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
522
                model.addResource(uri.toURL()); //Has to be added as URL, model asserts it
482
483
            }
523
            }
484
        }
524
        }
485
        int lastIndex = this.model.getSize()-1;
525
        int lastIndex = this.model.getSize()-1;
Lines 501-507 Link Here
501
        return new URI(null, null, path, null).getRawPath();
541
        return new URI(null, null, path, null).getRawPath();
502
    }
542
    }
503
543
504
    private String checkFile(File f, String volume) {
544
    @NonNull
545
    private static URI[] pathsToURIs(
546
            @NonNull final String[] fileNames,
547
            @NonNull final String volume,
548
            @NullAllowed final File baseFolder) throws MalformedURLException, URISyntaxException {
549
        final List<URI> result = new ArrayList<URI>(fileNames.length);
550
        for (String fileName : fileNames) {
551
            result.add(pathToURI(baseFolder,fileName,volume));
552
        }
553
        return result.toArray(new URI[result.size()]);
554
    }
555
556
    private static String checkFile(File f, String volume) {
505
        FileObject fo = FileUtil.toFileObject(f);
557
        FileObject fo = FileUtil.toFileObject(f);
506
        if (volume.equals(J2SELibraryTypeProvider.VOLUME_TYPE_JAVADOC)) {
558
        if (volume.equals(J2SELibraryTypeProvider.VOLUME_TYPE_JAVADOC)) {
507
            if (fo != null) {
559
            if (fo != null) {
(-)a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/platformdefinition/J2SEPlatformCustomizer.java (-25 / +33 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 105-111 Link Here
105
        this.initComponents ();
105
        this.initComponents ();
106
    }
106
    }
107
107
108
109
    private void initComponents () {
108
    private void initComponents () {
110
        this.getAccessibleContext().setAccessibleName (NbBundle.getMessage(J2SEPlatformCustomizer.class,"AN_J2SEPlatformCustomizer"));
109
        this.getAccessibleContext().setAccessibleName (NbBundle.getMessage(J2SEPlatformCustomizer.class,"AN_J2SEPlatformCustomizer"));
111
        this.getAccessibleContext().setAccessibleDescription (NbBundle.getMessage(J2SEPlatformCustomizer.class,"AD_J2SEPlatformCustomizer"));
110
        this.getAccessibleContext().setAccessibleDescription (NbBundle.getMessage(J2SEPlatformCustomizer.class,"AD_J2SEPlatformCustomizer"));
Lines 369-388 Link Here
369
        }
368
        }
370
369
371
        private void addPathElement () {
370
        private void addPathElement () {
372
            JFileChooser chooser = new JFileChooser ();
371
            final int firstIndex = this.resources.getModel().getSize();
373
            FileUtil.preventFileChooserSymlinkTraversal(chooser, null);
372
            final File[] cwd = new File[]{currentDir};
373
            if (select((PathModel)this.resources.getModel(),cwd, this)) {
374
                final int lastIndex = this.resources.getModel().getSize()-1;
375
                if (firstIndex<=lastIndex) {
376
                    int[] toSelect = new int[lastIndex-firstIndex+1];
377
                    for (int i = 0; i < toSelect.length; i++) {
378
                        toSelect[i] = firstIndex+i;
379
                    }
380
                    this.resources.setSelectedIndices(toSelect);
381
                }
382
                this.currentDir = cwd[0];
383
            }
384
        }
385
386
        private static boolean select(
387
            final PathModel model,
388
            final File[] currentDir,
389
            final Component parentComponent) {
390
            final JFileChooser chooser = new JFileChooser ();
374
            chooser.setMultiSelectionEnabled (true);
391
            chooser.setMultiSelectionEnabled (true);
375
            String title = null;
392
            String title = null;
376
            String message = null;
393
            String message = null;
377
            String approveButtonName = null;
394
            String approveButtonName = null;
378
            String approveButtonNameMne = null;
395
            String approveButtonNameMne = null;
379
            if (this.type == SOURCES) {
396
            if (model.type == SOURCES) {
380
                title = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_OpenSources");
397
                title = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_OpenSources");
381
                message = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_Sources");
398
                message = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_Sources");
382
                approveButtonName = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_OpenSources");
399
                approveButtonName = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_OpenSources");
383
                approveButtonNameMne = NbBundle.getMessage (J2SEPlatformCustomizer.class,"MNE_OpenSources");
400
                approveButtonNameMne = NbBundle.getMessage (J2SEPlatformCustomizer.class,"MNE_OpenSources");
384
            }
401
            } else if (model.type == JAVADOC) {
385
            else if (this.type == JAVADOC) {
386
                title = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_OpenJavadoc");
402
                title = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_OpenJavadoc");
387
                message = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_Javadoc");
403
                message = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_Javadoc");
388
                approveButtonName = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_OpenJavadoc");
404
                approveButtonName = NbBundle.getMessage (J2SEPlatformCustomizer.class,"TXT_OpenJavadoc");
Lines 399-412 Link Here
399
            //#61789 on old macosx (jdk 1.4.1) these two method need to be called in this order.
415
            //#61789 on old macosx (jdk 1.4.1) these two method need to be called in this order.
400
            chooser.setAcceptAllFileFilterUsed( false );
416
            chooser.setAcceptAllFileFilterUsed( false );
401
            chooser.setFileFilter (new ArchiveFileFilter(message,new String[] {"ZIP","JAR"}));   //NOI18N
417
            chooser.setFileFilter (new ArchiveFileFilter(message,new String[] {"ZIP","JAR"}));   //NOI18N
402
            if (this.currentDir != null) {
418
            if (currentDir[0] != null) {
403
                chooser.setCurrentDirectory(this.currentDir);
419
                chooser.setCurrentDirectory(currentDir[0]);
404
            }
420
            }
405
            if (chooser.showOpenDialog(this)==JFileChooser.APPROVE_OPTION) {
421
            if (chooser.showOpenDialog(parentComponent) == JFileChooser.APPROVE_OPTION) {
406
                File[] fs = chooser.getSelectedFiles();
422
                File[] fs = chooser.getSelectedFiles();
407
                PathModel model = (PathModel) this.resources.getModel();
408
                boolean addingFailed = false;
423
                boolean addingFailed = false;
409
                int firstIndex = this.resources.getModel().getSize();
410
                for (File f : fs) {
424
                for (File f : fs) {
411
                    //XXX: JFileChooser workaround (JDK bug #5075580), double click on folder returns wrong file
425
                    //XXX: JFileChooser workaround (JDK bug #5075580), double click on folder returns wrong file
412
                    // E.g. for /foo/src it returns /foo/src/src
426
                    // E.g. for /foo/src it returns /foo/src/src
Lines 425-440 Link Here
425
                    new NotifyDescriptor.Message (NbBundle.getMessage(J2SEPlatformCustomizer.class,"TXT_CanNotAddResolve"),
439
                    new NotifyDescriptor.Message (NbBundle.getMessage(J2SEPlatformCustomizer.class,"TXT_CanNotAddResolve"),
426
                            NotifyDescriptor.ERROR_MESSAGE);
440
                            NotifyDescriptor.ERROR_MESSAGE);
427
                }
441
                }
428
                int lastIndex = this.resources.getModel().getSize()-1;
442
                currentDir[0] = FileUtil.normalizeFile(chooser.getCurrentDirectory());
429
                if (firstIndex<=lastIndex) {
443
                return true;
430
                    int[] toSelect = new int[lastIndex-firstIndex+1];
431
                    for (int i = 0; i < toSelect.length; i++) {
432
                        toSelect[i] = firstIndex+i;
433
                    }
434
                    this.resources.setSelectedIndices(toSelect);
435
                }
436
                this.currentDir = FileUtil.normalizeFile(chooser.getCurrentDirectory());
437
            }
444
            }
445
            return false;
438
        }
446
        }
439
447
440
        private void removePathElement () {
448
        private void removePathElement () {
Lines 491-497 Link Here
491
    }
499
    }
492
500
493
501
494
    private static class PathModel extends AbstractListModel/*<String>*/ {
502
    static class PathModel extends AbstractListModel/*<String>*/ {
495
503
496
        private J2SEPlatformImpl platform;
504
        private J2SEPlatformImpl platform;
497
        private int type;
505
        private int type;
Lines 567-573 Link Here
567
            }
575
            }
568
        }       
576
        }       
569
577
570
        private boolean addPath (URL url) {
578
        boolean addPath (URL url) {
571
            if (FileUtil.isArchiveFile(url)) {
579
            if (FileUtil.isArchiveFile(url)) {
572
                url = FileUtil.getArchiveRoot (url);
580
                url = FileUtil.getArchiveRoot (url);
573
            }
581
            }
(-)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 (+161 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.MalformedURLException;
47
import java.net.URI;
48
import java.net.URL;
49
import java.util.List;
50
import org.netbeans.api.annotations.common.NonNull;
51
import org.netbeans.api.annotations.common.NullAllowed;
52
import org.netbeans.api.java.classpath.ClassPath;
53
import org.netbeans.api.java.platform.JavaPlatform;
54
import org.netbeans.api.java.platform.JavaPlatformManager;
55
import org.netbeans.api.java.platform.Specification;
56
import org.netbeans.api.java.queries.SourceJavadocAttacher.AttachmentListener;
57
import org.netbeans.modules.java.j2seplatform.queries.SourceJavadocAttacherUtil;
58
import org.netbeans.spi.java.queries.SourceJavadocAttacherImplementation;
59
import org.openide.util.Exceptions;
60
import org.openide.util.NbBundle;
61
import org.openide.util.lookup.ServiceProvider;
62
63
/**
64
 *
65
 * @author Tomas Zezula
66
 */
67
@ServiceProvider(service=SourceJavadocAttacherImplementation.class,position=150)
68
public class J2SEPlatformSourceJavadocAttacher implements SourceJavadocAttacherImplementation {
69
70
    @Override
71
    public boolean attachSources(
72
            @NonNull final URL root,
73
            @NullAllowed AttachmentListener listener) throws IOException {
74
        return attach(root, listener, J2SEPlatformCustomizer.SOURCES);
75
    }
76
77
    @Override
78
    public boolean attachJavadoc(
79
            @NonNull final URL root,
80
            @NullAllowed AttachmentListener listener) throws IOException {
81
        return attach(root, listener, J2SEPlatformCustomizer.JAVADOC);
82
    }
83
84
    @NbBundle.Messages({
85
        "TXT_Title=Browse ZIP/Folder",
86
        "TXT_JavadocFilterName=Library Javadoc (folder, ZIP or JAR file)",
87
        "TXT_SourcesFilterName=Library Sources (folder, ZIP or JAR file)"
88
    })
89
    private boolean attach(
90
            @NonNull final URL root,
91
            @NullAllowed final AttachmentListener listener,
92
            final int mode) {
93
        final J2SEPlatformImpl platform = findOwner(root);
94
        if (platform == null) {
95
            return false;
96
        }
97
        final Runnable call = new Runnable() {
98
            @Override
99
            public void run() {
100
                boolean success = false;
101
                try {
102
                    final List<? extends URI> selected;
103
                    if (mode == J2SEPlatformCustomizer.SOURCES) {
104
                        selected = SourceJavadocAttacherUtil.selectSources(
105
                            root,
106
                            SourceJavadocAttacherUtil.createDefaultBrowseCall(
107
                                Bundle.TXT_Title(),
108
                                Bundle.TXT_SourcesFilterName(),
109
                                new File[1]),
110
                            SourceJavadocAttacherUtil.createDefaultURIConvertor(true));
111
                    } else if (mode == J2SEPlatformCustomizer.JAVADOC) {
112
                        selected = SourceJavadocAttacherUtil.selectJavadoc(
113
                            root,
114
                            SourceJavadocAttacherUtil.createDefaultBrowseCall(
115
                                Bundle.TXT_Title(),
116
                                Bundle.TXT_JavadocFilterName(),
117
                                new File[1]),
118
                            SourceJavadocAttacherUtil.createDefaultURIConvertor(false));
119
                    } else {
120
                        throw new IllegalStateException(Integer.toString(mode));
121
                    }
122
                    if (selected != null) {
123
                        final J2SEPlatformCustomizer.PathModel model = new J2SEPlatformCustomizer.PathModel(platform, mode);
124
                        try {
125
                            for (URI uri : selected) {
126
                                model.addPath(uri.toURL());
127
                            }
128
                            success = true;
129
                        } catch (MalformedURLException e) {
130
                            Exceptions.printStackTrace(e);
131
                        }
132
                    }
133
                } finally {
134
                    SourceJavadocAttacherUtil.callListener(listener, success);
135
                }
136
            }
137
        };
138
        SourceJavadocAttacherUtil.scheduleInEDT(call);
139
        return true;
140
    }
141
142
    private J2SEPlatformImpl findOwner(final URL root) {
143
        for (JavaPlatform p : JavaPlatformManager.getDefault().getPlatforms(null, new Specification(J2SEPlatformImpl.PLATFORM_J2SE, null))) {
144
            if (!(p instanceof J2SEPlatformImpl)) {
145
                //Cannot handle unknown platform
146
                continue;
147
            }
148
            final J2SEPlatformImpl j2sep = (J2SEPlatformImpl) p;
149
            if (j2sep.isBroken()) {
150
                continue;
151
            }
152
            for (ClassPath.Entry entry : j2sep.getBootstrapLibraries().entries()) {
153
                if (root.equals(entry.getURL())) {
154
                    return j2sep;
155
                }
156
            }
157
        }
158
        return null;
159
    }
160
161
}
(-)a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/queries/Bundle.properties (+6 lines)
Line 0 Link Here
1
TXT_LocalJavadoc=&Local Javadoc:
2
TXT_RemoteJavadoc=&Remote Javadoc URL:
3
TXT_Browse=&Browse
4
TXT_AttachJavadocTo=Attach Javadoc to "{0}"
5
TXT_AttachSourcesTo=Attach Sources to "{0}"
6
TXT_LocalSources=Sources:
(-)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 (+156 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.URI;
48
import java.net.URL;
49
import java.util.List;
50
import org.netbeans.api.annotations.common.NonNull;
51
import org.netbeans.api.annotations.common.NullAllowed;
52
import org.netbeans.api.java.queries.SourceJavadocAttacher.AttachmentListener;
53
import org.netbeans.spi.java.queries.SourceJavadocAttacherImplementation;
54
import org.openide.filesystems.FileStateInvalidException;
55
import org.openide.util.Exceptions;
56
import org.openide.util.NbBundle;
57
import org.openide.util.lookup.ServiceProvider;
58
59
/**
60
 *
61
 * @author Tomas Zezula
62
 */
63
@ServiceProvider(service=SourceJavadocAttacherImplementation.class) //position=last
64
public class DefaultSourceJavadocAttacher implements SourceJavadocAttacherImplementation {
65
66
    @Override
67
    public boolean attachSources(
68
            @NonNull final URL root,
69
            @NullAllowed final AttachmentListener listener) throws IOException {
70
        return attach(root, listener, 0);
71
    }
72
73
    @Override
74
    public boolean attachJavadoc(
75
            @NonNull final URL root,
76
            @NullAllowed final AttachmentListener listener) throws IOException {
77
        return attach(root, listener, 1);
78
    }
79
80
    private boolean attach (
81
            @NonNull final URL root,
82
            @NullAllowed final AttachmentListener listener,
83
            final int mode) throws IOException {
84
        final Runnable call = new Runnable() {
85
            @Override
86
            public void run() {
87
                boolean success = false;
88
                try {
89
                    final URL[] toAttach = selectRoots(root, mode);
90
                    if (toAttach != null) {
91
                        switch (mode) {
92
                            case 0:
93
                                QueriesCache.getSources().updateRoot(root, toAttach);
94
                                break;
95
                            case 1:
96
                                QueriesCache.getJavadoc().updateRoot(root, toAttach);
97
                                break;
98
                            default:
99
                                throw new IllegalArgumentException(Integer.toString(mode));
100
                        }
101
                        success = true;
102
                    }
103
                } catch (MalformedURLException e) {
104
                    Exceptions.printStackTrace(e);
105
                } catch (FileStateInvalidException e) {
106
                    Exceptions.printStackTrace(e);
107
                } finally {
108
                    SourceJavadocAttacherUtil.callListener(listener,success);
109
                }
110
            }
111
        };
112
        SourceJavadocAttacherUtil.scheduleInEDT(call);
113
        return true;
114
    }
115
116
    @NbBundle.Messages({
117
        "TXT_Title=Browse ZIP/Folder",
118
        "TXT_Javadoc=Library Javadoc (folder, ZIP or JAR file)",
119
        "TXT_Sources=Library Sources (folder, ZIP or JAR file)"
120
    })
121
    private static URL[] selectRoots(final URL root, final int mode) throws MalformedURLException, FileStateInvalidException {
122
        final File[] cfh = new File[]{currentFolder};
123
        final List<? extends URI> selected;
124
        if (mode == 0) {
125
            selected = SourceJavadocAttacherUtil.selectSources(
126
                root,
127
                SourceJavadocAttacherUtil.createDefaultBrowseCall(
128
                    Bundle.TXT_Title(),
129
                    Bundle.TXT_Sources(),
130
                    cfh),
131
                SourceJavadocAttacherUtil.createDefaultURIConvertor(true));
132
        } else if (mode == 1) {
133
            selected = SourceJavadocAttacherUtil.selectJavadoc(
134
                root,
135
                SourceJavadocAttacherUtil.createDefaultBrowseCall(
136
                    Bundle.TXT_Title(),
137
                    Bundle.TXT_Javadoc(),
138
                    cfh),
139
                SourceJavadocAttacherUtil.createDefaultURIConvertor(false));
140
        } else {
141
            throw new IllegalStateException(Integer.toString(mode));
142
        }
143
144
        if (selected == null) {
145
            return null;
146
        }
147
        currentFolder = cfh[0];
148
        final URL[] result = new URL[selected.size()];
149
        for (int i=0; i< result.length; i++) {
150
            result[i] = selected.get(i).toURL();
151
        }
152
        return result;
153
    }
154
155
    private static File currentFolder;
156
}
(-)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.j2seplatform/src/org/netbeans/modules/java/j2seplatform/queries/SelectJavadocPanel.form (+125 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
  <NonVisualComponents>
5
    <Component class="javax.swing.ButtonGroup" name="javadocGroup">
6
    </Component>
7
  </NonVisualComponents>
8
  <AuxValues>
9
    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
10
    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
11
    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
12
    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
13
    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
14
    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
15
    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
16
    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
17
    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
18
  </AuxValues>
19
20
  <Layout>
21
    <DimensionLayout dim="0">
22
      <Group type="103" groupAlignment="0" attributes="0">
23
          <Group type="102" alignment="0" attributes="0">
24
              <EmptySpace max="-2" attributes="0"/>
25
              <Group type="103" groupAlignment="0" attributes="0">
26
                  <Component id="attachLbl" alignment="0" pref="498" max="32767" attributes="0"/>
27
                  <Group type="102" alignment="0" attributes="0">
28
                      <Group type="103" groupAlignment="0" attributes="0">
29
                          <Component id="remoteJavadoc" alignment="0" min="-2" max="-2" attributes="0"/>
30
                          <Component id="localJavadoc" alignment="0" min="-2" max="-2" attributes="0"/>
31
                      </Group>
32
                      <EmptySpace max="-2" attributes="0"/>
33
                      <Group type="103" groupAlignment="1" attributes="0">
34
                          <Group type="102" attributes="0">
35
                              <Component id="localField" pref="231" max="32767" attributes="0"/>
36
                              <EmptySpace max="-2" attributes="0"/>
37
                              <Component id="browse" min="-2" max="-2" attributes="0"/>
38
                          </Group>
39
                          <Component id="remoteField" pref="328" max="32767" attributes="0"/>
40
                      </Group>
41
                  </Group>
42
              </Group>
43
              <EmptySpace max="-2" attributes="0"/>
44
          </Group>
45
      </Group>
46
    </DimensionLayout>
47
    <DimensionLayout dim="1">
48
      <Group type="103" groupAlignment="0" attributes="0">
49
          <Group type="102" attributes="0">
50
              <EmptySpace max="-2" attributes="0"/>
51
              <Component id="attachLbl" min="-2" max="-2" attributes="0"/>
52
              <EmptySpace type="unrelated" max="-2" attributes="0"/>
53
              <Group type="103" groupAlignment="1" attributes="0">
54
                  <Component id="browse" min="-2" max="-2" attributes="0"/>
55
                  <Group type="103" alignment="1" groupAlignment="3" attributes="0">
56
                      <Component id="localJavadoc" alignment="3" min="-2" max="-2" attributes="0"/>
57
                      <Component id="localField" alignment="3" min="-2" max="-2" attributes="0"/>
58
                  </Group>
59
              </Group>
60
              <EmptySpace max="-2" attributes="0"/>
61
              <Group type="103" groupAlignment="3" attributes="0">
62
                  <Component id="remoteJavadoc" alignment="3" min="-2" max="-2" attributes="0"/>
63
                  <Component id="remoteField" alignment="3" min="-2" max="-2" attributes="0"/>
64
              </Group>
65
              <EmptySpace max="32767" attributes="0"/>
66
          </Group>
67
      </Group>
68
    </DimensionLayout>
69
  </Layout>
70
  <SubComponents>
71
    <Component class="javax.swing.JRadioButton" name="localJavadoc">
72
      <Properties>
73
        <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
74
          <ComponentRef name="javadocGroup"/>
75
        </Property>
76
        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
77
          <ResourceString bundle="org/netbeans/modules/java/j2seplatform/queries/Bundle.properties" key="TXT_LocalJavadoc" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
78
        </Property>
79
      </Properties>
80
      <AuxValues>
81
        <AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
82
      </AuxValues>
83
    </Component>
84
    <Component class="javax.swing.JTextField" name="localField">
85
      <Properties>
86
        <Property name="editable" type="boolean" value="false"/>
87
      </Properties>
88
    </Component>
89
    <Component class="javax.swing.JRadioButton" name="remoteJavadoc">
90
      <Properties>
91
        <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
92
          <ComponentRef name="javadocGroup"/>
93
        </Property>
94
        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
95
          <ResourceString bundle="org/netbeans/modules/java/j2seplatform/queries/Bundle.properties" key="TXT_RemoteJavadoc" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
96
        </Property>
97
      </Properties>
98
      <AuxValues>
99
        <AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
100
      </AuxValues>
101
    </Component>
102
    <Component class="javax.swing.JTextField" name="remoteField">
103
    </Component>
104
    <Component class="javax.swing.JButton" name="browse">
105
      <Properties>
106
        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
107
          <ResourceString bundle="org/netbeans/modules/java/j2seplatform/queries/Bundle.properties" key="TXT_Browse" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
108
        </Property>
109
      </Properties>
110
      <Events>
111
        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="browse"/>
112
      </Events>
113
      <AuxValues>
114
        <AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
115
      </AuxValues>
116
    </Component>
117
    <Component class="javax.swing.JLabel" name="attachLbl">
118
      <Properties>
119
        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
120
          <Connection code="NbBundle.getMessage(SelectJavadocPanel.class, &quot;TXT_AttachJavadocTo&quot;,fileName)" type="code"/>
121
        </Property>
122
      </Properties>
123
    </Component>
124
  </SubComponents>
125
</Form>
(-)a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/queries/SelectJavadocPanel.java (+218 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
43
/*
44
 * SelectJavadocPanel.java
45
 *
46
 * Created on Aug 8, 2011, 3:25:47 PM
47
 */
48
package org.netbeans.modules.java.j2seplatform.queries;
49
50
import java.awt.event.ItemEvent;
51
import java.awt.event.ItemListener;
52
import java.io.File;
53
import java.net.URI;
54
import java.util.ArrayList;
55
import java.util.Collections;
56
import java.util.List;
57
import java.util.concurrent.Callable;
58
import org.netbeans.api.annotations.common.NonNull;
59
import org.netbeans.modules.java.j2seplatform.queries.SourceJavadocAttacherUtil.Function;
60
import org.openide.util.Exceptions;
61
import org.openide.util.NbBundle;
62
63
/**
64
 *
65
 * @author Tomas Zezula
66
 */
67
class SelectJavadocPanel extends javax.swing.JPanel implements ItemListener {
68
69
    private final String fileName;
70
    private final Callable<List<? extends String>> browseCall;
71
    private final Function<String,URI> convertor;
72
73
    /** Creates new form SelectJavadocPanel */
74
    SelectJavadocPanel(
75
            @NonNull final String displayName,
76
            @NonNull final Callable<List<? extends String>> browseCall,
77
            @NonNull final Function<String,URI> convertor) {
78
        assert displayName != null;
79
        assert  browseCall != null;
80
        assert convertor != null;
81
        this.fileName = displayName;
82
        this.browseCall = browseCall;
83
        this.convertor = convertor;
84
        initComponents();
85
        postInitComponents();
86
    }
87
88
    private void postInitComponents() {
89
        localJavadoc.addItemListener(this);
90
        remoteJavadoc.addItemListener(this);
91
        localJavadoc.setSelected(true);
92
    }
93
94
    @NonNull
95
    List<URI> getJavadoc() throws Exception {
96
        if (localJavadoc.isSelected()) {
97
            final List<URI> paths = new ArrayList<URI>();
98
            final String str = localField.getText();
99
            for (String pathElement : str.split(File.pathSeparator)) {
100
                paths.add(convertor.call(pathElement.trim()));
101
            }
102
            return paths;
103
        } else if (remoteJavadoc.isSelected()) {
104
            return Collections.<URI>singletonList(new URI(remoteField.getText().trim()));
105
        } else {
106
            throw new IllegalStateException();
107
        }
108
    }
109
110
    /** This method is called from within the constructor to
111
     * initialize the form.
112
     * WARNING: Do NOT modify this code. The content of this method is
113
     * always regenerated by the Form Editor.
114
     */
115
    @SuppressWarnings("unchecked")
116
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
117
    private void initComponents() {
118
119
        javadocGroup = new javax.swing.ButtonGroup();
120
        localJavadoc = new javax.swing.JRadioButton();
121
        localField = new javax.swing.JTextField();
122
        remoteJavadoc = new javax.swing.JRadioButton();
123
        remoteField = new javax.swing.JTextField();
124
        browse = new javax.swing.JButton();
125
        attachLbl = new javax.swing.JLabel();
126
127
        javadocGroup.add(localJavadoc);
128
        org.openide.awt.Mnemonics.setLocalizedText(localJavadoc, org.openide.util.NbBundle.getMessage(SelectJavadocPanel.class, "TXT_LocalJavadoc")); // NOI18N
129
130
        localField.setEditable(false);
131
132
        javadocGroup.add(remoteJavadoc);
133
        org.openide.awt.Mnemonics.setLocalizedText(remoteJavadoc, org.openide.util.NbBundle.getMessage(SelectJavadocPanel.class, "TXT_RemoteJavadoc")); // NOI18N
134
135
        org.openide.awt.Mnemonics.setLocalizedText(browse, org.openide.util.NbBundle.getMessage(SelectJavadocPanel.class, "TXT_Browse")); // NOI18N
136
        browse.addActionListener(new java.awt.event.ActionListener() {
137
            public void actionPerformed(java.awt.event.ActionEvent evt) {
138
                browse(evt);
139
            }
140
        });
141
142
        attachLbl.setText(NbBundle.getMessage(SelectJavadocPanel.class, "TXT_AttachJavadocTo",fileName));
143
144
        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
145
        this.setLayout(layout);
146
        layout.setHorizontalGroup(
147
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
148
            .addGroup(layout.createSequentialGroup()
149
                .addContainerGap()
150
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
151
                    .addComponent(attachLbl, javax.swing.GroupLayout.DEFAULT_SIZE, 498, Short.MAX_VALUE)
152
                    .addGroup(layout.createSequentialGroup()
153
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
154
                            .addComponent(remoteJavadoc)
155
                            .addComponent(localJavadoc))
156
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
157
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
158
                            .addGroup(layout.createSequentialGroup()
159
                                .addComponent(localField, javax.swing.GroupLayout.DEFAULT_SIZE, 231, Short.MAX_VALUE)
160
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
161
                                .addComponent(browse))
162
                            .addComponent(remoteField, javax.swing.GroupLayout.DEFAULT_SIZE, 328, Short.MAX_VALUE))))
163
                .addContainerGap())
164
        );
165
        layout.setVerticalGroup(
166
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
167
            .addGroup(layout.createSequentialGroup()
168
                .addContainerGap()
169
                .addComponent(attachLbl)
170
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
171
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
172
                    .addComponent(browse)
173
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
174
                        .addComponent(localJavadoc)
175
                        .addComponent(localField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
176
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
177
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
178
                    .addComponent(remoteJavadoc)
179
                    .addComponent(remoteField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
180
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
181
        );
182
    }// </editor-fold>//GEN-END:initComponents
183
184
private void browse(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browse
185
    try {
186
        final List<? extends String> paths = browseCall.call();
187
        if (paths != null) {
188
            final StringBuilder sb = new StringBuilder();
189
            for (String pathElement : paths) {
190
                if (sb.length() != 0) {
191
                    sb.append(File.pathSeparatorChar);  //NOI18N
192
                }
193
                sb.append(pathElement);
194
            }
195
            localField.setText(sb.toString());
196
        }
197
    } catch (Exception ex) {
198
        Exceptions.printStackTrace(ex);
199
    }
200
}//GEN-LAST:event_browse
201
202
    // Variables declaration - do not modify//GEN-BEGIN:variables
203
    private javax.swing.JLabel attachLbl;
204
    private javax.swing.JButton browse;
205
    private javax.swing.ButtonGroup javadocGroup;
206
    private javax.swing.JTextField localField;
207
    private javax.swing.JRadioButton localJavadoc;
208
    private javax.swing.JTextField remoteField;
209
    private javax.swing.JRadioButton remoteJavadoc;
210
    // End of variables declaration//GEN-END:variables
211
212
    @Override
213
    public void itemStateChanged(ItemEvent e) {
214
        localField.setEnabled(localJavadoc.isSelected());
215
        browse.setEnabled(localJavadoc.isSelected());
216
        remoteField.setEnabled(remoteJavadoc.isSelected());
217
    }
218
}
(-)a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/queries/SelectSourcesPanel.form (+91 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" attributes="0">
20
              <EmptySpace max="-2" attributes="0"/>
21
              <Group type="103" groupAlignment="0" attributes="0">
22
                  <Component id="attachTo" alignment="0" min="-2" max="-2" attributes="0"/>
23
                  <Group type="102" alignment="0" attributes="0">
24
                      <Component id="lblSources" min="-2" max="-2" attributes="0"/>
25
                      <EmptySpace max="-2" attributes="0"/>
26
                      <Component id="sourcesField" pref="341" max="32767" attributes="0"/>
27
                      <EmptySpace max="-2" attributes="0"/>
28
                      <Component id="jButton1" min="-2" max="-2" attributes="0"/>
29
                  </Group>
30
              </Group>
31
              <EmptySpace max="-2" attributes="0"/>
32
          </Group>
33
      </Group>
34
    </DimensionLayout>
35
    <DimensionLayout dim="1">
36
      <Group type="103" groupAlignment="0" attributes="0">
37
          <Group type="102" alignment="0" attributes="0">
38
              <EmptySpace max="-2" attributes="0"/>
39
              <Component id="attachTo" min="-2" max="-2" attributes="0"/>
40
              <EmptySpace max="-2" attributes="0"/>
41
              <Group type="103" groupAlignment="3" attributes="0">
42
                  <Component id="lblSources" alignment="3" min="-2" max="-2" attributes="0"/>
43
                  <Component id="sourcesField" alignment="3" min="-2" max="-2" attributes="0"/>
44
                  <Component id="jButton1" alignment="3" min="-2" max="-2" attributes="0"/>
45
              </Group>
46
              <EmptySpace max="32767" attributes="0"/>
47
          </Group>
48
      </Group>
49
    </DimensionLayout>
50
  </Layout>
51
  <SubComponents>
52
    <Component class="javax.swing.JLabel" name="attachTo">
53
      <Properties>
54
        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
55
          <Connection code="NbBundle.getMessage(SelectSourcesPanel.class, &quot;TXT_AttachSourcesTo&quot;,displayName)" type="code"/>
56
        </Property>
57
      </Properties>
58
    </Component>
59
    <Component class="javax.swing.JLabel" name="lblSources">
60
      <Properties>
61
        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
62
          <ComponentRef name="sourcesField"/>
63
        </Property>
64
        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
65
          <ResourceString bundle="org/netbeans/modules/java/j2seplatform/queries/Bundle.properties" key="TXT_LocalSources" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
66
        </Property>
67
      </Properties>
68
      <AuxValues>
69
        <AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
70
      </AuxValues>
71
    </Component>
72
    <Component class="javax.swing.JTextField" name="sourcesField">
73
      <Properties>
74
        <Property name="editable" type="boolean" value="false"/>
75
      </Properties>
76
    </Component>
77
    <Component class="javax.swing.JButton" name="jButton1">
78
      <Properties>
79
        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
80
          <ResourceString bundle="org/netbeans/modules/java/j2seplatform/queries/Bundle.properties" key="TXT_Browse" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
81
        </Property>
82
      </Properties>
83
      <Events>
84
        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="browse"/>
85
      </Events>
86
      <AuxValues>
87
        <AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
88
      </AuxValues>
89
    </Component>
90
  </SubComponents>
91
</Form>
(-)a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/queries/SelectSourcesPanel.java (+177 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
43
/*
44
 * SelectSourcesPanel.java
45
 *
46
 * Created on Aug 8, 2011, 6:47:20 PM
47
 */
48
package org.netbeans.modules.java.j2seplatform.queries;
49
50
import java.io.File;
51
import java.net.URI;
52
import java.util.ArrayList;
53
import java.util.List;
54
import java.util.concurrent.Callable;
55
import org.netbeans.api.annotations.common.CheckForNull;
56
import org.netbeans.api.annotations.common.NonNull;
57
import org.netbeans.modules.java.j2seplatform.queries.SourceJavadocAttacherUtil.Function;
58
import org.openide.util.Exceptions;
59
import org.openide.util.NbBundle;
60
61
/**
62
 *
63
 * @author Tomas Zezula
64
 */
65
class SelectSourcesPanel extends javax.swing.JPanel {
66
67
    private final String displayName;
68
    private final Callable<List<? extends String>> browseCall;
69
    private final Function<String,URI> convertor;
70
71
    /** Creates new form SelectSourcesPanel */
72
    SelectSourcesPanel (
73
            @NonNull final String displayName,
74
            @NonNull final Callable<List<? extends String>> browseCall,
75
            @NonNull final Function<String,URI> convertor) {
76
        assert displayName != null;
77
        assert browseCall != null;
78
        assert convertor != null;
79
        this.displayName = displayName;
80
        this.browseCall = browseCall;
81
        this.convertor = convertor;
82
        initComponents();
83
    }
84
85
    @CheckForNull
86
    List<? extends URI> getSources() throws Exception {
87
        final List<URI> paths = new ArrayList<URI>();
88
        final String str = sourcesField.getText();
89
        for (String pathElement : str.split(File.pathSeparator)) {
90
            paths.add(convertor.call(pathElement));
91
        }
92
        return paths;
93
    }
94
95
    /** This method is called from within the constructor to
96
     * initialize the form.
97
     * WARNING: Do NOT modify this code. The content of this method is
98
     * always regenerated by the Form Editor.
99
     */
100
    @SuppressWarnings("unchecked")
101
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
102
    private void initComponents() {
103
104
        attachTo = new javax.swing.JLabel();
105
        lblSources = new javax.swing.JLabel();
106
        sourcesField = new javax.swing.JTextField();
107
        jButton1 = new javax.swing.JButton();
108
109
        attachTo.setText(NbBundle.getMessage(SelectSourcesPanel.class, "TXT_AttachSourcesTo",displayName));
110
111
        lblSources.setLabelFor(sourcesField);
112
        org.openide.awt.Mnemonics.setLocalizedText(lblSources, org.openide.util.NbBundle.getMessage(SelectSourcesPanel.class, "TXT_LocalSources")); // NOI18N
113
114
        sourcesField.setEditable(false);
115
116
        org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(SelectSourcesPanel.class, "TXT_Browse")); // NOI18N
117
        jButton1.addActionListener(new java.awt.event.ActionListener() {
118
            public void actionPerformed(java.awt.event.ActionEvent evt) {
119
                browse(evt);
120
            }
121
        });
122
123
        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
124
        this.setLayout(layout);
125
        layout.setHorizontalGroup(
126
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
127
            .addGroup(layout.createSequentialGroup()
128
                .addContainerGap()
129
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
130
                    .addComponent(attachTo)
131
                    .addGroup(layout.createSequentialGroup()
132
                        .addComponent(lblSources)
133
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
134
                        .addComponent(sourcesField, javax.swing.GroupLayout.DEFAULT_SIZE, 341, Short.MAX_VALUE)
135
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
136
                        .addComponent(jButton1)))
137
                .addContainerGap())
138
        );
139
        layout.setVerticalGroup(
140
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
141
            .addGroup(layout.createSequentialGroup()
142
                .addContainerGap()
143
                .addComponent(attachTo)
144
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
145
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
146
                    .addComponent(lblSources)
147
                    .addComponent(sourcesField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
148
                    .addComponent(jButton1))
149
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
150
        );
151
    }// </editor-fold>//GEN-END:initComponents
152
153
private void browse(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browse
154
    try {
155
        final List<? extends String> paths = browseCall.call();
156
        if (paths != null) {
157
            final StringBuilder sb = new StringBuilder();
158
            for (String pathElement : paths) {
159
                if (sb.length() != 0) {
160
                    sb.append(File.pathSeparatorChar);  //NOI18N
161
                }
162
                sb.append(pathElement);
163
            }
164
            sourcesField.setText(sb.toString());
165
        }
166
    } catch (Exception ex) {
167
        Exceptions.printStackTrace(ex);
168
    }
169
}//GEN-LAST:event_browse
170
171
    // Variables declaration - do not modify//GEN-BEGIN:variables
172
    private javax.swing.JLabel attachTo;
173
    private javax.swing.JButton jButton1;
174
    private javax.swing.JLabel lblSources;
175
    private javax.swing.JTextField sourcesField;
176
    // End of variables declaration//GEN-END:variables
177
}
(-)a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/queries/SourceJavadocAttacherUtil.java (+245 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.net.MalformedURLException;
46
import java.net.URI;
47
import java.net.URL;
48
import java.util.ArrayList;
49
import java.util.List;
50
import java.util.concurrent.Callable;
51
import javax.swing.JFileChooser;
52
import javax.swing.SwingUtilities;
53
import javax.swing.filechooser.FileFilter;
54
import org.netbeans.api.annotations.common.CheckForNull;
55
import org.netbeans.api.annotations.common.NonNull;
56
import org.netbeans.api.annotations.common.NullAllowed;
57
import org.netbeans.api.java.queries.SourceJavadocAttacher.AttachmentListener;
58
import org.netbeans.spi.java.project.support.JavadocAndSourceRootDetection;
59
import org.openide.DialogDescriptor;
60
import org.openide.DialogDisplayer;
61
import org.openide.filesystems.FileObject;
62
import org.openide.filesystems.FileUtil;
63
import org.openide.filesystems.URLMapper;
64
import org.openide.util.NbBundle;
65
import org.openide.util.Utilities;
66
67
/**
68
 *
69
 * @author Tomas Zezula
70
 */
71
public final class SourceJavadocAttacherUtil {
72
73
    private SourceJavadocAttacherUtil() {}
74
75
    @NonNull
76
    public static void scheduleInEDT(
77
        @NonNull final Runnable call) {
78
        assert call != null;
79
        if (SwingUtilities.isEventDispatchThread()) {
80
            call.run();
81
        } else {
82
            SwingUtilities.invokeLater(call);
83
        }
84
    }
85
86
    public static void callListener(
87
        @NullAllowed final AttachmentListener listener,
88
        final boolean success) {
89
        if (listener != null) {
90
            if (success) {
91
                listener.attachmentSucceeded();
92
            } else {
93
                listener.attachmentFailed();
94
            }
95
        }
96
    }
97
98
    @CheckForNull
99
    @NbBundle.Messages({
100
        "TXT_SelectJavadoc=Select Javadoc"
101
    })
102
    public static List<? extends URI> selectJavadoc(
103
            @NonNull final URL root,
104
            @NonNull final Callable<List<? extends String>> browseCall,
105
            @NonNull final Function<String,URI> convertor) {
106
        assert root != null;
107
        assert browseCall != null;
108
        assert convertor != null;
109
        final SelectJavadocPanel selectJavadoc = new SelectJavadocPanel(
110
                getDisplayName(root),
111
                browseCall,
112
                convertor);
113
        final DialogDescriptor dd = new DialogDescriptor(selectJavadoc, Bundle.TXT_SelectJavadoc());
114
        if (DialogDisplayer.getDefault().notify(dd) == DialogDescriptor.OK_OPTION) {
115
            try {
116
                return selectJavadoc.getJavadoc();
117
            } catch (Exception e) {
118
                //todo:
119
            }
120
        }
121
        return null;
122
    }
123
124
    @CheckForNull
125
    @NbBundle.Messages({
126
        "TXT_SelectSources=Select Sources"
127
    })
128
    public static List<? extends URI> selectSources(
129
            @NonNull final URL root,
130
            @NonNull final Callable<List<? extends String>> browseCall,
131
            @NonNull final Function<String,URI> convertor) {
132
        assert root != null;
133
        assert browseCall != null;
134
        assert convertor != null;
135
        final SelectSourcesPanel selectSources = new SelectSourcesPanel(
136
                getDisplayName(root),
137
                browseCall,
138
                convertor);
139
        final DialogDescriptor dd = new DialogDescriptor(selectSources, Bundle.TXT_SelectSources());
140
        if (DialogDisplayer.getDefault().notify(dd) == DialogDescriptor.OK_OPTION) {
141
            try {
142
                return selectSources.getSources();
143
            } catch (Exception e) {
144
                //todo:
145
            }
146
        }
147
        return null;
148
    }
149
150
    @NonNull
151
    @NbBundle.Messages({
152
        "TXT_Select=Add ZIP/Folder",
153
        "MNE_Select=A"
154
    })
155
    public static Callable<List<? extends String>> createDefaultBrowseCall(
156
            @NonNull final String title,
157
            @NonNull final String filterDescription,
158
            @NonNull final File[] currentFolder) {
159
        assert title != null;
160
        assert filterDescription != null;
161
        assert currentFolder != null;
162
        final Callable<List<? extends String>> call = new Callable<List<? extends String>>() {
163
            @Override
164
            public List<? extends String> call() throws Exception {
165
                final JFileChooser chooser = new JFileChooser();
166
                chooser.setMultiSelectionEnabled (true);
167
                chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
168
                if (Utilities.isMac()) {
169
                    //New JDKs and JREs are bundled into package, allow JFileChooser to navigate in
170
                    chooser.putClientProperty("JFileChooser.packageIsTraversable", "always");   //NOI18N
171
                }
172
                chooser.setDialogTitle(title);
173
                chooser.setFileFilter (new FileFilter() {
174
                    @Override
175
                    public boolean accept(File f) {
176
                        try {
177
                            return f.isDirectory() ||
178
                                FileUtil.isArchiveFile(f.toURI().toURL());
179
                        } catch (MalformedURLException ex) {
180
                            return false;
181
                        }
182
                    }
183
184
                    @Override
185
                    public String getDescription() {
186
                        return filterDescription;
187
                    }
188
                });
189
                chooser.setApproveButtonText(Bundle.TXT_Select());
190
                chooser.setApproveButtonMnemonic(Bundle.MNE_Select().charAt(0));
191
                if (currentFolder[0] != null) {
192
                    chooser.setCurrentDirectory(currentFolder[0]);
193
                }
194
                if (chooser.showOpenDialog(null) == chooser.APPROVE_OPTION) {
195
                    currentFolder[0] = chooser.getCurrentDirectory();
196
                    final File[] files = chooser.getSelectedFiles();
197
                    final List<String> result = new ArrayList<String>(files.length);
198
                    for (File f : files) {
199
                        result.add(f.getAbsolutePath());
200
                    }
201
                    return result;
202
                }
203
                return null;
204
            }
205
        };
206
        return call;
207
    }
208
209
    public static Function<String,URI> createDefaultURIConvertor(final boolean forSources) {
210
        return new Function<String, URI>() {
211
            @Override
212
            public URI call(String param) throws Exception {
213
                final File f = new File (param);
214
                assert f.isAbsolute();
215
                FileObject fo = FileUtil.toFileObject(f);
216
                if (fo.isData()) {
217
                    fo = FileUtil.getArchiveRoot(fo);
218
                }
219
                FileObject root = forSources ?
220
                    JavadocAndSourceRootDetection.findSourceRoot(fo) :
221
                    JavadocAndSourceRootDetection.findJavadocRoot(fo);
222
                if (root == null) {
223
                    root = fo;
224
                }
225
                return root.getURL().toURI();
226
            }
227
        };
228
    }
229
230
    public static interface Function<P,R> {
231
        R call (P param) throws Exception;
232
    }
233
234
    @NonNull
235
    private static String getDisplayName(@NonNull final URL root) {
236
        final URL file;
237
        if (FileUtil.getArchiveFile(root) != null) {
238
            file = FileUtil.getArchiveFile(root);
239
        } else {
240
            file = root;
241
        }
242
        final FileObject fo = URLMapper.findFileObject(file);
243
        return fo != null ? fo.getNameExt() : file.getPath();
244
    }
245
}
(-)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 (+56 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="1" attributes="0">
20
              <EmptySpace max="-2" attributes="0"/>
21
              <Component id="jLabel1" pref="608" max="32767" attributes="0"/>
22
              <EmptySpace min="-2" pref="22" max="-2" attributes="0"/>
23
              <Component id="jButton1" min="-2" max="-2" attributes="0"/>
24
              <EmptySpace max="-2" attributes="0"/>
25
          </Group>
26
      </Group>
27
    </DimensionLayout>
28
    <DimensionLayout dim="1">
29
      <Group type="103" groupAlignment="0" attributes="0">
30
          <Group type="103" alignment="0" groupAlignment="3" attributes="0">
31
              <Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
32
              <Component id="jButton1" alignment="3" min="-2" pref="25" max="-2" attributes="0"/>
33
          </Group>
34
      </Group>
35
    </DimensionLayout>
36
  </Layout>
37
  <SubComponents>
38
    <Component class="javax.swing.JLabel" name="jLabel1">
39
      <Properties>
40
        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
41
          <ResourceString bundle="org/netbeans/modules/java/classfile/Bundle.properties" key="AttachSourcePanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
42
        </Property>
43
      </Properties>
44
    </Component>
45
    <Component class="javax.swing.JButton" name="jButton1">
46
      <Properties>
47
        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
48
          <ResourceString bundle="org/netbeans/modules/java/classfile/Bundle.properties" key="AttachSourcePanel.jButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
49
        </Property>
50
      </Properties>
51
      <Events>
52
        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="attachSources"/>
53
      </Events>
54
    </Component>
55
  </SubComponents>
56
</Form>
(-)a/java.source/src/org/netbeans/modules/java/classfile/AttachSourcePanel.java (+170 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.java.classfile;
40
41
import java.net.URL;
42
import javax.swing.SwingUtilities;
43
import org.netbeans.api.actions.Openable;
44
import org.netbeans.api.annotations.common.NonNull;
45
import org.netbeans.api.java.classpath.ClassPath;
46
import org.netbeans.api.java.queries.SourceForBinaryQuery;
47
import org.netbeans.api.java.queries.SourceJavadocAttacher;
48
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
49
import org.openide.cookies.EditorCookie;
50
import org.openide.filesystems.FileObject;
51
import org.openide.filesystems.URLMapper;
52
import org.openide.loaders.DataObject;
53
import org.openide.loaders.DataObjectNotFoundException;
54
import org.openide.util.Exceptions;
55
import org.openide.util.RequestProcessor;
56
57
58
public class AttachSourcePanel extends javax.swing.JPanel {
59
60
    private final URL root;
61
    private final URL file;
62
    private final String binaryName;
63
64
    public AttachSourcePanel(
65
            @NonNull final URL root,
66
            @NonNull final URL file,
67
            @NonNull final String binaryName) {
68
        assert root != null;
69
        assert file != null;
70
        assert binaryName != null;
71
        this.root = root;
72
        this.file = file;
73
        this.binaryName = binaryName;
74
        initComponents();
75
    }
76
77
    /** This method is called from within the constructor to
78
     * initialize the form.
79
     * WARNING: Do NOT modify this code. The content of this method is
80
     * always regenerated by the Form Editor.
81
     */
82
    @SuppressWarnings("unchecked")
83
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
84
    private void initComponents() {
85
86
        jLabel1 = new javax.swing.JLabel();
87
        jButton1 = new javax.swing.JButton();
88
89
        jLabel1.setText(org.openide.util.NbBundle.getMessage(AttachSourcePanel.class, "AttachSourcePanel.jLabel1.text")); // NOI18N
90
91
        jButton1.setText(org.openide.util.NbBundle.getMessage(AttachSourcePanel.class, "AttachSourcePanel.jButton1.text")); // NOI18N
92
        jButton1.addActionListener(new java.awt.event.ActionListener() {
93
            public void actionPerformed(java.awt.event.ActionEvent evt) {
94
                attachSources(evt);
95
            }
96
        });
97
98
        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
99
        this.setLayout(layout);
100
        layout.setHorizontalGroup(
101
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
102
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
103
                .addContainerGap()
104
                .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 608, Short.MAX_VALUE)
105
                .addGap(22, 22, 22)
106
                .addComponent(jButton1)
107
                .addContainerGap())
108
        );
109
        layout.setVerticalGroup(
110
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
111
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
112
                .addComponent(jLabel1)
113
                .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE))
114
        );
115
    }// </editor-fold>//GEN-END:initComponents
116
117
private void attachSources(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_attachSources
118
        jButton1.setEnabled(false);
119
        SourceJavadocAttacher.attachSources(root, new SourceJavadocAttacher.AttachmentListener() {
120
            @Override
121
            public void attachmentSucceeded() {
122
                boolean success = false;
123
                final FileObject rootFo = URLMapper.findFileObject(root);
124
                final FileObject fileFo = URLMapper.findFileObject(file);
125
                if (rootFo != null && fileFo != null) {
126
                    final FileObject[] fos = SourceForBinaryQuery.findSourceRoots(root).getRoots();
127
                    if (fos.length > 0) {
128
                        final ClassPath cp = ClassPathSupport.createClassPath(fos);
129
                        final FileObject newFileFo = cp.findResource(binaryName + ".java"); //NOI18N
130
                        if (newFileFo != null) {
131
                            try {
132
                                final EditorCookie ec = DataObject.find(fileFo).getLookup().lookup(EditorCookie.class);
133
                                final Openable open = DataObject.find(newFileFo).getLookup().lookup(Openable.class);
134
                                if (ec != null && open != null) {
135
                                    ec.close();
136
                                    open.open();
137
                                    success = true;
138
                                }
139
                            } catch (DataObjectNotFoundException ex) {
140
                                Exceptions.printStackTrace(ex);
141
                            }
142
                        }
143
                    }
144
                }
145
                if (!success) {
146
                    enableAttach();
147
                }
148
            }
149
150
            @Override
151
            public void attachmentFailed() {
152
                enableAttach();
153
            }
154
155
            private void enableAttach() {
156
                SwingUtilities.invokeLater(new Runnable() {
157
                    @Override
158
                    public void run() {
159
                        jButton1.setEnabled(true);
160
                    }
161
                });
162
            }
163
        });
164
}//GEN-LAST:event_attachSources
165
166
    // Variables declaration - do not modify//GEN-BEGIN:variables
167
    private javax.swing.JButton jButton1;
168
    private javax.swing.JLabel jLabel1;
169
    // End of variables declaration//GEN-END:variables
170
}
(-)a/java.source/src/org/netbeans/modules/java/classfile/Bundle.properties (+2 lines)
Line 0 Link Here
1
AttachSourcePanel.jLabel1.text=Showing generated source file. No sources are attached to class' JAR file.
2
AttachSourcePanel.jButton1.text=Attach Sources...
(-)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 there is no associated Javadoc with the JAR file containing this item:{1}<p/>\
58
 <a href="associate-javadoc:{0}">Associate Javadoc...</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), null);
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 (+148 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 java.util.concurrent.Callable;
47
import java.util.concurrent.CancellationException;
48
import java.util.concurrent.ExecutionException;
49
import java.util.concurrent.Future;
50
import java.util.concurrent.TimeUnit;
51
import java.util.concurrent.TimeoutException;
52
import java.util.concurrent.atomic.AtomicReference;
53
import org.apache.maven.artifact.Artifact;
54
import org.apache.maven.artifact.repository.ArtifactRepository;
55
import org.apache.maven.artifact.resolver.AbstractArtifactResolutionException;
56
import org.netbeans.api.annotations.common.NonNull;
57
import org.netbeans.api.annotations.common.NullAllowed;
58
import org.netbeans.api.java.queries.SourceJavadocAttacher.AttachmentListener;
59
import org.netbeans.api.progress.aggregate.AggregateProgressFactory;
60
import org.netbeans.api.progress.aggregate.AggregateProgressHandle;
61
import org.netbeans.api.progress.aggregate.ProgressContributor;
62
import org.netbeans.modules.maven.embedder.EmbedderFactory;
63
import org.netbeans.modules.maven.embedder.MavenEmbedder;
64
import org.netbeans.modules.maven.embedder.exec.ProgressTransferListener;
65
import org.netbeans.modules.maven.indexer.api.RepositoryInfo;
66
import org.netbeans.modules.maven.indexer.api.RepositoryPreferences;
67
import org.netbeans.spi.java.queries.SourceJavadocAttacherImplementation;
68
import org.openide.filesystems.FileUtil;
69
import org.openide.util.NbBundle.Messages;
70
import org.openide.util.RequestProcessor;
71
import org.openide.util.lookup.ServiceProvider;
72
73
@ServiceProvider(service=SourceJavadocAttacherImplementation.class, position=200)
74
public class MavenSourceJavadocAttacher implements SourceJavadocAttacherImplementation {
75
76
    private static final RequestProcessor RP =
77
            new RequestProcessor(MavenSourceJavadocAttacher.class);
78
79
    @Override public boolean attachSources(
80
            @NonNull final URL root,
81
            @NullAllowed final AttachmentListener listener) throws IOException {
82
        return attach(root, listener, false);
83
    }
84
85
    @Override public boolean attachJavadoc(
86
            @NonNull final URL root,
87
            @NullAllowed final AttachmentListener listener) throws IOException {
88
        return attach(root, listener, true);
89
    }
90
91
    @Messages({"# {0} - artifact ID", "attaching=Attaching {0}"})
92
    private boolean attach(
93
        @NonNull final URL root,
94
        @NullAllowed final AttachmentListener listener,
95
        final boolean javadoc) throws IOException {
96
        final File file = FileUtil.archiveOrDirForURL(root);
97
        if (file == null) {
98
            return false;
99
        }
100
        final String[] coordinates = MavenFileOwnerQueryImpl.findCoordinates(file);
101
        if (coordinates == null) {
102
            return false;
103
        }
104
        final Runnable call = new Runnable() {
105
            @Override
106
            public void run() {
107
                boolean attached = false;
108
                try {
109
                    MavenEmbedder online = EmbedderFactory.getOnlineEmbedder();
110
                    Artifact art = online.createArtifactWithClassifier(coordinates[0], coordinates[1], coordinates[2], "jar", javadoc ? "javadoc" : "sources");
111
                    AggregateProgressHandle hndl = AggregateProgressFactory.createHandle(Bundle.attaching(art.getId()),
112
                        new ProgressContributor[] {AggregateProgressFactory.createProgressContributor("attach")},
113
                        ProgressTransferListener.cancellable(), null);
114
                    ProgressTransferListener.setAggregateHandle(hndl);
115
                    try {
116
                        hndl.start();
117
                        List<ArtifactRepository> repos = new ArrayList<ArtifactRepository>();
118
                        // XXX is there some way to determine from local metadata which remote repo it is from? (i.e. API to read _maven.repositories)
119
                        for (RepositoryInfo info : RepositoryPreferences.getInstance().getRepositoryInfos()) {
120
                            if (info.isRemoteDownloadable()) {
121
                                repos.add(EmbedderFactory.createRemoteRepository(online, info.getRepositoryUrl(), info.getId()));
122
                            }
123
                        }
124
                        online.resolve(art, repos, online.getLocalRepository());
125
                        if (art.getFile().isFile()) {
126
                            attached = true;
127
                        }
128
                    } catch (ThreadDeath d) {
129
                    } catch (AbstractArtifactResolutionException x) {
130
                    } finally {
131
                        hndl.finish();
132
                        ProgressTransferListener.clearAggregateHandle();
133
                    }
134
                } finally {
135
                    if (listener != null) {
136
                        if (attached) {
137
                            listener.attachmentSucceeded();
138
                        } else {
139
                            listener.attachmentFailed();
140
                        }
141
                    }
142
                }
143
            }
144
        };
145
        RP.post(call);
146
        return true;
147
    }
148
}
(-)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