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;
+}