[hg] main-silver: removed tasklistproviders, replaced add to act...

  • From: Tomas Stupka < >
  • To: ,
  • Subject: [hg] main-silver: removed tasklistproviders, replaced add to act...
  • Date: Fri, 03 May 2013 03:47:58 -0700

changeset 78b0a866474f in main-silver ((none))
details: http://hg.netbeans.org/main-silver/rev/78b0a866474f
description:
        removed tasklistproviders, replaced add to action items with add to 
category

diffstat:

 bugtracking/src/org/netbeans/modules/bugtracking/DelegatingConnector.java    
     |    7 -
 
bugtracking/src/org/netbeans/modules/bugtracking/spi/BugtrackingConnector.java
    |    8 -
 bugtracking/src/org/netbeans/modules/bugtracking/spi/BugtrackingFactory.java 
     |   15 +
 
bugtracking/src/org/netbeans/modules/bugtracking/spi/TaskListIssueProvider.java
   |  205 --
 bugtracking/src/org/netbeans/modules/bugtracking/tasklist/Bundle.properties  
     |   51 -
 
bugtracking/src/org/netbeans/modules/bugtracking/tasklist/TaskListProvider.java
   |  495 -----
 
bugtracking/src/org/netbeans/modules/bugtracking/tasks/DashboardTopComponent.java
 |    5 +
 bugzilla/src/org/netbeans/modules/bugzilla/Bugzilla.java                     
     |   10 -
 bugzilla/src/org/netbeans/modules/bugzilla/BugzillaConfig.java               
     |   99 -
 bugzilla/src/org/netbeans/modules/bugzilla/BugzillaConnector.java            
     |    8 -
 
bugzilla/src/org/netbeans/modules/bugzilla/issue/BugzillaTaskListProvider.java
    |  866 ---------
 bugzilla/src/org/netbeans/modules/bugzilla/issue/Bundle.properties           
     |    3 +-
 bugzilla/src/org/netbeans/modules/bugzilla/issue/IssuePanel.form             
     |    8 +-
 bugzilla/src/org/netbeans/modules/bugzilla/issue/IssuePanel.java             
     |  104 +-
 
bugzilla/src/org/netbeans/modules/bugzilla/repository/BugzillaRepository.java 
    |    4 -
 
bugzilla/test/unit/src/org/netbeans/modules/bugzilla/query/QueryRefreshTest.java
  |    6 -
 jira/src/org/netbeans/modules/jira/Jira.java                                 
     |    9 -
 jira/src/org/netbeans/modules/jira/JiraConnector.java                        
     |    8 -
 jira/src/org/netbeans/modules/jira/issue/Bundle.properties                   
     |    3 +-
 jira/src/org/netbeans/modules/jira/issue/IssuePanel.form                     
     |    9 +-
 jira/src/org/netbeans/modules/jira/issue/IssuePanel.java                     
     |   85 +-
 jira/src/org/netbeans/modules/jira/issue/JiraTaskListProvider.java           
     |  888 ----------
 jira/src/org/netbeans/modules/jira/repository/JiraRepository.java            
     |    3 -
 jira/src/org/netbeans/modules/jira/repository/JiraStorageManager.java        
     |   98 -
 24 files changed, 61 insertions(+), 2936 deletions(-)

diffs (truncated from 3536 to 3000 lines):

diff --git 
a/bugtracking/src/org/netbeans/modules/bugtracking/DelegatingConnector.java 
b/bugtracking/src/org/netbeans/modules/bugtracking/DelegatingConnector.java
--- 
a/bugtracking/src/org/netbeans/modules/bugtracking/DelegatingConnector.java
+++ 
b/bugtracking/src/org/netbeans/modules/bugtracking/DelegatingConnector.java
@@ -48,7 +48,6 @@
 import org.netbeans.modules.bugtracking.spi.BugtrackingConnector;
 import org.netbeans.modules.bugtracking.spi.IssueFinder;
 import org.netbeans.modules.bugtracking.spi.RepositoryInfo;
-import org.netbeans.modules.bugtracking.spi.TaskListIssueProvider;
 import org.openide.util.ImageUtilities;
 
 /**
@@ -144,10 +143,4 @@
         return d != null ? d.createRepository() : null;
     }
 
-    @Override
-    public TaskListIssueProvider getTasklistProvider() {
-        BugtrackingConnector d = getDelegate();
-        return d != null ? d.getTasklistProvider() : null;
     }
-
-}
diff --git 
a/bugtracking/src/org/netbeans/modules/bugtracking/spi/BugtrackingConnector.java
 
b/bugtracking/src/org/netbeans/modules/bugtracking/spi/BugtrackingConnector.java
--- 
a/bugtracking/src/org/netbeans/modules/bugtracking/spi/BugtrackingConnector.java
+++ 
b/bugtracking/src/org/netbeans/modules/bugtracking/spi/BugtrackingConnector.java
@@ -83,14 +83,6 @@
         return null;
     }
 
-    /**
-     * @deprecated issue won't be added to the tasklist anymore. 
-     * @return 
-     */
-    public TaskListIssueProvider getTasklistProvider() {
-        return null;
-    }
-    
     @Retention(RetentionPolicy.SOURCE)
     @Target({ElementType.TYPE, ElementType.METHOD})
     public @interface Registration {    
diff --git 
a/bugtracking/src/org/netbeans/modules/bugtracking/spi/BugtrackingFactory.java
 
b/bugtracking/src/org/netbeans/modules/bugtracking/spi/BugtrackingFactory.java
--- 
a/bugtracking/src/org/netbeans/modules/bugtracking/spi/BugtrackingFactory.java
+++ 
b/bugtracking/src/org/netbeans/modules/bugtracking/spi/BugtrackingFactory.java
@@ -37,8 +37,11 @@
  */
 package org.netbeans.modules.bugtracking.spi;
 
+import javax.swing.SwingUtilities;
 import org.netbeans.modules.bugtracking.*;
 import org.netbeans.modules.bugtracking.api.Repository;
+import org.netbeans.modules.bugtracking.tasks.DashboardTopComponent;
+import org.netbeans.modules.bugtracking.tasks.dashboard.DashboardViewer;
 import org.netbeans.modules.bugtracking.util.BugtrackingUtil;
 import org.netbeans.modules.bugtracking.util.UndoRedoSupport;
 
@@ -102,6 +105,18 @@
         }
     }
     
+    public void addToCategory(final Repository repository, final I i) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                IssueImpl issue = getIssueImpl(repository, i);
+                if (issue != null) {
+                    
DashboardTopComponent.findInstance().addTask(issue.getIssue());
+                }
+            }
+        });
+    }
+    
     public UndoRedoSupport getUndoRedoSupport(Repository repository, I i) {
         return UndoRedoSupport.getSupport(getIssueImpl(repository, i));
     }
diff --git 
a/bugtracking/src/org/netbeans/modules/bugtracking/spi/TaskListIssueProvider.java
 
b/bugtracking/src/org/netbeans/modules/bugtracking/spi/TaskListIssueProvider.java
deleted file mode 100644
--- 
a/bugtracking/src/org/netbeans/modules/bugtracking/spi/TaskListIssueProvider.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
- *
- * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
- * Other names may be trademarks of their respective owners.
- *
- * 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle 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 2009 Sun Microsystems, Inc.
- */
-
-package org.netbeans.modules.bugtracking.spi;
-
-import java.net.URL;
-import java.util.List;
-import javax.swing.Action;
-import org.netbeans.modules.bugtracking.spi.TaskListIssueProvider.LazyIssue;
-import org.netbeans.modules.bugtracking.tasklist.TaskListProvider;
-
-/**
- * Represents a provider of issues for the tasklist. Extend if you want to 
add your issues into the tasklist.
- * 
- * @author Ondra Vrabec
- */
-public abstract class TaskListIssueProvider {
-
-    /**
-     * Adds issues to the task list.
-     * @param openTaskList also opens the TaskList top component if set to 
<code>true</code>
-     * @param issuesToAdd issues to add
-     */
-    protected void add (boolean openTaskList, LazyIssue... issuesToAdd) {
-        TaskListProvider.getInstance().add(this, openTaskList, issuesToAdd);
-    }
-
-    /**
-     * Adds issues to the task list.
-     * @param issuesToAdd issues to add
-     */
-    protected void add (LazyIssue... issuesToAdd) {
-        add(false, issuesToAdd);
-    }
-
-    /**
-     * Removes issues from the task list.
-     * @param issuesToAdd issues to remove
-     */
-    protected void remove (LazyIssue... issuesToAdd) {
-        TaskListProvider.getInstance().remove(this, issuesToAdd);
-    }
-
-    /**
-     * Removes all issues previously added by this instance
-     */
-    protected void removeAll () {
-        TaskListProvider.getInstance().removeAll(this);
-    }
-
-    /**
-     * Called when an issue is removed from the TaskList in other way than 
through {@link 
#remove(org.netbeans.modules.bugtracking.util.IssueTaskListProvider.LazyIssue[])}
-     * or {@link #removeAll() }
-     * @param lazyIssue
-     */
-    public abstract void removed(LazyIssue lazyIssue);
-
-    /**
-     * Represents an issue displayed in the tasklist.
-     */
-    public static abstract class LazyIssue {
-        private final URL url;
-        private String name;
-        private boolean valid;
-
-        /**
-         *
-         * @param url url of the issue, cannot be null
-         * @param name displayed name showed in the tasklist
-         * @throws NullPointerException if url or name is null
-         */
-        public LazyIssue (URL url, String name) {
-            if (url == null) {
-                throw new NullPointerException();
-            }
-            if (name == null) {
-                throw new NullPointerException();
-            }
-            this.url = url;
-            this.name = name;
-        }
-
-        /**
-         * Returns displayed name of the issue
-         * @return displayed name of the issue
-         */
-        public final String getName () {
-            return name;
-        }
-
-        /**
-         * Sets the issue's name and refreshes the tasklist
-         * @param name new issue's name. If set to <code>null</code>, no 
action is taken.
-         */
-        protected final void setName (String name) {
-            if (name != null) {
-                this.name = name;
-                setValid(false);
-            }
-        }
-
-        /**
-         * /**
-         * Returns url of the issue
-         * @return url of the issue
-         */
-        public final URL getUrl () {
-            return url;
-        }
-
-        @Override
-        public final boolean equals(Object obj) {
-            if (obj != null && obj instanceof LazyIssue) {
-                return 
this.url.toString().equals(((LazyIssue)obj).url.toString());
-            }
-            return false;
-        }
-
-        @Override
-        public final int hashCode() {
-            return url.toString().hashCode();
-        }
-
-        /**
-         * If the issue is not valid (previously invalidated by {@link 
#setValid(boolean)},
-         * this will result in repainting the issue in the tasklist after 
it's next refresh.
-         * @return true if the issue is valid, false otherwise
-         */
-        public final boolean isValid() {
-            return valid;
-        }
-
-        /**
-         * Sets issues validity status.
-         * @param valid false will result in refreshing the issue in the 
next tasklist's refresh.
-         */
-        public final void setValid (boolean valid) {
-            this.valid = valid;
-            if (!valid) {
-                TaskListProvider.getInstance().refresh();
-            }
-        }
-
-        /**
-         * Implement this and return the url of the repository the issue is 
in.
-         * The value is used in deciding if the issue shall be displayed or 
hidden in the current tasklist's scope.
-         * @return name of the issuetracking repository the issue is in.
-         */
-        public abstract String getRepositoryUrl();
-
-        /**
-         * Implement this and return a list of actions you wish to be 
displayed in the popup menu of the issue in the tasklist.
-         * <strong>Note </strong> that actions <em>Open</em> and 
<em>Remove</em> are automatically displayed and they should not be
-         * items of the list
-         * @return list of actions displayed in the issue's popup menu.
-         */
-        public abstract List<? extends Action> getActions();
-
-        @Override
-        public String toString () {
-            return super.toString() + ": " + getName();                 
//NOI18N
-        }
-
-        public abstract void open();
-    }
-}
diff --git 
a/bugtracking/src/org/netbeans/modules/bugtracking/tasklist/Bundle.properties 
b/bugtracking/src/org/netbeans/modules/bugtracking/tasklist/Bundle.properties
deleted file mode 100644
--- 
a/bugtracking/src/org/netbeans/modules/bugtracking/tasklist/Bundle.properties
+++ /dev/null
@@ -1,51 +0,0 @@
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
-#
-# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
-#
-# Oracle and Java are registered trademarks of Oracle and/or its affiliates.
-# Other names may be trademarks of their respective owners.
-#
-# 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.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle 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-2009 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.
-
-LBL_TaskListProvider_DisplayName=Issues
-LBL_TaskListProvider_Description=List of currently watched issues
-LBL_issue_group=Issues
-HINT_issue_group=List of currently watched issues
-#NOI18N
-ICON_issue=org/netbeans/modules/bugtracking/ui/resources/bugtracking.png
-
-TaskListProvider.Action.open.name=Open Issue
-TaskListProvider.Action.remove.name=Remove
diff --git 
a/bugtracking/src/org/netbeans/modules/bugtracking/tasklist/TaskListProvider.java
 
b/bugtracking/src/org/netbeans/modules/bugtracking/tasklist/TaskListProvider.java
deleted file mode 100644
--- 
a/bugtracking/src/org/netbeans/modules/bugtracking/tasklist/TaskListProvider.java
+++ /dev/null
@@ -1,495 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
- *
- * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
- * Other names may be trademarks of their respective owners.
- *
- * 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle 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 2009 Sun Microsystems, Inc.
- */
-
-package org.netbeans.modules.bugtracking.tasklist;
-
-import java.awt.EventQueue;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.lang.ref.WeakReference;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.WeakHashMap;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.swing.AbstractAction;
-import javax.swing.Action;
-import org.netbeans.modules.bugtracking.*;
-import org.netbeans.modules.bugtracking.ide.spi.ProjectServices;
-import org.netbeans.modules.bugtracking.util.BugtrackingOwnerSupport;
-import org.netbeans.modules.bugtracking.spi.TaskListIssueProvider;
-import org.netbeans.modules.bugtracking.spi.TaskListIssueProvider.LazyIssue;
-import org.netbeans.spi.tasklist.PushTaskScanner;
-import org.netbeans.spi.tasklist.Task;
-import org.netbeans.spi.tasklist.TaskScanningScope;
-import org.openide.filesystems.FileObject;
-import org.openide.util.NbBundle;
-import org.openide.util.RequestProcessor;
-import org.openide.util.WeakSet;
-import org.openide.windows.TopComponent;
-import org.openide.windows.WindowManager;
-
-/**
- * Provider of issues/tasks for the tasklist. Keeps issues to display in the 
tasklist 
- * and acts as a bridge between the issuetracking and the tasklist.
- *
- * @author Ondra Vrabec
- */
-public final class TaskListProvider extends PushTaskScanner {
-    
-    private static TaskListProvider instance; //this class is a singleton
-
-    // tasklist oriented fields
-    private Callback callback;
-    private TaskScanningScope scope;
-    private WeakReference<TaskScanningScope> lastScope = new 
WeakReference<TaskScanningScope>(null);
-    private static final Object SCOPE_LOCK = new Object();
-    private static final String TASK_GROUP_NAME = "nb-tasklist-issue";  
//NOI18N
-    private static final String TC_TASKLIST_ID = "TaskListTopComponent"; 
//NOI18N
-
-    // issue-task mapping oriented fields
-    /**
-     * all cached tasks, a subset is selected and displayed in the tasklist 
when it's scope changes
-     */
-    private final WeakHashMap<TaskListIssueProvider.LazyIssue, Task> 
cachedTasks;
-    private final WeakHashMap<TaskListIssueProvider, 
Set<TaskListIssueProvider.LazyIssue> > cachedIssues;
-    private final WeakSet<TaskListIssueProvider.LazyIssue> validatedIssues;
-    /**
-     * Set of providers whose issues need to be validated. Validate means 
test if they belong to the current tasklist scope.
-     */
-    private final HashSet<TaskListIssueProvider> providersToValidate;
-    
-    private boolean providersInitialized;
-    public static final Logger LOG = 
Logger.getLogger("org.netbeans.modules.bugtracking.tasklist"); //NOI18N
-
-    private final RequestProcessor.Task refreshTask = new 
RequestProcessor("IssuesToTaskListProvider", 1, true).create(new 
RefreshTask()); //NOI18N
-
-    private TaskListProvider () {
-        super(NbBundle.getMessage(TaskListProvider.class, 
"LBL_TaskListProvider_DisplayName"), 
NbBundle.getMessage(TaskListProvider.class, 
"LBL_TaskListProvider_Description"), null); //NOI18N
-        cachedTasks = new WeakHashMap<TaskListIssueProvider.LazyIssue, 
Task>(10);
-        cachedIssues = new WeakHashMap<TaskListIssueProvider, 
Set<TaskListIssueProvider.LazyIssue>>(5);
-        providersToValidate = new HashSet<TaskListIssueProvider>(5);
-        validatedIssues = new WeakSet<LazyIssue>(10);
-    }
-
-    public static synchronized TaskListProvider getInstance() {
-        if (instance == null) {
-            instance = new TaskListProvider();
-            instance.refreshTasks(true);
-        }
-        return instance;
-    }
-
-    @Override
-    public void setScope(TaskScanningScope scope, Callback callback) {
-        synchronized (SCOPE_LOCK) {
-            if (!providersInitialized) {
-                // tasklist initialization
-                List<TaskListIssueProvider> providers = new 
LinkedList<TaskListIssueProvider>();
-                DelegatingConnector[] connectors = 
BugtrackingManager.getInstance().getConnectors();
-                for (DelegatingConnector c : connectors) {
-                    Collection<RepositoryImpl> repos = 
RepositoryRegistry.getInstance().getRepositories(c.getID());
-                    if(!repos.isEmpty()) {
-                        TaskListIssueProvider provider = 
c.getTasklistProvider();
-                        if(provider != null) {
-                            providers.add(provider);
-                        }
-                    }
-                }
-                
-                for (TaskListIssueProvider provider : providers) {
-                    LOG.log(Level.FINER, "TaskListProvider.setScope: waking 
up {0}", provider.getClass().getName()); //NOI18N
-                }
-                providersInitialized = true;
-            }
-            this.callback = callback;
-            this.scope = scope;
-            this.lastScope.clear();
-        }
-        refreshTasks(true);
-    }
-
-    /**
-     * Schedules given issues for addition to the tasklist.
-     * @param provider issuetracking provider
-     * @param openTaskList if set to true, the tasklist top component will 
be opened
-     * @param issuesToAdd issues to be added
-     */
-    public void add (TaskListIssueProvider provider, boolean openTaskList, 
TaskListIssueProvider.LazyIssue... issuesToAdd) {
-        if (provider == null || issuesToAdd == null || issuesToAdd.length == 
0) {
-            LOG.log(Level.FINE, "TaskListProvider.add: provider: {0}, 
issuesToAdd: {1}", new Object[]{provider, issuesToAdd}); //NOI18N
-            return;
-        }
-        LOG.log(Level.FINE, "TaskListProvider.add: adding {0} for {1}, 
request to open: {2}", new Object[]{issuesToAdd.length, provider, 
openTaskList}); //NOI18N
-        synchronized (cachedIssues) {
-            Set<TaskListIssueProvider.LazyIssue> issues = 
cachedIssues.get(provider);
-            if (issues == null) {
-                issues = new HashSet<TaskListIssueProvider.LazyIssue>(5);
-            }
-            for (TaskListIssueProvider.LazyIssue issue : issuesToAdd) {
-                issues.add(issue);
-            }
-            if (LOG.isLoggable(Level.FINER)) {
-                LOG.log(Level.FINER, "TaskListProvider.add: issues for {0}: 
{1}", new Object[]{provider, issues}); //NOI18N
-            }
-            cachedIssues.put(provider, issues);
-            // also schedule a validation of the provider's issues
-            providersToValidate.add(provider);
-        }
-        if (openTaskList) {
-            // openning the tasklist
-            EventQueue.invokeLater(new Runnable() {
-                @Override
-                public void run() {
-                    if (LOG.isLoggable(Level.FINER)) {
-                        LOG.finer("TaskListProvider.add: openning tasklist 
TC"); //NOI18N
-                    }
-                    TopComponent tc = 
WindowManager.getDefault().findTopComponent(TC_TASKLIST_ID); //NOI18N
-                    tc.open();
-                    tc.requestVisible();
-                }
-            });
-        }
-        refreshTasks(false);
-    }
-
-    /**
-     * Schedules given issues for removal
-     * @param provider issuetracking provider
-     * @param issuesToRemove issues to be removed from the tasklist
-     */
-    public void remove (TaskListIssueProvider provider, 
TaskListIssueProvider.LazyIssue... issuesToRemove) {
-        if (provider == null || issuesToRemove == null || 
issuesToRemove.length == 0) {
-            LOG.log(Level.FINE, "TaskListProvider.remove: provider: {0}, 
issuesToRemove: {1}", new Object[]{provider, issuesToRemove}); //NOI18N
-            return;
-        }
-        LOG.log(Level.FINE, "TaskListProvider.remove: removing {0} for {1}", 
new Object[]{issuesToRemove.length, provider}); //NOI18N
-        synchronized (cachedIssues) {
-            Set<TaskListIssueProvider.LazyIssue> issues = 
cachedIssues.get(provider);
-            if (issues != null) {
-                for (TaskListIssueProvider.LazyIssue issue : issuesToRemove) 
{
-                    issues.remove(issue);
-                }
-            }
-            if (LOG.isLoggable(Level.FINER)) {
-                LOG.log(Level.FINER, "TaskListProvider.remove: issues for 
{0}: {1}", new Object[]{provider, issues == null ? "empty" : issues}); 
//NOI18N
-            }
-        }
-        removeCachedTasks(issuesToRemove);
-        refreshTasks(false);
-    }
-
-    /**
-     * Removes all issues for the given provider
-     * @param provider
-     */
-    public void removeAll (TaskListIssueProvider provider) {
-        if (provider == null) {
-            LOG.fine("TaskListProvider.removeAll: provider is null");   
//NOI18N
-            return;
-        }
-        LOG.fine("TaskListProvider.removeAll: provider is null");       
//NOI18N
-        Set<LazyIssue> issues;
-        synchronized (cachedIssues) {
-            // clear the issues
-            issues = cachedIssues.remove(provider);
-            if (LOG.isLoggable(Level.FINER)) {
-                LOG.log(Level.FINER, "TaskListProvider.removeAll: issues for 
{0}: {1}", new Object[]{provider, cachedIssues.get(provider) == null ? 
"empty" : cachedIssues.get(provider)}); //NOI18N
-            }
-        }
-        if (issues != null) {
-            removeCachedTasks(issues.toArray(new LazyIssue[issues.size()]));
-        }
-        refreshTasks(false);
-    }
-
-    /*
-     * Schedules a refresh of issue tasks.
-     */
-    public void refresh () {
-        refreshTasks(false);
-    }
-
-    private void removeCachedTasks (LazyIssue... issues) {
-        synchronized (cachedTasks) {
-            for (LazyIssue issue : issues) {
-                cachedTasks.remove(issue);
-            }
-            if (LOG.isLoggable(Level.FINER)) {
-                LOG.log(Level.FINER, "TaskListProvider.removeCachedTasks: 
cached tasks: {0}", cachedTasks); //NOI18N
-            }
-        }
-    }
-
-    private Task createTask(final LazyIssue lazyIssue, final 
WeakReference<TaskListIssueProvider> providerRef) {
-        List<Action> actions = new LinkedList<Action>();
-        // open action: a default action for the first action added by 
tasklist and for a dbl-click on a task
-        ActionListener openIssueAL = new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                
BugtrackingManager.getInstance().getRequestProcessor().post(new Runnable() {
-                    @Override
-                    public void run() {
-                        lazyIssue.open();
-                    }
-                });
-            }
-        };
-        // remove action: always added
-        actions.add(new 
AbstractAction(NbBundle.getMessage(TaskListProvider.class, 
"TaskListProvider.Action.remove.name")) { //NOI18N
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                TaskListIssueProvider provider = providerRef.get();
-                if (provider != null) {
-                    LOG.log(Level.FINE, "TaskListProvider: removing issue 
{0}", lazyIssue.getName()); //NOI18N
-                    TaskListProvider.this.remove(provider, lazyIssue);
-                    provider.removed(lazyIssue);
-                }
-            }
-        });
-        List<? extends Action> additionalActions = lazyIssue.getActions();
-        if (additionalActions != null) {
-            if (LOG.isLoggable(Level.FINER)) {
-                LOG.log(Level.FINER, "TaskListProvider.createTask: provided 
actions {0}", additionalActions); //NOI18N
-            }
-            for (Action a : additionalActions) {
-                if (a != null) {
-                    actions.add(a);
-                }
-            }
-        }
-        Task task = Task.create(lazyIssue.getUrl(), TASK_GROUP_NAME, 
lazyIssue.getName(), openIssueAL, actions.toArray(new 
AbstractAction[actions.size()]));
-        cachedTasks.put(lazyIssue, task);
-        if (LOG.isLoggable(Level.FINER)) {
-            LOG.log(Level.FINER, "TaskListProvider.createTasks: cached 
tasks: {0}", cachedTasks); //NOI18N
-        }
-        // setting valid to true disables task re-creation in a next 
tasklist refresh
-        lazyIssue.setValid(true);
-        return task;
-    }
-
-    /**
-     *
-     * @param cancelRunningRefresh set to true only when the scope changes, 
otherwise the validation inside the refreshtask can return unexpected results
-     */
-    private void refreshTasks (boolean cancelRunningRefresh) {
-        LOG.log(Level.FINER, "TaskListProvider.refreshTasks: cancel={0}", 
cancelRunningRefresh); //NOI18N
-        if (cancelRunningRefresh) {
-            refreshTask.cancel();
-        }
-        refreshTask.schedule(200);
-    }
-
-    /**
-     * Refreshes issue tasks in the tasklist.
-     */
-    private class RefreshTask implements Runnable {
-        @Override
-        public void run() {
-            if (Thread.interrupted()) {
-                return;
-            }
-            TaskScanningScope scope;
-            Callback callback;
-            boolean scopeChanged;
-            synchronized (SCOPE_LOCK) {
-                // get current scope set by the tasklist
-                scope = TaskListProvider.this.scope;
-                callback = TaskListProvider.this.callback;
-                scopeChanged = scope != lastScope.get();
-                if (scopeChanged) {
-                    LOG.finer("RefreshTask.run: scope has changed, running 
the full scan."); //NOI18N
-                }
-            }
-            if (callback == null || scope == null) {
-                // this might happen, e.g. after startup
-                return;
-            }
-            // issues that can be directly included and don't need to be 
tested for belonging under the current scope
-            HashMap<TaskListIssueProvider.LazyIssue, TaskListIssueProvider> 
issuesToInclude = new HashMap<LazyIssue, TaskListIssueProvider>();
-            // issues that can't be directly included and need to be tested 
for belonging under the current scope
-            HashMap<TaskListIssueProvider.LazyIssue, TaskListIssueProvider> 
issuesToValidate = new HashMap<LazyIssue, TaskListIssueProvider>();
-            synchronized(cachedIssues) {
-                if (scopeChanged) {
-                    // when a scope changes, all issues need to be 
re-validated
-                    providersToValidate.addAll(cachedIssues.keySet());
-                }
-                if (LOG.isLoggable(Level.FINER)) {
-                    LOG.log(Level.FINER, "RefreshTask.run: providers to 
validate: {0}", providersToValidate); //NOI18N
-                }
-                for (Map.Entry<TaskListIssueProvider, 
Set<TaskListIssueProvider.LazyIssue>> e : cachedIssues.entrySet()) {
-                    if (providersToValidate.contains(e.getKey())) {
-                        for (LazyIssue issue : e.getValue()) {
-                            issuesToValidate.put(issue, e.getKey());
-                        }
-                    } else {
-                        for (LazyIssue issue : e.getValue()) {
-                            if (validatedIssues.contains(issue)) {
-                                issuesToInclude.put(issue, e.getKey());
-                            } else {
-                                issuesToValidate.put(issue, e.getKey());
-                            }
-                        }
-                    }
-                }
-                if (LOG.isLoggable(Level.FINER)) {
-                    LOG.log(Level.FINER, "RefreshTask.run: issues to 
validate: {0}", issuesToValidate); //NOI18N
-                }
-            }
-            List<String> repositoryUrls;
-            if (!issuesToValidate.isEmpty() && (repositoryUrls = 
getRepositoriesFor(scope)) != null) {
-                // if the issue's repository is not among 
allAssociatedRepositories, then it is probably not associated yet
-                // and the issue would never be displayed. So show 
unassociated issues/repositories by default.
-                Collection<String> allAssociatedRepositories = 
BugtrackingOwnerSupport.getInstance().getAllAssociatedUrls();
-                if (LOG.isLoggable(Level.FINER)) {
-                    LOG.log(Level.FINER, "RefreshTask.run: all associated 
repositories: {0}", allAssociatedRepositories); //NOI18N
-                }
-                // validate issues
-                for (Map.Entry<LazyIssue, TaskListIssueProvider> e : 
issuesToValidate.entrySet()) {
-                    if (isIssueFromRepository(e.getKey(), repositoryUrls, 
allAssociatedRepositories)) {
-                        if (LOG.isLoggable(Level.FINER)) {
-                            LOG.log(Level.FINER, "RefreshTask.run: issue {0} 
is valid under current scope", e.getKey().getName()); //NOI18N
-                        }
-                        issuesToInclude.put(e.getKey(), e.getValue());
-                    } else if (LOG.isLoggable(Level.FINER)) {
-                        LOG.log(Level.FINER, "RefreshTask.run: issue {0} is 
invalid under current scope", e.getKey().getName()); //NOI18N
-                    }
-                }
-            }
-            // list of tasks eventually inserted into the tasklist
-            LinkedList<Task> tasks = new LinkedList<Task>();
-            for (Map.Entry<LazyIssue, TaskListIssueProvider> e : 
issuesToInclude.entrySet()) {
-                LazyIssue issue = e.getKey();
-                Task t;
-                synchronized (cachedTasks) {
-                    if ((t = cachedTasks.get(issue)) == null    // task is 
not yet created
-                            || !issue.isValid()) {              // the issue 
is planned to be refreshed
-                        t = createTask(issue, new 
WeakReference<TaskListIssueProvider>(e.getValue()));
-                    }
-                }
-                tasks.add(t);
-            }
-            if (Thread.interrupted()) {
-                return;
-            }
-            synchronized(cachedIssues) {
-                TaskListProvider.this.providersToValidate.clear();
-                validatedIssues.clear();
-                validatedIssues.addAll(issuesToInclude.keySet());
-            }
-            callback.setTasks(tasks);
-            lastScope = new WeakReference<TaskScanningScope>(scope);
-        }
-    }
-
-    private List<String> getRepositoriesFor (TaskScanningScope scope) {
-        ProjectServices projectServices = 
BugtrackingManager.getInstance().getProjectServices();
-        if(projectServices == null) {
-            return Collections.EMPTY_LIST;
-        }
-        FileObject[] fos = 
projectServices.getProjectDirectories(scope.getLookup());
-        if(fos == null || fos.length == 0) {
-            // one file scope?
-            FileObject fo = scope.getLookup().lookup(FileObject.class);
-            if(fo != null) {
-                fo = projectServices.getFileOwnerDirectory(fo);
-                if(fo != null) {
-                    fos = new FileObject[] 
{projectServices.getFileOwnerDirectory(fo)};
-                }
-            }
-        }
-        LinkedList<String> repositoryUrls = new LinkedList<String>();
-        if (fos.length > 0) {
-            for (FileObject fo : fos) {
-                if (Thread.interrupted()) {
-                    return null;
-                }
-                long startTime = 0;
-                if (LOG.isLoggable(Level.FINER)) {
-                    startTime = System.currentTimeMillis();
-                }
-                // lookup a repository registered with current projects
-                RepositoryImpl repository = 
BugtrackingOwnerSupport.getInstance().getRepository(fo);
-                if (LOG.isLoggable(Level.FINER)) {
-                    LOG.log(Level.FINER, "getRepositoriesFor: repository: 
{0} for {1} after {2}", new Object[] {repository, fo, 
(System.currentTimeMillis() - startTime)});
-                }
-                if (repository != null) {
-                    repositoryUrls.add(repository.getUrl());
-                }
-            }
-        }
-        // XXX find somehow repositories not registered to any project
-        return repositoryUrls;
-    }
-
-    /**
-     * Issues are validated based on their repository's URLs.
-     * @param issue validated issue
-     * @param repositoryUrls collection of valid repository URLs in the 
current scope.
-     * @return
-     */
-    private boolean isIssueFromRepository (TaskListIssueProvider.LazyIssue 
issue, Collection<String> repositoryUrls, Collection<String> 
allAssociatedRepositories) {
-        String repositoryUrl = issue.getRepositoryUrl();
-        boolean returnValue = false;
-        if (repositoryUrl != null) {
-            for (String url : repositoryUrls) {
-                if (repositoryUrl.equals(url)) {
-                    LOG.log(Level.FINE, "isIssueFromRepository: issue {0} 
under an allowed repository", issue);
-                    returnValue = true;
-                    break;
-                }
-            }
-            // XXX kenai repositories, which have not yet been associated??
-            if (!returnValue && 
!allAssociatedRepositories.contains(repositoryUrl)) {
-                LOG.log(Level.FINE, "isIssueFromRepository: issue {0} under 
a unassociated repository", issue);
-                returnValue = true;
-            }
-        }
-        return returnValue;
-    }
-}
diff --git 
a/bugtracking/src/org/netbeans/modules/bugtracking/tasks/DashboardTopComponent.java
 
b/bugtracking/src/org/netbeans/modules/bugtracking/tasks/DashboardTopComponent.java
--- 
a/bugtracking/src/org/netbeans/modules/bugtracking/tasks/DashboardTopComponent.java
+++ 
b/bugtracking/src/org/netbeans/modules/bugtracking/tasks/DashboardTopComponent.java
@@ -66,6 +66,7 @@
 import javax.swing.AbstractAction;
 import javax.swing.Action;
 import javax.swing.SwingUtilities;
+import org.netbeans.modules.bugtracking.api.Issue;
 import org.netbeans.modules.bugtracking.api.RepositoryManager;
 import org.netbeans.modules.bugtracking.tasks.dashboard.TaskNode;
 import org.netbeans.modules.bugtracking.tasks.settings.DashboardSettings;
@@ -308,6 +309,10 @@
         return confirm;
     }
 
+    public void addTask(Issue issue) {
+        addTask(new TaskNode(issue, null));
+    }
+    
     public void addTask(TaskNode... taskNodes) {
         List<Category> categories = dashboard.getCategories(true);
         for (TaskNode taskNode : taskNodes) {
diff --git a/bugzilla/src/org/netbeans/modules/bugzilla/Bugzilla.java 
b/bugzilla/src/org/netbeans/modules/bugzilla/Bugzilla.java
--- a/bugzilla/src/org/netbeans/modules/bugzilla/Bugzilla.java
+++ b/bugzilla/src/org/netbeans/modules/bugzilla/Bugzilla.java
@@ -55,7 +55,6 @@
 import org.netbeans.modules.bugtracking.spi.BugtrackingFactory;
 import org.netbeans.modules.bugtracking.util.UndoRedoSupport;
 import org.netbeans.modules.bugzilla.issue.BugzillaIssue;
-import org.netbeans.modules.bugzilla.issue.BugzillaTaskListProvider;
 import org.netbeans.modules.bugzilla.query.BugzillaQuery;
 import org.netbeans.modules.bugzilla.util.BugzillaUtil;
 import org.openide.util.RequestProcessor;
@@ -81,17 +80,8 @@
     private IssueNode.ChangesProvider<BugzillaIssue> bcp;
 
     private Bugzilla() {
-
         brc = new BugzillaRepositoryConnector();
         clientManager = brc.getClientManager();
-
-        // lazy ping tasklist issue provider to load issues ...
-        getRequestProcessor().post(new Runnable() {
-            @Override
-            public void run() {
-                BugzillaTaskListProvider.getInstance();
-            }
-        });
     }
 
     public static synchronized Bugzilla getInstance() {
diff --git a/bugzilla/src/org/netbeans/modules/bugzilla/BugzillaConfig.java 
b/bugzilla/src/org/netbeans/modules/bugzilla/BugzillaConfig.java
--- a/bugzilla/src/org/netbeans/modules/bugzilla/BugzillaConfig.java
+++ b/bugzilla/src/org/netbeans/modules/bugzilla/BugzillaConfig.java
@@ -75,7 +75,6 @@
     private static final String ISSUE_REFRESH_INT   = 
"bugzilla.issue_refresh";         // NOI18N
     private static final String DELIMITER           = "<=>";                 
           // NOI18N
     private static final String ATTACH_LOG          = "bugzilla.attach_log"; 
           // NOI18N;
-    private static final String TASKLISTISSUES_STORAGE_FILE = 
"tasklistissues.data"; //NOI18N
     private static final Level LOG_LEVEL = BugzillaUtil.isAssertEnabled() ? 
Level.SEVERE : Level.INFO;
 
     public static final int DEFAULT_QUERY_REFRESH = 30;
@@ -205,104 +204,6 @@
     }
 
     /**
-     * Saves issue attributes permanently
-     * @param issues
-     */
-    public void setTaskListIssues(HashMap<String, List<String>> issues) {
-        Bugzilla.LOG.fine("setTaskListIssues: saving issues");              
//NOI18N
-        File f = new File(getNBConfigPath());
-        f.mkdirs();
-        if (!f.canWrite()) {
-            Bugzilla.LOG.warning("setTaskListIssues: Cannot create perm 
storage"); //NOI18N
-            return;
-        }
-        java.io.ObjectOutputStream out = null;
-        File file = new File(f, TASKLISTISSUES_STORAGE_FILE + ".tmp");
-        boolean success = false;
-        try {
-            // saving to a temp file
-            out = new java.io.ObjectOutputStream(new 
java.io.BufferedOutputStream(new java.io.FileOutputStream(file)));
-            out.writeInt(issues.size());
-            for (Map.Entry<String, List<String>> entry : issues.entrySet()) {
-                out.writeUTF(entry.getKey());
-                out.writeInt(entry.getValue().size());
-                for (String issueAttributes : entry.getValue()) {
-                    out.writeUTF(issueAttributes);
-                }
-            }
-            success = true;
-        } catch (IOException ex) {
-            Bugzilla.LOG.log(LOG_LEVEL, null, ex);
-        } finally {
-            if (out != null) {
-                try {
-                    out.close();
-                } catch (IOException e) {
-                }
-            }
-        }
-        if (success) {
-            // rename the temp file to the permanent one
-            File newFile = new File(f, TASKLISTISSUES_STORAGE_FILE);
-            try {
-                FileUtils.renameFile(file, newFile);
-            } catch (IOException ex) {
-                Bugzilla.LOG.log(LOG_LEVEL, null, ex);
-                success = false;
-            }
-        }
-        if (!success) {
-            Bugzilla.LOG.warning("setTaskListIssues: could not save 
issues"); //NOI18N
-            if (!file.delete()) {
-                file.deleteOnExit();
-            }
-        }
-    }
-
-    /**
-     * Loads issues from a permanent storage
-     * @return
-     */
-    public Map<String, List<String>> getTaskListIssues () {
-        Bugzilla.LOG.fine("loadTaskListIssues: loading issues");            
//NOI18N
-        File f = new File(getNBConfigPath());
-        java.io.ObjectInputStream ois = null;
-        File file = new File(f, TASKLISTISSUES_STORAGE_FILE);
-        if (!file.canRead()) {
-            Bugzilla.LOG.fine("loadTaskListIssues: no saved data");         
//NOI18N
-            return Collections.emptyMap();
-        }
-        try {
-            ois = new java.io.ObjectInputStream(new 
java.io.BufferedInputStream(new java.io.FileInputStream(file)));
-            int size = ois.readInt();
-            Bugzilla.LOG.fine("loadTaskListIssues: loading " + size + " 
records"); //NOI18N
-            HashMap<String, List<String>> issuesPerRepo = new 
HashMap<String, List<String>>(size);
-            while (size-- > 0) {
-                String repoUrl = ois.readUTF();
-                Bugzilla.LOG.fine("loadTaskListIssues: loading issues for " 
+ repoUrl); //NOI18N
-                int issueCount = ois.readInt();
-                Bugzilla.LOG.fine("loadTaskListIssues: loading " + 
issueCount + " issues"); //NOI18N
-                LinkedList<String> issues = new LinkedList<String>();
-                while (issueCount-- > 0) {
-                    issues.add(ois.readUTF());
-                }
-                issuesPerRepo.put(repoUrl, issues);
-            }
-            return issuesPerRepo;
-        } catch (IOException ex) {
-            Bugzilla.LOG.log(LOG_LEVEL, null, ex);
-        } finally {
-            if (ois != null) {
-                try {
-                    ois.close();
-                } catch (IOException e) {
-                }
-            }
-        }
-        return Collections.emptyMap();
-    }
-
-    /**
      * Returns the path for the Bugzilla configuration directory.
      *
      * @return the path
diff --git 
a/bugzilla/src/org/netbeans/modules/bugzilla/BugzillaConnector.java 
b/bugzilla/src/org/netbeans/modules/bugzilla/BugzillaConnector.java
--- a/bugzilla/src/org/netbeans/modules/bugzilla/BugzillaConnector.java
+++ b/bugzilla/src/org/netbeans/modules/bugzilla/BugzillaConnector.java
@@ -53,10 +53,8 @@
 import org.netbeans.modules.bugzilla.repository.BugzillaRepository;
 import org.netbeans.modules.bugtracking.spi.BugtrackingConnector;
 import org.netbeans.modules.bugtracking.spi.RepositoryInfo;
-import org.netbeans.modules.bugtracking.spi.TaskListIssueProvider;
 import org.netbeans.modules.bugzilla.api.NBBugzillaUtils;
 import org.netbeans.modules.bugtracking.util.SimpleIssueFinder;
-import org.netbeans.modules.bugzilla.issue.BugzillaTaskListProvider;
 import org.netbeans.modules.bugzilla.kenai.KenaiRepository;
 import org.netbeans.modules.bugzilla.repository.NBRepositorySupport;
 import org.netbeans.modules.bugzilla.util.BugzillaUtil;
@@ -112,12 +110,6 @@
         return SimpleIssueFinder.getInstance();
     }
 
-    @Override
-    public TaskListIssueProvider getTasklistProvider() {
-        return BugzillaTaskListProvider.getInstance();
-    }
-
-    
     
/******************************************************************************
      * Kenai
      
******************************************************************************/
diff --git 
a/bugzilla/src/org/netbeans/modules/bugzilla/issue/BugzillaTaskListProvider.java
 
b/bugzilla/src/org/netbeans/modules/bugzilla/issue/BugzillaTaskListProvider.java
deleted file mode 100644
--- 
a/bugzilla/src/org/netbeans/modules/bugzilla/issue/BugzillaTaskListProvider.java
+++ /dev/null
@@ -1,866 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
- *
- * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
- * Other names may be trademarks of their respective owners.
- *
- * 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle 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 2009 Sun Microsystems, Inc.
- */
-
-package org.netbeans.modules.bugzilla.issue;
-
-import java.beans.PropertyChangeEvent;
-import java.awt.EventQueue;
-import java.awt.event.ActionEvent;
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeSupport;
-import java.io.IOException;
-import java.lang.ref.WeakReference;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.text.MessageFormat;
-import java.util.*;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.swing.AbstractAction;
-import javax.swing.Action;
-import org.netbeans.api.progress.ProgressHandle;
-import org.netbeans.api.progress.ProgressHandleFactory;
-import org.netbeans.modules.bugtracking.api.Repository;
-import org.netbeans.modules.bugtracking.api.RepositoryManager;
-import org.netbeans.modules.bugtracking.kenai.spi.KenaiAccessor;
-import org.netbeans.modules.bugtracking.spi.IssueProvider;
-import org.netbeans.modules.bugtracking.spi.TaskListIssueProvider;
-import org.netbeans.modules.bugtracking.cache.IssueCache;
-import org.netbeans.modules.bugtracking.kenai.spi.KenaiUtil;
-import org.netbeans.modules.bugzilla.Bugzilla;
-import org.netbeans.modules.bugzilla.BugzillaConfig;
-import org.netbeans.modules.bugzilla.BugzillaConnector;
-import org.netbeans.modules.bugzilla.kenai.KenaiRepository;
-import org.netbeans.modules.bugzilla.repository.BugzillaRepository;
-import org.netbeans.modules.bugzilla.util.BugzillaUtil;
-import org.openide.DialogDisplayer;
-import org.openide.NotifyDescriptor;
-import org.openide.util.NbBundle;
-import org.openide.util.RequestProcessor;
-import org.openide.util.WeakListeners;
-
-/**
- *
- * @author Ondra Vrabec
- */
-public final class BugzillaTaskListProvider extends TaskListIssueProvider 
implements PropertyChangeListener {
-
-    private static BugzillaTaskListProvider instance;
-    private final Object LOCK = new Object();
-    private boolean initialized;
-    private HashMap<String, BugzillaLazyIssue> watchedIssues = new 
HashMap<String, BugzillaLazyIssue>(10);
-    private static final Logger LOG = 
Logger.getLogger("org.netbeans.modules.Bugzilla.tasklist"); //NOI18N
-    private static final Level LOG_LEVEL = BugzillaUtil.isAssertEnabled() ? 
Level.INFO : Level.FINE;
-    private final RequestProcessor rp = new 
RequestProcessor("BugzillaTaskListProvider", 1, false);
-    private static final String KENAI_REPOSITORY_IDENT_PREFIX = "K##";  
//NOI18N
-    private static final String STORAGE_KENAI_VERSION = "1";                 
 //NOI18N
-    private static final String STORAGE_COMMON_VERSION = "1";                
  //NOI18N
-    private final PropertyChangeSupport support;
-
-    public static final String PROPERTY_ISSUE_REMOVED = "issue-removed"; 
//NOI18N
-
-    public static synchronized BugzillaTaskListProvider getInstance() {
-        if (instance == null) {
-            instance = new BugzillaTaskListProvider();
-        }
-        return instance;
-    }
-
-    private BugzillaTaskListProvider () {
-        // initialization
-        support = new PropertyChangeSupport(this);
-        reloadAsync();
-    }
-
-    /**
-     * Schedules the given issue to be added to the tasklist
-     * @param issue issue to add to the tasklist
-     * @param openTaskList if set to true, the tasklist will also be asked 
to open
-     */
-    public void add (BugzillaIssue issue, boolean openTaskList) {
-        URL url = getUrl(issue);
-        BugzillaLazyIssue lazyIssue;
-        // local store
-        synchronized (LOCK) {
-            if (isAdded(url)) return;
-            try {
-                BugzillaRepository bugzillaRepository = 
issue.getRepository();
-                
-                Repository repository = 
BugzillaUtil.getRepository(bugzillaRepository);
-                repository.removePropertyChangeListener(this);
-                repository.addPropertyChangeListener(this);
-                
-                // create a representation of the real issue for tasklist
-                watchedIssues.put(url.toString(), lazyIssue =
-                        (bugzillaRepository instanceof KenaiRepository) ?
-                            new KenaiBugzillaLazyIssue(issue, this) :   // 
kenai lazy issue
-                            new BugzillaLazyIssue(issue, this));        // 
common Bugzilla lazy issue
-            } catch (MalformedURLException e) {
-                return;
-            }
-        }
-        saveIntern();
-
-        // schedule the addition to tasklist
-        super.add(openTaskList, lazyIssue);
-    }
-
-    /**
-     * Schedule given issue to be removed from the tasklist
-     * @param issue
-     */
-    public void remove (BugzillaIssue issue) {
-        URL url = getUrl(issue);
-        remove(url, true);
-    }
-
-    /**
-     * Tests if given issue is added to the tasklist.
-     * @param issue
-     * @return true if the given issue is already added.
-     */
-    public boolean isAdded(BugzillaIssue issue) {
-        URL url = getUrl(issue);
-        return isAdded(url);
-    }
-
-    @Override
-    public void removed(LazyIssue lazyIssue) {
-        BugzillaLazyIssue removedIssue;
-        synchronized (LOCK) {
-            if (!isAdded(lazyIssue.getUrl())) return;
-            removedIssue = 
watchedIssues.remove(lazyIssue.getUrl().toString());
-        }
-        saveIntern();
-        fireIssueRemoved(removedIssue);
-    }
-
-    /**
-     * These properties are fired:
-     * <ul>
-     * <li>{@link #PROPERTY_ISSUE_REMOVED} when an issue is removed from the 
tasklist in other way that with {@link 
#remove(org.netbeans.modules.Bugzilla.issue.BugzillaIssue),
-     * e.g. with a Remove action from a popup menu in the tasklist.</li>
-     * </ul>
-     * @param listener
-     */
-    public void addPropertyChangeListener (PropertyChangeListener listener) {
-        support.addPropertyChangeListener(listener);
-    }
-
-    public void removePropertyChangeListener (PropertyChangeListener 
listener) {
-        support.removePropertyChangeListener(listener);
-    }
-
-    @Override
-    public void propertyChange(PropertyChangeEvent evt) {
-        if 
(Repository.EVENT_ATTRIBUTES_CHANGED.equals(evt.getPropertyName())) {
-            if (evt.getOldValue() != null && evt.getOldValue() instanceof 
Map) {
-                Object oldValue = 
((Map)evt.getOldValue()).get(Repository.ATTRIBUTE_URL);
-                if (oldValue != null && oldValue instanceof String) {
-                    String oldRepoUrl = (String) oldValue;
-                    LinkedList<BugzillaLazyIssue> issuesToRefresh = new 
LinkedList<BugzillaLazyIssue>();
-                    synchronized (LOCK) {
-                        // lookup all issues with the same repository url as 
the changed value
-                        for (Map.Entry<String, BugzillaLazyIssue> e : 
watchedIssues.entrySet()) {
-                            BugzillaLazyIssue issue = e.getValue();
-                            Object sourceRepository = evt.getSource();
-                            if (!(issue instanceof KenaiBugzillaLazyIssue) 
&& sourceRepository != null && 
sourceRepository.equals(issue.getRepository())) {
-                                URL oldUrl = getUrl(oldRepoUrl, 
issue.issueId);
-                                if 
(issue.getUrl().toString().equals(oldUrl.toString()))  {
-                                    LOG.log(Level.FINE, "propertyChange: 
Issue {0} with url {1} needs to be refreshed, repository's url {2} has 
changed", //NOI18N
-                                            new String[] {issue.toString(), 
oldUrl.toString(), oldRepoUrl});
-                                    issuesToRefresh.add(issue);
-                                }
-                            }
-                        }
-                    }
-                    // refresh issues
-                    for (BugzillaLazyIssue issue : issuesToRefresh) {
-                        remove(issue.getUrl(), false);
-                        add(issue.getName(), issue.issueId, 
issue.getRepository());
-                    }
-                    // store new issues
-                    if (!issuesToRefresh.isEmpty()) {
-                        saveIntern();
-                    }
-                }
-            }
-        } 
-    }
-
-    /**
-     * Removes all issues from the tasklist which belong to the given 
repository
-     * @param repository
-     */
-    public void removeAllFor (BugzillaRepository repository) {
-        LinkedList<BugzillaLazyIssue> issuesToRemove = new 
LinkedList<BugzillaLazyIssue>();
-                 synchronized (LOCK) {
-            // lookup all issues with the same repository url as the changed 
value
-            for (Map.Entry<String, BugzillaLazyIssue> e : 
watchedIssues.entrySet()) {
-                BugzillaLazyIssue issue = e.getValue();
-                if (!(issue instanceof KenaiBugzillaLazyIssue) && repository 
== issue.getRepository()) {
-                    LOG.log(Level.FINE, "removeAllFor: issue {0} repository 
{1} has been removed", new String[]{issue.toString(), 
repository.toString()}); //NOI18N
-                    issuesToRemove.add(issue);
-                }
-            }
-        }
-        // remove issues
-        for (BugzillaLazyIssue issue : issuesToRemove) {
-            remove(issue.getUrl(), false);
-        }
-        // store issues
-        if (!issuesToRemove.isEmpty()) {
-            saveIntern();
-        }
-    }
-
-    /**
-     * Call when an issue is loaded for the first time.
-     * @param issue cannot be null
-     */
-    public void notifyIssueCreated (BugzillaIssue issue) {
-        URL url = getUrl(issue);
-        BugzillaLazyIssue lazyIssue = null;
-        synchronized (LOCK) {
-            lazyIssue = watchedIssues.get(url.toString());
-        }
-        if (lazyIssue != null) {
-            lazyIssue.setIssueReference(issue);
-        }
-    }
-
-    Map<String, BugzillaRepository> bugzillaRepositories = new 
HashMap<String, BugzillaRepository>();
-    public void notifyRepositoryCreated (BugzillaRepository repository) {
-        if(repository.getInfo() != null) {
-            bugzillaRepositories.put(repository.getID(), repository);
-        }
-    }
-    public void notifyRepositoryRemoved (BugzillaRepository repository) {
-        if(repository.getInfo() != null) {
-            bugzillaRepositories.remove(repository.getID());
-        }
-    }
-    
-    // **** private methods ***** //
-    private boolean isAdded(URL url) {
-        initializeIssues();
-        if (url == null) {
-            return false;
-        }
-        synchronized (LOCK) {
-            return watchedIssues.containsKey(url.toString());
-        }
-    }
-
-    private static URL getUrl (BugzillaIssue issue) {
-        return getUrl(issue.getRepository().getUrl(), issue.getID());
-    }
-
-    private static URL getUrl(String repositoryUrl, String issueId) {
-        String url = 
Bugzilla.getInstance().getRepositoryConnector().getTaskUrl(repositoryUrl, 
issueId);
-        try {
-            return new URL(url);
-        } catch (MalformedURLException ex) {
-            LOG.log(LOG_LEVEL, null, ex);
-        }
-        try {
-            return new URL(repositoryUrl + "#" + issueId);             
//NOI18N
-        } catch (MalformedURLException ex) {
-            LOG.log(LOG_LEVEL, null, ex);
-            return null;
-        }
-    }
-
-    private void reloadAsync() {
-        rp.post(new Runnable () {
-            @Override
-            public void run() {
-                initializeIssues();
-            }
-        });
-    }
-
-    private void saveIntern() {
-        BugzillaLazyIssue[] lazyIssues;
-        synchronized(LOCK) {
-            lazyIssues = watchedIssues.values().toArray(new 
BugzillaLazyIssue[watchedIssues.size()]);
-        }
-        final BugzillaLazyIssue[] lazyIssuesToSave = lazyIssues;
-        rp.post(new Runnable () {
-            @Override
-            public void run() {
-                initializeIssues();
-                LOG.log(Level.FINE, "saveIntern: saving issues");       
//NOI18N
-                HashMap<String, List<String>> issues = new HashMap<String, 
List<String>>();
-                for (BugzillaLazyIssue issue : lazyIssuesToSave) {
-                    String repositoryIdent = null;
-                    boolean isKenai = false;
-                    if (issue instanceof KenaiBugzillaLazyIssue) {
-                        BugzillaRepository repo = issue.getRepository();
-                        if (repo != null && !(repo instanceof 
KenaiRepository)) {
-                            LOG.warning("saveIntern: KenaiBugzillaIssue has 
no kenai repository: " + repo); //NOI18N
-                        } else {
-                            // kenai repository is identified by project's 
name, not by it's url
-                            repositoryIdent = KENAI_REPOSITORY_IDENT_PREFIX 
+ (repo == null
-                                    ? 
((KenaiBugzillaLazyIssue)issue).projectName
-                                    : ((KenaiRepository) 
repo).getProductName());
-                            isKenai = true;
-                        }
-                    } else {
-                        repositoryIdent = issue.getRepositoryUrl();
-                    }
-                    if (repositoryIdent != null) {
-                        List<String> issueAttributes = 
issues.get(repositoryIdent);
-                        if (issueAttributes == null) {
-                            issueAttributes = new LinkedList<String>();
-                            issueAttributes.add(isKenai ? 
STORAGE_KENAI_VERSION : STORAGE_COMMON_VERSION);
-                        }
-                        issueAttributes.add(issue.issueId);            // 
issue id
-                        issueAttributes.add(issue.getName());          // 
description
-                        if (isKenai) {
-                            issueAttributes.add(issue.getUrl().toString()); 
// url needed only for kenai repos
-                        }
-                        if (LOG.isLoggable(Level.FINE)) {
-                            LOG.fine("saveIntern: saving " + issueAttributes 
+ " for repo: " + repositoryIdent); //NOI18N
-                        }
-                        issues.put(repositoryIdent, issueAttributes);
-                    }
-                }
-                // save permanently
-                BugzillaConfig.getInstance().setTaskListIssues(issues);
-            }
-        });
-    }
-
-    private void initializeIssues () {
-        synchronized (LOCK) {
-            if (initialized) {
-                return;
-            }
-            initialized = true;
-            LOG.finer("initializeIssues: reloading saved issues");      
//NOI18N
-            // load from storage
-            Map<String, List<String>> repositoryIssues = 
BugzillaConfig.getInstance().getTaskListIssues();
-            if (repositoryIssues.isEmpty()) {
-                LOG.fine("initializeIssues: no saved issues");          
//NOI18N
-                return;
-            }
-            addCommonIssues(repositoryIssues);
-            addKenaiIssues(repositoryIssues);
-        }
-    }
-
-    private String getNextAttribute (ListIterator<String> it) {
-        String attr = null;
-        if (it.hasNext()) {
-            attr = it.next();
-        }
-        return attr;
-    }
-
-    private void addCommonIssues (Map<String, List<String>> 
repositoryIssues) {
-        Collection<Repository> repositories = 
RepositoryManager.getInstance().getRepositories(BugzillaConnector.ID);
-        for (Repository repository : repositories) {
-            // all issues for this repository
-            List<String> issueAttributes = 
repositoryIssues.get(repository.getUrl());
-            if (issueAttributes != null && issueAttributes.size() > 1) {
-                ListIterator<String> it = issueAttributes.listIterator();
-                if (!STORAGE_COMMON_VERSION.equals(it.next())) {
-                    LOG.log(Level.WARNING, "Old unsupported storage version, 
expecting {0}", STORAGE_COMMON_VERSION); //NOI18N
-                    break;
-                }
-                for (; it.hasNext();) {
-                    String issueId = getNextAttribute(it);
-                    String issueName = getNextAttribute(it);
-                    if (issueId == null || issueName == null) {
-                        LOG.log(Level.WARNING, "Corrupted issue attributes: 
{0} {1}", new String[]{issueId, issueName}); //NOI18N
-                        break;
-                    }
-                    BugzillaRepository bugzillaRepository = 
bugzillaRepositories.get(repository.getId());
-                    assert bugzillaRepository != null;
-                    add(issueName, issueId, bugzillaRepository);
-                }
-                repository.addPropertyChangeListener(this);
-                // remove processed attributes
-                repositoryIssues.remove(repository.getUrl());
-            }
-        }
-    }
-
-    private void addKenaiIssues (Map<String, List<String>> repositoryIssues) 
{
-        // now what remains are kenai issues and non-existant repositories
-        for (Map.Entry<String, List<String>> e : 
repositoryIssues.entrySet()) {
-            String projectName = e.getKey();
-            if (projectName.startsWith(KENAI_REPOSITORY_IDENT_PREFIX)) { // 
is kenai
-                projectName = 
projectName.substring(KENAI_REPOSITORY_IDENT_PREFIX.length());
-                List<String> issueAttributes = e.getValue();
-                if (issueAttributes != null && issueAttributes.size() > 1) {
-                    ListIterator<String> it = issueAttributes.listIterator();
-                    if (!STORAGE_KENAI_VERSION.equals(it.next())) {
-                        LOG.log(Level.WARNING, "Old unsupported storage 
version for kenai issues, expecting {0}", STORAGE_KENAI_VERSION); //NOI18N
-                        break;
-                    }
-                    for (; it.hasNext(); ) {
-                        String issueId = getNextAttribute(it);
-                        String issueName = getNextAttribute(it);
-                        String url = getNextAttribute(it);
-                        if (issueId == null || issueName == null || url == 
null) {
-                            LOG.log(Level.WARNING, "Corrupted kenai issue 
attributes: {0} {1} {2}", new String[]{issueId, issueName, url}); //NOI18N
-                            break;
-                        }
-                        URL issueUrl;
-                        try {
-                            issueUrl = new URL(url);
-                        } catch (MalformedURLException ex) {
-                            LOG.log(Level.INFO, null, ex);
-                            continue;
-                        }
-                        add(issueName, issueUrl, issueId, projectName);
-                        KenaiAccessor ka = KenaiUtil.getKenaiAccessor(url);
-                        if(ka != null) {
-                            String host = issueUrl.getHost();
-                            Map<String, PropertyChangeListener> kl = 
getKenaiListeners();
-                            PropertyChangeListener l = kl.get(host);
-                            if (l == null) {
-                                // kenai host not registered yet
-                                l = new KenaiListener(host);
-                                ka.addPropertyChangeListener(l, host);
-                                kl.put(host, l);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    private class KenaiListener implements PropertyChangeListener {
-        private final String kenaiHost;
-
-        public KenaiListener(String kenaiHost) {
-            this.kenaiHost = kenaiHost;
-        }
-
-        @Override
-        public void propertyChange(PropertyChangeEvent evt) {
-            if (KenaiAccessor.PROP_LOGIN.equals(evt.getPropertyName())) {
-                // kenai issues need instantiated repository so they can be 
shown in tasklist
-                // but some (e.g. private kenai projects) cannot be 
instantiated without being logged in. So kenai issues need to be notified
-                // when user loggs in so the repository can be created.
-                rp.post(new Runnable() { // do not block here
-                    @Override
-                    public void run() {
-                        notifyKenaiLogin(kenaiHost);
-                    }
-                });
-            }
-        }
-    }
-
-    private Map<String, PropertyChangeListener> kenaiListeners;
-    private Map<String, PropertyChangeListener> getKenaiListeners() {
-        if (kenaiListeners == null) {
-            kenaiListeners = new HashMap<String, PropertyChangeListener>();
-        }
-        return kenaiListeners;
-    }
-    
-    private void remove (URL url, boolean savePermanently) {
-        BugzillaLazyIssue lazyIssue;
-        synchronized (LOCK) {
-            if (!isAdded(url)) return;
-            lazyIssue = watchedIssues.remove(url.toString());
-        }
-        if (savePermanently) {
-            saveIntern();
-        }
-        // notify tasklist
-        super.remove(lazyIssue);
-    }
-
-    private void add (String issueName, URL issueUrl, String issueId, String 
projectName) {
-        KenaiBugzillaLazyIssue issue;
-        synchronized (LOCK) {
-            if (isAdded(issueUrl)) return;
-            watchedIssues.put(issueUrl.toString(), issue = new 
KenaiBugzillaLazyIssue(issueName, issueUrl, issueId, projectName, this));
-        }
-        // notify tasklist
-        super.add(issue);
-        if (LOG.isLoggable(Level.FINER)) {
-            LOG.log(Level.FINER, "initializeIssues: issue added: {0}", 
issue); //NOI18N
-        }
-    }
-
-    private void add (String issueName, String issueId, BugzillaRepository 
repository) {
-        URL issueUrl = getUrl(repository.getUrl(), issueId);
-        BugzillaLazyIssue issue;
-        synchronized (LOCK) {
-            if (issueUrl == null || isAdded(issueUrl)) return;
-            watchedIssues.put(issueUrl.toString(), issue = new 
BugzillaLazyIssue(issueName, issueUrl, issueId, repository, this));
-        }
-        // notify tasklist
-        super.add(issue);
-        if (LOG.isLoggable(Level.FINER)) {
-            LOG.log(Level.FINER, "initializeIssues: issue added: {0}", 
issue); //NOI18N
-        }
-    }
-
-    private static void runCancellableCommand(Runnable runnable, String 
progressMessage) {
-        RequestProcessor.Task task = 
Bugzilla.getInstance().getRequestProcessor().post(runnable);
-        ProgressHandle handle = 
ProgressHandleFactory.createHandle(progressMessage, task); //NOI18N
-        handle.start();
-        task.waitFinished();
-        handle.finish();
-    }
-
-    private BugzillaIssue getIssue(final BugzillaRepository repository, 
final String issueId) {
-        assert !EventQueue.isDispatchThread();
-        // XXX is there a simpler way to obtain an issue?
-        IssueCache.Status status = 
repository.getIssueCache().getStatus(issueId);
-        final BugzillaIssue[] issue = new BugzillaIssue[1];
-        if (status == IssueCache.Status.ISSUE_STATUS_UNKNOWN) { // not yet 
cached
-            Runnable runnable = new Runnable() {
-                @Override
-                public void run() {
-                    LOG.log(Level.FINE, "getIssue: creating issue {0}", 
repository.getUrl() + "#" + issueId); //NOI18N
-                    issue[0] = (BugzillaIssue) repository.getIssue(issueId);
-                }
-            };
-            runCancellableCommand(runnable, 
NbBundle.getMessage(BugzillaTaskListProvider.class, 
"BugzillaIssueProvider.loadingIssue"));
-        } else {
-            LOG.log(Level.FINER, "getIssue: getting issue {0} from the 
cache", repository.getUrl() + "#" + issueId); //NOI18N
-            issue[0] = repository.getIssueCache().getIssue(issueId);
-        }
-        return issue[0];
-    }
-
-    private void fireIssueRemoved(BugzillaLazyIssue lazyIssue) {
-        BugzillaIssue issue = lazyIssue.issueRef.get();
-        if (issue != null) {
-            support.firePropertyChange(PROPERTY_ISSUE_REMOVED, issue, null);
-        }
-    }
-
-    /*
-     * Notifies all kenai issues that user has logged on. Private kenai 
projects cannot be instantiated without being logged in
-     * and issue tracking repository cannot be created.
-     */
-    private void notifyKenaiLogin (String notifiedKenaiHost) {
-        assert notifiedKenaiHost != null;
-        synchronized (LOCK) {
-            for (BugzillaLazyIssue issue : watchedIssues.values()) {
-                if (issue instanceof KenaiBugzillaLazyIssue) {
-                    if(notifiedKenaiHost.equals(issue.getUrl().getHost())) {
-                        ((KenaiBugzillaLazyIssue) issue).notifyKenaiLogin();
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Common Bugzilla representation of LazyIssue
-     */
-    private static class BugzillaLazyIssue extends LazyIssue {
-        private final String issueId;
-        /**
-         *  cached repository for the issue
-         */
-        private WeakReference<BugzillaRepository> repositoryRef;
-        protected final BugzillaTaskListProvider provider;
-        private WeakReference<BugzillaIssue> issueRef;
-        private PropertyChangeListener issueListener;
-
-        public BugzillaLazyIssue (BugzillaIssue issue, 
BugzillaTaskListProvider provider) throws MalformedURLException {
-            super(BugzillaTaskListProvider.getUrl(issue), 
issue.getDisplayName());
-            this.issueId = issue.getID();
-            this.provider = provider;
-            this.repositoryRef = new 
WeakReference<BugzillaRepository>(issue.getRepository());
-            this.issueRef = new WeakReference<BugzillaIssue>(issue);
-            attachIssueListener(issue);
-        }
-
-        public BugzillaLazyIssue (String name, URL url, String issueId, 
BugzillaRepository repository, BugzillaTaskListProvider provider) {
-            super(url, name);
-            this.issueId = issueId;
-            this.repositoryRef = new 
WeakReference<BugzillaRepository>(repository);
-            this.provider = provider;
-            this.issueRef = new WeakReference<BugzillaIssue>(null);
-        }
-
-        public BugzillaIssue getIssue() {
-            BugzillaIssue issue = issueRef.get();
-            if (issue == null) {
-                BugzillaRepository repository = getRepository();
-                if (repository == null) {
-                    LOG.log(Level.INFO, "Repository unavailable for {0}", 
getUrl().toString()); //NOI18N
-                    if (canBeAutoRemoved()) {
-                        // no repository found for this issue and the issue 
can be removed automaticaly
-                        provider.remove(getUrl(), true);
-                    }
-                } else {
-                    issue = provider.getIssue(repository, issueId);
-                }
-                setIssueReference(issue);
-            }
-            return issue;
-        }
-
-        private BugzillaRepository getRepository() {
-            return repositoryRef.get();
-        }
-
-        /**
-         * Sets the reference to the issue and attaches an issue listener
-         * @param issue if null then this only clears the reference.
-         */
-        private void setIssueReference (BugzillaIssue issue) {
-            issueRef = new WeakReference<BugzillaIssue>(issue);
-            if (issue != null) {
-                applyChangesFor(issue);
-                attachIssueListener(issue);
-            }
-        }
-
-        private void attachIssueListener (BugzillaIssue issue) {
-            if (issueListener == null) {
-                issueListener = new PropertyChangeListener() {
-                    @Override
-                    public void propertyChange(PropertyChangeEvent evt) {
-                        BugzillaIssue issue = issueRef.get();
-                        if 
(IssueProvider.EVENT_ISSUE_REFRESHED.equals(evt.getPropertyName()) && issue 
!= null) {
-                            // issue has somehow changed, checks for its 
changes and apply them in the tasklist
-                            applyChangesFor(issue);
-                        }
-                    }
-                };
-            }
-            LOG.log(Level.FINE, "attachIssueListener: on issue {0}", 
issue.toString());
-            
issue.addPropertyChangeListener(WeakListeners.propertyChange(issueListener, 
issue));
-        }
-
-        private void applyChangesFor (BugzillaIssue issue) {
-            boolean requiresSave = false;
-            if (!getName().equals(issue.getDisplayName())) {
-                setName(issue.getDisplayName());
-                requiresSave = true;
-            }
-            if (requiresSave) {
-                provider.saveIntern();
-            }
-        }
-
-        @Override
-        public String getRepositoryUrl() {
-            String repoUrl = null;
-            BugzillaRepository repository = getRepository();
-            if (repository != null) {
-                repoUrl = repository.getUrl();
-            }
-            return repoUrl;
-        }
-
-        @Override
-        public List<? extends Action> getActions() {
-            List<AbstractAction> actions = new LinkedList<AbstractAction>();
-            actions.add(new 
AbstractAction(NbBundle.getMessage(BugzillaTaskListProvider.class, 
"BugzillaIssueProvider.resolveAction")) { //NOI18N
-                @Override
-                public void actionPerformed(ActionEvent e) {
-                    RequestProcessor.getDefault().post(new Runnable() {
-                        @Override
-                        public void run() {
-                            final BugzillaIssue issue = getIssue();
-                            if (issue == null) {
-                                LOG.fine("Resole action: null issue 
returned"); //NOI18N
-                            } else {
-                                if (!issue.isResolveAvailable()) {
-                                    DialogDisplayer.getDefault().notify(new 
NotifyDescriptor.Message(
-                                            
NbBundle.getMessage(BugzillaTaskListProvider.class, 
"BugzillaIssueProvider.resolveAction.notPermitted"),
-                                            
NotifyDescriptor.INFORMATION_MESSAGE));
-                                    return;
-                                }
-                                ResolveIssuePanel panel = new 
ResolveIssuePanel(issue);
-                                if (panel.showDialog()) {
-                                    LOG.finer("Resolve action: 
resolving..."); //NOI18N
-                                    String pattern = 
NbBundle.getMessage(BugzillaTaskListProvider.class, 
"BugzillaIssueProvider.resolveIssueMessage"); //NOI18N
-                                    final String resolution = 
panel.getSelectedResolution();
-                                    final String duplicateId = 
panel.getDuplicateId();
-                                    final String comment = 
panel.getComment();
-                                    runCancellableCommand(new Runnable () {
-                                        @Override
-                                        public void run() {
-                                            if 
(BugzillaIssue.RESOLVE_DUPLICATE.equals(resolution)) {
-                                                issue.duplicate(duplicateId);
-                                            } else {
-                                                issue.resolve(resolution);
-                                            }
-                                            if (comment.length() > 0) {
-                                                issue.addComment(comment);
-                                            }
-                                            if (issue.submitAndRefresh()) {
-                                                
BugzillaUtil.openIssue(issue);
-                                            }
-                                        }
-                                    }, MessageFormat.format(pattern, 
issue.getID()));
-                                }
-                            }
-                        }
-                    });
-                }
-
-                @Override
-                public boolean isEnabled() {
-                    // try to disable the action for cached closed issues
-                    boolean allowed = true;
-                    BugzillaIssue issue = issueRef.get();
-                    if (issue != null) {
-                        allowed = issue.isResolveAvailable();
-                    }
-                    return allowed;
-                }
-            });
-            return actions;
-        }
-
-        /**
-         * Returns true if the issue can be automatically removed, which 
should not be met for kenai issues
-         * @return
-         */
-        protected boolean canBeAutoRemoved() {
-            return true;
-        }
-
-        /**
-         * Stores a reference to the repository for quick access
-         * @param repository
-         */
-        protected void setRepositoryReference(BugzillaRepository repository) 
{
-            if (repository != null) {
-                repositoryRef = new 
WeakReference<BugzillaRepository>(repository);
-            }
-        }
-
-        @Override
-        public void open() {
-            BugzillaIssue issue = getIssue();
-            if (issue != null) {
-                LOG.log(Level.FINER, "TaskListProvider: openning issue {0}", 
getName()); //NOI18N
-                // openning the real issue in it's top component
-                BugzillaUtil.openIssue(issue);
-            } else {
-                LOG.log(Level.FINE, "null issue returned for {0}", 
getName()); //NOI18N
-            }
-        }
-    }
-
-    /**
-     * Specific kenai Bugzilla lazy issue.
-     */
-    private static final class KenaiBugzillaLazyIssue extends 
BugzillaLazyIssue {
-
-        private final String projectName;
-        private boolean loginStatusChanged = true;
-
-        public KenaiBugzillaLazyIssue (BugzillaIssue issue, 
BugzillaTaskListProvider provider) throws MalformedURLException {
-            super(issue, provider);
-            BugzillaRepository repo = issue.getRepository();
-            if (!(repo instanceof KenaiRepository)) {
-                throw new IllegalStateException("Cannot instantiate with a 
non kenai issue: " + issue); //NOI18N
-            }
-            projectName = ((KenaiRepository) repo).getProductName();
-        }
-
-        public KenaiBugzillaLazyIssue (String name, URL url, String issueId, 
String projectName, BugzillaTaskListProvider provider) {
-            super(name, url, issueId, null, provider);
-            this.projectName = projectName;
-        }
-
-        protected KenaiRepository lookupRepository () {
-            KenaiRepository kenaiRepo = null;
-            BugzillaRepository repo = null;
-            if (loginStatusChanged) {
-                try {
-                    LOG.log(Level.FINE, 
"KenaiBugzillaLazyIssue.lookupRepository: getting repository for: " + 
projectName);
-                    String url = getUrl().toString();
-                    Repository repository = KenaiUtil.getRepository(url, 
projectName);
-                    repo = repository != null ? 
provider.bugzillaRepositories.get(repository.getId()) : null;
-                } catch (IOException ex) {
-                    LOG.log(Level.FINE, 
"KenaiBugzillaLazyIssue.lookupRepository: getting repository for " + 
projectName, ex);
-                }
-                loginStatusChanged = false;
-            }
-            if (repo != null && repo instanceof KenaiRepository) {
-                kenaiRepo = (KenaiRepository) repo;
-            } else {
-                LOG.log(Level.FINE, 
"KenaiBugzillaLazyIssue.lookupRepository: no repository for: " + projectName);
-            }
-            return kenaiRepo;
-        }
-
-        @Override
-        protected boolean canBeAutoRemoved() {
-            return false;
-        }
-
-        @Override
-        /**
-         * Stored Kenai issues have no repository url, but rather a project 
name as a repository identifier,
-         * so the repository must be looked up.
-         */
-        public String getRepositoryUrl() {
-            String repoUrl = super.getRepositoryUrl();
-            if (repoUrl == null) {
-                KenaiRepository repo = lookupRepository();
-                if (repo != null) {
-                    setRepositoryReference(repo);
-                    repoUrl = repo.getUrl();
-                }
-            }
-            return repoUrl;
-        }
-
-        private void notifyKenaiLogin () {
-            loginStatusChanged = true;
-            setValid(false);
-        }
-    }
-}
diff --git 
a/bugzilla/src/org/netbeans/modules/bugzilla/issue/Bundle.properties 
b/bugzilla/src/org/netbeans/modules/bugzilla/issue/Bundle.properties
--- a/bugzilla/src/org/netbeans/modules/bugzilla/issue/Bundle.properties
+++ b/bugzilla/src/org/netbeans/modules/bugzilla/issue/Bundle.properties
@@ -143,8 +143,7 @@
 IssuePanel.reloadMessage=Reloading server attributes
 IssuePanel.refreshButton.toolTipText=Load the latest issue data from the 
server.
 IssuePanel.reloadButton.toolTipText=Reload sever attributes like the list of 
components, versions, etc.
-IssuePanel.tasklistButton.add=Add to Action Items
-IssuePanel.tasklistButton.remove=Remove from Action Items
+IssuePanel.tasklistButton.add=Add to Category
 IssuePanel.statusWhiteboardLabel.text=Status Whiteboard:
 IssuePanel.issueTypeLabel.text=Issue Type:
 
diff --git a/bugzilla/src/org/netbeans/modules/bugzilla/issue/IssuePanel.form 
b/bugzilla/src/org/netbeans/modules/bugzilla/issue/IssuePanel.form
--- a/bugzilla/src/org/netbeans/modules/bugzilla/issue/IssuePanel.form
+++ b/bugzilla/src/org/netbeans/modules/bugzilla/issue/IssuePanel.form
@@ -323,7 +323,7 @@
                   <Group type="102" alignment="1" attributes="0">
                       <Component id="headerField" max="32767" 
attributes="0"/>
                       <EmptySpace max="-2" attributes="0"/>
-                      <Component id="tasklistButton" min="-2" max="-2" 
attributes="0"/>
+                      <Component id="addToCategoryButton" min="-2" max="-2" 
attributes="0"/>
                       <EmptySpace max="-2" attributes="0"/>
                       <Component id="separatorLabel2" min="-2" max="-2" 
attributes="0"/>
                       <EmptySpace max="-2" attributes="0"/>
@@ -505,7 +505,7 @@
               <Group type="103" groupAlignment="0" attributes="0">
                   <Component id="headerField" alignment="0" min="-2" 
max="-2" attributes="0"/>
                   <Component id="separatorLabel2" linkSize="6" alignment="0" 
min="-2" max="-2" attributes="0"/>
-                  <Component id="tasklistButton" alignment="0" min="-2" 
max="-2" attributes="0"/>
+                  <Component id="addToCategoryButton" alignment="0" min="-2" 
max="-2" attributes="0"/>
                   <Component id="separatorLabel" linkSize="6" alignment="0" 
min="-2" max="-2" attributes="0"/>
                   <Component id="reloadButton" linkSize="6" alignment="0" 
min="-2" max="-2" attributes="0"/>
                   <Component id="refreshButton" linkSize="6" alignment="0" 
min="-2" max="-2" attributes="0"/>
@@ -1176,14 +1176,14 @@
         </Property>
       </Properties>
     </Component>
-    <Component class="org.netbeans.modules.bugtracking.util.LinkButton" 
name="tasklistButton">
+    <Component class="org.netbeans.modules.bugtracking.util.LinkButton" 
name="addToCategoryButton">
       <Properties>
         <Property name="text" type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
           <ResourceString 
bundle="org/netbeans/modules/bugzilla/issue/Bundle.properties" 
key="IssuePanel.tasklistButton.add" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
         </Property>
       </Properties>
       <Events>
-        <EventHandler event="actionPerformed" 
listener="java.awt.event.ActionListener" 
parameters="java.awt.event.ActionEvent" 
handler="tasklistButtonActionPerformed"/>
+        <EventHandler event="actionPerformed" 
listener="java.awt.event.ActionListener" 
parameters="java.awt.event.ActionEvent" 
handler="addToCategoryButtonActionPerformed"/>
       </Events>
     </Component>
     <Component class="javax.swing.JLabel" name="separatorLabel2">
diff --git a/bugzilla/src/org/netbeans/modules/bugzilla/issue/IssuePanel.java 
b/bugzilla/src/org/netbeans/modules/bugzilla/issue/IssuePanel.java
--- a/bugzilla/src/org/netbeans/modules/bugzilla/issue/IssuePanel.java
+++ b/bugzilla/src/org/netbeans/modules/bugzilla/issue/IssuePanel.java
@@ -166,7 +166,6 @@
     private boolean reloading;
     private boolean skipReload;
     private boolean usingTargetMilestones;
-    private PropertyChangeListener tasklistListener;
     private OwnerInfo ownerInfo;
     private String assignee = null;
     private UndoRedoSupport undoRedoSupport;
@@ -358,7 +357,6 @@
             swap(layout, severityWarning, issueTypeWarning, temp);
         }
                 
-        tasklistButton.setEnabled(false);
         reloadForm(true);
 
         if (issue.isNew()) {
@@ -669,7 +667,6 @@
         if (force && !isNew) {
             addCommentArea.setText(""); // NOI18N
         }
-        updateTasklistButton();
         updateFieldStatuses();
         updateNoSummary();
         if ((fieldWarnings.size() != noWarnings) || (fieldErrors.size() != 
noErrors)) {
@@ -1247,58 +1244,6 @@
         }
     }
 
-    private void attachTasklistListener (BugzillaTaskListProvider provider) {
-        if (tasklistListener == null) { // is not attached yet
-            // listens on events comming from the tasklist, like when an 
issue is removed, etc.
-            // needed to correctly update tasklistButton label and status
-            tasklistListener = new PropertyChangeListener() {
-                @Override
-                public void propertyChange(PropertyChangeEvent evt) {
-                    if 
(BugzillaTaskListProvider.PROPERTY_ISSUE_REMOVED.equals(evt.getPropertyName())
 && issue.equals(evt.getOldValue())) {
-                        Runnable inAWT = new Runnable() {
-                            @Override
-                            public void run() {
-                                updateTasklistButton();
-                            }
-                        };
-                        if (EventQueue.isDispatchThread()) {
-                            inAWT.run();
-                        } else {
-                            EventQueue.invokeLater(inAWT);
-                        }
-                    }
-                }
-            };
-            
provider.addPropertyChangeListener(org.openide.util.WeakListeners.propertyChange(tasklistListener,
 provider));
-        }
-    }
-
-    private void updateTasklistButton() {
-        tasklistButton.setEnabled(false);
-        RP.post(new Runnable() {
-            @Override
-            public void run() {
-                BugzillaTaskListProvider provider = 
BugzillaTaskListProvider.getInstance();
-                if (provider == null || issue.isNew()) { // do not enable 
button for new issues
-                    return;
-                }
-                final boolean isInTasklist = provider.isAdded(issue);
-                if (isInTasklist) {
-                    attachTasklistListener(provider);
-                }
-                EventQueue.invokeLater(new Runnable() {
-                    @Override
-                    public void run() {
-                        String tasklistMessage = 
NbBundle.getMessage(IssuePanel.class,
-                                isInTasklist ? 
"IssuePanel.tasklistButton.remove" : "IssuePanel.tasklistButton.add"); // 
NOI18N
-                        tasklistButton.setText(tasklistMessage);
-                        tasklistButton.setEnabled(true);
-                    }
-                });
-            }
-        });
-    }
-
     private void initSpellChecker () {
         Spellchecker.register(summaryField);
         Spellchecker.register(addCommentArea);
@@ -1535,7 +1480,7 @@
         showInBrowserButton = new 
org.netbeans.modules.bugtracking.util.LinkButton();
         separatorLabel = new javax.swing.JLabel();
         resolutionLabel = new javax.swing.JLabel();
-        tasklistButton = new 
org.netbeans.modules.bugtracking.util.LinkButton();
+        addToCategoryButton = new 
org.netbeans.modules.bugtracking.util.LinkButton();
         separatorLabel2 = new javax.swing.JLabel();
         separatorLabel3 = new javax.swing.JLabel();
         productLabel = new javax.swing.JLabel();
@@ -1840,8 +1785,8 @@
 
         org.openide.awt.Mnemonics.setLocalizedText(resolutionLabel, 
org.openide.util.NbBundle.getMessage(IssuePanel.class, 
"IssuePanel.resolutionLabel.text")); // NOI18N
 
-        org.openide.awt.Mnemonics.setLocalizedText(tasklistButton, 
org.openide.util.NbBundle.getMessage(IssuePanel.class, 
"IssuePanel.tasklistButton.add")); // NOI18N
-        tasklistButton.addActionListener(formListener);
+        org.openide.awt.Mnemonics.setLocalizedText(addToCategoryButton, 
org.openide.util.NbBundle.getMessage(IssuePanel.class, 
"IssuePanel.tasklistButton.add")); // NOI18N
+        addToCategoryButton.addActionListener(formListener);
 
         
separatorLabel2.setBorder(javax.swing.BorderFactory.createLineBorder(new 
java.awt.Color(0, 0, 0)));
 
@@ -1917,7 +1862,7 @@
                     .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, 
layout.createSequentialGroup()
                         .addComponent(headerField)
                         
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                        .addComponent(tasklistButton, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
+                        .addComponent(addToCategoryButton, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
                         
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                         .addComponent(separatorLabel2)
                         
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
@@ -2075,7 +2020,7 @@
                 
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                     .addComponent(headerField, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
                     .addComponent(separatorLabel2)
-                    .addComponent(tasklistButton, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addComponent(addToCategoryButton, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
                     .addComponent(separatorLabel)
                     .addComponent(reloadButton, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
                     .addComponent(refreshButton, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
@@ -2201,7 +2146,6 @@
                 
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                     .addComponent(addCommentLabel)
                     .addComponent(scrollPane1, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE))
-                
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                 
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                     .addGroup(layout.createSequentialGroup()
                         .addGap(2, 2, 2)
@@ -2296,8 +2240,8 @@
             else if (evt.getSource() == showInBrowserButton) {
                 IssuePanel.this.showInBrowserButtonActionPerformed(evt);
             }
-            else if (evt.getSource() == tasklistButton) {
-                IssuePanel.this.tasklistButtonActionPerformed(evt);
+            else if (evt.getSource() == addToCategoryButton) {
+                IssuePanel.this.addToCategoryButtonActionPerformed(evt);
             }
             else if (evt.getSource() == versionCombo) {
                 IssuePanel.this.versionComboActionPerformed(evt);
@@ -2317,21 +2261,21 @@
             else if (evt.getSource() == submitButton) {
                 IssuePanel.this.submitButtonActionPerformed(evt);
             }
+            else if (evt.getSource() == cancelButton) {
+                IssuePanel.this.cancelButtonActionPerformed(evt);
+            }
+            else if (evt.getSource() == attachLogCheckBox) {
+                IssuePanel.this.attachLogCheckBoxActionPerformed(evt);
+            }
+            else if (evt.getSource() == viewLogButton) {
+                IssuePanel.this.viewLogButtonActionPerformed(evt);
+            }
             else if (evt.getSource() == resolutionCombo) {
                 IssuePanel.this.resolutionComboActionPerformed(evt);
             }
             else if (evt.getSource() == assignedCombo) {
                 IssuePanel.this.assignedComboActionPerformed(evt);
             }
-            else if (evt.getSource() == attachLogCheckBox) {
-                IssuePanel.this.attachLogCheckBoxActionPerformed(evt);
-            }
-            else if (evt.getSource() == viewLogButton) {
-                IssuePanel.this.viewLogButtonActionPerformed(evt);
-            }
-            else if (evt.getSource() == cancelButton) {
-                IssuePanel.this.cancelButtonActionPerformed(evt);
-            }
         }
 
         public void focusGained(java.awt.event.FocusEvent evt) {
@@ -2798,17 +2742,9 @@
         }
     }//GEN-LAST:event_duplicateButtonActionPerformed
 
-    private void tasklistButtonActionPerformed(java.awt.event.ActionEvent 
evt) {//GEN-FIRST:event_tasklistButtonActionPerformed
-        tasklistButton.setEnabled(false);
-        BugzillaTaskListProvider provider = 
BugzillaTaskListProvider.getInstance();
-        if (provider.isAdded(issue)) {
-            provider.remove(issue);
-        } else {
-            attachTasklistListener(provider);
-            provider.add(issue, true);
-        }
-        updateTasklistButton();
-    }//GEN-LAST:event_tasklistButtonActionPerformed
+    private void 
addToCategoryButtonActionPerformed(java.awt.event.ActionEvent evt) 
{//GEN-FIRST:event_addToCategoryButtonActionPerformed
+        
Bugzilla.getInstance().getBugtrackingFactory().addToCategory(BugzillaUtil.getRepository(issue.getRepository()),
 issue);
+    }//GEN-LAST:event_addToCategoryButtonActionPerformed
 
     private void assignedComboActionPerformed(java.awt.event.ActionEvent 
evt) {//GEN-FIRST:event_assignedComboActionPerformed
         cancelHighlight(assignedLabel);
@@ -2918,6 +2854,7 @@
     private javax.swing.JLabel actualWarning;
     private javax.swing.JTextArea addCommentArea;
     private javax.swing.JLabel addCommentLabel;
+    private org.netbeans.modules.bugtracking.util.LinkButton 
addToCategoryButton;
     private javax.swing.JCheckBox assignToDefaultCheckBox;
     private javax.swing.JComboBox assignedCombo;
     private javax.swing.JTextField assignedField;
@@ -3025,7 +2962,6 @@
     private javax.swing.JLabel summaryWarning;
     private javax.swing.JComboBox targetMilestoneCombo;
     private javax.swing.JLabel targetMilestoneLabel;
-    private org.netbeans.modules.bugtracking.util.LinkButton tasklistButton;
     private javax.swing.JLabel timetrackingLabel;
     private javax.swing.JPanel timetrackingPanel;
     private javax.swing.JTextField urlField;
diff --git 
a/bugzilla/src/org/netbeans/modules/bugzilla/repository/BugzillaRepository.java
 
b/bugzilla/src/org/netbeans/modules/bugzilla/repository/BugzillaRepository.java
--- 
a/bugzilla/src/org/netbeans/modules/bugzilla/repository/BugzillaRepository.java
+++ 
b/bugzilla/src/org/netbeans/modules/bugzilla/repository/BugzillaRepository.java
@@ -81,7 +81,6 @@
 import org.netbeans.modules.bugzilla.commands.BugzillaExecutor;
 import org.netbeans.modules.mylyn.util.GetMultiTaskDataCommand;
 import org.netbeans.modules.mylyn.util.PerformQueryCommand;
-import org.netbeans.modules.bugzilla.issue.BugzillaTaskListProvider;
 import org.netbeans.modules.bugzilla.query.QueryController;
 import org.netbeans.modules.bugzilla.query.QueryParameter;
 import org.netbeans.modules.bugzilla.util.BugzillaConstants;
@@ -152,8 +151,6 @@
         String url = info.getUrl();
         boolean shortLoginEnabled = 
Boolean.parseBoolean(info.getValue(IBugzillaConstants.REPOSITORY_SETTING_SHORT_LOGIN));
         taskRepository = createTaskRepository(name, url, user, password, 
httpUser, httpPassword, shortLoginEnabled);
-        
-        BugzillaTaskListProvider.getInstance().notifyRepositoryCreated(this);
     }
 
     public RepositoryInfo getInfo() {
@@ -205,7 +202,6 @@
             removeQuery(q);
         }
         resetRepository(true);
-        BugzillaTaskListProvider.getInstance().notifyRepositoryRemoved(this);
     }
 
     public Lookup getLookup() {
diff --git 
a/bugzilla/test/unit/src/org/netbeans/modules/bugzilla/query/QueryRefreshTest.java
 
b/bugzilla/test/unit/src/org/netbeans/modules/bugzilla/query/QueryRefreshTest.java
--- 
a/bugzilla/test/unit/src/org/netbeans/modules/bugzilla/query/QueryRefreshTest.java
+++ 
b/bugzilla/test/unit/src/org/netbeans/modules/bugzilla/query/QueryRefreshTest.java
@@ -43,22 +43,17 @@
 package org.netbeans.modules.bugzilla.query;
 
 import java.text.MessageFormat;
-import java.util.Collection;
 import java.util.logging.Level;
 import org.netbeans.junit.NbTestCase;
-import org.netbeans.junit.RandomlyFails;
 import org.netbeans.modules.bugtracking.TestKit;
 import org.netbeans.modules.bugtracking.dummies.DummyBugtrackingOwnerSupport;
 import org.netbeans.modules.bugtracking.util.BugtrackingUtil;
 import org.netbeans.modules.bugzilla.Bugzilla;
-import org.netbeans.modules.bugzilla.BugzillaConfig;
 import org.netbeans.modules.bugzilla.LogHandler;
 import org.netbeans.modules.bugzilla.TestConstants;
 import org.netbeans.modules.bugzilla.TestUtil;
 import org.netbeans.modules.bugzilla.issue.BugzillaIssue;
-import org.netbeans.modules.bugzilla.issue.BugzillaTaskListProvider;
 import org.netbeans.modules.bugzilla.repository.BugzillaRepository;
-import org.netbeans.modules.bugzilla.util.BugzillaUtil;
 import org.openide.util.lookup.AbstractLookup;
 import org.openide.util.lookup.InstanceContent;
 import org.openide.util.test.MockLookup;
@@ -129,7 +124,6 @@
         private TestLookup(InstanceContent ic) {
             super(ic);
             ic.add(new DummyBugtrackingOwnerSupport());
-            ic.add(BugzillaTaskListProvider.getInstance());
         }
     }
 
diff --git a/jira/src/org/netbeans/modules/jira/Jira.java 
b/jira/src/org/netbeans/modules/jira/Jira.java
--- a/jira/src/org/netbeans/modules/jira/Jira.java
+++ b/jira/src/org/netbeans/modules/jira/Jira.java
@@ -45,13 +45,11 @@
 import com.atlassian.connector.eclipse.internal.jira.core.JiraClientFactory;
 import 
com.atlassian.connector.eclipse.internal.jira.core.JiraRepositoryConnector;
 import com.atlassian.connector.eclipse.internal.jira.core.service.JiraClient;
-import 
com.atlassian.connector.eclipse.internal.jira.core.service.JiraException;
 import java.util.logging.Logger;
 import org.eclipse.mylyn.tasks.core.TaskRepository;
 import org.netbeans.modules.bugtracking.issuetable.IssueNode;
 import org.netbeans.modules.bugtracking.spi.BugtrackingFactory;
 import org.netbeans.modules.bugtracking.util.UndoRedoSupport;
-import org.netbeans.modules.jira.issue.JiraTaskListProvider;
 import org.netbeans.modules.jira.issue.NbJiraIssue;
 import org.netbeans.modules.jira.query.JiraQuery;
 import org.netbeans.modules.jira.repository.JiraRepository;
@@ -85,13 +83,6 @@
     public static synchronized Jira getInstance() {
         if(instance == null) {
             instance = new Jira();
-            // lazy ping tasklist issue provider to load issues ...
-            instance.getRequestProcessor().post(new Runnable() {
-                @Override
-                public void run() {
-                    JiraTaskListProvider.getInstance();
-                }
-            });
         }
         return instance;
     }
diff --git a/jira/src/org/netbeans/modules/jira/JiraConnector.java 
b/jira/src/org/netbeans/modules/jira/JiraConnector.java
--- a/jira/src/org/netbeans/modules/jira/JiraConnector.java
+++ b/jira/src/org/netbeans/modules/jira/JiraConnector.java
@@ -54,13 +54,10 @@
 import org.netbeans.modules.jira.repository.JiraRepository;
 import org.netbeans.modules.bugtracking.spi.BugtrackingConnector;
 import org.netbeans.modules.bugtracking.spi.RepositoryInfo;
-import org.netbeans.modules.bugtracking.spi.TaskListIssueProvider;
 import org.netbeans.modules.jira.issue.JiraIssueFinder;
-import org.netbeans.modules.jira.issue.JiraTaskListProvider;
 import org.netbeans.modules.jira.kenai.KenaiRepository;
 import org.netbeans.modules.jira.util.JiraUtils;
 import org.openide.util.Exceptions;
-import org.openide.util.Lookup;
 import org.openide.util.NbBundle;
 
 /**
@@ -123,11 +120,6 @@
         return JiraIssueFinder.getInstance();
     }
 
-    @Override
-    public TaskListIssueProvider getTasklistProvider() {
-        return JiraTaskListProvider.getInstance();
-    }
-    
     
/******************************************************************************
      * Kenai
      
******************************************************************************/
diff --git a/jira/src/org/netbeans/modules/jira/issue/Bundle.properties 
b/jira/src/org/netbeans/modules/jira/issue/Bundle.properties
--- a/jira/src/org/netbeans/modules/jira/issue/Bundle.properties
+++ b/jira/src/org/netbeans/modules/jira/issue/Bundle.properties
@@ -161,8 +161,7 @@
 IssuePanel.reopenIssueMessage=Reopening issue {0}
 IssuePanel.logWorkButton2.text=Log Work on this Issue
 IssuePanel.logWorkMessage=Logging work on issue {0}
-IssuePanel.tasklistButton.add=Add to ActionItems
-IssuePanel.tasklistButton.remove=Remove from ActionItems
+IssuePanel.tasklistButton.add=Add to Category
 IssuePanel.issueLinksLabel.text=Issue Links:
 
 # ResolveIssuePanel
diff --git a/jira/src/org/netbeans/modules/jira/issue/IssuePanel.form 
b/jira/src/org/netbeans/modules/jira/issue/IssuePanel.form
--- a/jira/src/org/netbeans/modules/jira/issue/IssuePanel.form
+++ b/jira/src/org/netbeans/modules/jira/issue/IssuePanel.form
@@ -727,7 +727,7 @@
                       <Component id="stopProgressButton" alignment="0" 
min="-2" max="-2" attributes="0"/>
                       <Component id="closeIssueButton" alignment="0" 
min="-2" max="-2" attributes="0"/>
                       <Component id="reopenIssueButton" alignment="0" 
min="-2" max="-2" attributes="0"/>
-                      <Component id="tasklistButton" alignment="0" min="-2" 
max="-2" attributes="0"/>
+                      <Component id="addToCategoryButton" alignment="0" 
min="-2" max="-2" attributes="0"/>
                       <Component id="showInBrowserButton" alignment="0" 
min="-2" max="-2" attributes="0"/>
                   </Group>
                   <EmptySpace max="32767" attributes="0"/>
@@ -756,7 +756,7 @@
                   <EmptySpace max="-2" attributes="0"/>
                   <Component id="logWorkButton" min="-2" max="-2" 
attributes="0"/>
                   <EmptySpace max="-2" attributes="0"/>
-                  <Component id="tasklistButton" min="-2" max="-2" 
attributes="0"/>
+                  <Component id="addToCategoryButton" min="-2" max="-2" 
attributes="0"/>
                   <EmptySpace max="-2" attributes="0"/>
                   <Component id="showInBrowserButton" min="-2" max="-2" 
attributes="0"/>
                   <EmptySpace max="-2" attributes="0"/>
@@ -866,15 +866,14 @@
             <EventHandler event="actionPerformed" 
listener="java.awt.event.ActionListener" 
parameters="java.awt.event.ActionEvent" 
handler="reopenIssueButtonActionPerformed"/>
           </Events>
         </Component>
-        <Component class="org.netbeans.modules.bugtracking.util.LinkButton" 
name="tasklistButton">
+        <Component class="org.netbeans.modules.bugtracking.util.LinkButton" 
name="addToCategoryButton">
           <Properties>
             <Property name="text" type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
               <ResourceString 
bundle="org/netbeans/modules/jira/issue/Bundle.properties" 
key="IssuePanel.tasklistButton.add" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
             </Property>
-            <Property name="enabled" type="boolean" value="false"/>
           </Properties>
           <Events>
-            <EventHandler event="actionPerformed" 
listener="java.awt.event.ActionListener" 
parameters="java.awt.event.ActionEvent" 
handler="tasklistButtonActionPerformed"/>
+            <EventHandler event="actionPerformed" 
listener="java.awt.event.ActionListener" 
parameters="java.awt.event.ActionEvent" 
handler="addToCategoryButtonActionPerformed"/>
           </Events>
         </Component>
         <Component class="org.netbeans.modules.bugtracking.util.LinkButton" 
name="showInBrowserButton">
diff --git a/jira/src/org/netbeans/modules/jira/issue/IssuePanel.java 
b/jira/src/org/netbeans/modules/jira/issue/IssuePanel.java
--- a/jira/src/org/netbeans/modules/jira/issue/IssuePanel.java
+++ b/jira/src/org/netbeans/modules/jira/issue/IssuePanel.java
@@ -167,7 +167,6 @@
     private boolean skipReload;
     private boolean reloading;
     private Map<NbJiraIssue.IssueField,Object> initialValues = new 
EnumMap<NbJiraIssue.IssueField,Object>(NbJiraIssue.IssueField.class);
-    private PropertyChangeListener tasklistListener;
     private UndoRedoSupport undoRedoSupport;
 
     public IssuePanel() {
@@ -803,7 +802,6 @@
                 });
             }
         }
-        updateTasklistButton();
         updateFieldStatuses();
         reloading = false;
     }
@@ -1138,58 +1136,6 @@
         return allowedStatuses;
     }
 
-    private void updateTasklistButton() {
-        tasklistButton.setEnabled(false);
-        RP.post(new Runnable() {
-            @Override
-            public void run() {
-                JiraTaskListProvider provider = 
JiraTaskListProvider.getInstance();
-                if (provider == null || issue.isNew()) { // do not enable 
button for new issues
-                    return;
-                }
-                final boolean isInTasklist = provider.isAdded(issue);
-                if (isInTasklist) {
-                    attachTasklistListener(provider);
-                }
-                EventQueue.invokeLater(new Runnable() {
-                    @Override
-                    public void run() {
-                        String tasklistMessage = 
NbBundle.getMessage(IssuePanel.class,
-                                isInTasklist ? 
"IssuePanel.tasklistButton.remove" : "IssuePanel.tasklistButton.add"); // 
NOI18N
-                        tasklistButton.setText(tasklistMessage);
-                        tasklistButton.setEnabled(true);
-                    }
-                });
-            }
-        });
-    }
-
-    private void attachTasklistListener (JiraTaskListProvider provider) {
-        if (tasklistListener == null) { // is not attached yet
-            // listens on events comming from the tasklist, like when an 
issue is removed, etc.
-            // needed to correctly update tasklistButton label and status
-            tasklistListener = new PropertyChangeListener() {
-                @Override
-                public void propertyChange(PropertyChangeEvent evt) {
-                    if 
(JiraTaskListProvider.PROPERTY_ISSUE_REMOVED.equals(evt.getPropertyName()) && 
issue.equals(evt.getOldValue())) {
-                        Runnable inAWT = new Runnable() {
-                            @Override
-                            public void run() {
-                                updateTasklistButton();
-                            }
-                        };
-                        if (EventQueue.isDispatchThread()) {
-                            inAWT.run();
-                        } else {
-                            EventQueue.invokeLater(inAWT);
-                        }
-                    }
-                }
-            };
-            
provider.addPropertyChangeListener(org.openide.util.WeakListeners.propertyChange(tasklistListener,
 provider));
-        }
-    }
-
     private void submitChange(final Runnable change, String progressMessage) 
 {
         final ProgressHandle handle = 
ProgressHandleFactory.createHandle(progressMessage);
         handle.start();
@@ -1314,7 +1260,7 @@
         logWorkButton = new 
org.netbeans.modules.bugtracking.util.LinkButton();
         refreshButton = new 
org.netbeans.modules.bugtracking.util.LinkButton();
         reopenIssueButton = new 
org.netbeans.modules.bugtracking.util.LinkButton();
-        tasklistButton = new 
org.netbeans.modules.bugtracking.util.LinkButton();
+        addToCategoryButton = new 
org.netbeans.modules.bugtracking.util.LinkButton();
         showInBrowserButton = new 
org.netbeans.modules.bugtracking.util.LinkButton();
         originalEstimatePanel = new javax.swing.JPanel();
         remainingEstimatePanel = new javax.swing.JPanel();
@@ -1534,11 +1480,10 @@
             }
         });
 
-        
tasklistButton.setText(org.openide.util.NbBundle.getMessage(IssuePanel.class, 
"IssuePanel.tasklistButton.add")); // NOI18N
-        tasklistButton.setEnabled(false);
-        tasklistButton.addActionListener(new java.awt.event.ActionListener() 
{
+        
addToCategoryButton.setText(org.openide.util.NbBundle.getMessage(IssuePanel.class,
 "IssuePanel.tasklistButton.add")); // NOI18N
+        addToCategoryButton.addActionListener(new 
java.awt.event.ActionListener() {
             public void actionPerformed(java.awt.event.ActionEvent evt) {
-                tasklistButtonActionPerformed(evt);
+                addToCategoryButtonActionPerformed(evt);
             }
         });
 
@@ -1566,9 +1511,9 @@
                     .addComponent(stopProgressButton, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
                     .addComponent(closeIssueButton, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
                     .addComponent(reopenIssueButton, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
-                    .addComponent(tasklistButton, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addComponent(addToCategoryButton, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
                     .addComponent(showInBrowserButton, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE))
-                .addContainerGap())
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, 
Short.MAX_VALUE))
         );
         actionPanelLayout.setVerticalGroup(
             
actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@@ -1592,7 +1537,7 @@
                 
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                 .addComponent(logWorkButton, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
                 
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                .addComponent(tasklistButton, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addComponent(addToCategoryButton, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
                 
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                 .addComponent(showInBrowserButton, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
                 
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
@@ -2188,17 +2133,9 @@
         }
     }//GEN-LAST:event_logWorkButtonActionPerformed
 
-    private void tasklistButtonActionPerformed(java.awt.event.ActionEvent 
evt) {//GEN-FIRST:event_tasklistButtonActionPerformed
-        tasklistButton.setEnabled(false);
-        JiraTaskListProvider provider = JiraTaskListProvider.getInstance();
-        if (provider.isAdded(issue)) {
-            provider.remove(issue);
-        } else {
-            attachTasklistListener(provider);
-            provider.add(issue, true);
-        }
-        updateTasklistButton();
-    }//GEN-LAST:event_tasklistButtonActionPerformed
+    private void 
addToCategoryButtonActionPerformed(java.awt.event.ActionEvent evt) 
{//GEN-FIRST:event_addToCategoryButtonActionPerformed
+        
Jira.getInstance().getBugtrackingFactory().addToCategory(JiraUtils.getRepository(issue.getRepository()),
 issue); 
+    }//GEN-LAST:event_addToCategoryButtonActionPerformed
 
     private void 
createSubtaskButtonActionPerformed(java.awt.event.ActionEvent evt) 
{//GEN-FIRST:event_createSubtaskButtonActionPerformed
         NbJiraIssue subTask = 
(NbJiraIssue)issue.getRepository().createIssue();
@@ -2246,6 +2183,7 @@
     private javax.swing.JTextArea addCommentArea;
     private javax.swing.JLabel addCommentLabel;
     private javax.swing.JScrollPane addCommentScrollPane;
+    private org.netbeans.modules.bugtracking.util.LinkButton 
addToCategoryButton;
     private javax.swing.JLabel affectsVersionLabel;
     private javax.swing.JList affectsVersionList;
     private javax.swing.JScrollPane affectsVersionScrollPane;
@@ -2316,7 +2254,6 @@
     private javax.swing.JLabel subtaskLabel;
     private javax.swing.JTextField summaryField;
     private javax.swing.JLabel summaryLabel;
-    private org.netbeans.modules.bugtracking.util.LinkButton tasklistButton;
     private javax.swing.JTextField timeSpentField;
     private javax.swing.JLabel timeSpentLabel;
     private javax.swing.JPanel timeSpentPanel;
diff --git 
a/jira/src/org/netbeans/modules/jira/issue/JiraTaskListProvider.java 
b/jira/src/org/netbeans/modules/jira/issue/JiraTaskListProvider.java
deleted file mode 100644
--- a/jira/src/org/netbeans/modules/jira/issue/JiraTaskListProvider.java
+++ /dev/null
@@ -1,888 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
- *
- * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
- * Other names may be trademarks of their respective owners.
- *
- * 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle 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 2009 Sun Microsystems, Inc.
- */
-
-package org.netbeans.modules.jira.issue;
-
-import 
com.atlassian.connector.eclipse.internal.jira.core.JiraRepositoryConnector;
-import com.atlassian.connector.eclipse.internal.jira.core.model.Resolution;
-import java.beans.PropertyChangeEvent;
-import org.netbeans.modules.bugtracking.kenai.spi.KenaiAccessor;
-import org.netbeans.modules.jira.repository.*;
-import java.awt.EventQueue;
-import java.awt.event.ActionEvent;
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeSupport;
-import java.io.IOException;
-import java.lang.ref.WeakReference;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.text.MessageFormat;
-import java.util.*;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.swing.AbstractAction;
-import javax.swing.Action;
-import org.netbeans.api.progress.ProgressHandle;
-import org.netbeans.api.progress.ProgressHandleFactory;
-import org.netbeans.modules.bugtracking.api.Repository;
-import org.netbeans.modules.bugtracking.api.RepositoryManager;
-import org.netbeans.modules.bugtracking.spi.IssueProvider;
-import org.netbeans.modules.bugtracking.spi.TaskListIssueProvider;
-import org.netbeans.modules.bugtracking.cache.IssueCache;
-import org.netbeans.modules.bugtracking.util.BugtrackingUtil;
-import org.netbeans.modules.bugtracking.kenai.spi.KenaiUtil;
-import org.netbeans.modules.jira.Jira;
-import org.netbeans.modules.jira.JiraConnector;
-import org.netbeans.modules.jira.kenai.KenaiRepository;
-import org.netbeans.modules.jira.util.JiraUtils;
-import org.openide.DialogDisplayer;
-import org.openide.NotifyDescriptor;
-import org.openide.util.NbBundle;
-import org.openide.util.RequestProcessor;
-import org.openide.util.WeakListeners;
-
-/**
- *
- * @author Ondra Vrabec
- */
-public final class JiraTaskListProvider extends TaskListIssueProvider 
implements PropertyChangeListener {
-
-    private static JiraTaskListProvider instance;
-    private final Object LOCK = new Object();
-    private boolean initialized;
-    private HashMap<String, JiraLazyIssue> watchedIssues = new 
HashMap<String, JiraLazyIssue>(10);
-    private static final Logger LOG = 
Logger.getLogger("org.netbeans.modules.jira.tasklist"); //NOI18N
-    private static final Level LOG_LEVEL = JiraUtils.isAssertEnabled() ? 
Level.INFO : Level.FINE;
-    private final RequestProcessor rp = new 
RequestProcessor("JiraTaskListProvider", 1, false);
-    private static final String KENAI_REPOSITORY_IDENT_PREFIX = "K##";  
//NOI18N
-    private static final String STORAGE_KENAI_VERSION = "1";                 
 //NOI18N
-    private static final String STORAGE_COMMON_VERSION = "1";                
  //NOI18N
-    private final PropertyChangeSupport support;
-
-    public static final String PROPERTY_ISSUE_REMOVED = "issue-removed"; 
//NOI18N
-
-    public static synchronized JiraTaskListProvider getInstance() {
-        if (instance == null) {
-            instance = new JiraTaskListProvider();
-        }
-        return instance;
-    }
-
-    private JiraTaskListProvider () {
-        // initialization
-        support = new PropertyChangeSupport(this);
-        reloadAsync();
-    }
-
-    /**
-     * Schedules the given issue to be added to the tasklist
-     * @param issue issue to add to the tasklist
-     * @param openTaskList if set to true, the tasklist will also be asked 
to open
-     */
-    public void add (NbJiraIssue issue, boolean openTaskList) {
-        URL url = getUrl(issue);
-        JiraLazyIssue lazyIssue;
-        // local store
-        synchronized (LOCK) {
-            if (isAdded(url)) return;
-            try {
-                JiraRepository jiraRepository = issue.getRepository();
-                
-                Repository repository = 
JiraUtils.getRepository(jiraRepository);
-                repository.removePropertyChangeListener(this);
-                repository.addPropertyChangeListener(this);
-                // create a representation of the real issue for tasklist
-                watchedIssues.put(url.toString(), lazyIssue =
-                        (jiraRepository instanceof KenaiRepository) ?
-                            new KenaiJiraLazyIssue(issue, this) :   // kenai 
lazy issue
-                            new JiraLazyIssue(issue, this));        // 
common jira lazy issue
-            } catch (MalformedURLException e) {
-                return;
-            }
-        }
-        saveIntern();
-
-        // schedule the addition to tasklist
-        super.add(openTaskList, lazyIssue);
-    }
-
-    /**
-     * Schedule given issue to be removed from the tasklist
-     * @param issue
-     */
-    public void remove (NbJiraIssue issue) {
-        URL url = getUrl(issue);
-        remove(url, true);
-    }
-
-    /**
-     * Tests if given issue is added to the tasklist.
-     * @param issue
-     * @return true if the given issue is already added.
-     */
-    public boolean isAdded(NbJiraIssue issue) {
-        URL url = getUrl(issue);
-        return isAdded(url);
-    }
-
-    @Override
-    public void removed(LazyIssue lazyIssue) {
-        JiraLazyIssue removedIssue;
-        synchronized (LOCK) {
-            if (!isAdded(lazyIssue.getUrl())) return;
-            removedIssue = 
watchedIssues.remove(lazyIssue.getUrl().toString());
-        }
-        saveIntern();
-        fireIssueRemoved(removedIssue);
-    }
-
-    /**
-     * These properties are fired:
-     * <ul>
-     * <li>{@link #PROPERTY_ISSUE_REMOVED} when an issue is removed from the 
tasklist in other way that with {@link 
#remove(org.netbeans.modules.jira.issue.NbJiraIssue),
-     * e.g. with a Remove action from a popup menu in the tasklist.</li>
-     * </ul>
-     * @param listener
-     */
-    public void addPropertyChangeListener (PropertyChangeListener listener) {
-        support.addPropertyChangeListener(listener);
-    }
-
-    public void removePropertyChangeListener (PropertyChangeListener 
listener) {
-        support.removePropertyChangeListener(listener);
-    }
-
-    @Override
-    public void propertyChange(PropertyChangeEvent evt) {
-        if 
(Repository.EVENT_ATTRIBUTES_CHANGED.equals(evt.getPropertyName())) {
-            if (evt.getOldValue() != null && evt.getOldValue() instanceof 
Map) {
-                Object oldValue = 
((Map)evt.getOldValue()).get(Repository.ATTRIBUTE_URL);
-                if (oldValue != null && oldValue instanceof String) {
-                    String oldRepoUrl = (String) oldValue;
-                    LinkedList<JiraLazyIssue> issuesToRefresh = new 
LinkedList<JiraLazyIssue>();
-                    synchronized (LOCK) {
-                        // lookup all issues with the same repository url as 
the changed value
-                        for (Map.Entry<String, JiraLazyIssue> e : 
watchedIssues.entrySet()) {
-                            JiraLazyIssue issue = e.getValue();
-                            Object sourceRepository = evt.getSource();
-                            if (!(issue instanceof KenaiJiraLazyIssue) && 
sourceRepository != null && sourceRepository.equals(issue.getRepository())) {
-                                URL oldUrl = getUrl(oldRepoUrl, 
issue.issueKey);
-                                if 
(issue.getUrl().toString().equals(oldUrl.toString()))  {
-                                    LOG.log(Level.FINE, "propertyChange: 
Issue {0} with url {1} needs to be refreshed, repository's url {2} has 
changed", //NOI18N
-                                            new String[] {issue.toString(), 
oldUrl.toString(), oldRepoUrl});
-                                    issuesToRefresh.add(issue);
-                                }
-                            }
-                        }
-                    }
-                    // refresh issues
-                    for (JiraLazyIssue issue : issuesToRefresh) {
-                        remove(issue.getUrl(), false);
-                        add(issue.getName(), issue.issueKey, 
issue.getRepository());
-                    }
-                    // store new issues
-                    if (!issuesToRefresh.isEmpty()) {
-                        saveIntern();
-                    }
-                }
-            }
-        } 
-    }
-
-    /**
-     * Removes all issues from the tasklist which belong to the given 
repository
-     * @param repository
-     */
-    public void removeAllFor (JiraRepository repository) {
-        LinkedList<JiraLazyIssue> issuesToRemove = new 
LinkedList<JiraLazyIssue>();
-                 synchronized (LOCK) {
-            // lookup all issues with the same repository url as the changed 
value
-            for (Map.Entry<String, JiraLazyIssue> e : 
watchedIssues.entrySet()) {
-                JiraLazyIssue issue = e.getValue();
-                if (!(issue instanceof KenaiJiraLazyIssue) && repository == 
issue.getRepository()) {
-                    LOG.log(Level.FINE, "removeAllFor: issue {0} repository 
{1} has been removed", new String[]{issue.toString(), 
repository.toString()}); //NOI18N
-                    issuesToRemove.add(issue);
-                }
-            }
-        }
-        // remove issues
-        for (JiraLazyIssue issue : issuesToRemove) {
-            remove(issue.getUrl(), false);
-        }
-        // store issues
-        if (!issuesToRemove.isEmpty()) {
-            saveIntern();
-        }
-    }
-
-    /**
-     * Call when an issue is loaded for the first time.
-     * @param issue cannot be null
-     */
-    public void notifyIssueCreated (NbJiraIssue issue) {
-        URL url = getUrl(issue);
-        JiraLazyIssue lazyIssue = null;
-        synchronized (LOCK) {
-            lazyIssue = watchedIssues.get(url.toString());
-        }
-        if (lazyIssue != null) {
-            lazyIssue.setIssueReference(issue);
-        }
-    }
-    
-    Map<String, JiraRepository> jiraRepositories = new HashMap<String, 
JiraRepository>();
-    public void notifyRepositoryCreated (JiraRepository repository) {
-        jiraRepositories.put(repository.getID(), repository);
-    }
-    public void notifyRepositoryRemoved (JiraRepository repository) {
-        jiraRepositories.remove(repository.getID());
-    }    
-
-    // **** private methods ***** //
-    private boolean isAdded(URL url) {
-        initializeIssues();
-        if (url == null) {
-            return false;
-        }
-        synchronized (LOCK) {
-            return watchedIssues.containsKey(url.toString());
-        }
-    }
-
-    private static URL getUrl (NbJiraIssue issue) {
-        return getUrl(issue.getRepository().getUrl(), issue.getID());
-    }
-
-    private static URL getUrl(String repositoryUrl, String issueKey) {
-        String url = 
JiraRepositoryConnector.getTaskUrlFromKey(repositoryUrl, issueKey);
-        try {
-            return new URL(url);
-        } catch (MalformedURLException ex) {
-            LOG.log(LOG_LEVEL, null, ex);
-        }
-        try {
-            return new URL(repositoryUrl + "#" + issueKey);             
//NOI18N
-        } catch (MalformedURLException ex) {
-            LOG.log(LOG_LEVEL, null, ex);
-            return null;
-        }
-    }
-
-    private void reloadAsync() {
-        rp.post(new Runnable () {
-            @Override
-            public void run() {
-                initializeIssues();
-            }
-        });
-    }
-
-    private void saveIntern() {
-        JiraLazyIssue[] lazyIssues;
-        synchronized(LOCK) {
-            lazyIssues = watchedIssues.values().toArray(new 
JiraLazyIssue[watchedIssues.size()]);
-        }
-        final JiraLazyIssue[] lazyIssuesToSave = lazyIssues;
-        rp.post(new Runnable () {
-            @Override
-            public void run() {
-                initializeIssues();
-                LOG.log(Level.FINE, "saveIntern: saving issues");       
//NOI18N
-                HashMap<String, List<String>> issues = new HashMap<String, 
List<String>>();
-                for (JiraLazyIssue issue : lazyIssuesToSave) {
-                    String repositoryIdent = null;
-                    boolean isKenai = false;
-                    if (issue instanceof KenaiJiraLazyIssue) {
-                        JiraRepository repo = issue.getRepository();
-                        if (repo != null && !(repo instanceof 
KenaiRepository)) {
-                            LOG.warning("saveIntern: KenaiJiraIssue has no 
kenai repository: " + repo); //NOI18N
-                        } else {
-                            // kenai repository is identified by project's 
name, not by it's url
-                            repositoryIdent = KENAI_REPOSITORY_IDENT_PREFIX 
+ (repo == null
-                                    ? ((KenaiJiraLazyIssue)issue).projectName
-                                    : ((KenaiRepository) 
repo).getDisplayName());
-                            isKenai = true;
-                        }
-                    } else {
-                        repositoryIdent = issue.getRepositoryUrl();
-                    }
-                    if (repositoryIdent != null) {
-                        List<String> issueAttributes = 
issues.get(repositoryIdent);
-                        if (issueAttributes == null) {
-                            issueAttributes = new LinkedList<String>();
-                            issueAttributes.add(isKenai ? 
STORAGE_KENAI_VERSION : STORAGE_COMMON_VERSION);
-                        }
-                        issueAttributes.add(issue.issueKey);            // 
key
-                        issueAttributes.add(issue.getName());           // 
description
-                        if (isKenai) {
-                            issueAttributes.add(issue.getUrl().toString()); 
// url needed only for kenai repos
-                        }
-                        if (LOG.isLoggable(Level.FINE)) {
-                            LOG.fine("saveIntern: saving " + issueAttributes 
+ " for repo: " + repositoryIdent); //NOI18N
-                        }
-                        issues.put(repositoryIdent, issueAttributes);
-                    }
-                }
-                // save permanently
-                JiraStorageManager.getInstance().setTaskListIssues(issues);
-            }
-        });
-    }
-
-    private void initializeIssues () {
-        synchronized (LOCK) {
-            if (initialized) {
-                return;
-            }
-            initialized = true;
-            LOG.finer("initializeIssues: reloading saved issues");      
//NOI18N
-            // load from storage
-            Map<String, List<String>> repositoryIssues = 
JiraStorageManager.getInstance().getTaskListIssues();
-            if (repositoryIssues.isEmpty()) {
-                LOG.fine("initializeIssues: no saved issues");          
//NOI18N
-                return;
-            }
-            addCommonIssues(repositoryIssues);
-            addKenaiIssues(repositoryIssues);
-        }
-    }
-
-    private String getNextAttribute (ListIterator<String> it) {
-        String attr = null;
-        if (it.hasNext()) {
-            attr = it.next();
-        }
-        return attr;
-    }
-
-    private void addCommonIssues (Map<String, List<String>> 
repositoryIssues) {
-        Collection<Repository> repositories = 
RepositoryManager.getInstance().getRepositories(JiraConnector.ID);
-            for (Repository repository : repositories) {
-                // all issues for this repository
-                List<String> issueAttributes = 
repositoryIssues.get(repository.getUrl());
-                if (issueAttributes != null && issueAttributes.size() > 1) {
-                    ListIterator<String> it = issueAttributes.listIterator();
-                    if (!STORAGE_COMMON_VERSION.equals(it.next())) {
-                        LOG.log(Level.WARNING, "Old unsupported storage 
version, expecting {0}", STORAGE_COMMON_VERSION); //NOI18N
-                        break;
-                    }
-                    for (; it.hasNext(); ) {
-                        String issueKey = getNextAttribute(it);
-                        String issueName = getNextAttribute(it);
-                        if (issueKey == null || issueName == null) {
-                            LOG.log(Level.WARNING, "Corrupted issue 
attributes: {0} {1}", new String[]{issueKey, issueName}); //NOI18N
-                            break;
-                        }
-                        JiraRepository jiraRepository = 
jiraRepositories.get(repository.getId());
-                        add(issueName, issueKey, jiraRepository);
-                    }
-                    repository.addPropertyChangeListener(this);
-                    // remove processed attributes
-                    repositoryIssues.remove(repository.getUrl());
-                }
-            }
-    }
-
-    private void addKenaiIssues (Map<String, List<String>> repositoryIssues) 
{
-        // now what remains are kenai issues and non-existant repositories
-        for (Map.Entry<String, List<String>> e : 
repositoryIssues.entrySet()) {
-            String projectName = e.getKey();
-            if (projectName.startsWith(KENAI_REPOSITORY_IDENT_PREFIX)) { // 
is kenai
-                projectName = 
projectName.substring(KENAI_REPOSITORY_IDENT_PREFIX.length());
-                List<String> issueAttributes = e.getValue();
-                if (issueAttributes != null && issueAttributes.size() > 1) {
-                    ListIterator<String> it = issueAttributes.listIterator();
-                    if (!STORAGE_KENAI_VERSION.equals(it.next())) {
-                        LOG.log(Level.WARNING, "Old unsupported storage 
version for kenai issues, expecting {0}", STORAGE_KENAI_VERSION); //NOI18N
-                        break;
-                    }
-                    for (; it.hasNext(); ) {
-                        String issueKey = getNextAttribute(it);
-                        String issueName = getNextAttribute(it);
-                        String url = getNextAttribute(it);
-                        if (issueKey == null || issueName == null || url == 
null) {
-                            LOG.log(Level.WARNING, "Corrupted kenai issue 
attributes: {0} {1} {2}", new String[]{issueKey, issueName, url}); //NOI18N
-                            break;
-                        }
-                        URL issueUrl;
-                        try {
-                            issueUrl = new URL(url);
-                        } catch (MalformedURLException ex) {
-                            LOG.log(Level.INFO, null, ex);
-                            continue;
-                        }
-                        add(issueName, issueUrl, issueKey, projectName);
-                        KenaiAccessor ka = KenaiUtil.getKenaiAccessor(url);
-                        if(ka != null) {
-                            String host = issueUrl.getHost();
-                            Map<String, PropertyChangeListener> kl = 
getKenaiListeners();
-                            PropertyChangeListener l = kl.get(host);
-                            if (l == null) {
-                                // kenai host not registered yet
-                                l = new KenaiListener(host);
-                                ka.addPropertyChangeListener(l, host);
-                                kl.put(host, l);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    private class KenaiListener implements PropertyChangeListener {
-        private final String kenaiHost;
-
-        public KenaiListener(String kenaiHost) {
-            this.kenaiHost = kenaiHost;
-        }
-
-        @Override
-        public void propertyChange(PropertyChangeEvent evt) {
-            if (KenaiAccessor.PROP_LOGIN.equals(evt.getPropertyName())) {
-                // kenai issues need instantiated repository so they can be 
shown in tasklist
-                // but some (e.g. private kenai projects) cannot be 
instantiated without being logged in. So kenai issues need to be notified
-                // when user loggs in so the repository can be created.
-                rp.post(new Runnable() { // do not block here
-                    @Override
-                    public void run() {
-                        notifyKenaiLogin(kenaiHost);
-                    }
-                });
-            }
-        }
-    }
-

[hg] main-silver: removed tasklistproviders, replaced add to act...

Tomas Stupka 05/03/2013

Project Features

About this Project

ConnectedDeveloper was started in November 2009, is owned by tpavek, and has 92 members.
By use of this website, you agree to the NetBeans Policies and Terms of Use (revision 20150626.29986a4). © 2014, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo
 
 
Close
loading
Please Confirm
Close