001    /*
002     *  Licensed under the Apache License, Version 2.0 (the "License");
003     *  you may not use this file except in compliance with the License.
004     *  You may obtain a copy of the License at
005     *
006     *      http://www.apache.org/licenses/LICENSE-2.0
007     *
008     *  Unless required by applicable law or agreed to in writing, software
009     *  distributed under the License is distributed on an "AS IS" BASIS,
010     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011     *  See the License for the specific language governing permissions and
012     *  limitations under the License.
013     */
014    /*
015     * This file has been modified by Chris Pheby in accordance with Section 4.2
016     * of the Apache Software License
017     */
018    package org.jadira.dependencynavigator.gui;
019    
020    /**********************************************************************you may not use this file except in compliance with the License. You may obtain a copy of the License at
021     * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software
022     * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
023     * either express or implied. See the License for the specific language governing permissions and limitations under the
024     * License. Contributors:
025     **********************************************************************/
026    import java.awt.Cursor;
027    import java.awt.Dimension;
028    import java.awt.FlowLayout;
029    import java.awt.event.ActionEvent;
030    import java.awt.event.ActionListener;
031    import java.awt.event.MouseAdapter;
032    import java.awt.event.MouseEvent;
033    import java.io.IOException;
034    import java.io.InputStream;
035    import java.util.Properties;
036    
037    import javax.swing.BoxLayout;
038    import javax.swing.JButton;
039    import javax.swing.JCheckBox;
040    import javax.swing.JFrame;
041    import javax.swing.JLabel;
042    import javax.swing.JPanel;
043    import javax.swing.JScrollPane;
044    import javax.swing.JSplitPane;
045    import javax.swing.JTable;
046    import javax.swing.JTree;
047    import javax.swing.ListSelectionModel;
048    import javax.swing.SwingUtilities;
049    import javax.swing.table.JTableHeader;
050    
051    import org.jadira.dependencynavigator.controller.ArtifactResolver;
052    import org.jadira.dependencynavigator.controller.Controller;
053    import org.jadira.dependencynavigator.controller.model.DuplicatesListManager;
054    import org.jadira.dependencynavigator.implementations.WorkspaceLoader;
055    import org.jadira.dependencynavigator.model.ArtifactInitialisationException;
056    import org.jadira.repositorysnapshot.RepositorySnapshotFactory;
057    
058    public class DependencyBrowserGui {
059    
060        public static final String ROLE = "org.jadira.dependencynavigator.gui.DependencyBrowserGui";
061    
062        private static final String PROPERTIES = "/META-INF/maven/org.jadira/maven-dependency-browser-swing-gui/pom.properties";
063    
064        private JTree tree;
065        private Controller controller;
066        private JFrame frame;
067        private JTable versions;
068        private JTable duplicates;
069        private WorkspaceLoader workspaceLoader;
070        private ArtifactResolver resolver;
071        private DuplicatesListManager duplicatesListManager;
072        private ProgressMeter progressMeter;
073        private RepositorySnapshotFactory repositorySnapshotFactory;
074    
075        public void open() {
076            frame.setTitle("Maven Dependency Navigator" + loadVersion());
077            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
078            frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.PAGE_AXIS));
079    
080            JPanel topPanel = new JPanel();
081            topPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
082    
083            topPanel.add(createLoadButton());
084            topPanel.add(createCheckBox("compile", controller.getCheckShowCompile()));
085            topPanel.add(createCheckBox("test", controller.getCheckShowTest()));
086            topPanel.add(createCheckBox("runtime", controller.getCheckShowRuntime()));
087            topPanel.add(createCheckBox("provided", controller.getCheckShowProvided()));
088            topPanel.add(createCheckBox("exclusions", controller.getResolveExclusions()));
089            topPanel.add(createSnapshotButton());
090    
091            JPanel bottomPanel = new JPanel();
092            bottomPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
093            JLabel progressLabel = new JLabel();
094            bottomPanel.add(progressLabel);
095            progressMeter = new ProgressMeter(progressLabel);
096            progressMeter.ready();
097    
098            tree = new JTree(new DependencyTreeModel(workspaceLoader.getRoot()));
099            tree.setCellRenderer(new DependencyTreeRenderer());
100            versions = new JTable(new VersionsTableModel(duplicatesListManager));
101            versions.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
102            versions.setDefaultRenderer(String.class, new SelectableTableModelRenderer());
103            versions.addMouseListener(new MouseAdapter() {
104    
105                @Override
106                public void mouseClicked(MouseEvent e) {
107                    JTable table = (JTable) e.getComponent();
108                    duplicatesListManager.deselect();
109                    duplicatesListManager.getVersionsListManager().select(table.getSelectedRow());
110                    tree.repaint();
111                    versions.repaint();
112                    duplicates.repaint();
113                }
114    
115            });
116            versions.getTableHeader().addMouseListener(new MouseAdapter() {
117    
118                @Override
119                public void mouseClicked(MouseEvent e) {
120                    JTableHeader h = (JTableHeader) e.getSource();
121                    int vColIndex = h.getColumnModel().getColumnIndexAtX(e.getX());
122                    int mColIndex = h.getTable().convertColumnIndexToModel(vColIndex);
123                    duplicatesListManager.getVersionsListManager().setArtifactInstanceMapComparator(mColIndex);
124                    versions.repaint();
125                }
126    
127            });
128            duplicates = new JTable(new DuplicatesTableModel(duplicatesListManager));
129            duplicates.setDefaultRenderer(String.class, new SelectableTableModelRenderer());
130            duplicates.addMouseListener(new MouseAdapter() {
131    
132                @Override
133                public void mouseClicked(MouseEvent e) {
134                    JTable table = (JTable) e.getComponent();
135                    duplicatesListManager.select(table.getSelectedRow());
136                    tree.repaint();
137                    versions.repaint();
138                    duplicates.repaint();
139                }
140    
141            });
142            duplicates.getTableHeader().addMouseListener(new MouseAdapter() {
143                @Override
144                public void mouseClicked(MouseEvent e) {
145                    duplicatesListManager.setOrderByIdentifier();
146                    duplicates.repaint();
147                }
148            });
149    
150            JSplitPane versionsSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT, new JScrollPane(versions), new JScrollPane(duplicates));
151            JPanel versionsPanel = new JPanel();
152            versionsPanel.setLayout(new BoxLayout(versionsPanel, BoxLayout.PAGE_AXIS));
153            versionsPanel.add(versionsSplit);
154    
155            JSplitPane mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(tree), versionsPanel);
156    
157            JPanel mainPanel = new JPanel();
158            mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.LINE_AXIS));
159            mainPanel.add(mainSplitPane);
160    
161            mainPanel.setPreferredSize(new Dimension(800, 600));
162    
163            frame.getContentPane().add(topPanel);
164            frame.getContentPane().add(mainPanel);
165            frame.getContentPane().add(bottomPanel);
166            frame.pack();
167            frame.setVisible(true);
168    
169            mainSplitPane.setDividerLocation(0.5);
170            mainSplitPane.setResizeWeight(0.5);
171            versionsSplit.setDividerLocation(0.7);
172            versionsSplit.setResizeWeight(0.7);
173        }
174    
175        private JButton createLoadButton() {
176            JButton loadButton = new JButton("Load");
177            loadButton.addActionListener(new ActionListener() {
178    
179                public void actionPerformed(ActionEvent e) {
180                    frame.setCursor(new Cursor(Cursor.WAIT_CURSOR));
181                    PomLoaderThread pomLoader = new PomLoaderThread(workspaceLoader, "pom loader") {
182    
183                        public void run() {
184                            try {
185    
186                                duplicatesListManager.reset();
187                                duplicates.repaint();
188                                versions.repaint();
189    
190                                workspaceLoader.loadPom();
191                                if (workspaceLoader.getRoot() != null) {
192                                    workspaceLoader.getRoot().resolveDependencies(resolver, progressMeter);
193                                }
194                                progressMeter.ready();
195                            } catch (ArtifactInitialisationException e) {
196                                progressMeter.error(e);
197                                e.printStackTrace();
198                            } catch (RuntimeException e) {
199                                progressMeter.error(e);
200                                e.printStackTrace();
201                            }
202                            updateModel();
203                        }
204                    };
205                    pomLoader.start();
206                }
207    
208            });
209    
210            return loadButton;
211        }
212    
213        private JCheckBox createCheckBox(String label, final Controller.BooleanController bcontroller) {
214            JCheckBox checkBox = new JCheckBox(label, bcontroller.getValue());
215            checkBox.addActionListener(new ActionListener() {
216    
217                public void actionPerformed(ActionEvent e) {
218                    frame.setCursor(new Cursor(Cursor.WAIT_CURSOR));
219                    bcontroller.toggle();
220                    PomLoaderThread pomLoader = new PomLoaderThread(workspaceLoader, "pom loader") {
221    
222                        public void run() {
223                            try {
224                                duplicatesListManager.reset();
225                                workspaceLoader.reloadPom();
226                                workspaceLoader.getRoot().resolveDependencies(resolver, progressMeter);
227                                progressMeter.ready();
228                            } catch (ArtifactInitialisationException e) {
229                                progressMeter.error(e);
230                            } catch (RuntimeException e) {
231                                progressMeter.error(e);
232                            }
233                            updateModel();
234                        }
235                    };
236                    pomLoader.start();
237                }
238            });
239            return checkBox;
240        }
241    
242        private abstract class PomLoaderThread implements Runnable {
243    
244            protected WorkspaceLoader workspaceLoader;
245            private String name;
246    
247            public PomLoaderThread(WorkspaceLoader workspaceLoader, String name) {
248                this.workspaceLoader = workspaceLoader;
249                this.name = name;
250            }
251    
252            public void start() {
253                Thread thread = new Thread(this);
254                thread.setName(name);
255                thread.setDaemon(true);
256                thread.start();
257            }
258        }
259    
260        /**
261         * called by background thread to queue a gui model reload
262         */
263        public void updateModel() {
264            Runnable modelUpdate = new Runnable() {
265    
266                public void run() {
267                    tree.setModel(new DependencyTreeModel(workspaceLoader.getRoot()));
268                    versions.setModel(new VersionsTableModel(duplicatesListManager));
269                    duplicates.setModel(new DuplicatesTableModel(duplicatesListManager));
270                    frame.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
271                }
272            };
273            SwingUtilities.invokeLater(modelUpdate);
274        }
275    
276        /**
277         * extract the version number from the maven pom.properties file. fail silently if we can't find it as this
278         * functionality is optional.
279         */
280        private String loadVersion() {
281            InputStream resourceStream = DependencyBrowserGui.class.getResourceAsStream(PROPERTIES);
282            if (resourceStream == null) {
283                return "";
284            }
285            Properties properties = new Properties();
286            try {
287                properties.load(resourceStream);
288            } catch (IOException e) {
289                return "";
290            }
291            String version = properties.getProperty("version");
292            if (version == null || version.trim().length() == 0) {
293                return "";
294            }
295            return " " + version;
296        }
297    
298        private JButton createSnapshotButton() {
299            JButton snapshotButton = new JButton("Snapshot");
300            snapshotButton.setEnabled(repositorySnapshotFactory.isSnapshotEnabled());
301            snapshotButton.addActionListener(new ActionListener() {
302    
303                public void actionPerformed(ActionEvent e) {
304                    repositorySnapshotFactory.createSnapshot(progressMeter);
305                }
306            });
307            return snapshotButton;
308        }
309    }