Bug 386349 - Support adding TransferDropTargetListener to Web Page
Editor's Outline view
diff --git a/jsf/plugins/org.eclipse.jst.pagedesigner/schema/pageDesignerExtension.exsd b/jsf/plugins/org.eclipse.jst.pagedesigner/schema/pageDesignerExtension.exsd
index 4cc47e2..588fbf6 100644
--- a/jsf/plugins/org.eclipse.jst.pagedesigner/schema/pageDesignerExtension.exsd
+++ b/jsf/plugins/org.eclipse.jst.pagedesigner/schema/pageDesignerExtension.exsd
@@ -30,6 +30,7 @@
             <element ref="paletteFactory" minOccurs="0" maxOccurs="unbounded"/>
             <element ref="attributeValueResolver" minOccurs="0" maxOccurs="unbounded"/>
             <element ref="elValueResolver" minOccurs="0" maxOccurs="unbounded"/>
+            <element ref="outlineTargetListener" minOccurs="0" maxOccurs="unbounded"/>
          </sequence>
          <attribute name="point" type="string" use="required">
             <annotation>
@@ -281,6 +282,21 @@
       </complexType>
    </element>
 
+   <element name="outlineTargetListener">
+      <complexType>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+                  Provide a TransferDropTargetListener implementation for each Transfer type to be supported in the Outline view.  The TransferDropTargetListener implementation must provide a no-arg constructor.
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java" basedOn=":org.eclipse.jface.util.TransferDropTargetListener"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
    <annotation>
       <appInfo>
          <meta.section type="since"/>
diff --git a/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/IJMTConstants.java b/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/IJMTConstants.java
index 7dbd5b8..9575b7b 100644
--- a/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/IJMTConstants.java
+++ b/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/IJMTConstants.java
@@ -96,6 +96,11 @@
 	public static final String ELEMENT_EDIT_FACTORY = "elementEditFactory"; //$NON-NLS-1$
 
 	/**
+	 * local name of outline target listener extension
+	 */
+	public static final String OUTLINE_TARGET_LISTENER = "outlineTargetListener"; //$NON-NLS-1$
+	
+	/**
 	 * local name of link creator extension
 	 */
 	public static final String LINK_CREATOR = "linkCreator"; //$NON-NLS-1$
diff --git a/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/OutlineConfiguration.java b/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/OutlineConfiguration.java
index d35de2d..07cf30c 100644
--- a/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/OutlineConfiguration.java
+++ b/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/OutlineConfiguration.java
@@ -15,6 +15,7 @@
 import java.util.List;
 
 import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.util.TransferDropTargetListener;
 import org.eclipse.jface.viewers.ISelection;
 import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.jface.viewers.StructuredSelection;
@@ -78,4 +79,39 @@
 		}
 		return selectedStructures;
 	}
+
+    @Override
+    public TransferDropTargetListener[] getTransferDropTargetListeners(
+            TreeViewer treeViewer)
+    {
+        TransferDropTargetListener[] originalListeners =  
+                super.getTransferDropTargetListeners(treeViewer);
+        
+        List<TransferDropTargetListener> configuredListeners = 
+                getConfiguredTransferDropTargetListeners();
+        
+        TransferDropTargetListener[] consolidated = 
+                new TransferDropTargetListener[originalListeners.length + configuredListeners.size()];
+        
+        int i = 0;
+        // Put the configured listeners ahead of the original,
+        // which just allows reordering of the nodes/tags;
+        // otherwise, the LocalSelectionTransfer (for reordering)
+        // takes precedence over a ResourceTransfer.
+        for (TransferDropTargetListener configured : configuredListeners)
+        {
+            consolidated[i++] = configured;
+        }
+        for (TransferDropTargetListener original : originalListeners)
+        {
+            consolidated[i++] = original;
+        }
+        
+        return consolidated;
+    }
+	
+    private List<TransferDropTargetListener> getConfiguredTransferDropTargetListeners()
+    {
+        return OutlineTargetListenerReader.getListeners();
+    }
 }
diff --git a/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/OutlineTargetListenerReader.java b/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/OutlineTargetListenerReader.java
new file mode 100644
index 0000000..a5b8e1c
--- /dev/null
+++ b/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/OutlineTargetListenerReader.java
@@ -0,0 +1,78 @@
+package org.eclipse.jst.pagedesigner.editors;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.util.TransferDropTargetListener;
+import org.eclipse.jst.pagedesigner.IJMTConstants;
+import org.eclipse.jst.pagedesigner.PDPlugin;
+
+class OutlineTargetListenerReader
+{
+    private final static String CLASS = "class"; //$NON-NLS-1$
+    
+    private static List<TransferDropTargetListener> _listeners;
+    
+    public static synchronized List<TransferDropTargetListener> getListeners()
+    {
+        if (_listeners == null)
+        {
+            _listeners = readListeners();
+        }
+        return Collections.unmodifiableList(_listeners);
+    }
+
+    private static List<TransferDropTargetListener> readListeners()
+    {
+        List<TransferDropTargetListener> listeners = new ArrayList<TransferDropTargetListener>();
+        
+        IExtensionPoint extensionPoint = 
+            Platform.getExtensionRegistry()
+                .getExtensionPoint(PDPlugin.getPluginId(),
+                                   IJMTConstants.EXTENSION_POINT_PAGEDESIGNER);
+        IExtension[] extensions = extensionPoint.getExtensions();
+
+        for (int i=0; i<extensions.length; i++)
+        {
+            IExtension ext = extensions[i];
+            IConfigurationElement[] pageDesignerElements = ext.getConfigurationElements();
+            
+            for (int j=0; j<pageDesignerElements.length; j++)
+            {
+                final IConfigurationElement pageDesignerElement = pageDesignerElements[j];
+                if (pageDesignerElement.getName().equals(IJMTConstants.OUTLINE_TARGET_LISTENER))
+                {
+                    pageDesignerElement.getAttribute(CLASS);
+                    Object object;
+                    try
+                    {
+                        object = pageDesignerElement.createExecutableExtension(CLASS);
+                        if (object instanceof TransferDropTargetListener)
+                            
+                        {
+                            listeners.add((TransferDropTargetListener)object);
+                        }
+                    }
+                    catch (CoreException e)
+                    {
+                        PDPlugin.log("Problem loading transfer drop target listener for " +  //$NON-NLS-1$
+                                pageDesignerElement, e);
+                    }
+                }
+            }
+        }
+        return listeners;
+    }
+    
+    private OutlineTargetListenerReader()
+    {
+        throw new IllegalStateException("Should not be instantiated!"); //$NON-NLS-1$
+    }
+
+}