| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.netbeans.modules.java.project.ui; |
| |
| import java.awt.Color; |
| import java.awt.Component; |
| import java.beans.PropertyChangeEvent; |
| import java.beans.PropertyChangeListener; |
| import java.io.IOException; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Optional; |
| import java.util.concurrent.Future; |
| import javax.swing.AbstractListModel; |
| import javax.swing.ComboBoxModel; |
| import javax.swing.DefaultListCellRenderer; |
| import javax.swing.JButton; |
| import javax.swing.JList; |
| import javax.swing.UIManager; |
| import org.netbeans.api.annotations.common.NonNull; |
| import org.netbeans.api.annotations.common.NullAllowed; |
| import org.netbeans.api.java.classpath.ClassPath; |
| import org.netbeans.api.java.platform.JavaPlatform; |
| import org.netbeans.api.java.platform.JavaPlatformManager; |
| import org.netbeans.api.java.platform.PlatformsCustomizer; |
| import org.netbeans.api.java.platform.Specification; |
| import org.netbeans.api.project.FileOwnerQuery; |
| import org.netbeans.api.project.Project; |
| import org.netbeans.api.project.ProjectManager; |
| import org.netbeans.spi.java.project.support.ui.BrokenReferencesSupport; |
| import org.netbeans.spi.project.support.ant.AntProjectHelper; |
| import org.netbeans.spi.project.support.ant.EditableProperties; |
| import org.netbeans.spi.project.support.ant.PropertyEvaluator; |
| import org.netbeans.spi.project.ui.ProjectProblemsProvider; |
| import org.openide.filesystems.FileObject; |
| import org.openide.util.Exceptions; |
| import org.openide.util.Mutex; |
| import org.openide.util.NbBundle; |
| import org.openide.util.Parameters; |
| import org.openide.util.RequestProcessor; |
| import org.openide.util.WeakListeners; |
| |
| /** |
| * |
| * @author Tomas Zezula |
| */ |
| final class FixPlatform extends javax.swing.JPanel { |
| private static final RequestProcessor WORKER = new RequestProcessor(FixPlatform.class); |
| |
| private final String propertName; |
| private final String requiredPlatformId; |
| private final PropertyEvaluator eval; |
| private final AntProjectHelper helper; |
| private final BrokenReferencesSupport.PlatformUpdatedCallBack callback; |
| private final JButton ok; |
| |
| /** |
| * Creates new form FixPlatform |
| */ |
| FixPlatform( |
| @NonNull final String propertyName, |
| @NonNull final String requiredPlatformId, |
| @NullAllowed final String platformType, |
| @NonNull final PropertyEvaluator eval, |
| @NonNull final AntProjectHelper helper, |
| @NullAllowed final BrokenReferencesSupport.PlatformUpdatedCallBack callback, |
| @NonNull final JButton ok) { |
| Parameters.notNull("propertyName", propertyName); //NOI18N |
| Parameters.notNull("requiredPlatformId", requiredPlatformId); //NOI18N |
| Parameters.notNull("eval", eval); //NOI18N |
| Parameters.notNull("helper", helper); //NOI18N |
| Parameters.notNull("ok", ok); //NOI18N |
| this.propertName = propertyName; |
| this.requiredPlatformId = requiredPlatformId; |
| this.eval = eval; |
| this.helper = helper; |
| this.callback = callback; |
| this.ok = ok; |
| initComponents(); |
| ok.setEnabled(false); |
| this.platforms.setModel(new PlatformsModel(requiredPlatformId, platformType)); |
| this.platforms.setRenderer(new PlatformsRenderer()); |
| this.platforms.addActionListener((ae) -> { |
| final JavaPlatform jp = (JavaPlatform) this.platforms.getSelectedItem(); |
| ok.setEnabled(jp != null && !jp.getInstallFolders().isEmpty()); |
| }); |
| } |
| |
| final Future<ProjectProblemsProvider.Result> resolve() { |
| final JavaPlatform selected = (JavaPlatform) platforms.getSelectedItem(); |
| if (selected == null) { |
| return ProjectProblemsProviders.future( |
| ProjectProblemsProvider.Result.create(ProjectProblemsProvider.Status.UNRESOLVED)); |
| } |
| final String antName = getJavaPlatformAntName(selected); |
| if (requiredPlatformId.equals(antName)) { |
| return ProjectProblemsProviders.future( |
| ProjectProblemsProvider.Result.create(ProjectProblemsProvider.Status.RESOLVED)); |
| } |
| return WORKER.submit(() -> { |
| return ProjectManager.mutex().writeAccess(() -> { |
| try { |
| final EditableProperties ep = helper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH); |
| ep.setProperty(propertName, antName); |
| helper.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, ep); |
| if (callback != null) { |
| callback.platformPropertyUpdated(selected); |
| } |
| final Project p = FileOwnerQuery.getOwner(helper.getProjectDirectory()); |
| ProjectManager.getDefault().saveProject(p); |
| return ProjectProblemsProvider.Result.create(ProjectProblemsProvider.Status.RESOLVED); |
| } catch (IOException ioe) { |
| Exceptions.printStackTrace(ioe); |
| return ProjectProblemsProvider.Result.create(ProjectProblemsProvider.Status.UNRESOLVED); |
| } |
| }); |
| }); |
| } |
| |
| /** |
| * 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. |
| */ |
| @SuppressWarnings("unchecked") |
| // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents |
| private void initComponents() { |
| |
| label1 = new javax.swing.JLabel(); |
| jLabel1 = new javax.swing.JLabel(); |
| create = new javax.swing.JButton(); |
| jLabel2 = new javax.swing.JLabel(); |
| platforms = new javax.swing.JComboBox<>(); |
| hint = new javax.swing.JLabel(); |
| |
| org.openide.awt.Mnemonics.setLocalizedText(label1, NbBundle.getMessage(FixPlatform.class, "LBL_MissingPlatform", getHtmlColor(getErrorForeground()), requiredPlatformId)); |
| |
| org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(FixPlatform.class, "LBL_CreateNewPlatform")); // NOI18N |
| |
| org.openide.awt.Mnemonics.setLocalizedText(create, org.openide.util.NbBundle.getMessage(FixPlatform.class, "FixPlatform.create.text")); // NOI18N |
| create.addActionListener(new java.awt.event.ActionListener() { |
| public void actionPerformed(java.awt.event.ActionEvent evt) { |
| createActionPerformed(evt); |
| } |
| }); |
| |
| jLabel2.setLabelFor(platforms); |
| org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(FixPlatform.class, "LBL_UseExistingPlatform")); // NOI18N |
| |
| org.openide.awt.Mnemonics.setLocalizedText(hint, NbBundle.getMessage(FixPlatform.class, "LBL_PlatformHint", requiredPlatformId)); |
| hint.setFocusable(false); |
| |
| javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); |
| this.setLayout(layout); |
| layout.setHorizontalGroup( |
| layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) |
| .addGroup(layout.createSequentialGroup() |
| .addContainerGap() |
| .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) |
| .addGroup(layout.createSequentialGroup() |
| .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) |
| .addComponent(hint, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) |
| .addGroup(layout.createSequentialGroup() |
| .addComponent(label1) |
| .addGap(0, 0, Short.MAX_VALUE))) |
| .addContainerGap()) |
| .addGroup(layout.createSequentialGroup() |
| .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) |
| .addComponent(jLabel2) |
| .addComponent(jLabel1)) |
| .addGap(18, 18, 18) |
| .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) |
| .addGroup(layout.createSequentialGroup() |
| .addComponent(create) |
| .addGap(0, 0, Short.MAX_VALUE)) |
| .addComponent(platforms, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))) |
| ); |
| layout.setVerticalGroup( |
| layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) |
| .addGroup(layout.createSequentialGroup() |
| .addContainerGap() |
| .addComponent(label1) |
| .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) |
| .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) |
| .addComponent(jLabel1) |
| .addComponent(create)) |
| .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) |
| .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) |
| .addComponent(jLabel2) |
| .addComponent(platforms, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) |
| .addGap(22, 22, 22) |
| .addComponent(hint) |
| .addContainerGap(67, Short.MAX_VALUE)) |
| ); |
| }// </editor-fold>//GEN-END:initComponents |
| |
| private void createActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_createActionPerformed |
| PlatformsCustomizer.showCustomizer(null); |
| }//GEN-LAST:event_createActionPerformed |
| |
| private static String getJavaPlatformAntName(@NonNull final JavaPlatform jp) { |
| return jp.getProperties().get(ProjectProblemsProviders.PLAT_PROP_ANT_NAME); |
| } |
| |
| @NonNull |
| private static Color getErrorForeground() { |
| Color result = UIManager.getDefaults().getColor("nb.errorForeground"); //NOI18N |
| if (result == null) { |
| result = Color.RED; |
| } |
| return result; |
| } |
| |
| @NonNull |
| private static String getHtmlColor(@NonNull final Color c) { |
| final int r = c.getRed(); |
| final int g = c.getGreen(); |
| final int b = c.getBlue(); |
| final StringBuilder result = new StringBuilder(); |
| result.append ("#"); //NOI18N |
| final String rs = Integer.toHexString (r); |
| final String gs = Integer.toHexString (g); |
| final String bs = Integer.toHexString (b); |
| if (r < 0x10) |
| result.append('0'); |
| result.append(rs); |
| if (g < 0x10) |
| result.append ('0'); |
| result.append(gs); |
| if (b < 0x10) |
| result.append ('0'); |
| result.append(bs); |
| return result.toString(); |
| } |
| |
| // Variables declaration - do not modify//GEN-BEGIN:variables |
| private javax.swing.JButton create; |
| private javax.swing.JLabel hint; |
| private javax.swing.JLabel jLabel1; |
| private javax.swing.JLabel jLabel2; |
| private javax.swing.JLabel label1; |
| private javax.swing.JComboBox<JavaPlatform> platforms; |
| // End of variables declaration//GEN-END:variables |
| |
| private static final class PlatformsModel extends AbstractListModel<JavaPlatform> |
| implements ComboBoxModel<JavaPlatform>, PropertyChangeListener { |
| private final String requiredPlatformId; |
| private final String platformType; |
| private final JavaPlatformManager pm; |
| private final BrokenPlatform broken; |
| private JavaPlatform[] platforms; |
| private JavaPlatform selected; |
| |
| PlatformsModel( |
| @NonNull final String requiredPlatformId, |
| @NullAllowed final String platformType) { |
| Parameters.notNull("requiredPlatformId", requiredPlatformId); //NOI18N |
| this.requiredPlatformId = requiredPlatformId; |
| this.platformType = platformType; |
| this.broken = new BrokenPlatform(requiredPlatformId); |
| this.pm = JavaPlatformManager.getDefault(); |
| this.pm.addPropertyChangeListener(WeakListeners.propertyChange(this, this.pm)); |
| init(); |
| } |
| |
| @Override |
| public int getSize() { |
| return platforms.length; |
| } |
| |
| @Override |
| public JavaPlatform getElementAt(int index) { |
| return platforms[index]; |
| } |
| |
| private void init () { |
| final List<JavaPlatform> newPlatfs = new ArrayList<>(); |
| Arrays.stream(this.pm.getPlatforms(null, new Specification( |
| this.platformType, |
| null))) |
| .filter((jp) -> !jp.getInstallFolders().isEmpty()) |
| .forEach(newPlatfs::add); |
| final Optional<JavaPlatform> resolved = newPlatfs.stream() |
| .filter((jp) -> requiredPlatformId.equals(getJavaPlatformAntName(jp))) |
| .findAny(); |
| JavaPlatform toSelect; |
| if (resolved.isPresent()) { |
| toSelect = resolved.get(); |
| } else { |
| toSelect = broken; |
| newPlatfs.add(broken); |
| } |
| Collections.sort(newPlatfs, (p1,p2) -> { |
| if (p1 == broken) { |
| return -1; |
| } |
| if (p2 == broken) { |
| return 1; |
| } |
| return p1.getDisplayName().compareTo(p2.getDisplayName()); |
| }); |
| platforms = newPlatfs.toArray(new JavaPlatform[newPlatfs.size()]); |
| setSelectedItem(toSelect); |
| } |
| |
| @Override |
| public void setSelectedItem(Object anItem) { |
| selected = (JavaPlatform) anItem; |
| } |
| |
| @Override |
| public Object getSelectedItem() { |
| return selected; |
| } |
| |
| @Override |
| public void propertyChange(@NonNull final PropertyChangeEvent evt) { |
| Mutex.EVENT.readAccess(()-> { |
| int up = platforms == null ? |
| 0 : |
| platforms.length; |
| init(); |
| up = Math.max(up, platforms.length); |
| fireContentsChanged(this, 0, up); |
| }); |
| } |
| } |
| |
| private static final class PlatformsRenderer extends DefaultListCellRenderer { |
| @Override |
| public Component getListCellRendererComponent( |
| @NonNull final JList<?> list, |
| @NonNull Object value, |
| final int index, |
| final boolean isSelected, |
| final boolean cellHasFocus) { |
| if (value instanceof JavaPlatform) { |
| final JavaPlatform jp = (JavaPlatform) value; |
| value = jp.getDisplayName(); |
| if (jp.getInstallFolders().isEmpty()) { |
| value = String.format( |
| "<html><font color=\"%s\">%s</font>", //NOI18N |
| getHtmlColor(getErrorForeground()), |
| value); |
| } |
| |
| } |
| return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); |
| } |
| } |
| |
| private static final class BrokenPlatform extends JavaPlatform { |
| private final String id; |
| |
| BrokenPlatform(@NonNull final String id) { |
| this.id = id; |
| } |
| |
| @Override |
| public String getDisplayName() { |
| return this.id; |
| } |
| |
| @Override |
| public Map<String, String> getProperties() { |
| return Collections.singletonMap( |
| ProjectProblemsProviders.PLAT_PROP_ANT_NAME, id); |
| } |
| |
| @Override |
| public ClassPath getBootstrapLibraries() { |
| return ClassPath.EMPTY; |
| } |
| |
| @Override |
| public ClassPath getStandardLibraries() { |
| return ClassPath.EMPTY; |
| } |
| |
| @Override |
| public String getVendor() { |
| return ""; //NOI18N |
| } |
| |
| @Override |
| public Specification getSpecification() { |
| return new Specification(null, null); |
| } |
| |
| @Override |
| public Collection<FileObject> getInstallFolders() { |
| return Collections.emptySet(); |
| } |
| |
| @Override |
| public FileObject findTool(String toolName) { |
| return null; |
| } |
| |
| @Override |
| public ClassPath getSourceFolders() { |
| return ClassPath.EMPTY; |
| } |
| |
| @Override |
| public List<URL> getJavadocFolders() { |
| return Collections.emptyList(); |
| } |
| } |
| } |