diff --git a/pmd-jdeveloper1013/LICENSE.txt b/pmd-jdeveloper1013/LICENSE.txt new file mode 100644 index 0000000000..49e91d0d1d --- /dev/null +++ b/pmd-jdeveloper1013/LICENSE.txt @@ -0,0 +1,31 @@ +Copyright (c) 2003, InfoEther, LLC +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + * The end-user documentation included with the redistribution, if +any, must include the following acknowledgement: + "This product includes software developed in part by support from +the Defense Advanced Research Project Agency (DARPA)" + * Neither the name of InfoEther, LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/pmd-jdeveloper1013/etc/build.xml b/pmd-jdeveloper1013/etc/build.xml new file mode 100644 index 0000000000..1a7e9f5520 --- /dev/null +++ b/pmd-jdeveloper1013/etc/build.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pmd-jdeveloper1013/etc/changelog.txt b/pmd-jdeveloper1013/etc/changelog.txt new file mode 100644 index 0000000000..608df3fa01 --- /dev/null +++ b/pmd-jdeveloper1013/etc/changelog.txt @@ -0,0 +1,2 @@ +August 04, 2005 - 1.6: +Forked plugin code to provide a 10.1.13 version. diff --git a/pmd-jdeveloper1013/etc/doing_the_next_pmd_jdeveloper_release.txt b/pmd-jdeveloper1013/etc/doing_the_next_pmd_jdeveloper_release.txt new file mode 100644 index 0000000000..1d916a9167 --- /dev/null +++ b/pmd-jdeveloper1013/etc/doing_the_next_pmd_jdeveloper_release.txt @@ -0,0 +1,36 @@ +update the release date in the changelog +change the build.xml to reflect pmd-jdeveloper1013 release 1.6 +Update Plugin.version() to reflect release 1.6. + +Create the binary release: +ant release +TESTS: +1) Does it unzip neatly on top of the jdev/ext/lib directory? +2) Can you run it it on a file and find some unused code? +3) Are options persistant? + +Check everything in + +Create the src release: + +CVSROOT=:ext:tomcopeland@cvs.sourceforge.net:/cvsroot/pmd && export CVSROOT +cd ~/pmd/ +cvs -q tag -D tomorrow "pmd_jdeveloper1013_release_1_6" pmd-jdeveloper1013 +rm -rf ~/tmp/pmd-jdeveloper1013 +mkdir -p ~/tmp/pmd-jdeveloper1013 +cvs -q export -d tmp -r pmd_jdeveloper1013_release_1_6 pmd-jdeveloper1013 +mv tmp/* ~/tmp/pmd-jdeveloper1013 +rmdir tmp/ +cp pmd-jdeveloper1013/lib/pmd-jdeveloper1013-1.6.jar ~/tmp/pmd-jdeveloper1013/lib +cd ~/tmp +zip -q -r pmd-jdeveloper1013-src-1.6.zip pmd-jdeveloper1013 +ncftpput upload.sourceforge.net incoming/ pmd-jdeveloper1013-bin-1.6.zip pmd-jdeveloper1013-src-1.6.zip +rm -rf pmd-jdeveloper1013/ + +Go to Admin, Edit/Release Files, click on Add new release +Paste stuff into the changelog/readme boxes +Add the pmd-jdeveloper1013-src-1.6.zip file +Add the pmd-jdeveloper1013-bin-1.6.zip file +Classify the file + +Submit some news saying "hey, new release of the jdeveloper 1013 plugin!" diff --git a/pmd-jdeveloper1013/etc/jdev-ext.xml b/pmd-jdeveloper1013/etc/jdev-ext.xml new file mode 100644 index 0000000000..5677afd706 --- /dev/null +++ b/pmd-jdeveloper1013/etc/jdev-ext.xml @@ -0,0 +1,18 @@ + + +10.1.3 + + + + net.sourceforge.pmd.jdeveloper.Plugin + jaxen-core-1.0-fcs.jar + saxpath-1.0-fcs.jar + + net.sourceforge.pmd.jdeveloper.Plugin + General + Projects + + + + + diff --git a/pmd-jdeveloper1013/etc/scp.bat b/pmd-jdeveloper1013/etc/scp.bat new file mode 100755 index 0000000000..50fb731083 --- /dev/null +++ b/pmd-jdeveloper1013/etc/scp.bat @@ -0,0 +1,15 @@ +@echo off +set CVSROOT=:ext:tomcopeland@cvs.sourceforge.net:/cvsroot/pmd +set CVS_RSH=c:\data\bin\ssh\ssh +set HOME=c:\data +set ANT_HOME=c:\ant +set PATH=c:\j2sdk1.4.2_04\bin;c:\ant\bin\;%PATH% +set CLASSPATH=../build/ +set CLASSPATH=%CLASSPATH%;../ +set CLASSPATH=%CLASSPATH%;../lib/jaxen-core-1.0-fcs.jar +set CLASSPATH=%CLASSPATH%;../lib/saxpath-1.0-fcs.jar +set CLASSPATH=%CLASSPATH%;../lib/xercesImpl-2.6.2.jar +set CLASSPATH=%CLASSPATH%;../lib/xmlParserAPIs-2.6.2.jar +set CLASSPATH=%CLASSPATH%;c:\javacc2.1\bin\lib\JavaCC.zip +set CLASSPATH=%CLASSPATH%;c:\ant\lib\ant.jar +set CLASSPATH=%CLASSPATH%;c:\ant\lib\junit.j \ No newline at end of file diff --git a/pmd-jdeveloper1013/lib/ide.jar b/pmd-jdeveloper1013/lib/ide.jar new file mode 100644 index 0000000000..cbe668b5be Binary files /dev/null and b/pmd-jdeveloper1013/lib/ide.jar differ diff --git a/pmd-jdeveloper1013/lib/javatools.jar b/pmd-jdeveloper1013/lib/javatools.jar new file mode 100644 index 0000000000..472842d1a9 Binary files /dev/null and b/pmd-jdeveloper1013/lib/javatools.jar differ diff --git a/pmd-jdeveloper1013/lib/jaxen-core-1.0-fcs.jar b/pmd-jdeveloper1013/lib/jaxen-core-1.0-fcs.jar new file mode 100644 index 0000000000..e52bf679cc Binary files /dev/null and b/pmd-jdeveloper1013/lib/jaxen-core-1.0-fcs.jar differ diff --git a/pmd-jdeveloper1013/lib/jdev.jar b/pmd-jdeveloper1013/lib/jdev.jar new file mode 100644 index 0000000000..f0dda15d8d Binary files /dev/null and b/pmd-jdeveloper1013/lib/jdev.jar differ diff --git a/pmd-jdeveloper1013/lib/pmd-3.2.jar b/pmd-jdeveloper1013/lib/pmd-3.2.jar new file mode 100644 index 0000000000..e63aa7fbb3 Binary files /dev/null and b/pmd-jdeveloper1013/lib/pmd-3.2.jar differ diff --git a/pmd-jdeveloper1013/lib/saxpath-1.0-fcs.jar b/pmd-jdeveloper1013/lib/saxpath-1.0-fcs.jar new file mode 100644 index 0000000000..2b43955bab Binary files /dev/null and b/pmd-jdeveloper1013/lib/saxpath-1.0-fcs.jar differ diff --git a/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/FileStorage.java b/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/FileStorage.java new file mode 100644 index 0000000000..a5f51e2f74 --- /dev/null +++ b/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/FileStorage.java @@ -0,0 +1,59 @@ +package net.sourceforge.pmd.jdeveloper; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.util.Date; +import java.util.Iterator; +import java.util.Properties; + +public class FileStorage implements SettingsStorage { + + private File file; + + public FileStorage(File file) { + this.file = file; + } + + public void save(Properties newProperties) throws SettingsException { + try { + Properties savedProperties = new Properties(); + + if (file.exists()) { + FileInputStream fis = new FileInputStream(file); + savedProperties.load(fis); + fis.close(); + } + + for (Iterator i = newProperties.keySet().iterator(); i.hasNext();) { + String key = (String)i.next(); + String value = newProperties.getProperty(key); + savedProperties.setProperty(key, value); + } + + FileOutputStream fos = new FileOutputStream(file); + savedProperties.store(fos, "PMD-JDeveloper rule selections " + new Date()); + fos.close(); + } catch (Exception e) { + e.printStackTrace(); + throw new SettingsException(e.getMessage()); + } + } + + public String load(String key) throws SettingsException { + try { + if (file.exists()) { + Properties properties = new Properties(); + FileInputStream fis = new FileInputStream(file); + properties.load(fis); + fis.close(); + return properties.getProperty(key); + } + return "false"; + } catch (Exception e) { + e.printStackTrace(); + throw new SettingsException(e.getMessage()); + } + } + +} diff --git a/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/IDEStorage.java b/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/IDEStorage.java new file mode 100644 index 0000000000..d14a7592b1 --- /dev/null +++ b/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/IDEStorage.java @@ -0,0 +1,21 @@ +package net.sourceforge.pmd.jdeveloper; + +import oracle.ide.Ide; + +import java.util.Iterator; +import java.util.Properties; + +public class IDEStorage implements SettingsStorage { + + public void save(Properties props) throws SettingsException { + for (Iterator i = props.keySet().iterator(); i.hasNext();) { + String key = (String)i.next(); + String value = props.getProperty(key); + Ide.setProperty(key, value); + } + } + + public String load(String key) throws SettingsException { + return Ide.getProperty(key); + } +} diff --git a/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/JumpingSelectionModel.java b/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/JumpingSelectionModel.java new file mode 100644 index 0000000000..5dc04122db --- /dev/null +++ b/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/JumpingSelectionModel.java @@ -0,0 +1,36 @@ +package net.sourceforge.pmd.jdeveloper; + +import net.sourceforge.pmd.RuleViolation; +import oracle.ide.editor.EditorManager; +import oracle.ide.net.URLFactory; +import oracle.jdeveloper.ceditor.CodeEditor; + +import javax.swing.*; + +/** + * This class was inspired by a class on Sun's web site in the JList tutorial section. It's + * been twiddled somewhat since then. + */ +public class JumpingSelectionModel extends DefaultListSelectionModel { + + private DefaultListModel model; + + public JumpingSelectionModel(DefaultListModel model) { + this.model = model; + } + + public JumpingSelectionModel() { + setSelectionMode(SINGLE_SELECTION); + } + + public void setSelectionInterval(int index0, int index1) { + int oldIndex = getMinSelectionIndex(); + super.setSelectionInterval(index0, index1); + int newIndex = getMinSelectionIndex(); + if (oldIndex != newIndex) { + RuleViolation rv = ((RuleViolationWrapper)model.getElementAt(newIndex)).getRuleViolation(); + EditorManager.getEditorManager().openDefaultEditorInFrame(URLFactory.newFileURL(rv.getFilename())); + ((CodeEditor)EditorManager.getEditorManager().getCurrentEditor()).gotoLine(rv.getLine(), 0, false); + } + } +} diff --git a/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/Plugin.java b/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/Plugin.java new file mode 100644 index 0000000000..8a67b556a2 --- /dev/null +++ b/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/Plugin.java @@ -0,0 +1,181 @@ +package net.sourceforge.pmd.jdeveloper; + +import net.sourceforge.pmd.*; +import oracle.ide.AddinManager; +import oracle.ide.ContextMenu; +import oracle.ide.Ide; +import oracle.ide.IdeAction; +import oracle.ide.addin.Addin; +import oracle.ide.addin.Context; +import oracle.ide.addin.ContextMenuListener; +import oracle.ide.addin.Controller; +import oracle.ide.config.IdeSettings; +import oracle.ide.editor.EditorManager; +import oracle.ide.log.LogManager; +import oracle.ide.model.Element; +import oracle.ide.model.Project; +import oracle.ide.navigator.NavigatorManager; +import oracle.ide.panels.Navigable; +import oracle.jdeveloper.model.JProject; +import oracle.jdeveloper.model.JavaSourceNode; + +import javax.swing.*; +import java.io.File; +import java.io.FileInputStream; +import java.util.Iterator; + +public class Plugin implements Addin, Controller, ContextMenuListener { + + public static final String CHECK_CMD = "net.sourceforge.pmd.jdeveloper.Check"; + public static final int CHECK_CMD_ID = Ide.createCmdID("PMDJDeveloperPlugin.CHECK_CMD_ID"); + public static final String TITLE = "PMD"; + + private static final int UNUSED = -1; + private static final int SOURCE = 0; + private static final int PROJECT = 6; + + private JMenuItem checkItem; + private RuleViolationPage rvPage; + + public Plugin() { + super(); + } + + // Addin + public void initialize() { + IdeAction action = IdeAction.get(CHECK_CMD_ID, AddinManager.getAddinManager().getCommand(CHECK_CMD_ID, CHECK_CMD), TITLE, TITLE, null, null, null, true); + action.addController(this); + checkItem = Ide.getMenubar().createMenuItem(action); + checkItem.setText(TITLE); + checkItem.setMnemonic('P'); + NavigatorManager.getWorkspaceNavigatorManager().addContextMenuListener(this, null); + EditorManager.getEditorManager().getContextMenu().addContextMenuListener(this, null); + IdeSettings.registerUI(new Navigable(TITLE, SettingsPanel.class, new Navigable[] {})); + Ide.getVersionInfo().addComponent(TITLE, " JDeveloper Extension " + version()); + rvPage = new RuleViolationPage(); + } + + public void shutdown() { + NavigatorManager.getWorkspaceNavigatorManager().removeContextMenuListener(this); + EditorManager.getEditorManager().getContextMenu().removeContextMenuListener(this); + } + + public float version() { + return 1.6f; + } + + public float ideVersion() { + return 0.1f; + } + + public boolean canShutdown() { + return true; + } + // Addin + + // Controller + public Controller supervisor() { + return null; + } + + private boolean added; + + public boolean handleEvent(IdeAction ideAction, Context context) { + if (!added) { + LogManager.getLogManager().addPage(rvPage); + LogManager.getLogManager().showLog(); + added = true; + } + if (ideAction.getCommandId() == CHECK_CMD_ID) { + try { + PMD pmd = new PMD(); + SelectedRules rs = new SelectedRules(SettingsPanel.createSettingsStorage()); + RuleContext ctx = new RuleContext(); + ctx.setReport(new Report()); + if (resolveType(context.getDocument()) == PROJECT) { + Project project = (Project)context.getDocument(); + Iterator kids = project.getChildren(); + while (kids.hasNext()) { + Object obj = kids.next(); + if (!(obj instanceof JavaSourceNode)) { + continue; + } + JavaSourceNode jsn = (JavaSourceNode)obj; + LogManager.getLogManager().getMsgPage().log(jsn.getSourceFile()); + if (jsn.getLongLabel().endsWith(".java") && new File(jsn.getLongLabel()).exists()) { + ctx.setSourceCodeFilename(jsn.getLongLabel()); + FileInputStream fis = new FileInputStream(new File(jsn.getLongLabel())); + pmd.processFile(fis, rs.getSelectedRules(), ctx); + fis.close(); + } + } + render(ctx); + } else if (resolveType(context.getDocument()) == SOURCE) { + ctx.setSourceCodeFilename(context.getDocument().getLongLabel()); + pmd.processFile(context.getDocument().getInputStream(), rs.getSelectedRules(), ctx); + render(ctx); + } + return true; + } catch (PMDException e) { + e.printStackTrace(); + e.getReason().printStackTrace(); + JOptionPane.showMessageDialog(null, "Error while running PMD: " + e.getMessage(), TITLE, JOptionPane.ERROR_MESSAGE); + } catch (Exception e) { + e.printStackTrace(); + JOptionPane.showMessageDialog(null, "Error while running PMD: " + e.getMessage(), TITLE, JOptionPane.ERROR_MESSAGE); + } + } + return true; + } + + /** + * TODO investigate CompilerPage as a replacement for RuleViolationPage; or could perhaps subclass it instead. + */ + private void render(RuleContext ctx) { + rvPage.show(); + rvPage.clearAll(); + if (ctx.getReport().isEmpty()) { + JOptionPane.showMessageDialog(null, "No problems found", TITLE, JOptionPane.INFORMATION_MESSAGE); + LogManager.getLogManager().getMsgPage().show(); + } else { + for (Iterator i = ctx.getReport().iterator(); i.hasNext();) { + rvPage.add((RuleViolation)i.next()); + } + } + } + + public boolean update(IdeAction ideAction, Context context) { + return false; + } + + public void checkCommands(Context context, Controller controller) {} + // Controller + + // ContextMenuListener + public void poppingUp(ContextMenu contextMenu) { + Element doc = contextMenu.getContext().getDocument(); + if (resolveType(doc) == PROJECT || resolveType(doc) == SOURCE) { + contextMenu.add(checkItem); + } + } + + public void poppingDown(ContextMenu contextMenu) {} + + public boolean handleDefaultAction(Context context) { + return false; + } + // ContextMenuListener + + public static String getVersion() { + return Package.getPackage("net.sourceforge.pmd.jdeveloper").getImplementationVersion(); + } + + private int resolveType(Element element) { + if (element instanceof JavaSourceNode) { + return SOURCE; + } else if (element instanceof JProject) { + return PROJECT; + } + return UNUSED; + } +} diff --git a/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/RuleViolationPage.java b/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/RuleViolationPage.java new file mode 100644 index 0000000000..245aa2fd42 --- /dev/null +++ b/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/RuleViolationPage.java @@ -0,0 +1,34 @@ +package net.sourceforge.pmd.jdeveloper; + +import net.sourceforge.pmd.RuleViolation; +import oracle.ide.layout.ViewId; +import oracle.ide.log.AbstractLogPage; + +import javax.swing.*; +import java.awt.*; + +public class RuleViolationPage extends AbstractLogPage { + + private DefaultListModel model = new DefaultListModel(); + private JScrollPane scrollPane; + private JList list; + + public RuleViolationPage() { + super(new ViewId("PMDPage", Plugin.TITLE), null, false); + list = new JList(model); + list.setSelectionModel(new JumpingSelectionModel(model)); + scrollPane = new JScrollPane(list); + } + + public void add(RuleViolation ruleViolation) { + model.addElement(new RuleViolationWrapper(ruleViolation)); + } + + public Component getGUI() { + return scrollPane; + } + + public void clearAll() { + model.clear(); + } +} diff --git a/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/RuleViolationWrapper.java b/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/RuleViolationWrapper.java new file mode 100644 index 0000000000..bbbcd192cf --- /dev/null +++ b/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/RuleViolationWrapper.java @@ -0,0 +1,20 @@ +package net.sourceforge.pmd.jdeveloper; + +import net.sourceforge.pmd.RuleViolation; + +public class RuleViolationWrapper { + + private RuleViolation ruleViolation; + + public RuleViolationWrapper(RuleViolation ruleViolation) { + this.ruleViolation = ruleViolation; + } + + public RuleViolation getRuleViolation() { + return this.ruleViolation; + } + + public String toString() { + return ruleViolation.getFilename() + "; line " + ruleViolation.getLine() +"; ("+ ruleViolation.getRule().getName() + ") " + ruleViolation.getDescription(); + } +} diff --git a/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/SelectedRules.java b/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/SelectedRules.java new file mode 100644 index 0000000000..71199f62bf --- /dev/null +++ b/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/SelectedRules.java @@ -0,0 +1,96 @@ +package net.sourceforge.pmd.jdeveloper; + +import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.RuleSet; +import net.sourceforge.pmd.RuleSetFactory; +import net.sourceforge.pmd.RuleSetNotFoundException; + +import javax.swing.*; +import java.util.*; + +public class SelectedRules { + + // Rule -> JCheckBox + private Map rules = new TreeMap(new Comparator() { + public int compare(Object o1, Object o2) { + Rule r1 = (Rule)o1; + Rule r2 = (Rule)o2; + return r1.getName().compareTo(r2.getName()); + } + }); + + public SelectedRules(SettingsStorage settings) throws RuleSetNotFoundException { + RuleSetFactory rsf = new RuleSetFactory(); + for (Iterator i = rsf.getRegisteredRuleSets(); i.hasNext();) { + RuleSet rs = (RuleSet)i.next(); + for (Iterator j = rs.getRules().iterator(); j.hasNext();) { + Rule rule = (Rule)j.next(); + rules.put(rule, createCheckBox(rule.getName(), settings)); + } + } + } + + public int size() { + return rules.size(); + } + + public Rule getRule(JCheckBox candidate) { + for (Iterator i = rules.keySet().iterator(); i.hasNext();) { + Rule rule = (Rule)i.next(); + JCheckBox box = (JCheckBox)rules.get(rule); + if (box.equals(candidate)) { + return rule; + } + } + throw new RuntimeException("Couldn't find a rule that mapped to the passed in JCheckBox " + candidate); + } + + public JCheckBox get(Object key) { + return (JCheckBox)rules.get(key); + } + + public Object[] getAllBoxes() { + Object[] foo = new Object[rules.size()]; + int idx = 0; + for (Iterator i = rules.values().iterator(); i.hasNext();) { + foo[idx] = i.next(); + idx++; + } + return foo; + } + + public void save(SettingsStorage settings) throws SettingsException { + Properties properties = new Properties(); + for (Iterator i = rules.keySet().iterator(); i.hasNext();) { + Rule rule = (Rule)i.next(); + properties.setProperty("pmd.rule." + rule.getName(), String.valueOf(get(rule).isSelected())); + } + settings.save(properties); + } + + public RuleSet getSelectedRules() { + RuleSet newRuleSet = new RuleSet(); + for (Iterator i = rules.keySet().iterator(); i.hasNext();) { + Rule rule = (Rule)i.next(); + if (get(rule).isSelected()) { + newRuleSet.addRule(rule); + } + } + return newRuleSet; + } + + private JCheckBox createCheckBox(String name, SettingsStorage settings) { + JCheckBox box = new JCheckBox(name); + try { + box.setSelected(load(settings, name)); + } catch (SettingsException se) { + System.out.println("Can't load settings so this rule will not be enabled"); + } + return box; + } + + private boolean load(SettingsStorage settings, String name) throws SettingsException { + return Boolean.valueOf(settings.load("pmd.rule." + name)).booleanValue(); + } + +} diff --git a/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/SettingsException.java b/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/SettingsException.java new file mode 100644 index 0000000000..f4bee4adc6 --- /dev/null +++ b/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/SettingsException.java @@ -0,0 +1,7 @@ +package net.sourceforge.pmd.jdeveloper; + +public class SettingsException extends Exception { + public SettingsException(String ex) { + super(ex); + } +} diff --git a/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/SettingsPanel.java b/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/SettingsPanel.java new file mode 100644 index 0000000000..cb3cd1cc5e --- /dev/null +++ b/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/SettingsPanel.java @@ -0,0 +1,155 @@ +package net.sourceforge.pmd.jdeveloper; + +import net.sourceforge.pmd.RuleSetNotFoundException; +import oracle.ide.Ide; +import oracle.ide.panels.DefaultTraversablePanel; +import oracle.ide.panels.TraversableContext; + +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.File; + +public class SettingsPanel extends DefaultTraversablePanel { + + + private class FindListener implements ActionListener { + public void actionPerformed(ActionEvent evt){ + FileDialog fdlg = new FileDialog(new Frame(), "Find", FileDialog.LOAD); + fdlg.setVisible(true); + String selected = fdlg.getDirectory() + fdlg.getFile(); + if (fdlg.getFile() == null) { + return; + } + selectedRulesSeparateFileNameField.setText(selected); + } + } + + public class CheckboxList extends JList { + + private class MyMouseAdapter extends MouseAdapter { + public void mouseEntered(MouseEvent e) { + int index = locationToIndex(e.getPoint()); + if (index != -1) { + JCheckBox box = (JCheckBox)getModel().getElementAt(index); + String example = rules.getRule(box).getExample(); + exampleTextArea.setText(example); + exampleTextArea.setCaretPosition(0); + } + } + + public void mousePressed(MouseEvent e) { + int index = locationToIndex(e.getPoint()); + if (index != -1) { + JCheckBox box = (JCheckBox)getModel().getElementAt(index); + box.setSelected(!box.isSelected()); + repaint(); + } + } + } + + public class CheckboxListCellRenderer implements ListCellRenderer { + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + JCheckBox box = (JCheckBox)value; + box.setEnabled(isEnabled()); + box.setFont(getFont()); + box.setFocusPainted(false); + box.setBorderPainted(true); + box.setBorder(isSelected ? UIManager.getBorder("List.focusCellHighlightBorder") : new EmptyBorder(1,1,1,1)); + return box; + } + } + + public CheckboxList(Object[] args) { + super(args); + setCellRenderer(new CheckboxListCellRenderer()); + addMouseListener(new MyMouseAdapter()); + } + + } + + public static final String RULE_SELECTIONS_STORED_SEPARATELY = "pmd.settings.separate"; + public static final String RULE_SELECTIONS_FILENAME = "pmd.settings.separate.name"; + + private JTextArea exampleTextArea= new JTextArea(10, 50); + private JCheckBox selectedRulesStoredSeparatelyBox = new JCheckBox("", Boolean.valueOf(Ide.getProperty(RULE_SELECTIONS_STORED_SEPARATELY)).booleanValue()); + private JTextField selectedRulesSeparateFileNameField = new JTextField(30); + private SelectedRules rules; + + public static SettingsStorage createSettingsStorage() { + if (Boolean.valueOf(Ide.getProperty(RULE_SELECTIONS_STORED_SEPARATELY)).booleanValue()) { + return new FileStorage(new File(Ide.getProperty(RULE_SELECTIONS_FILENAME))); + } + return new IDEStorage(); + } + + public void onEntry(TraversableContext tc) { + removeAll(); + try { + rules = new SelectedRules(createSettingsStorage()); + } catch (RuleSetNotFoundException rsne) { + rsne.printStackTrace(); + } + + JPanel mainPanel = new JPanel(new BorderLayout()); + mainPanel.add(createTopPanel(), BorderLayout.NORTH); + mainPanel.add(createRulesSelectionPanel(), BorderLayout.SOUTH); + add(mainPanel); + } + + private JPanel createRulesSelectionPanel() { + JPanel checkBoxesPanel = new JPanel(); + checkBoxesPanel.setBorder(BorderFactory.createTitledBorder("Rules")); + JList rulesList = new CheckboxList(rules.getAllBoxes()); + rulesList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + checkBoxesPanel.add(new JScrollPane(rulesList), BorderLayout.NORTH); + JPanel examplePanel = new JPanel(); + examplePanel.setBorder(BorderFactory.createTitledBorder("Example")); + examplePanel.add(new JScrollPane(exampleTextArea)); + JPanel rulesSelectionPanel = new JPanel(); + rulesSelectionPanel.setLayout(new BorderLayout()); + rulesSelectionPanel.add(checkBoxesPanel, BorderLayout.NORTH); + rulesSelectionPanel.add(examplePanel, BorderLayout.CENTER); + return rulesSelectionPanel; + } + + private JPanel createTopPanel() { + selectedRulesSeparateFileNameField.setText(Ide.getProperty(RULE_SELECTIONS_FILENAME)); + selectedRulesStoredSeparatelyBox.setSelected(Boolean.valueOf(Ide.getProperty(RULE_SELECTIONS_STORED_SEPARATELY)).booleanValue()); + + JPanel topPanel = new JPanel(new BorderLayout()); + topPanel.add(new JLabel(" InfoEther(tm) PMD JDeveloper plugin"), BorderLayout.NORTH); + JPanel customStoragePanel = new JPanel(new BorderLayout()); + customStoragePanel.setBorder(BorderFactory.createTitledBorder("Settings storage")); + + JPanel customStorageCheckBoxPanel = new JPanel(); + customStorageCheckBoxPanel.add(new JLabel("Use centrally managed rule settings?")); + customStorageCheckBoxPanel.add(selectedRulesStoredSeparatelyBox); + customStoragePanel.add(customStorageCheckBoxPanel, BorderLayout.NORTH); + + JPanel customStorageTextFieldPanel = new JPanel(); + customStorageTextFieldPanel.add(new JLabel("File:")); + customStorageTextFieldPanel.add(selectedRulesSeparateFileNameField); + JButton findButton = new JButton("Find file"); + findButton.addActionListener(new FindListener()); + customStorageTextFieldPanel.add(findButton); + + customStoragePanel.add(customStorageTextFieldPanel, BorderLayout.SOUTH); + topPanel.add(customStoragePanel, BorderLayout.CENTER); + return topPanel; + } + + public void onExit(TraversableContext tc) { + Ide.setProperty(RULE_SELECTIONS_STORED_SEPARATELY, String.valueOf(selectedRulesStoredSeparatelyBox.isSelected())); + Ide.setProperty(RULE_SELECTIONS_FILENAME, selectedRulesSeparateFileNameField.getText()); + try { + rules.save(createSettingsStorage()); + } catch (SettingsException se) { + JOptionPane.showMessageDialog(null, "Can't save selected rules to the file " + selectedRulesSeparateFileNameField.getText() + ":" + se.getMessage(), "Can't save settings", JOptionPane.ERROR_MESSAGE); + } + } +} diff --git a/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/SettingsStorage.java b/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/SettingsStorage.java new file mode 100644 index 0000000000..af2c90030f --- /dev/null +++ b/pmd-jdeveloper1013/src/net/sourceforge/pmd/jdeveloper/SettingsStorage.java @@ -0,0 +1,8 @@ +package net.sourceforge.pmd.jdeveloper; + +import java.util.Properties; + +public interface SettingsStorage { + void save(Properties props) throws SettingsException; + String load(String key) throws SettingsException; +}