diff -r ffef4cca2ff4 java.project/apichanges.xml --- a/java.project/apichanges.xml Tue Jan 22 05:32:07 2008 +0000 +++ b/java.project/apichanges.xml Thu Feb 21 14:36:40 2008 +0100 @@ -40,8 +40,8 @@ Version 2 license, then the option applies only if the new code is made subject to such option by the copyright holder. --> - - + + + + + Support for project-specific libraries + + + + + +

A new utility class for helping project types create UI for + sharable Libraries. +

+

An additional protected method for use in ProjectClassPathModifierImplementation subclasses named + performSharabilityHeuristics(URL,AntProjectHelper) that takes classpath roots and tries to find the best way to reference that jar/folder. +

+ +
+ + + +
+ + + Added support classes for attaching javadoc/source to jar-based classpath items + + + + + + 3 new utility classes to allow attaching javadoc/source to existing jar dependencies of an Ant-based project. + These classes are for use by project type owners. Specifically +
    +
  • ExtraSourceJavadocSupport.createExtraSourceQueryImplementation() and + ExtraSourceJavadocSupport.createExtraJavadocQueryImplementation() + create instances to be added to project's Lookup.
  • +
  • LookupMergerSupport.createSFBLookupMerger() and LookupMergerSupport.createJFBLookupMerger() + provide simple implementations of lookup mergers for respective query implementations. + A typical project implementation will put the lookup merger and the Extra*Support's instance in the project's lookup.
  • +
  • EditJarSupport.showEditDialog() is a facotry method for creating editing UI. To be added to Project's properties dialog + preferably the "Libraries" panel. Client code (project type owner) is assumed to write down the ant properties + source.reference.__name__ and javadoc.reference.__name__ in the same manner as file.reference.__name__ is persisted.
  • +
+
+ + + + +
+ Added IncludeExcludeVisualizer support class diff -r ffef4cca2ff4 java.project/src/org/netbeans/api/java/project/classpath/ProjectClassPathModifier.java --- a/java.project/src/org/netbeans/api/java/project/classpath/ProjectClassPathModifier.java Tue Jan 22 05:32:07 2008 +0000 +++ b/java.project/src/org/netbeans/api/java/project/classpath/ProjectClassPathModifier.java Thu Feb 21 14:36:40 2008 +0100 @@ -41,6 +41,7 @@ package org.netbeans.api.java.project.classpath; +import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URL; @@ -52,6 +53,8 @@ import org.netbeans.api.project.libraries.Library; import org.netbeans.modules.java.project.classpath.ProjectClassPathModifierAccessor; import org.netbeans.spi.java.project.classpath.ProjectClassPathModifierImplementation; +import org.netbeans.spi.project.libraries.support.LibrariesSupport; +import org.netbeans.spi.project.support.ant.PropertyUtils; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; import org.openide.filesystems.URLMapper; @@ -129,7 +132,7 @@ /** * Adds archive files or folders into the project's classpath if the * entries are not already there. - * @param classPathRoots roots to be added, each root has to be either a root of an archive or a folder + * @param classPathRoots roots to be added, each root has to be either a root of an archive or a folder url can be absolute or relative * @param projectArtifact a file whose classpath should be extended * @param classPathType the type of classpath to be extended, @see ClassPath * @return true in case the classpath was changed, (at least one classpath root was added to the classpath), @@ -149,12 +152,20 @@ } else if (extensible.pcpe != null) { boolean result = false; + final Project project = FileOwnerQuery.getOwner(projectArtifact); + final File projectFolderFile = FileUtil.toFile(project.getProjectDirectory()); for (int i=0; i< classPathRoots.length; i++) { URL urlToAdd = classPathRoots[i]; if ("jar".equals(urlToAdd.getProtocol())) { urlToAdd = FileUtil.getArchiveFile (urlToAdd); } - final FileObject fo = URLMapper.findFileObject(urlToAdd); + final FileObject fo; + if (LibrariesSupport.isAbsoluteURL(urlToAdd)) { + fo = URLMapper.findFileObject(urlToAdd); + } else { + File f = PropertyUtils.resolveFile(projectFolderFile, LibrariesSupport.convertURLToFilePath(urlToAdd)); + fo = FileUtil.toFileObject(f); + } if (fo == null) { throw new UnsupportedOperationException ("Adding of a non existent root is not supported by project."); //NOI18N } @@ -251,7 +262,7 @@ throw new UnsupportedOperationException (); } - + /** * Returns {@link ProjectClassPathModifier#Extensible} for given project artifact and classpath type. * An Extensible implies a classpath to be extended. Different project type may provide different types diff -r ffef4cca2ff4 java.project/src/org/netbeans/spi/java/project/classpath/ProjectClassPathModifierImplementation.java --- a/java.project/src/org/netbeans/spi/java/project/classpath/ProjectClassPathModifierImplementation.java Tue Jan 22 05:32:07 2008 +0000 +++ b/java.project/src/org/netbeans/spi/java/project/classpath/ProjectClassPathModifierImplementation.java Thu Feb 21 14:36:40 2008 +0100 @@ -41,14 +41,21 @@ package org.netbeans.spi.java.project.classpath; +import java.io.File; import java.io.IOException; import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; import org.netbeans.api.project.SourceGroup; import org.netbeans.api.project.ant.AntArtifact; import org.netbeans.api.project.libraries.Library; +import org.netbeans.api.queries.CollocationQuery; import org.netbeans.modules.java.project.classpath.ProjectClassPathModifierAccessor; +import org.netbeans.spi.project.libraries.support.LibrariesSupport; +import org.netbeans.spi.project.support.ant.AntProjectHelper; +import org.netbeans.spi.project.support.ant.PropertyUtils; import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; /** * An SPI for project's classpaths modification. @@ -184,7 +191,94 @@ * removing of an artifact from the classpath of the given type. */ protected abstract boolean removeAntArtifacts (AntArtifact[] artifacts, URI[] artifactElements, SourceGroup sourceGroup, String type) throws IOException, UnsupportedOperationException; - + + /** + * Takes a classpath root and tries to figure the best way to reference that file for that particular project. + * The possible actions include relativization of path, copying to sharable libraries folder etc. + * @param classpathRoot passed in through the addRoots() and removeRoots() methods + * @param helper + * @return a relative or absolute path to the original jar/folder or to a copy of it. + * @throws java.net.URISyntaxException + * @since org.netbeans.modules.java.project/1 1.15 + */ + protected final String performSharabilityHeuristics(URL classpathRoot, AntProjectHelper helper) throws URISyntaxException, IOException { + assert classpathRoot != null; + assert classpathRoot.toExternalForm().endsWith("/"); //NOI18N + URL toAdd = FileUtil.getArchiveFile(classpathRoot); + if (toAdd == null) { + toAdd = classpathRoot; + } + File prjRoot = FileUtil.toFile(helper.getProjectDirectory()); + assert LibrariesSupport.isAbsoluteURL(toAdd); + final File file = new File(toAdd.toURI()); + String f; + if (CollocationQuery.areCollocated(file, prjRoot)) { + //colocated get always relative path + f = PropertyUtils.relativizeFile(prjRoot, file); + } else { + if (helper.isSharableProject()) { + //library location is not collocated.. + //-> use absolute path + // sort of heuristics to have the + File library = PropertyUtils.resolveFile(prjRoot, helper.getLibrariesLocation()); + boolean fileLibraryCol = CollocationQuery.areCollocated(library.getParentFile(), file); + boolean libraryAbsolute = LibrariesSupport.isAbsoluteURL(LibrariesSupport.convertFilePathToURL(helper.getLibrariesLocation())); + // when library location is absolute, we are most probably dealing with the famous X: drive location + // since the library is absolute, it shoudl be safe to reference everything under it as absolute as well. + if (libraryAbsolute && fileLibraryCol) { + f = file.getAbsolutePath(); + } else if (libraryAbsolute && !fileLibraryCol) { + File fl = copyFile(file, FileUtil.toFileObject(library.getParentFile())); + f = fl.getAbsolutePath(); + } else if (!libraryAbsolute && fileLibraryCol) { + f = PropertyUtils.relativizeFile(prjRoot, file); + } else { // if (!libraryAbsolute && !fileLibraryCol) + File fl = copyFile(file, FileUtil.toFileObject(library.getParentFile())); + f = PropertyUtils.relativizeFile(prjRoot, fl); + } + } else { + //nonsharable project are ok with absolute path + f = file.getAbsolutePath(); + } + } + return f; + } + + private File copyFile(File file, FileObject newRoot) throws IOException { + FileObject fo = FileUtil.toFileObject(file); + if (fo.isFolder()) { + return FileUtil.toFile(copyFolderRecursively(fo, newRoot)); + } else { + FileObject foExists = newRoot.getFileObject(fo.getName(), fo.getExt()); + if (foExists != null) { + foExists.delete(); + } + return FileUtil.toFile(FileUtil.copyFile(fo, newRoot, fo.getName(), fo.getExt())); + } + } + + + //copied from FileChooserAccessory + private FileObject copyFolderRecursively(FileObject sourceFolder, FileObject destination) throws IOException { + assert sourceFolder.isFolder() : sourceFolder; + assert destination.isFolder() : destination; + FileObject destinationSubFolder = destination.getFileObject(sourceFolder.getName()); + if (destinationSubFolder == null) { + destinationSubFolder = destination.createFolder(sourceFolder.getName()); + } + for (FileObject fo : sourceFolder.getChildren()) { + if (fo.isFolder()) { + copyFolderRecursively(fo, destinationSubFolder); + } else { + FileObject foExists = destinationSubFolder.getFileObject(fo.getName(), fo.getExt()); + if (foExists != null) { + foExists.delete(); + } + FileUtil.copyFile(fo, destinationSubFolder, fo.getName(), fo.getExt()); + } + } + return destinationSubFolder; + } private static class Accessor extends ProjectClassPathModifierAccessor { diff -r ffef4cca2ff4 java.project/src/org/netbeans/spi/java/project/support/ExtraSourceJavadocSupport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.project/src/org/netbeans/spi/java/project/support/ExtraSourceJavadocSupport.java Thu Feb 21 14:36:40 2008 +0100 @@ -0,0 +1,88 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2008 Sun Microsystems, Inc. + */ + +package org.netbeans.spi.java.project.support; + +import org.netbeans.api.project.Project; +import org.netbeans.modules.java.project.ExtraProjectSourceForBinaryQueryImpl; +import org.netbeans.modules.java.project.ExtraProjectJavadocForBinaryQueryImpl; +import org.netbeans.spi.java.queries.JavadocForBinaryQueryImplementation; +import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation; +import org.netbeans.spi.project.support.ant.AntProjectHelper; +import org.netbeans.spi.project.support.ant.PropertyEvaluator; + +/** + * Utility factory class for ant-based project implementors, the created instances, once + * put into project's lookup, make sure the javadoc and source references in project properties + * are correctly recognized and used by the java infrastructure. + * The format of project properties used is as follows: + *
    + *
  • file.reference.__jarName__ - the binary file reference used to point to files on project classpath.
  • + *
  • javadoc.reference.__jarName__ - the file reference pointing to javadoc for file.reference.__jarName__
  • + *
  • source.reference.__jarName__ - the file reference pointing to sources for file.reference.__jarName__
  • + *
+ * @author mkleint + * @since org.netbeans.modules.java.project 1.14 + */ +public class ExtraSourceJavadocSupport { + + /** + * Create project's SourceForBinaryQueryImplementation object for handling + * property based sources + * @param helper project's AntProjectHelper instance + * @param eval project's PropertyEvaluator instance + * @return object to use in project's lookup. + */ + public static SourceForBinaryQueryImplementation createExtraSourceQueryImplementation (Project project, AntProjectHelper helper, PropertyEvaluator eval) { + return new ExtraProjectSourceForBinaryQueryImpl(project, helper, eval); + } + + /** + * Create project's JavadocForBinaryQueryImplementation object for handling + * property based javadoc + * @param helper project's AntProjectHelper instance + * @param eval project's PropertyEvaluator instance + * @return object to use in project's lookup. + */ + public static JavadocForBinaryQueryImplementation createExtraJavadocQueryImplementation (Project project, AntProjectHelper helper, PropertyEvaluator eval) { + return new ExtraProjectJavadocForBinaryQueryImpl(project, helper, eval); + } + + +} diff -r ffef4cca2ff4 java.project/src/org/netbeans/spi/java/project/support/LookupMergerSupport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.project/src/org/netbeans/spi/java/project/support/LookupMergerSupport.java Thu Feb 21 14:36:40 2008 +0100 @@ -0,0 +1,142 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2008 Sun Microsystems, Inc. + */ + +package org.netbeans.spi.java.project.support; + +import java.net.URL; +import java.util.Collection; +import org.netbeans.api.java.queries.JavadocForBinaryQuery; +import org.netbeans.api.java.queries.SourceForBinaryQuery; +import org.netbeans.spi.java.queries.JavadocForBinaryQueryImplementation; +import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation; +import org.netbeans.spi.project.LookupMerger; +import org.openide.util.Lookup; + + +/** + * Factory class for creation of {@link org.netbeans.spi.project.LookupMerger} instances. + * @author mkleint + * @since org.netbeans.modules.java.project 1.14 + */ +public final class LookupMergerSupport { + + /** + * Create a simple instance of LookupMerger for SourceForBinaryQueryImplementation. It takes + * all implemntations it finds inthe provided lookup and iterates them until a result + * is found. + * @return + */ + public static LookupMerger createSFBLookupMerger() { + return new SFBLookupMerger(); + } + + /** + * Create a simple instance of LookupMerger for JavadocForBinaryQueryImplementation. It takes + * all implemntations it finds inthe provided lookup and iterates them until a result + * is found. + * @return + */ + public static LookupMerger createJFBLookupMerger() { + return new JFBLookupMerger(); + } + + private static class SFBLookupMerger implements LookupMerger { + + public Class getMergeableClass() { + return SourceForBinaryQueryImplementation.class; + } + + public SourceForBinaryQueryImplementation merge(Lookup lookup) { + return new SFBIMerged(lookup); + } + + } + + private static class SFBIMerged implements SourceForBinaryQueryImplementation { + private Lookup lookup; + + public SFBIMerged(Lookup lkp) { + lookup = lkp; + } + public SourceForBinaryQuery.Result findSourceRoots(URL binaryRoot) { + Collection col = lookup.lookupAll(SourceForBinaryQueryImplementation.class); + for (SourceForBinaryQueryImplementation impl : col) { + SourceForBinaryQuery.Result res = impl.findSourceRoots(binaryRoot); + if (res != null) { + return res; + } + } + return null; + } + + } + + private static class JFBLookupMerger implements LookupMerger { + + public Class getMergeableClass() { + return JavadocForBinaryQueryImplementation.class; + } + + public JavadocForBinaryQueryImplementation merge(Lookup lookup) { + return new JFBIMerged(lookup); + } + + } + + private static class JFBIMerged implements JavadocForBinaryQueryImplementation { + private Lookup lookup; + + public JFBIMerged(Lookup lkp) { + lookup = lkp; + } + + public JavadocForBinaryQuery.Result findJavadoc(URL binaryRoot) { + Collection col = lookup.lookupAll(JavadocForBinaryQueryImplementation.class); + for (JavadocForBinaryQueryImplementation impl : col) { + JavadocForBinaryQuery.Result res = impl.findJavadoc(binaryRoot); + if (res != null) { + return res; + } + } + return null; + } + + } + +} diff -r ffef4cca2ff4 java.project/src/org/netbeans/spi/java/project/support/ui/BrokenReferencesSupport.java --- a/java.project/src/org/netbeans/spi/java/project/support/ui/BrokenReferencesSupport.java Tue Jan 22 05:32:07 2008 +0000 +++ b/java.project/src/org/netbeans/spi/java/project/support/ui/BrokenReferencesSupport.java Thu Feb 21 14:36:41 2008 +0100 @@ -107,7 +107,7 @@ */ public static boolean isBroken(AntProjectHelper projectHelper, ReferenceHelper referenceHelper, String[] properties, String[] platformProperties) { - return BrokenReferencesModel.isBroken(projectHelper, + return BrokenReferencesModel.isBroken(projectHelper, referenceHelper, projectHelper.getStandardPropertyEvaluator(), properties, platformProperties); } diff -r ffef4cca2ff4 java.project/src/org/netbeans/spi/java/project/support/ui/EditJarPanel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.project/src/org/netbeans/spi/java/project/support/ui/EditJarPanel.java Thu Feb 21 14:36:41 2008 +0100 @@ -0,0 +1,282 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2008 Sun Microsystems, Inc. + */ + +package org.netbeans.spi.java.project.support.ui; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import javax.swing.JFileChooser; +import javax.swing.SwingUtilities; +import javax.swing.filechooser.FileFilter; +import org.netbeans.api.project.ant.FileChooser; +import org.netbeans.spi.java.project.support.ui.EditJarSupport; +import org.netbeans.spi.project.support.ant.AntProjectHelper; +import org.openide.filesystems.FileUtil; +import org.openide.util.Exceptions; +import org.openide.util.NbBundle; + +/** + * + * @author mkleint + */ +class EditJarPanel extends javax.swing.JPanel { + + private EditJarSupport.Item item; + private AntProjectHelper helper; + + /** Creates new form EditJarPanel */ + private EditJarPanel() { + initComponents(); + } + + EditJarPanel(EditJarSupport.Item item, AntProjectHelper helper) { + this(); + this.item = item; + this.helper = helper; + txtJar.setText(item.getJarFile()); + if (item.getSourceFile() != null) { + txtSource.setText(item.getSourceFile()); + } + if (item.getJavadocFile() != null) { + txtJavadoc.setText(item.getJavadocFile()); + } + } + + EditJarSupport.Item assignValues() { + if (txtSource.getText() != null && txtSource.getText().trim().length() > 0) { + item.setSourceFile(txtSource.getText().trim()); + } else { + item.setSourceFile(null); + } + if (txtJavadoc.getText() != null && txtJavadoc.getText().trim().length() > 0) { + item.setJavadocFile(txtJavadoc.getText().trim()); + } else { + item.setJavadocFile(null); + } + return item; + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + lblJar = new javax.swing.JLabel(); + txtJar = new javax.swing.JTextField(); + lblJavadoc = new javax.swing.JLabel(); + txtJavadoc = new javax.swing.JTextField(); + btnJavadoc = new javax.swing.JButton(); + lblSource = new javax.swing.JLabel(); + txtSource = new javax.swing.JTextField(); + btnSource = new javax.swing.JButton(); + + lblJar.setLabelFor(txtJar); + org.openide.awt.Mnemonics.setLocalizedText(lblJar, org.openide.util.NbBundle.getMessage(EditJarPanel.class, "EditJarPanel.lblJar.text")); // NOI18N + + txtJar.setEditable(false); + + lblJavadoc.setLabelFor(txtJavadoc); + org.openide.awt.Mnemonics.setLocalizedText(lblJavadoc, org.openide.util.NbBundle.getMessage(EditJarPanel.class, "EditJarPanel.lblJavadoc.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(btnJavadoc, org.openide.util.NbBundle.getMessage(EditJarPanel.class, "EditJarPanel.btnJavadoc.text")); // NOI18N + btnJavadoc.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnJavadocActionPerformed(evt); + } + }); + + lblSource.setLabelFor(txtSource); + org.openide.awt.Mnemonics.setLocalizedText(lblSource, org.openide.util.NbBundle.getMessage(EditJarPanel.class, "EditJarPanel.lblSource.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(btnSource, org.openide.util.NbBundle.getMessage(EditJarPanel.class, "EditJarPanel.btnSource.text")); // NOI18N + btnSource.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnSourceActionPerformed(evt); + } + }); + + org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(layout.createSequentialGroup() + .addContainerGap() + .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(lblJar) + .add(lblJavadoc) + .add(lblSource)) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(layout.createSequentialGroup() + .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(txtSource, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 320, Short.MAX_VALUE) + .add(txtJavadoc, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 320, Short.MAX_VALUE)) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(btnSource) + .add(btnJavadoc))) + .add(txtJar, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 425, Short.MAX_VALUE)) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(layout.createSequentialGroup() + .addContainerGap() + .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) + .add(lblJar) + .add(txtJar, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) + .add(18, 18, 18) + .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) + .add(lblJavadoc) + .add(btnJavadoc) + .add(txtJavadoc, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) + .add(lblSource) + .add(btnSource) + .add(txtSource, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + lblJavadoc.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(EditJarPanel.class, "ACSD_lblJavadoc")); // NOI18N + btnJavadoc.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(EditJarPanel.class, "ACSD_btnJavadoc")); // NOI18N + lblSource.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(EditJarPanel.class, "ACSD_lblSource")); // NOI18N + btnSource.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(EditJarPanel.class, "ACSD_btnSource")); // NOI18N + }// //GEN-END:initComponents + private void btnJavadocActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnJavadocActionPerformed + // Let user search for the Jar file + FileChooser chooser = new FileChooser(helper, true); + FileUtil.preventFileChooserSymlinkTraversal(chooser, null); + chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + chooser.setMultiSelectionEnabled(false); + chooser.setDialogTitle(NbBundle.getMessage(EditJarPanel.class, "LBL_Edit_Jar_Panel_browse")); + //#61789 on old macosx (jdk 1.4.1) these two method need to be called in this order. + chooser.setAcceptAllFileFilterUsed(false); + chooser.setFileFilter(new SimpleFileFilter( + "Javadoc Entry (folder, ZIP or JAR file)", + new String[]{"ZIP", "JAR"})); // NOI18N + File curDir = helper.resolveFile(item.getJarFile()); + chooser.setCurrentDirectory(curDir); + int option = chooser.showOpenDialog(SwingUtilities.getWindowAncestor(this)); // Sow the chooser + + if (option == JFileChooser.APPROVE_OPTION) { + String files[]; + try { + files = chooser.getSelectedPaths(); + } catch (IOException ex) { + // TODO: add localized message + Exceptions.printStackTrace(ex); + return; + } + txtJavadoc.setText(files[0]); + } + + }//GEN-LAST:event_btnJavadocActionPerformed + + private void btnSourceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSourceActionPerformed + FileChooser chooser = new FileChooser(helper, true); + FileUtil.preventFileChooserSymlinkTraversal(chooser, null); + chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + chooser.setMultiSelectionEnabled(false); + chooser.setDialogTitle(NbBundle.getMessage(EditJarPanel.class, "LBL_Edit_Jar_Panel_browse")); + //#61789 on old macosx (jdk 1.4.1) these two method need to be called in this order. + chooser.setAcceptAllFileFilterUsed(false); + chooser.setFileFilter(new SimpleFileFilter( + "Source Entry (folder, ZIP or JAR file)", + new String[]{"ZIP", "JAR"})); // NOI18N + File curDir = helper.resolveFile(item.getJarFile()); + chooser.setCurrentDirectory(curDir); + int option = chooser.showOpenDialog(SwingUtilities.getWindowAncestor(this)); // Sow the chooser + + if (option == JFileChooser.APPROVE_OPTION) { + String files[]; + try { + files = chooser.getSelectedPaths(); + } catch (IOException ex) { + // TODO: add localized message + Exceptions.printStackTrace(ex); + return; + } + txtSource.setText(files[0]); + } + + }//GEN-LAST:event_btnSourceActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnJavadoc; + private javax.swing.JButton btnSource; + private javax.swing.JLabel lblJar; + private javax.swing.JLabel lblJavadoc; + private javax.swing.JLabel lblSource; + private javax.swing.JTextField txtJar; + private javax.swing.JTextField txtJavadoc; + private javax.swing.JTextField txtSource; + // End of variables declaration//GEN-END:variables + private static class SimpleFileFilter extends FileFilter { + + private String description; + private Collection extensions; + + public SimpleFileFilter(String description, String[] extensions) { + this.description = description; + this.extensions = Arrays.asList(extensions); + } + + public boolean accept(File f) { + if (f.isDirectory()) { + return true; + } + String name = f.getName(); + int index = name.lastIndexOf('.'); //NOI18N + if (index <= 0 || index == name.length() - 1) { + return false; + } + String extension = name.substring(index + 1).toUpperCase(); + return this.extensions.contains(extension); + } + + public String getDescription() { + return this.description; + } + } +} diff -r ffef4cca2ff4 java.project/src/org/netbeans/spi/java/project/support/ui/EditJarSupport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.project/src/org/netbeans/spi/java/project/support/ui/EditJarSupport.java Thu Feb 21 14:36:41 2008 +0100 @@ -0,0 +1,118 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2008 Sun Microsystems, Inc. + */ + +package org.netbeans.spi.java.project.support.ui; + +import org.netbeans.spi.project.support.ant.AntProjectHelper; +import org.openide.DialogDescriptor; +import org.openide.DialogDisplayer; + +/** + * Factory for creating a dialog for editing jar/folder-based classpath dependencies + * for Ant based projects. Allows to add/modify/remove source and javadoc jars. + * @author mkleint + * + * @since org.netbeans.modules.java.project 1.14 + */ +public final class EditJarSupport { + + /** + * Show dialog that allows to edit source and javadoc jar/folder locations + * for a given jar/folder on the classpath. Returns null when dialog was cancelled, + * otherwise returns EditJarSupport.Item bean with new values. + * + * @param helper + * @param item - bean with currently used values for classpath jar, source and javadoc jars location + * @return null if dialog cancelled, or the original item with modified values + */ + public static Item showEditDialog(AntProjectHelper helper, Item item) { + EditJarPanel panel = new EditJarPanel(item, helper); + DialogDescriptor dd = new DialogDescriptor(panel, "Edit jar reference"); + Object ret = DialogDisplayer.getDefault().notify(dd); + if (DialogDescriptor.OK_OPTION == ret) { + return panel.assignValues(); + } + return null; + } + + /** + * Simple object holding information used for passing information in and out of the + * EditJarSupport.showEditDialog method. + * + */ + public static final class Item { + private String jarFile; + private String sourceFile; + private String javadocFile; + + /** + * classpath file location, can be relative or absolute path (relative to project basedir) + */ + public String getJarFile() { + return jarFile; + } + + public void setJarFile(String jarFile) { + this.jarFile = jarFile; + } + + /** + * source file location, can be relative or absolute path (relative to project basedir) + */ + public String getSourceFile() { + return sourceFile; + } + + public void setSourceFile(String sourceFile) { + this.sourceFile = sourceFile; + } + + /** + * javadoc file location, can be relative or absolute path (relative to project basedir) + */ + public String getJavadocFile() { + return javadocFile; + } + + public void setJavadocFile(String javadocFile) { + this.javadocFile = javadocFile; + } + } + +} diff -r ffef4cca2ff4 java.project/src/org/netbeans/spi/java/project/support/ui/MakeSharableVisualPanel1.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.project/src/org/netbeans/spi/java/project/support/ui/MakeSharableVisualPanel1.java Thu Feb 21 14:36:41 2008 +0100 @@ -0,0 +1,218 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun + * Microsystems, Inc. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package org.netbeans.spi.java.project.support.ui; + +import java.io.File; +import javax.swing.JPanel; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import org.netbeans.api.queries.CollocationQuery; +import org.netbeans.spi.project.support.ant.AntProjectHelper; +import org.netbeans.spi.project.support.ant.PropertyUtils; +import org.openide.WizardDescriptor; +import org.openide.filesystems.FileUtil; +import org.openide.util.ChangeSupport; +import org.openide.util.NbBundle; + + +final class MakeSharableVisualPanel1 extends JPanel { + + private AntProjectHelper helper; + private ChangeSupport support; + private WizardDescriptor settings; + private DocumentListener docListener; + + /** Creates new form MakeSharableVisualPanel1 */ + public MakeSharableVisualPanel1(ChangeSupport supp) { + initComponents(); + this.support = supp; + docListener = new DocumentListener() { + public void insertUpdate(DocumentEvent e) { + support.fireChange(); + } + + public void removeUpdate(DocumentEvent e) { + support.fireChange(); + } + + public void changedUpdate(DocumentEvent e) { + support.fireChange(); + } + + }; + txtDefinition.getDocument().addDocumentListener(docListener); + } + + @Override + public String getName() { + return NbBundle.getMessage(MakeSharableVisualPanel1.class, "TIT_LibraryDefinitionSelection"); //NOI18N + } + + boolean isValidPanel() { + String location = getLibraryLocation(); + boolean wrong = false; + if (new File(location).isAbsolute()) { + settings.putProperty("WizardPanel_errorMessage", // NOI18N + org.openide.util.NbBundle.getMessage(MakeSharableVisualPanel1.class, "WARN_MakeSharable.absolutePath")); + wrong = true; + } else { + File projectLoc = helper.resolveFile(location); + File libLoc = PropertyUtils.resolveFile(projectLoc, location); + if (!CollocationQuery.areCollocated(projectLoc, libLoc)) { + settings.putProperty("WizardPanel_errorMessage", // NOI18N + org.openide.util.NbBundle.getMessage(MakeSharableVisualPanel1.class, "WARN_makeSharable.relativePath")); + wrong = true; + } + } + if (!wrong) { + settings.putProperty("WizardPanel_errorMessage", null);// NOI18N + } + + return true; + } + + private String getLibraryLocation() { + return txtDefinition.getText().trim(); + } + + private void setLibraryLocation(String loc) { + txtDefinition.setText(loc); + } + + void readSettings(WizardDescriptor wiz) { + settings = wiz; + String loc = (String) wiz.getProperty(SharableLibrariesUtils.PROP_LOCATION); + helper = (AntProjectHelper) wiz.getProperty(SharableLibrariesUtils.PROP_HELPER); + if (loc == null) { + loc = ".." + File.separator + "libraries"; //NOI18N + } else { + loc.substring(loc.length() - SharableLibrariesUtils.DEFAULT_LIBRARIES_FILENAME.length(), loc.length()); + } + setLibraryLocation(loc); + support.fireChange(); + } + + void storeSettings(WizardDescriptor wiz) { + String librariesDefinition = getLibraryLocation(); + if (librariesDefinition != null) { + if (!librariesDefinition.endsWith(File.separator)) { + librariesDefinition += File.separatorChar; + } + librariesDefinition += SharableLibrariesUtils.DEFAULT_LIBRARIES_FILENAME; + } + + wiz.putProperty(SharableLibrariesUtils.PROP_LOCATION, librariesDefinition); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + lblDefinition = new javax.swing.JLabel(); + txtDefinition = new javax.swing.JTextField(); + btnDefinition = new javax.swing.JButton(); + lblNote = new javax.swing.JLabel(); + + lblDefinition.setLabelFor(txtDefinition); + org.openide.awt.Mnemonics.setLocalizedText(lblDefinition, org.openide.util.NbBundle.getMessage(MakeSharableVisualPanel1.class, "MakeSharableVisualPanel1.lblDefinition.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(btnDefinition, org.openide.util.NbBundle.getMessage(MakeSharableVisualPanel1.class, "MakeSharableVisualPanel1.btnDefinition.text")); // NOI18N + btnDefinition.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnDefinitionActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(lblNote, org.openide.util.NbBundle.getMessage(MakeSharableVisualPanel1.class, "MakeSharableVisualPanel1.lblNote.text")); // NOI18N + lblNote.setVerticalAlignment(javax.swing.SwingConstants.TOP); + + org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(layout.createSequentialGroup() + .add(lblDefinition) + .add(10, 10, 10) + .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(lblNote, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 362, Short.MAX_VALUE) + .add(layout.createSequentialGroup() + .add(txtDefinition, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 257, Short.MAX_VALUE) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(btnDefinition)))) + ); + layout.setVerticalGroup( + layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(layout.createSequentialGroup() + .addContainerGap() + .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) + .add(btnDefinition) + .add(lblDefinition) + .add(txtDefinition, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(lblNote, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 129, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addContainerGap(116, Short.MAX_VALUE)) + ); + + lblDefinition.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(MakeSharableVisualPanel1.class, "ACSD_lblDefinition")); // NOI18N + btnDefinition.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(MakeSharableVisualPanel1.class, "ACSD_btnDefinition")); // NOI18N + }// //GEN-END:initComponents + +private void btnDefinitionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDefinitionActionPerformed + File f = FileUtil.toFile(helper.getProjectDirectory()); // NOI18N + String curr = SharableLibrariesUtils.browseForLibraryLocation(getLibraryLocation(), this, f); + if (curr != null) { + setLibraryLocation(curr); + } + +}//GEN-LAST:event_btnDefinitionActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnDefinition; + private javax.swing.JLabel lblDefinition; + private javax.swing.JLabel lblNote; + private javax.swing.JTextField txtDefinition; + // End of variables declaration//GEN-END:variables +} + diff -r ffef4cca2ff4 java.project/src/org/netbeans/spi/java/project/support/ui/MakeSharableVisualPanel2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.project/src/org/netbeans/spi/java/project/support/ui/MakeSharableVisualPanel2.java Thu Feb 21 14:36:41 2008 +0100 @@ -0,0 +1,471 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun + * Microsystems, Inc. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package org.netbeans.spi.java.project.support.ui; + +import java.awt.Component; +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; +import javax.swing.Action; +import javax.swing.DefaultCellEditor; +import javax.swing.DefaultComboBoxModel; +import javax.swing.DefaultListCellRenderer; +import javax.swing.JComboBox; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JTable; +import javax.swing.ListSelectionModel; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableColumn; +import org.netbeans.api.project.ant.AntArtifact; +import org.netbeans.api.project.libraries.Library; +import org.netbeans.api.project.libraries.LibraryManager; +import org.netbeans.api.queries.CollocationQuery; +import org.netbeans.spi.project.libraries.LibraryTypeProvider; +import org.netbeans.spi.project.libraries.support.LibrariesSupport; +import org.netbeans.spi.project.support.ant.AntProjectHelper; +import org.netbeans.spi.project.support.ant.ReferenceHelper; +import org.openide.WizardDescriptor; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.filesystems.URLMapper; +import org.openide.util.Exceptions; +import org.openide.util.NbBundle; + + +final class MakeSharableVisualPanel2 extends JPanel { + + DefaultTableModel model; + private String location = null; + AntProjectHelper helper; + private ReferenceHelper refhelper; + String ACTION_COPY = "copy"; //NOI18N + String ACTION_RELATIVE = "keep"; //NOI18N + String ACTION_ABSOLUTE = "abs"; //NOI18N + String ACTION_USE_LOCAL_LIBRARY = "use"; + String[] comboValues = new String[]{ + ACTION_COPY, ACTION_RELATIVE, ACTION_ABSOLUTE, ACTION_USE_LOCAL_LIBRARY + }; + String[] comboValuesJar = new String[]{ + ACTION_COPY, ACTION_RELATIVE, ACTION_ABSOLUTE + }; + + /** Creates new form MakeSharableVisualPanel2 */ + public MakeSharableVisualPanel2() { + initComponents(); + createTableDefinition(); + + } + + @Override + public String getName() { + return NbBundle.getMessage(MakeSharableVisualPanel2.class, "MakeSharablePanel2.LBL_Actions"); + } + + void readSettings(WizardDescriptor wiz) { + String loc = (String) wiz.getProperty(SharableLibrariesUtils.PROP_LOCATION); + helper = (AntProjectHelper) wiz.getProperty(SharableLibrariesUtils.PROP_HELPER); + refhelper = (ReferenceHelper) wiz.getProperty(SharableLibrariesUtils.PROP_REFERENCE_HELPER); + List libraries = (List) wiz.getProperty(SharableLibrariesUtils.PROP_LIBRARIES); + List jars = (List) wiz.getProperty(SharableLibrariesUtils.PROP_JAR_REFS); + if (!loc.equals(location)) { + location = loc; + populateTable(helper, libraries, jars); + populateDescriptionField(); + } + } + + void storeSettings(WizardDescriptor wiz) { + refhelper = (ReferenceHelper) wiz.getProperty(SharableLibrariesUtils.PROP_REFERENCE_HELPER); + helper = (AntProjectHelper) wiz.getProperty(SharableLibrariesUtils.PROP_HELPER); + + List actions = new ArrayList(); + for (int i = 0; i < model.getRowCount(); i++) { + Object item = model.getValueAt(i, 0); + String action = (String) model.getValueAt(i, 1); + if (item instanceof Library) { + Library lib = (Library) item; + if (ACTION_ABSOLUTE.equals(action)) { + actions.add(new SharableLibrariesUtils.KeepLibraryAtLocation(lib, false, helper)); + } else if (ACTION_RELATIVE.equals(action)) { + actions.add(new SharableLibrariesUtils.KeepLibraryAtLocation(lib, true, helper)); + } else if (ACTION_COPY.equals(action)) { + actions.add(new SharableLibrariesUtils.CopyLibraryJars(refhelper, lib)); + } else if (ACTION_USE_LOCAL_LIBRARY.equals(action)) { + //do nothing + } else { + assert false : "No handling defined for action: " + action; + } + } else if (item instanceof String) { + //file reference + String ref = (String) item; + if (ACTION_ABSOLUTE.equals(action)) { + actions.add(new SharableLibrariesUtils.KeepJarAtLocation(ref, false, helper, refhelper)); + } else if (ACTION_RELATIVE.equals(action)) { + actions.add(new SharableLibrariesUtils.KeepJarAtLocation(ref, true, helper, refhelper)); + } else if (ACTION_COPY.equals(action)) { + actions.add(new SharableLibrariesUtils.CopyJars(refhelper, helper, ref)); + } else { + assert false : "no handling defined for action: " + action; + } + } else if (item instanceof AntArtifact) { + //project dependency.. do we want to handle? proably not.. + } + } + wiz.putProperty(SharableLibrariesUtils.PROP_ACTIONS, actions); + + } + + private void createTableDefinition() { + model = new DefaultTableModel() { + + @Override + public boolean isCellEditable(int row, int col) { + return col == 1; + } + }; + model.addColumn("jar"); + model.addColumn("action"); + tblJars.setModel(model); + TableColumn col1 = tblJars.getColumn("jar"); + col1.setHeaderValue(NbBundle.getMessage(MakeSharableVisualPanel2.class, "tblJars.header1")); + col1.setResizable(true); + col1.setCellRenderer(new DefaultTableCellRenderer() { + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + String text = ""; + if (value instanceof Library) { + Library lib = (Library) value; + text = lib.getDisplayName(); + } else if (value instanceof String) { + String v = helper.getStandardPropertyEvaluator().evaluate((String) value); + File absFile = helper.resolveFile(v); + text = absFile.getAbsolutePath(); + } + + return super.getTableCellRendererComponent(table, text, isSelected, hasFocus, row, column); + } + }); + TableColumn col2 = tblJars.getColumn("action"); + col2.setHeaderValue(NbBundle.getMessage(MakeSharableVisualPanel2.class, "tblJars.header2")); + col2.sizeWidthToFit(); + + JComboBox editorBox = new JComboBox(comboValues); + editorBox.setEditable(false); + DefaultCellEditor ed = new MyCellEditor(editorBox); + col2.setCellEditor(ed); + col2.setCellRenderer(new DefaultTableCellRenderer() { + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + String val = (String) value; + if (table.getValueAt(row, 0) instanceof Library) { + if (ACTION_ABSOLUTE.equals(val)) { + val = NbBundle.getMessage(MakeSharableVisualPanel2.class, "TXT_Absolute"); + } else if (ACTION_COPY.equals(val)) { + val = NbBundle.getMessage(MakeSharableVisualPanel2.class, "TXT_Copy"); + } else if (ACTION_RELATIVE.equals(val)) { + val = NbBundle.getMessage(MakeSharableVisualPanel2.class, "TXT_Keep"); + } else if (ACTION_USE_LOCAL_LIBRARY.equals(val)) { + val = NbBundle.getMessage(MakeSharableVisualPanel2.class, "TXT_UseLocal"); + } + } else { + if (ACTION_ABSOLUTE.equals(val)) { + val = NbBundle.getMessage(MakeSharableVisualPanel2.class, "TXT_AbsoluteJar"); + } else if (ACTION_COPY.equals(val)) { + val = NbBundle.getMessage(MakeSharableVisualPanel2.class, "TXT_CopyJar"); + } else if (ACTION_RELATIVE.equals(val)) { + val = NbBundle.getMessage(MakeSharableVisualPanel2.class, "TXT_KeepJar"); + } + } + return super.getTableCellRendererComponent(table, val, isSelected, hasFocus, row, column); + } + }); + tblJars.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + + public void valueChanged(ListSelectionEvent e) { + populateDescriptionField(); + } + }); + tblJars.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + lblHint = new javax.swing.JLabel(); + lblJars = new javax.swing.JLabel(); + jScrollPane1 = new javax.swing.JScrollPane(); + tblJars = new javax.swing.JTable(); + lblDetails = new javax.swing.JLabel(); + jScrollPane2 = new javax.swing.JScrollPane(); + taDetails = new javax.swing.JTextArea(); + + org.openide.awt.Mnemonics.setLocalizedText(lblHint, org.openide.util.NbBundle.getMessage(MakeSharableVisualPanel2.class, "MakeSharableVisualPanel2.lblHint.text")); // NOI18N + lblHint.setVerticalAlignment(javax.swing.SwingConstants.TOP); + + lblJars.setLabelFor(tblJars); + org.openide.awt.Mnemonics.setLocalizedText(lblJars, org.openide.util.NbBundle.getMessage(MakeSharableVisualPanel2.class, "MakeSharableVisualPanel2.lblJars.text")); // NOI18N + + jScrollPane1.setViewportView(tblJars); + + lblDetails.setLabelFor(taDetails); + org.openide.awt.Mnemonics.setLocalizedText(lblDetails, org.openide.util.NbBundle.getMessage(MakeSharableVisualPanel2.class, "MakeSharableVisualPanel2.lblDetails.text")); // NOI18N + + taDetails.setColumns(20); + taDetails.setRows(5); + jScrollPane2.setViewportView(taDetails); + + org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(lblHint, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 469, Short.MAX_VALUE) + .add(layout.createSequentialGroup() + .add(lblJars) + .addContainerGap()) + .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 469, Short.MAX_VALUE) + .add(layout.createSequentialGroup() + .add(lblDetails) + .addContainerGap()) + .add(jScrollPane2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 469, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(layout.createSequentialGroup() + .add(lblHint, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 86, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(lblJars) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 160, Short.MAX_VALUE) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(lblDetails) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(jScrollPane2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 104, Short.MAX_VALUE)) + ); + + lblJars.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(MakeSharableVisualPanel2.class, "ACSD_lblJars")); // NOI18N + lblDetails.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(MakeSharableVisualPanel2.class, "ACSD_lblDetails")); // NOI18N + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JScrollPane jScrollPane2; + private javax.swing.JLabel lblDetails; + private javax.swing.JLabel lblHint; + private javax.swing.JLabel lblJars; + private javax.swing.JTextArea taDetails; + private javax.swing.JTable tblJars; + // End of variables declaration//GEN-END:variables + private void populateTable(AntProjectHelper helper, List libraries, List jars) { + createTableDefinition(); + try { + File libraryFile = helper.resolveFile(location); + File prjDir = FileUtil.toFile(helper.getProjectDirectory()); + boolean absoluteLibrary = LibrariesSupport.isAbsoluteURL(LibrariesSupport.convertFilePathToURL(location)); + LibraryManager newmanager = LibraryManager.forLocation(libraryFile.toURI().toURL()); + LibraryManager oldmanager = LibraryManager.getDefault(); //TODO once we support moving from one place to another, change this + for (String lib : libraries) { + Library library = oldmanager.getLibrary(lib); + Library newLib = newmanager.getLibrary(lib); + String action = ACTION_COPY; + //TODO when library contents inside the same SCM or relative to new library location, + // use the relative path as default.. + if (newLib != null) { + action = ACTION_USE_LOCAL_LIBRARY; + } + if (library != null) { + model.addRow(new Object[]{library, action}); + } + } + for (String jar : jars) { + if (jar != null) { + String value = helper.getStandardPropertyEvaluator().evaluate(jar); + if (!value.startsWith("${")) { + File jarFile = helper.resolveFile(value); + String action = ACTION_COPY; + if (CollocationQuery.areCollocated(prjDir, jarFile)) { + // in the same VCS, without one project structure.. + action = ACTION_RELATIVE; + } else if (absoluteLibrary && CollocationQuery.areCollocated(libraryFile.getParentFile(), jarFile)) { + // jar within the libraries folder or somehow relative to it.. + // the path to libraries is absolute though.. absolute path is best guess then as well. + action = ACTION_ABSOLUTE; + } else if (CollocationQuery.areCollocated(libraryFile.getParentFile(), jarFile)) { + action = ACTION_RELATIVE; + } + model.addRow(new Object[]{jar, action}); + } else { + Logger.getLogger(MakeSharableVisualPanel2.class.getName()).info("Cannot find jar reference:" + jar); + } + } else { + Logger.getLogger(MakeSharableVisualPanel2.class.getName()).info("Cannot find jar reference:" + jar); + } + } + } catch (MalformedURLException ex) { + Exceptions.printStackTrace(ex); + } + } + + private void populateDescriptionField() { + int row = tblJars.getSelectedRow(); + if (row != -1) { + Object val = tblJars.getModel().getValueAt(row, 0); + if (val instanceof Library) { + Library lib = (Library) val; + String type = lib.getType(); + LibraryTypeProvider provider = LibrariesSupport.getLibraryTypeProvider(type); + assert provider != null; + String typeString = provider.getDisplayName(); + String[] volumes = provider.getSupportedVolumeTypes(); + StringBuffer contents = new StringBuffer(); + for (String vol : volumes) { + List urls = lib.getContent(vol); + for (URL url : urls) { + FileObject fo = URLMapper.findFileObject(url); + if (fo != null) { + if (FileUtil.getArchiveFile(fo) != null) { + url = URLMapper.findURL(FileUtil.getArchiveFile(fo), URLMapper.EXTERNAL); + } + } + contents.append(url).append("\n"); + } + } + taDetails.setText("Library (" + typeString + ")\n" + + "Contents:\n" + contents); + } else if (val instanceof String) { + String ref = (String) val; + String text = "Jar/Folder\nBinary:"; + String value = helper.getStandardPropertyEvaluator().evaluate(ref); + File absFile = helper.resolveFile(value); + text = text + absFile.getAbsolutePath(); + String source = ref.replace("${file.reference", "${source.reference"); //NOI18N + value = helper.getStandardPropertyEvaluator().evaluate(source); + if (!value.startsWith("${source.")) { //NOI18N + absFile = helper.resolveFile(value); + text = text + "\nSources:" + absFile.getAbsolutePath(); + } + String javadoc = ref.replace("${file.reference", "${javadoc.reference"); //NOI18N + value = helper.getStandardPropertyEvaluator().evaluate(javadoc); + if (!value.startsWith("${javadoc.")) { //NOI18N + absFile = helper.resolveFile(value); + text = text + "\nJavadoc:" + absFile.getAbsolutePath(); + } + + + taDetails.setText(text); + } + } else { + taDetails.setText(""); + } + } + + private class MyCellEditor extends DefaultCellEditor { + + + private JComboBox cb; + private DefaultListCellRenderer library; + private DefaultListCellRenderer jar; + + MyCellEditor(JComboBox combo) { + super(combo); + cb = combo; + library = new DefaultListCellRenderer() { + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + String val = (String) value; + if (ACTION_ABSOLUTE.equals(val)) { + val = NbBundle.getMessage(MakeSharableVisualPanel2.class, "TXT_Absolute"); + } else if (ACTION_COPY.equals(val)) { + val = NbBundle.getMessage(MakeSharableVisualPanel2.class, "TXT_Copy"); + } else if (ACTION_RELATIVE.equals(val)) { + val = NbBundle.getMessage(MakeSharableVisualPanel2.class, "TXT_Keep"); + } else if (ACTION_USE_LOCAL_LIBRARY.equals(val)) { + val = NbBundle.getMessage(MakeSharableVisualPanel2.class, "TXT_UseLocal"); + } + return super.getListCellRendererComponent(list, val, index, isSelected, cellHasFocus); + } + }; + jar = new DefaultListCellRenderer() { + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + String val = (String) value; + if (ACTION_ABSOLUTE.equals(val)) { + val = NbBundle.getMessage(MakeSharableVisualPanel2.class, "TXT_AbsoluteJar"); + } else if (ACTION_COPY.equals(val)) { + val = NbBundle.getMessage(MakeSharableVisualPanel2.class, "TXT_CopyJar"); + } else if (ACTION_RELATIVE.equals(val)) { + val = NbBundle.getMessage(MakeSharableVisualPanel2.class, "TXT_KeepJar"); + } else if (ACTION_USE_LOCAL_LIBRARY.equals(val)) { + val = NbBundle.getMessage(MakeSharableVisualPanel2.class, "TXT_UseLocalJar"); + } + return super.getListCellRendererComponent(list, val, index, isSelected, cellHasFocus); + } + }; + + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + if (table.getValueAt(row, 0) instanceof Library) { + cb.setRenderer(library); + cb.setModel(new DefaultComboBoxModel(comboValues)); + } else { + cb.setRenderer(jar); + cb.setModel(new DefaultComboBoxModel(comboValuesJar)); + } + super.getTableCellEditorComponent(table, value, isSelected, row, column); + return cb; + } + } +} + diff -r ffef4cca2ff4 java.project/src/org/netbeans/spi/java/project/support/ui/MakeSharableWizardPanel1.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.project/src/org/netbeans/spi/java/project/support/ui/MakeSharableWizardPanel1.java Thu Feb 21 14:36:41 2008 +0100 @@ -0,0 +1,107 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun + * Microsystems, Inc. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package org.netbeans.spi.java.project.support.ui; + +import java.awt.Component; +import javax.swing.event.ChangeListener; +import org.openide.WizardDescriptor; +import org.openide.util.ChangeSupport; +import org.openide.util.HelpCtx; + +class MakeSharableWizardPanel1 implements WizardDescriptor.Panel { + + /** + * The visual component that displays this panel. If you need to access the + * component from this class, just use getComponent(). + */ + private MakeSharableVisualPanel1 component; + private ChangeSupport support = new ChangeSupport(this); + + // Get the visual component for the panel. In this template, the component + // is kept separate. This can be more efficient: if the wizard is created + // but never displayed, or not all panels are displayed, it is better to + // create only those which really need to be visible. + public Component getComponent() { + if (component == null) { + component = new MakeSharableVisualPanel1(support); + } + return component; + } + + public HelpCtx getHelp() { + // Show no Help button for this panel: + return HelpCtx.DEFAULT_HELP; + // If you have context help: + // return new HelpCtx(SampleWizardPanel1.class); + } + + public boolean isValid() { + // If it is always OK to press Next or Finish, then: + return component.isValidPanel(); + // If it depends on some condition (form filled out...), then: + // return someCondition(); + // and when this condition changes (last form field filled in...) then: + // fireChangeEvent(); + // and uncomment the complicated stuff below. + } + + public final void addChangeListener(ChangeListener l) { + support.addChangeListener(l); + } + public final void removeChangeListener(ChangeListener l) { + support.removeChangeListener(l); + } + + // You can use a settings object to keep track of state. Normally the + // settings object will be the WizardDescriptor, so you can use + // WizardDescriptor.getProperty & putProperty to store information entered + // by the user. + public void readSettings(Object settings) { + WizardDescriptor wiz = (WizardDescriptor) settings; + component.readSettings(wiz); + } + + public void storeSettings(Object settings) { + WizardDescriptor wiz = (WizardDescriptor) settings; + component.storeSettings(wiz); + } +} + diff -r ffef4cca2ff4 java.project/src/org/netbeans/spi/java/project/support/ui/MakeSharableWizardPanel2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.project/src/org/netbeans/spi/java/project/support/ui/MakeSharableWizardPanel2.java Thu Feb 21 14:36:41 2008 +0100 @@ -0,0 +1,127 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun + * Microsystems, Inc. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package org.netbeans.spi.java.project.support.ui; + +import java.awt.Component; +import javax.swing.event.ChangeListener; +import org.openide.WizardDescriptor; +import org.openide.util.HelpCtx; + +class MakeSharableWizardPanel2 implements WizardDescriptor.Panel { + + /** + * The visual component that displays this panel. If you need to access the + * component from this class, just use getComponent(). + */ + private MakeSharableVisualPanel2 component; + + // Get the visual component for the panel. In this template, the component + // is kept separate. This can be more efficient: if the wizard is created + // but never displayed, or not all panels are displayed, it is better to + // create only those which really need to be visible. + public Component getComponent() { + if (component == null) { + component = new MakeSharableVisualPanel2(); + } + return component; + } + + public HelpCtx getHelp() { + // Show no Help button for this panel: + return HelpCtx.DEFAULT_HELP; + // If you have context help: + // return new HelpCtx(SampleWizardPanel1.class); + } + + public boolean isValid() { + // If it is always OK to press Next or Finish, then: + return true; + // If it depends on some condition (form filled out...), then: + // return someCondition(); + // and when this condition changes (last form field filled in...) then: + // fireChangeEvent(); + // and uncomment the complicated stuff below. + } + + public final void addChangeListener(ChangeListener l) { + } + + public final void removeChangeListener(ChangeListener l) { + } + /* + private final Set listeners = new HashSet(1); // or can use ChangeSupport in NB 6.0 + public final void addChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.add(l); + } + } + public final void removeChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.remove(l); + } + } + protected final void fireChangeEvent() { + Iterator it; + synchronized (listeners) { + it = new HashSet(listeners).iterator(); + } + ChangeEvent ev = new ChangeEvent(this); + while (it.hasNext()) { + it.next().stateChanged(ev); + } + } + */ + + // You can use a settings object to keep track of state. Normally the + // settings object will be the WizardDescriptor, so you can use + // WizardDescriptor.getProperty & putProperty to store information entered + // by the user. + public void readSettings(Object settings) { + WizardDescriptor wiz = (WizardDescriptor) settings; + component.readSettings(wiz); + } + + public void storeSettings(Object settings) { + WizardDescriptor wiz = (WizardDescriptor) settings; + component.storeSettings(wiz); + } +} + diff -r ffef4cca2ff4 java.project/src/org/netbeans/spi/java/project/support/ui/SharableLibrariesUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.project/src/org/netbeans/spi/java/project/support/ui/SharableLibrariesUtils.java Thu Feb 21 14:36:41 2008 +0100 @@ -0,0 +1,465 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun + * Microsystems, Inc. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package org.netbeans.spi.java.project.support.ui; + +import java.awt.Component; +import java.awt.Dialog; +import java.awt.event.ActionEvent; +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import org.netbeans.api.project.FileOwnerQuery; +import org.netbeans.api.project.ProjectManager; +import org.netbeans.api.project.ant.FileChooser; +import org.netbeans.api.project.libraries.Library; +import org.netbeans.api.project.libraries.LibraryManager; +import org.netbeans.spi.project.libraries.LibraryTypeProvider; +import org.netbeans.spi.project.libraries.support.LibrariesSupport; +import org.netbeans.spi.project.support.ant.AntProjectHelper; +import org.netbeans.spi.project.support.ant.PropertyUtils; +import org.netbeans.spi.project.support.ant.ReferenceHelper; +import org.openide.DialogDisplayer; +import org.openide.WizardDescriptor; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileSystem; +import org.openide.filesystems.FileUtil; +import org.openide.filesystems.URLMapper; +import org.openide.util.Exceptions; +import org.openide.util.Mutex; +import org.openide.util.MutexException; +import org.openide.util.NbBundle; + +/** + * Utility methods related to sharable libraries UI. + * @since org.netbeans.modules.java.project 1.15 + * + */ +public final class SharableLibrariesUtils { + + static final String PROP_LOCATION = "location"; //NOI18N + static final String PROP_ACTIONS = "actions"; //NOI18N + static final String PROP_HELPER = "helper"; //NOI18N + static final String PROP_REFERENCE_HELPER = "refhelper"; //NOI18N + static final String PROP_LIBRARIES = "libraries"; //NOI18N + static final String PROP_JAR_REFS = "jars"; //NOI18N + + /** + * The default filename for sharable library definition file. + */ + public static final String DEFAULT_LIBRARIES_FILENAME = "nblibraries.properties"; + + + + /** + * File chooser implementation for browsing for shared library location. + * @param current + * @param comp + * @param projectLocation + * @return relative or absolute path to project libraries folder. + */ + public static String browseForLibraryLocation(String current, Component comp, File projectLocation) { + File lib = PropertyUtils.resolveFile(projectLocation, current); + if (!lib.exists()) { + lib = lib.getParentFile(); + } + lib = FileUtil.normalizeFile(lib); + FileChooser chooser = new FileChooser(projectLocation, null); + chooser.setCurrentDirectory(lib); + chooser.setFileSelectionMode( JFileChooser.DIRECTORIES_ONLY ); + chooser.setDialogTitle(NbBundle.getMessage(SharableLibrariesUtils.class,"LBL_Browse_Libraries_Title")); + chooser.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(SharableLibrariesUtils.class,"ASCD_Browse_Libraries_Title")); + if (JFileChooser.APPROVE_OPTION == chooser.showOpenDialog(comp)) { + String[] files; + try { + files = chooser.getSelectedPaths(); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + return null; + } + if (files.length == 1) { + String currentLibrariesLocation = files[0]; + return currentLibrariesLocation; + } + } + return null; + } + + /** + * Show a multistep wizard for converting a non-sharable project to a sharable, self-contained one. + * @param helper + * @param ref + * @param libraryNames + * @param jarReferences + * @return true is migration was performed, false when aborted. + */ + public static boolean showMakeSharableWizard(final AntProjectHelper helper, ReferenceHelper ref, List libraryNames, List jarReferences) { + + final WizardDescriptor wizardDescriptor = new WizardDescriptor(getPanels()); + // {0} will be replaced by WizardDesriptor.Panel.getComponent().getName() + wizardDescriptor.setTitleFormat(new MessageFormat("{0}")); + wizardDescriptor.setTitle(NbBundle.getMessage(SharableLibrariesUtils.class, "TIT_MakeSharableWizard")); + wizardDescriptor.putProperty(PROP_HELPER, helper); + wizardDescriptor.putProperty(PROP_REFERENCE_HELPER, ref); + wizardDescriptor.putProperty(PROP_LIBRARIES, libraryNames); + wizardDescriptor.putProperty(PROP_JAR_REFS, jarReferences); + Dialog dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor); + dialog.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(SharableLibrariesUtils.class, "ACSD_MakeSharableWizard")); + dialog.setVisible(true); + dialog.toFront(); + boolean cancelled = wizardDescriptor.getValue() != WizardDescriptor.FINISH_OPTION; + if (!cancelled) { + final String loc = (String) wizardDescriptor.getProperty(PROP_LOCATION); + assert loc != null; + try { + // create libraries property file if it does not exist: + File f = new File(loc); + if (!f.isAbsolute()) { + f = new File(FileUtil.toFile(helper.getProjectDirectory()), loc); + } + f = FileUtil.normalizeFile(f); + if (!f.exists()) { + FileUtil.createData(f); + } + + try { + ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction() { + + public Object run() throws IOException { + try { + helper.getProjectDirectory().getFileSystem().runAtomicAction(new FileSystem.AtomicAction() { + public void run() throws IOException { + helper.setLibrariesLocation(loc); + + // TODO or make just runnables? + List actions = (List) wizardDescriptor.getProperty(PROP_ACTIONS); + for (Action act : actions) { + act.actionPerformed(null); + } + ProjectManager.getDefault().saveProject(FileOwnerQuery.getOwner(helper.getProjectDirectory())); + } + }); + } catch (IllegalArgumentException ex) { + Exceptions.printStackTrace(ex); + } + + return null; + } + }); + } catch (MutexException ex) { + throw (IOException) ex.getException(); + } + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + + + } + return !cancelled; + } + + /** + * Initialize panels representing individual wizard's steps and sets + * various properties for them influencing wizard appearance. + */ + private static WizardDescriptor.Panel[] getPanels() { + WizardDescriptor.Panel[] panels = new WizardDescriptor.Panel[]{ + new MakeSharableWizardPanel1(), + new MakeSharableWizardPanel2() + }; + String[] steps = new String[panels.length]; + for (int i = 0; i < panels.length; i++) { + Component c = panels[i].getComponent(); + // Default step name to component name of panel. Mainly useful + // for getting the name of the target chooser to appear in the + // list of steps. + steps[i] = c.getName(); + if (c instanceof JComponent) { // assume Swing components + JComponent jc = (JComponent) c; + // Sets step number of a component + jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i)); + // Sets steps names for a panel + jc.putClientProperty("WizardPanel_contentData", steps); + // Turn on subtitle creation on each step + jc.putClientProperty("WizardPanel_autoWizardStyle", Boolean.TRUE); + // Show steps on the left side with the image on the background + jc.putClientProperty("WizardPanel_contentDisplayed", Boolean.TRUE); + // Turn on numbering of all steps + jc.putClientProperty("WizardPanel_contentNumbered", Boolean.TRUE); + } + } + return panels; + } + + static class CopyJars extends AbstractAction { + private ReferenceHelper refhelper; + private AntProjectHelper ahelper; + private String reference; + + public CopyJars(ReferenceHelper helper, AntProjectHelper anthelper, String ref) { + this.reference = ref; + this.ahelper = anthelper; + refhelper = helper; + } + + public void actionPerformed(ActionEvent e) { + String value = ahelper.getStandardPropertyEvaluator().evaluate(reference); + File absFile = ahelper.resolveFile(value); + String location = ahelper.getLibrariesLocation(); + File libraryFile = ahelper.resolveFile(location); + File directory = libraryFile.getParentFile(); + if (!directory.exists()) { + directory.mkdirs(); + FileUtil.refreshFor(directory); + } + FileObject dir = FileUtil.toFileObject(directory); + updateReference(absFile, reference, true, dir); + //now process source reference + String source = reference.replace("${file.reference", "${source.reference"); //NOI18N + value = ahelper.getStandardPropertyEvaluator().evaluate(source); + if (!value.startsWith("${source.")) { //NOI18N + absFile = ahelper.resolveFile(value); + updateReference(absFile, source.replace("${", "").replace("}", ""), false, dir); + } + //now process javadoc reference + String javadoc = reference.replace("${file.reference", "${javadoc.reference"); //NOI18N + value = ahelper.getStandardPropertyEvaluator().evaluate(javadoc); + if (!value.startsWith("${javadoc.")) { //NOI18N + absFile = ahelper.resolveFile(value); + updateReference(absFile, javadoc.replace("${", "").replace("}", ""), false, dir); + } + } + + private void updateReference(File oldFile, String key, boolean main, FileObject dir) { + FileObject src = FileUtil.toFileObject(oldFile); + FileObject newFile; + try { + //TODO it could actually already exist.. + newFile = FileUtil.copyFile(src, dir, src.getName()); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + newFile = src; + } + File absFile = FileUtil.toFile(newFile); + //always relative when possible. + // assume we have relative path to library as well, thus relative path is + //good default value. + String newVal = PropertyUtils.relativizeFile(FileUtil.toFile(ahelper.getProjectDirectory()), absFile); + if (newVal == null) { + //fallback + newVal = absFile.getAbsolutePath(); + } + if (main) { + // mkleint: why isn't there a way to set the reference, but one always have to create it + // creating will create a unique key.. + refhelper.destroyReference(key); + refhelper.createForeignFileReferenceAsIs(newVal, key); + } else { + refhelper.destroyReference(key); + refhelper.createExtraForeignFileReferenceAsIs(newVal, key); + } + } + + } + + static class KeepJarAtLocation extends AbstractAction { + private ReferenceHelper refhelper; + private AntProjectHelper ahelper; + private String reference; + private boolean relative; + + public KeepJarAtLocation(String ref, boolean b, AntProjectHelper anthelper, ReferenceHelper helper) { + this.reference = ref; + this.ahelper = anthelper; + refhelper = helper; + relative = b; + } + + public void actionPerformed(ActionEvent e) { + String value = ahelper.getStandardPropertyEvaluator().evaluate(reference); + updateReference(value, reference, true); + //now process source reference + String source = reference.replace("${file.reference", "${source.reference"); //NOI18N + value = ahelper.getStandardPropertyEvaluator().evaluate(source); + if (!value.startsWith("${source.")) { //NOI18N + updateReference(value, source.replace("${", "").replace("}", ""), false); + } + //now process javadoc reference + String javadoc = reference.replace("${file.reference", "${javadoc.reference"); //NOI18N + value = ahelper.getStandardPropertyEvaluator().evaluate(javadoc); + if (!value.startsWith("${javadoc.")) { //NOI18N + updateReference(value, javadoc.replace("${", "").replace("}", ""), false); + } + } + + private void updateReference(String value, String key, boolean main) { + File absFile = ahelper.resolveFile(value); + String newVal = relative ? PropertyUtils.relativizeFile(FileUtil.toFile(ahelper.getProjectDirectory()), absFile) : absFile.getAbsolutePath(); + if (newVal == null) { + //fallback + newVal = absFile.getAbsolutePath(); + } + if (!newVal.equals(value)) { + if (main) { + refhelper.createForeignFileReferenceAsIs(newVal, key); + } else { + refhelper.createExtraForeignFileReferenceAsIs(newVal, key); + } + } + } + } + + static class KeepLibraryAtLocation extends AbstractAction { + private boolean keepRelativeLocations; + private Library library; + private AntProjectHelper helper; + + KeepLibraryAtLocation(Library l , boolean relative, AntProjectHelper h) { + library = l; + keepRelativeLocations = relative; + helper = h; + } + public void actionPerformed(ActionEvent e) { + String loc = helper.getLibrariesLocation(); + assert loc != null; + File mainPropertiesFile = helper.resolveFile(loc); + try { + LibraryManager man = LibraryManager.forLocation(mainPropertiesFile.toURI().toURL()); + Map> volumes = new HashMap>(); + LibraryTypeProvider provider = LibrariesSupport.getLibraryTypeProvider(library.getType()); + assert provider != null; + for (String volume : provider.getSupportedVolumeTypes()) { + List urls = library.getContent(volume); + List newurls = new ArrayList(); + for (URL url : urls) { + String jarFolder = null; + boolean isArchive = false; + if ("jar".equals(url.getProtocol())) { // NOI18N + jarFolder = getJarFolder(url); + url = FileUtil.getArchiveFile(url); + isArchive = true; + } + FileObject fo = URLMapper.findFileObject(url); + + if (fo != null) { + if (keepRelativeLocations) { + File path = FileUtil.toFile(fo); + String str = PropertyUtils.relativizeFile(mainPropertiesFile.getParentFile(), path); + url = LibrariesSupport.convertFilePathToURL(str); + } else { + url = fo.getURL(); + } + if (isArchive) { + url = FileUtil.getArchiveRoot(url); + } + if (jarFolder != null) { + url = appendJarFolder(url, jarFolder); + } + + } + + + newurls.add(url); + } + volumes.put(volume, newurls); + } + + man.createLibrary(library.getType(), library.getName(), volumes); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + + } + + static class CopyLibraryJars extends AbstractAction { + private Library library; + private ReferenceHelper refHelper; + + CopyLibraryJars(ReferenceHelper h, Library l) { + refHelper = h; + library = l; + } + + public void actionPerformed(ActionEvent e) { + assert library.getManager() == LibraryManager.getDefault() : "Only converting from non-sharable to sharable is supported."; //NOi18N + try { + refHelper.copyLibrary(library); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + + } + + + + + /** for jar url this method returns path wihtin jar or null*/ + private static String getJarFolder(URL url) { + assert "jar".equals(url.getProtocol()) : url; + String u = url.toExternalForm(); + int index = u.indexOf("!/"); //NOI18N + if (index != -1 && index + 2 < u.length()) { + return u.substring(index + 2); + } + return null; + } + + /** append path to given jar root url */ + private static URL appendJarFolder(URL u, String jarFolder) { + assert "jar".equals(u.getProtocol()) && u.toExternalForm().endsWith("!/") : u; + try { + return new URL(u + jarFolder.replace('\\', '/')); //NOI18N + } catch (MalformedURLException e) { + throw new AssertionError(e); + } + } +}