[282114] enable snippet view to work with objects not only strings
diff --git a/org.eclipse.wst.common.snippets.tests/META-INF/MANIFEST.MF b/org.eclipse.wst.common.snippets.tests/META-INF/MANIFEST.MF
index efc1bd8..e51a408 100644
--- a/org.eclipse.wst.common.snippets.tests/META-INF/MANIFEST.MF
+++ b/org.eclipse.wst.common.snippets.tests/META-INF/MANIFEST.MF
@@ -17,6 +17,8 @@
  org.eclipse.ui,
  org.eclipse.wst.common.snippets,
  org.eclipse.ui.ide,
- org.eclipse.ui.workbench.texteditor
+ org.eclipse.ui.workbench.texteditor,
+ org.eclipse.gef
 Eclipse-LazyStart: true
+Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: J2SE-1.4
diff --git a/org.eclipse.wst.common.snippets.tests/build.properties b/org.eclipse.wst.common.snippets.tests/build.properties
index 9457d9f..6fcacc2 100644
--- a/org.eclipse.wst.common.snippets.tests/build.properties
+++ b/org.eclipse.wst.common.snippets.tests/build.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2005, 2006 IBM Corporation and others.
+# Copyright (c) 2005, 2009 IBM Corporation and others.
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
@@ -19,8 +19,7 @@
                about.html,\
                META-INF/,\
                META-INF/
-src.includes = src/,\
-               build.properties
 jars.compile.order = snippetstests.jar
 source.snippetstests.jar = src/
 output.snippetstests.jar = bin/
+
diff --git a/org.eclipse.wst.common.snippets.tests/plugin.xml b/org.eclipse.wst.common.snippets.tests/plugin.xml
index 3926b2b..7921eae 100644
--- a/org.eclipse.wst.common.snippets.tests/plugin.xml
+++ b/org.eclipse.wst.common.snippets.tests/plugin.xml
@@ -29,5 +29,33 @@
 			</item>
 		</category>
 	</extension>
+ <extension
+       point="org.eclipse.wst.common.snippets.SnippetProvider">
+    <provider
+          class="org.eclipse.wst.common.snippets.tests.helpers.TextSnippetProvider2"
+          priority="101">
+       <enablement>
+          <instanceof
+                value="org.eclipse.ui.texteditor.ITextEditor">
+          </instanceof></enablement>
+    </provider>
+    <provider
+          class="org.eclipse.wst.common.snippets.tests.helpers.DummyProvider"
+          priority="2">
+       <enablement>
+          <instanceof
+                value="org.eclipse.wst.common.snippets.tests.helpers.CommonApplicableInterface">
+          </instanceof>
+       </enablement>
+    </provider>
+    <provider
+          class="org.eclipse.wst.common.snippets.tests.helpers.ComplexProvider"
+          priority="20">
+       <enablement>
+          <instanceof
+                value="org.eclipse.wst.common.snippets.tests.helpers.SApplicableEditor">
+          </instanceof></enablement>
+    </provider>
+ </extension>
 
 </plugin>
diff --git a/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/AllTests.java b/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/AllTests.java
index 6783855..6936b71 100644
--- a/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/AllTests.java
+++ b/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/AllTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005 IBM Corporation and others.
+ * Copyright (c) 2005, 2009 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -15,6 +15,9 @@
 import junit.framework.TestSuite;
 
 import org.eclipse.wst.common.snippets.core.tests.SnippetCoreTests;
+import org.eclipse.wst.common.snippets.tests.providers.SnippetProviderExtensionTests;
+import org.eclipse.wst.common.snippets.tests.providers.TextProviderTests;
+import org.eclipse.wst.common.snippets.tests.scenarios.ObjectOrientedSnippetScenario;
 import org.eclipse.wst.common.snippets.ui.tests.SnippetUITests;
 
 
@@ -27,6 +30,9 @@
 	public AllTests() {
 		super();
 		addTest(new TestSuite(SnippetCoreTests.class));
+		addTest(new TestSuite(SnippetProviderExtensionTests.class));
+		addTest(new TestSuite(TextProviderTests.class));
 		addTest(new TestSuite(SnippetUITests.class));
+		addTest(new TestSuite(ObjectOrientedSnippetScenario.class));
 	}
 }
diff --git a/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/TestsPlugin.java b/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/TestsPlugin.java
index 102b528..8766170 100644
--- a/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/TestsPlugin.java
+++ b/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/TestsPlugin.java
@@ -9,6 +9,7 @@
  */
 public class TestsPlugin extends AbstractUIPlugin {
 
+	public static final String PLUGIN_ID = "org.eclipse.wst.common.snippets.tests";
 	//The shared instance.
 	private static TestsPlugin plugin;
 	
diff --git a/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/helpers/CommonApplicableInterface.java b/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/helpers/CommonApplicableInterface.java
new file mode 100644
index 0000000..0eb5850
--- /dev/null
+++ b/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/helpers/CommonApplicableInterface.java
@@ -0,0 +1,106 @@
+package org.eclipse.wst.common.snippets.tests.helpers;

+

+import org.eclipse.core.runtime.IProgressMonitor;

+import org.eclipse.swt.graphics.Image;

+import org.eclipse.swt.widgets.Composite;

+import org.eclipse.ui.IEditorInput;

+import org.eclipse.ui.IEditorPart;

+import org.eclipse.ui.IEditorSite;

+import org.eclipse.ui.IPropertyListener;

+import org.eclipse.ui.IWorkbenchPartSite;

+import org.eclipse.ui.PartInitException;

+

+public class CommonApplicableInterface implements IEditorPart{

+

+	public IEditorInput getEditorInput() {

+		// TODO Auto-generated method stub

+		return null;

+	}

+

+	public IEditorSite getEditorSite() {

+		// TODO Auto-generated method stub

+		return null;

+	}

+

+	public void init(IEditorSite site, IEditorInput input)

+			throws PartInitException {

+		// TODO Auto-generated method stub

+		

+	}

+

+	public void addPropertyListener(IPropertyListener listener) {

+		// TODO Auto-generated method stub

+		

+	}

+

+	public void createPartControl(Composite parent) {

+		// TODO Auto-generated method stub

+		

+	}

+

+	public void dispose() {

+		// TODO Auto-generated method stub

+		

+	}

+

+	public IWorkbenchPartSite getSite() {

+		// TODO Auto-generated method stub

+		return null;

+	}

+

+	public String getTitle() {

+		// TODO Auto-generated method stub

+		return null;

+	}

+

+	public Image getTitleImage() {

+		// TODO Auto-generated method stub

+		return null;

+	}

+

+	public String getTitleToolTip() {

+		// TODO Auto-generated method stub

+		return null;

+	}

+

+	public void removePropertyListener(IPropertyListener listener) {

+		// TODO Auto-generated method stub

+		

+	}

+

+	public void setFocus() {

+		// TODO Auto-generated method stub

+		

+	}

+

+	public Object getAdapter(Class adapter) {

+		// TODO Auto-generated method stub

+		return null;

+	}

+

+	public void doSave(IProgressMonitor monitor) {

+		// TODO Auto-generated method stub

+		

+	}

+

+	public void doSaveAs() {

+		// TODO Auto-generated method stub

+		

+	}

+

+	public boolean isDirty() {

+		// TODO Auto-generated method stub

+		return false;

+	}

+

+	public boolean isSaveAsAllowed() {

+		// TODO Auto-generated method stub

+		return false;

+	}

+

+	public boolean isSaveOnCloseNeeded() {

+		// TODO Auto-generated method stub

+		return false;

+	}

+

+}

diff --git a/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/helpers/ComplexInsertion.java b/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/helpers/ComplexInsertion.java
new file mode 100644
index 0000000..986a5d8
--- /dev/null
+++ b/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/helpers/ComplexInsertion.java
@@ -0,0 +1,36 @@
+package org.eclipse.wst.common.snippets.tests.helpers;

+

+import org.eclipse.swt.dnd.DragSourceEvent;

+import org.eclipse.swt.dnd.Transfer;

+import org.eclipse.ui.IEditorPart;

+import org.eclipse.wst.common.snippets.core.ISnippetItem;

+import org.eclipse.wst.common.snippets.ui.ISnippetInsertion;

+

+public class ComplexInsertion implements ISnippetInsertion {

+

+	public void dragSetData(DragSourceEvent event, ISnippetItem item) {

+		// TODO Auto-generated method stub

+

+	}

+

+	public Transfer[] getTransfers() {

+		// TODO Auto-generated method stub

+		return new Transfer[0];

+	}

+

+	public void insert(IEditorPart editorPart) {

+		// TODO Auto-generated method stub

+

+	}

+

+	public void setEditorPart(IEditorPart targetPart) {

+		// TODO Auto-generated method stub

+

+	}

+

+	public void setItem(ISnippetItem item) {

+		// TODO Auto-generated method stub

+

+	}

+

+}

diff --git a/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/helpers/ComplexProvider.java b/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/helpers/ComplexProvider.java
new file mode 100644
index 0000000..46d950d
--- /dev/null
+++ b/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/helpers/ComplexProvider.java
@@ -0,0 +1,72 @@
+package org.eclipse.wst.common.snippets.tests.helpers;

+

+import java.io.BufferedWriter;

+import java.io.File;

+import java.io.FileNotFoundException;

+import java.io.FileWriter;

+import java.io.IOException;

+

+import org.eclipse.core.runtime.IPath;

+import org.eclipse.core.runtime.IStatus;

+import org.eclipse.core.runtime.Status;

+import org.eclipse.jface.viewers.ISelection;

+import org.eclipse.wst.common.snippets.internal.AbstractSnippetProvider;

+import org.eclipse.wst.common.snippets.internal.editors.ISnippetEditor;

+import org.eclipse.wst.common.snippets.tests.TestsPlugin;

+import org.eclipse.wst.common.snippets.ui.ISnippetInsertion;

+

+public class ComplexProvider extends AbstractSnippetProvider {

+

+	public static final String TEST_TXT = "test.txt";

+	public static final String TESTING = "testing 1, 2, 3, 4, 5, 6";

+

+	public String getId() {

+		return "Complex_Example";

+	}

+

+	public ISnippetInsertion getSnippetInsertion() {

+		return new ComplexInsertion();

+	}

+

+	public boolean isActionEnabled(ISelection selection) {

+		return true;

+	}

+

+	public IStatus saveAdditionalContent(IPath path) {

+		if (path == null){

+			throw new IllegalArgumentException("path is null");

+		}

+		File f = new File(path.toOSString());

+		if (!f.exists()){

+		  f.mkdir();

+		}

+		File testSave = new File(f, TEST_TXT);

+		try {

+			saveTextFile(testSave);

+		} catch (IOException e) {

+			return new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID, "could not save file");

+		}

+		return Status.OK_STATUS;

+	}

+

+	private void saveTextFile(File testSave) throws IOException {

+		BufferedWriter bw = null;

+		try {

+			bw = new BufferedWriter(new FileWriter(testSave));

+			bw.write(TESTING);

+			

+		} catch (FileNotFoundException e) {

+			e.printStackTrace();

+		} finally {

+			if (bw != null){

+				bw.close();

+			}

+		}

+	}

+

+	public ISnippetEditor getSnippetEditor() {

+		// TODO Auto-generated method stub

+		return null;

+	}

+

+}

diff --git a/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/helpers/DummyProvider.java b/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/helpers/DummyProvider.java
new file mode 100644
index 0000000..f3ed8ec
--- /dev/null
+++ b/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/helpers/DummyProvider.java
@@ -0,0 +1,34 @@
+package org.eclipse.wst.common.snippets.tests.helpers;

+

+import org.eclipse.core.runtime.IPath;

+import org.eclipse.core.runtime.IStatus;

+import org.eclipse.jface.viewers.ISelection;

+import org.eclipse.wst.common.snippets.internal.AbstractSnippetProvider;

+import org.eclipse.wst.common.snippets.internal.editors.ISnippetEditor;

+import org.eclipse.wst.common.snippets.ui.ISnippetInsertion;

+

+public class DummyProvider extends AbstractSnippetProvider {

+

+	public String getId() {

+		return "dummy";

+	}

+

+	public ISnippetInsertion getSnippetInsertion() {

+		return null;

+	}

+

+	public boolean isActionEnabled(ISelection selection) {

+		return false;

+	}

+

+	public IStatus saveAdditionalContent(IPath path) {

+		return null;

+	}

+

+	public ISnippetEditor getSnippetEditor() {

+		// TODO Auto-generated method stub

+		return null;

+	}

+

+

+}

diff --git a/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/helpers/SApplicableEditor.java b/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/helpers/SApplicableEditor.java
new file mode 100644
index 0000000..ec06e76
--- /dev/null
+++ b/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/helpers/SApplicableEditor.java
@@ -0,0 +1,103 @@
+package org.eclipse.wst.common.snippets.tests.helpers;

+

+import org.eclipse.core.runtime.IProgressMonitor;

+import org.eclipse.swt.graphics.Image;

+import org.eclipse.swt.widgets.Composite;

+import org.eclipse.ui.IEditorInput;

+import org.eclipse.ui.IEditorPart;

+import org.eclipse.ui.IEditorSite;

+import org.eclipse.ui.IPropertyListener;

+import org.eclipse.ui.IWorkbenchPartSite;

+import org.eclipse.ui.PartInitException;

+

+public class SApplicableEditor implements IEditorPart {

+

+	public IEditorInput getEditorInput() {

+		return null;

+	}

+

+	public IEditorSite getEditorSite() {

+		return null;

+	}

+

+	public void init(IEditorSite site, IEditorInput input)

+			throws PartInitException {

+

+	}

+

+	public void addPropertyListener(IPropertyListener listener) {

+		// TODO Auto-generated method stub

+

+	}

+

+	public void createPartControl(Composite parent) {

+		// TODO Auto-generated method stub

+

+	}

+

+	public void dispose() {

+		// TODO Auto-generated method stub

+

+	}

+

+	public IWorkbenchPartSite getSite() {

+		// TODO Auto-generated method stub

+		return null;

+	}

+

+	public String getTitle() {

+		// TODO Auto-generated method stub

+		return null;

+	}

+

+	public Image getTitleImage() {

+		// TODO Auto-generated method stub

+		return null;

+	}

+

+	public String getTitleToolTip() {

+		// TODO Auto-generated method stub

+		return null;

+	}

+

+	public void removePropertyListener(IPropertyListener listener) {

+		// TODO Auto-generated method stub

+

+	}

+

+	public void setFocus() {

+		// TODO Auto-generated method stub

+

+	}

+

+	public Object getAdapter(Class adapter) {

+		// TODO Auto-generated method stub

+		return null;

+	}

+

+	public void doSave(IProgressMonitor monitor) {

+		// TODO Auto-generated method stub

+

+	}

+

+	public void doSaveAs() {

+		// TODO Auto-generated method stub

+

+	}

+

+	public boolean isDirty() {

+		// TODO Auto-generated method stub

+		return false;

+	}

+

+	public boolean isSaveAsAllowed() {

+		// TODO Auto-generated method stub

+		return false;

+	}

+

+	public boolean isSaveOnCloseNeeded() {

+		// TODO Auto-generated method stub

+		return false;

+	}

+

+}

diff --git a/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/helpers/TextSnippetProvider2.java b/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/helpers/TextSnippetProvider2.java
new file mode 100644
index 0000000..92b4ecf
--- /dev/null
+++ b/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/helpers/TextSnippetProvider2.java
@@ -0,0 +1,8 @@
+package org.eclipse.wst.common.snippets.tests.helpers;

+

+import org.eclipse.wst.common.snippets.ui.TextSnippetProvider;

+

+public class TextSnippetProvider2 extends TextSnippetProvider {

+

+

+}

diff --git a/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/providers/SnippetProviderExtensionTests.java b/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/providers/SnippetProviderExtensionTests.java
new file mode 100644
index 0000000..533a4c1
--- /dev/null
+++ b/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/providers/SnippetProviderExtensionTests.java
@@ -0,0 +1,39 @@
+package org.eclipse.wst.common.snippets.tests.providers;

+

+import junit.framework.TestCase;

+

+import org.eclipse.ui.texteditor.AbstractTextEditor;

+import org.eclipse.wst.common.snippets.core.ISnippetProvider;

+import org.eclipse.wst.common.snippets.internal.util.SnippetProviderManager;

+import org.eclipse.wst.common.snippets.tests.helpers.CommonApplicableInterface;

+import org.eclipse.wst.common.snippets.tests.helpers.TextSnippetProvider2;

+import org.eclipse.wst.common.snippets.ui.TextSnippetProvider;

+

+public class SnippetProviderExtensionTests extends TestCase {

+

+	public void testEnablement() throws Exception {

+		ISnippetProvider applicableProvider = SnippetProviderManager.getApplicableProvider(new AbstractTextEditor(){});

+		assertNotNull(applicableProvider);

+		applicableProvider = SnippetProviderManager.getApplicableProvider(new CommonApplicableInterface(){});

+		assertNotNull(applicableProvider);

+		assertEquals("dummy", applicableProvider.getId());

+		

+	}

+	

+	public void testDefaultTextSnippetProviderRegistration() throws Exception {

+		ISnippetProvider applicableProvider = SnippetProviderManager.getApplicableProvider(new AbstractTextEditor(){});

+		assertNotNull(applicableProvider);

+		assertEquals(applicableProvider.getClass(), TextSnippetProvider.class);

+	}

+	

+	

+	public void testPriority() throws Exception {

+		ISnippetProvider applicableProvider = SnippetProviderManager.getApplicableProvider(new AbstractTextEditor(){});

+		assertNotNull(applicableProvider);

+		assertEquals(applicableProvider.getClass(), TextSnippetProvider.class);

+		assertNotNull(SnippetProviderManager.findProvider(TextSnippetProvider2.class.getName()));

+	}

+	

+	

+	

+}

diff --git a/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/providers/TextProviderTests.java b/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/providers/TextProviderTests.java
new file mode 100644
index 0000000..fdfcba9
--- /dev/null
+++ b/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/providers/TextProviderTests.java
@@ -0,0 +1,76 @@
+package org.eclipse.wst.common.snippets.tests.providers;

+

+import java.io.ByteArrayInputStream;

+

+import junit.framework.TestCase;

+

+import org.eclipse.core.resources.IFile;

+import org.eclipse.core.resources.IProject;

+import org.eclipse.core.resources.ResourcesPlugin;

+import org.eclipse.core.runtime.NullProgressMonitor;

+import org.eclipse.gef.palette.PaletteDrawer;

+import org.eclipse.swt.widgets.Display;

+import org.eclipse.swt.widgets.Shell;

+import org.eclipse.ui.IEditorPart;

+import org.eclipse.ui.PlatformUI;

+import org.eclipse.ui.ide.IDE;

+import org.eclipse.ui.texteditor.ITextEditor;

+import org.eclipse.wst.common.snippets.internal.SnippetsPlugin;

+import org.eclipse.wst.common.snippets.internal.palette.SnippetPaletteDrawerFactory;

+import org.eclipse.wst.common.snippets.internal.palette.SnippetPaletteItem;

+import org.eclipse.wst.common.snippets.internal.palette.SnippetPaletteRoot;

+import org.eclipse.wst.common.snippets.internal.ui.SnippetsView;

+import org.eclipse.wst.common.snippets.ui.TextSnippetProvider;

+

+public class TextProviderTests extends TestCase {

+	

+	private IFile file;

+

+	protected void setUp() throws Exception {

+		super.setUp();

+		String projectName = System.currentTimeMillis() + "";

+		IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);

+		if (!project.exists()){

+			project.create(new NullProgressMonitor());

+		}

+		if (!project.isOpen()){

+			project.open(new NullProgressMonitor());

+		}

+		file = project.getFile("testTextSnippet.txt");

+		if (!file.exists()){

+			ByteArrayInputStream sr = new ByteArrayInputStream("test Text Snippet Provider".getBytes());

+			file.create(sr, true, new NullProgressMonitor());

+		}

+	}

+

+	public void testTextSnippetCreation() throws Exception {

+		SnippetsView view;

+		SnippetPaletteRoot anchor = null;

+		view = (SnippetsView) SnippetsPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage().findView(SnippetsPlugin.NAMES.VIEW_ID);

+		if (view == null) {

+			view = (SnippetsView) SnippetsPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage().showView(SnippetsPlugin.NAMES.VIEW_ID);

+		}

+		if (view != null) {

+			anchor = view.getRoot();

+		}

+		Shell activeShell = Display.getDefault().getActiveShell();

+		assertNotNull(activeShell);

+		PaletteDrawer drawer = (PaletteDrawer) new SnippetPaletteDrawerFactory().createNewEntry(activeShell, anchor);

+		drawer.setLabel("testName");

+		TextSnippetProvider textSnippetProvider = new TextSnippetProvider();

+		IEditorPart openEditor = IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file);

+		assertNotNull(openEditor);

+		textSnippetProvider.setEditor(openEditor);

+		

+		

+		SnippetPaletteItem createSnippet = textSnippetProvider.createSnippet(drawer);

+		assertNotNull(createSnippet);

+		ITextEditor editor = (ITextEditor) openEditor;

+		editor.selectAndReveal(0, 5);

+		

+		assertFalse(textSnippetProvider.isActionEnabled(null));

+		assertTrue(textSnippetProvider.isActionEnabled(editor.getSelectionProvider().getSelection()));

+		editor.selectAndReveal(0, 0);

+		assertFalse(textSnippetProvider.isActionEnabled(editor.getSelectionProvider().getSelection()));

+	}

+}

diff --git a/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/scenarios/ObjectOrientedSnippetScenario.java b/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/scenarios/ObjectOrientedSnippetScenario.java
new file mode 100644
index 0000000..4483515
--- /dev/null
+++ b/org.eclipse.wst.common.snippets.tests/src/org/eclipse/wst/common/snippets/tests/scenarios/ObjectOrientedSnippetScenario.java
@@ -0,0 +1,130 @@
+package org.eclipse.wst.common.snippets.tests.scenarios;

+

+import java.io.BufferedReader;

+import java.io.ByteArrayInputStream;

+import java.io.File;

+import java.io.FileReader;

+import java.io.IOException;

+

+import junit.framework.TestCase;

+

+import org.eclipse.core.resources.IFile;

+import org.eclipse.core.resources.IProject;

+import org.eclipse.core.resources.ResourcesPlugin;

+import org.eclipse.core.runtime.NullProgressMonitor;

+import org.eclipse.gef.palette.PaletteDrawer;

+import org.eclipse.swt.widgets.Display;

+import org.eclipse.swt.widgets.Shell;

+import org.eclipse.ui.IEditorPart;

+import org.eclipse.ui.PlatformUI;

+import org.eclipse.ui.ide.IDE;

+import org.eclipse.wst.common.snippets.core.ISnippetsEntry;

+import org.eclipse.wst.common.snippets.internal.SnippetsPlugin;

+import org.eclipse.wst.common.snippets.internal.palette.SnippetPaletteDrawerFactory;

+import org.eclipse.wst.common.snippets.internal.palette.SnippetPaletteItem;

+import org.eclipse.wst.common.snippets.internal.palette.SnippetPaletteRoot;

+import org.eclipse.wst.common.snippets.internal.ui.SnippetsView;

+import org.eclipse.wst.common.snippets.tests.helpers.ComplexProvider;

+

+public class ObjectOrientedSnippetScenario extends TestCase {

+

+

+	private IFile file;

+

+	protected void setUp() throws Exception {

+		super.setUp();

+		String projectName = System.currentTimeMillis() + "";

+		IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);

+		if (!project.exists()){

+			project.create(new NullProgressMonitor());

+		}

+		if (!project.isOpen()){

+			project.open(new NullProgressMonitor());

+		}

+		file = project.getFile("testTextSnippet.txt");

+		if (!file.exists()){

+			ByteArrayInputStream sr = new ByteArrayInputStream("test Text Snippet Provider".getBytes());

+			file.create(sr, true, new NullProgressMonitor());

+		}

+	}

+	

+	public void testSave() throws Exception {

+		SnippetsView view;

+		SnippetPaletteRoot anchor = null;

+		view = (SnippetsView) SnippetsPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage().findView(SnippetsPlugin.NAMES.VIEW_ID);

+		if (view == null) {

+			view = (SnippetsView) SnippetsPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage().showView(SnippetsPlugin.NAMES.VIEW_ID);

+		}

+		if (view != null) {

+			anchor = view.getRoot();

+		}

+		Shell activeShell = Display.getDefault().getActiveShell();

+		assertNotNull(activeShell);

+		PaletteDrawer drawer = (PaletteDrawer) new SnippetPaletteDrawerFactory().createNewEntry(activeShell, anchor);

+		drawer.setLabel("testName");

+		

+		ComplexProvider provider = new ComplexProvider();

+		IEditorPart openEditor = IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file);

+		provider.setEditor(openEditor);

+		SnippetPaletteItem createSnippet = provider.createSnippet(drawer);

+		assertNotNull(createSnippet);

+		File f = new File (createSnippet.getStorageLocation().toOSString());

+		assertTrue(f.exists());

+		assertEquals(1, f.list().length);

+		assertEquals(ComplexProvider.TEST_TXT, f.listFiles()[0].getName());

+		assertEquals(ComplexProvider.TESTING.trim(), getContents(f.listFiles()[0]).trim());

+}	

+

+	public void testProviderBasedSourceType() throws Exception {

+		SnippetsView view;

+		SnippetPaletteRoot anchor = null;

+		view = (SnippetsView) SnippetsPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage().findView(SnippetsPlugin.NAMES.VIEW_ID);

+		if (view == null) {

+			view = (SnippetsView) SnippetsPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage().showView(SnippetsPlugin.NAMES.VIEW_ID);

+		}

+		if (view != null) {

+			anchor = view.getRoot();

+		}

+		Shell activeShell = Display.getDefault().getActiveShell();

+		assertNotNull(activeShell);

+		PaletteDrawer drawer = (PaletteDrawer) new SnippetPaletteDrawerFactory().createNewEntry(activeShell, anchor);

+		drawer.setLabel(getName());

+		

+		ComplexProvider provider = new ComplexProvider();

+		IEditorPart openEditor = IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file);

+		provider.setEditor(openEditor);

+		SnippetPaletteItem createSnippet = provider.createSnippet(drawer);

+		assertNotNull(createSnippet);

+		File f = new File (createSnippet.getStorageLocation().toOSString());

+		assertTrue(f.exists());

+		assertEquals(1, f.list().length);

+		assertEquals(ComplexProvider.TEST_TXT, f.listFiles()[0].getName());

+		assertEquals(ComplexProvider.TESTING.trim(), getContents(f.listFiles()[0]).trim());

+		

+		assertEquals(ISnippetsEntry.SNIPPET_SOURCE_USER, createSnippet.getSourceType());

+}	

+

+	

+	public String getContents(File aFile) {

+		StringBuffer contents = new StringBuffer();

+

+		try {

+			BufferedReader input =  new BufferedReader(new FileReader(aFile));

+			try {

+				String line = null; //not declared within while loop

+				while (( line = input.readLine()) != null){

+					contents.append(line);

+					contents.append(System.getProperty("line.separator"));

+				}

+			}

+			finally {

+				input.close();

+			}

+		}

+		catch (IOException ex){

+			ex.printStackTrace();

+		}

+

+		return contents.toString();

+	}

+}

diff --git a/org.eclipse.wst.common.snippets/META-INF/MANIFEST.MF b/org.eclipse.wst.common.snippets/META-INF/MANIFEST.MF
index e4fef62..15b3392 100644
--- a/org.eclipse.wst.common.snippets/META-INF/MANIFEST.MF
+++ b/org.eclipse.wst.common.snippets/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %Snippets_View.name
 Bundle-SymbolicName: org.eclipse.wst.common.snippets; singleton:=true
-Bundle-Version: 1.1.300.qualifier
+Bundle-Version: 1.2.0.qualifier
 Bundle-Activator: org.eclipse.wst.common.snippets.internal.SnippetsPlugin
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
@@ -25,6 +25,7 @@
  org.eclipse.ui;bundle-version="[3.4.0,4.0.0)",
  org.eclipse.jface.text;bundle-version="[3.4.0,4.0.0)",
  org.eclipse.core.resources;bundle-version="[3.4.0,4.0.0)",
- org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)"
+ org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.core.expressions;bundle-version="[3.4.0,4.0.0)"
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: J2SE-1.4
diff --git a/org.eclipse.wst.common.snippets/build.properties b/org.eclipse.wst.common.snippets/build.properties
index c11b581..abebd47 100644
--- a/org.eclipse.wst.common.snippets/build.properties
+++ b/org.eclipse.wst.common.snippets/build.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2004, 2006 IBM Corporation and others.
+# Copyright (c) 2004, 2009 IBM Corporation and others.
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
@@ -21,6 +21,5 @@
 src.includes = schema/,\
                doc/,\
                javadoc.xml,\
-               component.xml,\
-               build.properties
+               component.xml
 source.. = src/
diff --git a/org.eclipse.wst.common.snippets/plugin.properties b/org.eclipse.wst.common.snippets/plugin.properties
index fd13b66..f945ac2 100644
--- a/org.eclipse.wst.common.snippets/plugin.properties
+++ b/org.eclipse.wst.common.snippets/plugin.properties
@@ -11,5 +11,7 @@
 providerName=Eclipse.org
 Snippets_View.name=Snippets View
 Snippets.name=Snippets
-Snippets_View_Contributions_Extension.name=Snippets View Contributions Extension
+Snippets_View_Contributions_Extension.name=Snippets View Contributions
 Add_to_Snippets.name=Add to Snippets...
+
+extension-point.name.0 = Snippets View Content Provider
\ No newline at end of file
diff --git a/org.eclipse.wst.common.snippets/plugin.xml b/org.eclipse.wst.common.snippets/plugin.xml
index 5da2de6..61ee182 100644
--- a/org.eclipse.wst.common.snippets/plugin.xml
+++ b/org.eclipse.wst.common.snippets/plugin.xml
@@ -6,6 +6,11 @@
 		id="SnippetContributions"
 		name="%Snippets_View_Contributions_Extension.name"
 		schema="schema/SnippetContributions.exsd" />
+		
+ <extension-point 
+ 	id="SnippetProvider" 
+ 	name="%extension-point.name.0" 
+ 	schema="schema/SnippetProvider.exsd"/>
 
 	<!-- the view itself -->
 	<extension point="org.eclipse.ui.views">
@@ -175,4 +180,17 @@
 			</action>
 		</viewerContribution>
 	</extension>
+	
+ <extension point="org.eclipse.wst.common.snippets.SnippetProvider">
+    <provider
+          class="org.eclipse.wst.common.snippets.ui.TextSnippetProvider"
+          priority="100">
+       <enablement>
+          <or>
+             <adapt type="org.eclipse.ui.texteditor.ITextEditor"/>
+             <instanceof value="org.eclipse.ui.texteditor.ITextEditor"/>
+          </or>
+       </enablement>
+    </provider>
+ </extension>
 </plugin>
diff --git a/org.eclipse.wst.common.snippets/schema/SnippetProvider.exsd b/org.eclipse.wst.common.snippets/schema/SnippetProvider.exsd
new file mode 100644
index 0000000..fe5b021
--- /dev/null
+++ b/org.eclipse.wst.common.snippets/schema/SnippetProvider.exsd
@@ -0,0 +1,141 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.common.snippets" xmlns="http://www.w3.org/2001/XMLSchema">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.common.snippets" id="SnippetProvider" name="SnippetProvider"/>

+      </appInfo>

+      <documentation>

+         Snippet Provider extension point gives the plugin developers the opertunity to contribute processor for snippets artifacts. The provider should provide logic for saving additional artifacts (if needed). And inserting the saved content in an editor. The extensionpoint requires implementation of ISnippetProvider interface, statement of enablement depending on the active editor (enablement is based on org.eclipse.expressions). Priority can be used to override some existing SnippetProvider.

+      </documentation>

+   </annotation>

+

+   <include schemaLocation="schema://org.eclipse.core.expressions/schema/expressionLanguage.exsd"/>

+

+   <element name="extension">

+      <annotation>

+         <appInfo>

+            <meta.element />

+         </appInfo>

+      </annotation>

+      <complexType>

+         <sequence>

+            <element ref="provider" minOccurs="1" maxOccurs="unbounded"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+               <appInfo>

+                  <meta.attribute translatable="true"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="provider">

+      <complexType>

+         <sequence>

+            <element ref="enablement"/>

+         </sequence>

+         <attribute name="class" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+               <appInfo>

+                  <meta.attribute kind="java" basedOn=":org.eclipse.wst.common.snippets.ui.ISnippetProvider"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+         <attribute name="priority" type="string">

+            <annotation>

+               <documentation>

+                  0 highest 

+100 lowest

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="since"/>

+      </appInfo>

+      <documentation>

+         WTP 3.x

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         &lt;extension point=&quot;org.eclipse.wst.common.snippets.SnippetProvider&quot;&gt;

+    &lt;provider

+          class=&quot;org.eclipse.wst.common.snippets.ui.TextSnippetProvider&quot;

+          priority=&quot;100&quot;&gt;

+       &lt;enablement&gt;

+          &lt;or&gt;

+             &lt;adapt type=&quot;org.eclipse.ui.texteditor.ITextEditor&quot;/&gt;

+             &lt;instanceof value=&quot;org.eclipse.ui.texteditor.ITextEditor&quot;/&gt;

+          &lt;/or&gt;

+       &lt;/enablement&gt;

+    &lt;/provider&gt;

+ &lt;/extension&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiinfo"/>

+      </appInfo>

+      <documentation>

+         [Enter API information here.]

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="implementation"/>

+      </appInfo>

+      <documentation>

+         [Enter information about supplied implementation of this extension point.]

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2009 by SAP AG, Walldorf. 

+All rights reserved. This program and the accompanying materials

+are made available under the terms of the Eclipse Public License v1.0

+which accompanies this distribution, and is available at

+http://www.eclipse.org/legal/epl-v10.html

+

+Contributors:

+  SAP AG - initial API and implementation

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/core/ISnippetProvider.java b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/core/ISnippetProvider.java
new file mode 100644
index 0000000..fde79fe
--- /dev/null
+++ b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/core/ISnippetProvider.java
@@ -0,0 +1,92 @@
+/*******************************************************************************

+ * Copyright (c) 2009 by SAP AG, Walldorf. 

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    SAP AG - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.wst.common.snippets.core;

+

+import org.eclipse.core.runtime.CoreException;

+import org.eclipse.core.runtime.IPath;

+import org.eclipse.core.runtime.IStatus;

+import org.eclipse.gef.palette.PaletteEntry;

+import org.eclipse.jface.viewers.ISelection;

+import org.eclipse.ui.IEditorPart;

+import org.eclipse.wst.common.snippets.internal.editors.ISnippetEditor;

+import org.eclipse.wst.common.snippets.internal.palette.SnippetPaletteItem;

+import org.eclipse.wst.common.snippets.ui.ISnippetInsertion;

+

+/**

+ * ISnippetProvider presents the possibility for plug-in developers to develop

+ * logic that can take advantage of the snippet concept. Thus allowing the 

+ * end user to apply frequently reusable content.

+ * 

+ * Using AbstractSnippetProveider is recommended where most of the methods 

+ * have default implementation.

+ * @author Dimitar Giormov

+ */

+public interface ISnippetProvider {

+	

+	/**

+	 * Implementors should create new SnippetPaletteItem instance.

+	 * Using AbstractSnippetProveider is recommended where this method is implemented.

+	 * 

+	 * @param drawer

+	 * @return

+	 * @throws CoreException

+	 */

+	public SnippetPaletteItem createSnippet(PaletteEntry drawer) throws CoreException ;

+	

+	/**

+	 * Specifies if the Add to Snippets action will be available 

+	 * on the current selection. 

+	 * 

+	 * @param selection

+	 * @return true if the Add to Snippets action will be available in the popup menu.

+	 */

+	public boolean isActionEnabled(ISelection selection);

+

+	/**

+	 * Saves additional content is special designated folder.

+	 * 

+	 * @param path - where the resources can be saved.

+	 * @return status of the operation.

+	 */

+	public IStatus saveAdditionalContent(IPath path);

+	

+	/**

+	 * Returns snippet insertion class for reproducing the saved content in the editor.

+	 * 

+	 * @return

+	 */

+	public ISnippetInsertion getSnippetInsertion();

+	

+	/**

+	 * UID for the provider.

+	 * 

+	 * @return

+	 */

+	public String getId();

+	

+	/**

+	 * Snippet enabled editor, on which the snippet will be applied or taken from.

+	 * 

+	 * @param editor

+	 */

+	public void setEditor(IEditorPart editor);

+	

+	/**

+	 * Returns custom snippet editor, which will be shown in customize dialog

+	 * User can return the VariableItemEditor if variables will be reused.

+	 * Null if no editor is necessary.

+	 * Or custom editor.

+	 * 

+	 * @return

+	 */

+	public ISnippetEditor getSnippetEditor();

+	

+}

diff --git a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/AbstractSnippetProvider.java b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/AbstractSnippetProvider.java
new file mode 100644
index 0000000..83f98fa
--- /dev/null
+++ b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/AbstractSnippetProvider.java
@@ -0,0 +1,72 @@
+/*******************************************************************************

+ * Copyright (c) 2009 SAP AG and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *     SAP AG - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.wst.common.snippets.internal;

+

+import org.eclipse.core.runtime.CoreException;

+import org.eclipse.core.runtime.IStatus;

+import org.eclipse.gef.palette.PaletteEntry;

+import org.eclipse.ui.IEditorPart;

+import org.eclipse.wst.common.snippets.core.ISnippetProvider;

+import org.eclipse.wst.common.snippets.internal.editors.ISnippetEditor;

+import org.eclipse.wst.common.snippets.internal.palette.SnippetPaletteItem;

+import org.eclipse.wst.common.snippets.internal.palette.SnippetPaletteItemFactory;

+

+/**

+ * Default implementation of common methods required by ISnippetProvider

+ * 

+ * @author Dimitar Giormov

+ *

+ */

+public abstract class AbstractSnippetProvider implements ISnippetProvider {

+	

+	protected IEditorPart fEditorPart;

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.wst.common.snippets.core.ISnippetProvider#setEditor(org.eclipse.ui.IEditorPart)

+	 */

+	public void setEditor(IEditorPart editor) {

+		fEditorPart = editor;

+

+	}

+	

+	/* (non-Javadoc)

+	 * @see org.eclipse.wst.common.snippets.core.ISnippetProvider#createSnippet(org.eclipse.gef.palette.PaletteEntry)

+	 */

+	public SnippetPaletteItem createSnippet(PaletteEntry drawer) throws CoreException {

+		SnippetPaletteItem snippet = createSnippetMetadata(drawer);

+		return snippet;

+	}

+	

+	/**

+	 * Creates snippet metadata and saves additional content.

+	 * 

+	 * 

+	 * @param drawer - drawer to which the snippet will be added.

+	 * @return

+	 * @throws CoreException

+	 */

+	protected SnippetPaletteItem createSnippetMetadata(PaletteEntry drawer) throws CoreException {

+		SnippetPaletteItem item = (SnippetPaletteItem) new SnippetPaletteItemFactory().createNewEntry(fEditorPart.getSite().getShell(), drawer);

+//		item.setSourceType(ISnippetsEntry.SNIPPET_SOURCE_PLUGINS);

+		item.setProvider(this);

+		IStatus status = saveAdditionalContent(item.getStorageLocation());

+		if (status!= null && status.getSeverity() == IStatus.ERROR){

+			throw new CoreException(status);

+		}

+		return item;

+	}

+	

+

+	public ISnippetEditor getSnippetEditor() {

+		return null;

+	}

+

+}

diff --git a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/SnippetContributor.java b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/SnippetContributor.java
new file mode 100644
index 0000000..fea7880
--- /dev/null
+++ b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/SnippetContributor.java
@@ -0,0 +1,107 @@
+/*******************************************************************************

+ * Copyright (c) 2009 SAP AG and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *     SAP AG - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.wst.common.snippets.internal;

+

+import org.eclipse.core.expressions.EvaluationContext;

+import org.eclipse.core.expressions.EvaluationResult;

+import org.eclipse.core.expressions.Expression;

+import org.eclipse.core.expressions.ExpressionConverter;

+import org.eclipse.core.runtime.CoreException;

+import org.eclipse.core.runtime.IConfigurationElement;

+import org.eclipse.wst.common.snippets.core.ISnippetProvider;

+

+public class SnippetContributor {

+

+	public static final String ID_EXTENSION_POINT_PROVIDER = SnippetsPlugin.BUNDLE_ID + ".SnippetProvider"; //$NON-NLS-1$

+	public static final String CLASS = "class"; //$NON-NLS-1$

+	public static final String PRIORITY = "priority"; //$NON-NLS-1$

+	public static final String ENABLEMENT = "enablement"; //$NON-NLS-1$

+

+	private ISnippetProvider provider;

+	private IConfigurationElement extPointElement;

+	// 100 = lowest, 0 = highest

+	private byte priority = 100;

+

+	private boolean initExecuted = false;

+

+

+	public SnippetContributor(IConfigurationElement extPointElement) {

+		super();

+		this.extPointElement = extPointElement;

+		initPriority();

+	}

+

+	private void initPriority() {

+		if (extPointElement.getAttribute(PRIORITY) != null) {

+			try {

+				priority = (byte) Integer.parseInt(extPointElement.getAttribute(PRIORITY));

+				if (priority < 0 || priority > 100) {

+					priority = 100;

+				}

+			}

+			catch (NumberFormatException e) {

+				priority = 100;

+				Logger.logException(e);

+			}

+		}

+	}

+

+	private void initProvider() {

+		initExecuted = true;

+		try {

+			provider = (ISnippetProvider) extPointElement.createExecutableExtension(CLASS);

+		}

+		catch (CoreException e) {

+			Logger.logException(e);

+		}

+

+

+	}

+

+

+	public boolean isApplicable(Object o) {

+		IConfigurationElement[] configurationElements = extPointElement.getChildren(ENABLEMENT);

+		boolean enabled = false;

+		for (int i = 0; i < configurationElements.length; i++) {

+			try {

+				enabled |= testEnablement(configurationElements[i], o);

+			}

+			catch (CoreException e) {

+				// nothing to do testEnablement fails.

+				return false;

+			}

+		}

+		return enabled;

+	}

+

+	private boolean testEnablement(IConfigurationElement enable, Object o) throws CoreException {

+		Expression exp = ExpressionConverter.getDefault().perform(enable);

+		EvaluationContext context = new EvaluationContext(null, o);

+		context.setAllowPluginActivation(true);

+		return EvaluationResult.TRUE == exp.evaluate(context);

+	}

+

+

+	public ISnippetProvider getProvider() {

+		if (!initExecuted) {

+			initProvider();

+		}

+		return provider;

+	}

+

+	public byte getPriority() {

+		return priority;

+	}

+

+	public String toString() {

+		return super.toString() + ":" + extPointElement.getAttribute(CLASS);

+	}

+}

diff --git a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/SnippetTransfer.java b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/SnippetTransfer.java
index 033f48a..b34b2c4 100644
--- a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/SnippetTransfer.java
+++ b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/SnippetTransfer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -10,9 +10,8 @@
  *******************************************************************************/
 package org.eclipse.wst.common.snippets.internal;
 
-
-
 import org.eclipse.swt.dnd.ByteArrayTransfer;
+import org.eclipse.swt.dnd.TransferData;
 
 /**
  * Transfer type used for clipboard operations
@@ -29,6 +28,7 @@
 	private static String[] names = null;
 	private static int types[] = null;
 
+
 	/**
 	 * @return the registered Transfer instance
 	 */
@@ -56,5 +56,36 @@
 	protected String[] getTypeNames() {
 		return names;
 	}
+	
+	/**
+	 * This records the time at which the transfer data was recorded.
+	 */
+	protected long startTime;
+	
+	/**
+	 * This records the data being transferred.
+	 */
+	protected Object object;
+	
+	/**
+	 * This records the object and current time and encodes only the current
+	 * time into the transfer data.
+	 */
+	public void javaToNative(Object object, TransferData transferData) {
+		startTime = System.currentTimeMillis();
+		this.object = object;
+		if (transferData != null) {
+			super.javaToNative(String.valueOf(startTime).getBytes(), transferData);
+		}
+	}
+
+	/**
+	 * This decodes the time of the transfer and returns the recorded the
+	 * object if the recorded time and the decoded time match.
+	 */
+	public Object nativeToJava(TransferData transferData) {
+		long startTime = Long.valueOf(new String((byte[]) super.nativeToJava(transferData))).longValue();
+		return this.startTime == startTime ? object : null;
+	}
 
 }
diff --git a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/SnippetsPlugin.java b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/SnippetsPlugin.java
index a0754c6..94806f5 100644
--- a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/SnippetsPlugin.java
+++ b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/SnippetsPlugin.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -43,6 +43,7 @@
 		String VARIABLES = "variables"; //$NON-NLS-1$
 		String VERSION = "version"; //$NON-NLS-1$
 		String VIEW_ID = "org.eclipse.wst.common.snippets.internal.ui.SnippetsView"; //$NON-NLS-1$
+		String PROVIDER_ID = "snippetProvider";//$NON-NLS-1$
 	}
 
 	public static final String BUNDLE_ID = "org.eclipse.wst.common.snippets"; //$NON-NLS-1$
diff --git a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/SnippetsPluginResources.properties b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/SnippetsPluginResources.properties
index 3bf968e..fbabc17 100644
--- a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/SnippetsPluginResources.properties
+++ b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/SnippetsPluginResources.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2004, 2005 IBM Corporation and others.
+# Copyright (c) 2004, 2009 IBM Corporation and others.
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
@@ -29,7 +29,7 @@
 Description_6=Description
 Default_Value_7=Default Value
 Remove_15=Remove
-Template_Pattern__16=Template Pattern:
+Template_Pattern__16=Template:
 Insert_Variable_17=Insert &Variable Placeholder...
 #
 Insert___=Insert...
diff --git a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/actions/AddToSnippetsEditorActionDelegate.java b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/actions/AddToSnippetsEditorActionDelegate.java
index df31d6c..bd2510d 100644
--- a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/actions/AddToSnippetsEditorActionDelegate.java
+++ b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/actions/AddToSnippetsEditorActionDelegate.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -10,10 +10,10 @@
  *******************************************************************************/
 package org.eclipse.wst.common.snippets.internal.actions;
 
+import org.eclipse.core.runtime.CoreException;
 import org.eclipse.gef.palette.PaletteDrawer;
 import org.eclipse.gef.ui.palette.customize.PaletteCustomizerDialog;
 import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.text.BadLocationException;
 import org.eclipse.jface.text.IDocument;
 import org.eclipse.jface.text.ITextSelection;
 import org.eclipse.jface.text.TextSelection;
@@ -25,32 +25,34 @@
 import org.eclipse.ui.IWorkbenchPart;
 import org.eclipse.ui.PartInitException;
 import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.common.snippets.core.ISnippetProvider;
 import org.eclipse.wst.common.snippets.internal.Logger;
 import org.eclipse.wst.common.snippets.internal.SnippetsPlugin;
 import org.eclipse.wst.common.snippets.internal.palette.SnippetPaletteItem;
-import org.eclipse.wst.common.snippets.internal.palette.SnippetPaletteItemFactory;
 import org.eclipse.wst.common.snippets.internal.ui.SnippetsView;
-import org.eclipse.wst.common.snippets.internal.util.StringUtils;
+import org.eclipse.wst.common.snippets.internal.util.SnippetProviderManager;
 import org.eclipse.wst.common.snippets.internal.util.UserDrawerSelector;
 
 
 public class AddToSnippetsEditorActionDelegate implements IEditorActionDelegate, IViewActionDelegate {
 
-	private IAction fAction;
 	private IEditorPart fEditorPart;
-	private IViewPart fViewPart = null;
+	private ISnippetProvider snippetProvider;
 
-	/**
-	 * 
-	 */
 	public AddToSnippetsEditorActionDelegate() {
 		super();
 	}
 
+	/**
+	 * @deprecated
+	 */
 	public IDocument getDocument() {
 		return getTextEditor().getDocumentProvider().getDocument(fEditorPart.getEditorInput());
 	}
 
+	/**
+	 * @deprecated
+	 */
 	protected ITextSelection getSelection() {
 		ITextEditor editor = getTextEditor();
 		if (editor != null) {
@@ -62,9 +64,12 @@
 		return new TextSelection(0, 0);
 	}
 
+	/**
+	 * @deprecated
+	 */
 	protected ITextEditor getTextEditor() {
 		ITextEditor editor = null;
-		IWorkbenchPart activePart = fViewPart;
+		IWorkbenchPart activePart = fEditorPart;
 		if (activePart == null) {
 			activePart = fEditorPart;
 		}
@@ -77,6 +82,7 @@
 		return editor;
 	}
 
+
 	/**
 	 * Prompts the user as needed to obtain a category to contain the new
 	 * Snippet
@@ -90,15 +96,10 @@
 		return drawer;
 	}
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.eclipse.ui.IViewActionDelegate#init(org.eclipse.ui.IViewPart)
-	 */
 	public void init(IViewPart view) {
-		fViewPart = view;
 	}
 
+
 	/*
 	 * (non-Javadoc)
 	 * 
@@ -108,25 +109,25 @@
 		PaletteDrawer drawer = getUserDrawer();
 
 		if (drawer != null) {
-			ITextSelection selection = getSelection();
-			String selectedText = null;
+			if (snippetProvider == null) {
+				snippetProvider = SnippetProviderManager.getApplicableProvider(fEditorPart);
+				if (snippetProvider == null) {
+					return;
+				}
+			}
+
 			try {
-				selectedText = getDocument().get(selection.getOffset(), selection.getLength());
-
-				SnippetPaletteItem item = (SnippetPaletteItem) new SnippetPaletteItemFactory().createNewEntry(fEditorPart.getSite().getShell(), drawer);
-				item.setDescription(StringUtils.firstLineOf(selectedText).trim() + "..."); //$NON-NLS-1$
-				item.setContentString(selectedText);
-
-				IViewPart snippets = fEditorPart.getEditorSite().getPage().showView(SnippetsPlugin.NAMES.VIEW_ID); //$NON-NLS-1$
+				SnippetPaletteItem item = snippetProvider.createSnippet(drawer);
+				IViewPart snippets = fEditorPart.getEditorSite().getPage().showView(SnippetsPlugin.NAMES.VIEW_ID);
 				PaletteCustomizerDialog dialog = ((SnippetsView) snippets).getViewer().getCustomizerDialog();
 				dialog.setDefaultSelection(item);
 				dialog.open();
 			}
-			catch (BadLocationException e) {
+			catch (PartInitException e) {
 				Logger.logException(e);
 			}
-			catch (PartInitException e1) {
-				Logger.logException(e1);
+			catch (CoreException e) {
+				Logger.logException(e);
 			}
 		}
 	}
@@ -138,8 +139,12 @@
 	 *      org.eclipse.jface.viewers.ISelection)
 	 */
 	public void selectionChanged(IAction action, ISelection selection) {
-		fAction = action;
-		updateWith(selection);
+		if (selection != null && fEditorPart != null && snippetProvider != null) {
+			action.setEnabled(snippetProvider.isActionEnabled(selection));
+		}
+		else {
+			action.setEnabled(false);
+		}
 	}
 
 	/*
@@ -150,26 +155,13 @@
 	 */
 	public void setActiveEditor(IAction action, IEditorPart targetEditor) {
 		fEditorPart = targetEditor;
-		fAction = action;
-		if (targetEditor != null && targetEditor.getEditorSite() != null && targetEditor.getEditorSite().getSelectionProvider() != null) {
-			updateWith(targetEditor.getEditorSite().getSelectionProvider().getSelection());
+		action.setEnabled(fEditorPart != null);
+		if (fEditorPart != null) {
+			snippetProvider = SnippetProviderManager.getApplicableProvider(fEditorPart);
+		}
+		else {
+			snippetProvider = null;
 		}
 	}
 
-	public void updateWith(ISelection selection) {
-		if (fAction != null) {
-			boolean enable = false;
-			if (selection != null) {
-				if (selection instanceof ITextSelection) {
-					if (((ITextSelection) selection).getLength() > 0) {
-						enable = true;
-					}
-				}
-				else {
-					enable = !selection.isEmpty();
-				}
-			}
-			fAction.setEnabled(enable);
-		}
-	}
 }
diff --git a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/model/SnippetManager.java b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/model/SnippetManager.java
index dd7433a..7df3422 100644
--- a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/model/SnippetManager.java
+++ b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/model/SnippetManager.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,9 +13,12 @@
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Iterator;
@@ -23,6 +26,15 @@
 
 import javax.xml.parsers.DocumentBuilder;
 
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
 import org.eclipse.gef.palette.PaletteContainer;
 import org.eclipse.wst.common.snippets.core.ISnippetCategory;
 import org.eclipse.wst.common.snippets.core.ISnippetsEntry;
@@ -40,6 +52,7 @@
 import org.eclipse.wst.common.snippets.internal.palette.WorkspaceModelDumper;
 import org.eclipse.wst.common.snippets.internal.team.CategoryFileInfo;
 import org.eclipse.wst.common.snippets.internal.util.CommonXML;
+import org.osgi.framework.Bundle;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
@@ -55,6 +68,8 @@
  */
 public class SnippetManager implements ISnippetManager, PropertyChangeListener {
 
+	private static final String STORAGE_FOLDER_NAME = "storage"; //$NON-NLS-1$
+
 	private static File hiddenStateFile = new File("/hidden.xml"); //$NON-NLS-1$
 
 	private static SnippetManager instance = null;
@@ -63,11 +78,19 @@
 		if (instance == null) {
 			instance = new SnippetManager();
 			try {
-				hiddenStateFile = SnippetsPlugin.getDefault().getStateLocation().append("hidden.xml").toFile(); //$NON-NLS-1$
+				hiddenStateFile = SnippetsPlugin.getDefault().getStateLocation().append("hidden.xml").toFile();
 			}
 			catch (Exception e) {
 				hiddenStateFile = new File("/hidden.xml"); //$NON-NLS-1$
 			}
+			
+			try {
+				File storageLocation = SnippetsPlugin.getDefault().getStateLocation().append(STORAGE_FOLDER_NAME).toFile();
+				storageLocation.mkdirs();
+			}
+			catch (SecurityException e) {
+				Logger.logException(e);
+			}
 			// hook resource listener and load categories from workspace
 			// nsd_TODO: disable in-workspace support until fully stabilized
 			// SnippetsPlugin.getDefault().initializeResourceChangeListener();
@@ -407,5 +430,92 @@
 			Logger.logException(e);
 		}
 	}
+	
+	/**
+	 * @param id
+	 * @return the computed storage location for a snippet with this ID
+	 */
+	public IPath getStorageLocation(String id) {
+		Bundle bundle = Platform.getBundle(SnippetsPlugin.BUNDLE_ID);
+		return Platform.getStateLocation(bundle).append(STORAGE_FOLDER_NAME).addTrailingSeparator().append(id);
+	}
+	
+	/**
+	 * Helper method for saving resources in designated snippet resource folder.
+	 * 
+	 * @param snippetId - UID of the snippet that is saving content.
+	 * @param pathList - Project relative path list. The resources are copied in the same structure 
+	 * 					 in the storage path. e.g. having test.jsp file in project root will result in
+	 * 					 test.jsp in the storage root. If the jsp  is in [Project Root]/resources/test.jsp
+	 * 					 this will result in [Snippet Storage Root]/resources/test.jsp 
+	 * @return
+	 */
+	public IStatus moveFilesInStorageFolder(IPath snippetStorage, IPath[] pathList, IProject project){
+		File storageFolder = new File(snippetStorage.toOSString());
+		if (!storageFolder.exists()){
+			if (!storageFolder.mkdirs()){
+				return createErrorStatus("Could not create snippet storage folder.", null);
+			}
+		}
+		for (int i = 0; i < pathList.length; i++) {
+			IFile file = project.getFile(pathList[i]);
+			IPath destPath = snippetStorage.append(pathList[i]);
+			File destination = new File(destPath.toOSString());
+			if (!destination.getParentFile().exists()){
+				if (!destination.getParentFile().mkdirs()){
+					return createErrorStatus("Could not create snippet storage folder.", null);
+				}
+			}	
+			try {
+				copy(file, destination);
+			} catch (FileNotFoundException e) {
+				return createErrorStatus(e.getLocalizedMessage(), e);
+			} catch (IOException e) {
+				return createErrorStatus(e.getLocalizedMessage(), e);
+			} catch (CoreException e) {
+				return e.getStatus();
+			}
+		}
+		
+		return Status.OK_STATUS;
+	}
+	
+	public IStatus moveFilesInWorkspace(File[] fileList, IProject target, IPath storagePath) {
+		for (int i = 0; i < fileList.length; i++) {
+			String fileRelativePath = fileList[i].getAbsolutePath().substring(storagePath.toOSString().length());
+			IFile ifile = target.getFile(new Path(fileRelativePath));
+			try {
+				ifile.create(new FileInputStream(fileList[i]), true, new NullProgressMonitor());
+			} catch (FileNotFoundException e) {
+				return createErrorStatus(e.getLocalizedMessage(), e);
+			} catch (CoreException e) {
+				return createErrorStatus(e.getLocalizedMessage(), e);
+			}
+		}
+		
+		return Status.OK_STATUS;
+	}
+	
+	private void copy(IFile source, File destination) throws FileNotFoundException, IOException, CoreException{
+		copy(source.getContents(), new FileOutputStream(destination));
+	}	
+	
+	private void copy(InputStream in, OutputStream out) throws IOException {
+		byte[] buffer = new byte[4096];
+		try {
+			int n = in.read(buffer);
+			while (n > 0) {
+				out.write(buffer, 0, n);
+				n = in.read(buffer);
+			}
+		} finally {
+			in.close();
+			out.close();
+		}
+	}
+	
+	private IStatus createErrorStatus(String msg, Exception e) {
+		return new Status(IStatus.ERROR, SnippetsPlugin.BUNDLE_ID, msg, e);
+	}	
 
 }
diff --git a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/palette/AbstractModelFactory.java b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/palette/AbstractModelFactory.java
index bc7734e..8771da9 100644
--- a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/palette/AbstractModelFactory.java
+++ b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/palette/AbstractModelFactory.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -20,6 +20,7 @@
 import org.eclipse.wst.common.snippets.internal.Logger;
 import org.eclipse.wst.common.snippets.internal.SnippetDefinitions;
 import org.eclipse.wst.common.snippets.internal.SnippetsPlugin;
+import org.eclipse.wst.common.snippets.internal.util.SnippetProviderManager;
 
 public abstract class AbstractModelFactory {
 
@@ -73,6 +74,7 @@
 		setProperties(item, source);
 
 		migrate50to51(item);
+		
 		return item;
 	}
 
@@ -176,6 +178,8 @@
 			item.setContentString(propertyValue.toString());
 		else if (property.equals(SnippetsPlugin.NAMES.EDITORCLASSNAME))
 			item.setEditorClassName(propertyValue.toString());
+		else if (property.equals(SnippetsPlugin.NAMES.PROVIDER_ID))
+			item.setProvider(SnippetProviderManager.findProvider(propertyValue.toString()));
 		else
 			setEntryProperty(item, property, propertyValue);
 	}
diff --git a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/palette/ModelFactoryForUser.java b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/palette/ModelFactoryForUser.java
index 3a91dd0..8a68321 100644
--- a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/palette/ModelFactoryForUser.java
+++ b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/palette/ModelFactoryForUser.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -219,11 +219,47 @@
 
 		return definitions;
 	}
-
+	
 	public SnippetDefinitions loadCurrent() {
 		return load(getFilename());
 	}
 
+	public SnippetDefinitions load(InputStream in) {
+		SnippetDefinitions definitions = new SnippetDefinitions();
+		Document document = null;
+		try {
+			DocumentBuilder builder = CommonXML.getDocumentBuilder();
+			if (builder != null) {
+				document = builder.parse(new InputSource(in));
+			}
+			else {
+				Logger.log(Logger.ERROR, "Couldn't obtain a DocumentBuilder"); //$NON-NLS-1$
+			}
+		}
+		catch (FileNotFoundException e) {
+			// typical of new workspace, don't log it
+			document = null;
+		}
+		catch (IOException e) {
+			Logger.logException("Could not load user items", e); //$NON-NLS-1$
+			return definitions;
+		}
+		catch (SAXException e) {
+			Logger.logException("Could not load user items", e); //$NON-NLS-1$
+			return definitions;
+		}
+		if (document == null)
+			return definitions;
+		Element library = document.getDocumentElement();
+		if (library == null || !library.getNodeName().equals(SnippetsPlugin.NAMES.SNIPPETS))
+			return definitions;
+		loadDefinitions(definitions, library);
+
+		connectItemsAndCategories(definitions);
+
+		return definitions;
+	}
+
 	protected void loadDefinitions(SnippetDefinitions definitions, Node library) {
 		NodeList children = library.getChildNodes();
 		int length = children.getLength();
@@ -313,6 +349,7 @@
 		setProperty(item, SnippetsPlugin.NAMES.ID, element.getAttribute(SnippetsPlugin.NAMES.ID));
 		setProperty(item, SnippetsPlugin.NAMES.LABEL, element.getAttribute(SnippetsPlugin.NAMES.LABEL));
 		setProperty(item, SnippetsPlugin.NAMES.LARGEICON, element.getAttribute(SnippetsPlugin.NAMES.LARGEICON));
+		setProperty(item, SnippetsPlugin.NAMES.PROVIDER_ID, element.getAttribute(SnippetsPlugin.NAMES.PROVIDER_ID));
 
 		NodeList children = element.getChildNodes();
 		for (int i = 0; i < children.getLength(); i++) {
diff --git a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/palette/SnippetCustomizerDialog.java b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/palette/SnippetCustomizerDialog.java
index 3a0e299..9926388 100644
--- a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/palette/SnippetCustomizerDialog.java
+++ b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/palette/SnippetCustomizerDialog.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -10,12 +10,23 @@
  *******************************************************************************/
 package org.eclipse.wst.common.snippets.internal.palette;
 
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.Enumeration;
 import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
 
+import org.eclipse.core.runtime.Platform;
 import org.eclipse.gef.palette.PaletteDrawer;
 import org.eclipse.gef.palette.PaletteEntry;
 import org.eclipse.gef.palette.PaletteRoot;
@@ -32,16 +43,24 @@
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.ui.PlatformUI;
 import org.eclipse.wst.common.snippets.core.ISnippetCategory;
+import org.eclipse.wst.common.snippets.core.ISnippetItem;
 import org.eclipse.wst.common.snippets.internal.IHelpContextIds;
 import org.eclipse.wst.common.snippets.internal.SnippetDefinitions;
 import org.eclipse.wst.common.snippets.internal.SnippetsMessages;
+import org.eclipse.wst.common.snippets.internal.SnippetsPlugin;
 import org.eclipse.wst.common.snippets.internal.SnippetsPluginImageHelper;
 import org.eclipse.wst.common.snippets.internal.SnippetsPluginImages;
 import org.eclipse.wst.common.snippets.internal.model.SnippetManager;
 import org.eclipse.wst.common.snippets.internal.ui.SnippetsCustomizer;
+import org.osgi.framework.Bundle;
 
 public class SnippetCustomizerDialog extends PaletteCustomizerDialog {
 
+	private static class EXPORT_IMPORT_STRATEGY {
+		static EXPORT_IMPORT_STRATEGY ARCHIVE = new EXPORT_IMPORT_STRATEGY();
+		static EXPORT_IMPORT_STRATEGY XML = new EXPORT_IMPORT_STRATEGY();
+	}
+
 	private class ExportAction extends PaletteCustomizationAction {
 		public ExportAction() {
 			setEnabled(false);
@@ -54,33 +73,96 @@
 
 		protected void handleExport() {
 			PaletteDrawer exportCategory = (PaletteDrawer) getSelectedPaletteEntry();
+			EXPORT_IMPORT_STRATEGY strategy = exportStrategy(exportCategory);
 
-			final FileDialog fileDialog = new FileDialog(getShell(), SWT.SAVE);
-			fileDialog.setText(SnippetsMessages.Export_Snippets);
-			fileDialog.setFileName("snippets.xml"); //$NON-NLS-1$
-			String[] filterExtensions = new String[2];
-			filterExtensions[0] = "*.xml"; //$NON-NLS-1$
-			filterExtensions[1] = "*.*"; //$NON-NLS-1$
-			fileDialog.setFilterExtensions(filterExtensions);
-			String filename = fileDialog.open();
+			if (EXPORT_IMPORT_STRATEGY.ARCHIVE == strategy) {
+				exportArchive(exportCategory);
+			}
+			else {
+				exportXML(exportCategory);
+			}
+			updateActions();
+		}
+
+		private EXPORT_IMPORT_STRATEGY exportStrategy(PaletteDrawer exportCategory) {
+			List children = exportCategory.getChildren();
+			for (int i = 0; i < children.size(); i++) {
+				ISnippetItem snippetItem = (ISnippetItem) children.get(i);
+				File folder = new File(SnippetManager.getInstance().getStorageLocation(snippetItem.getId()).toOSString());
+				if (folder.exists()) {
+					return EXPORT_IMPORT_STRATEGY.ARCHIVE;
+				}
+			}
+			return EXPORT_IMPORT_STRATEGY.XML;
+		}
+
+		private void exportArchive(PaletteDrawer exportCategory) {
+			String filename = openFileDialog("*.zip");//$NON-NLS-1$
 			if (filename != null) {
-				SnippetDefinitions definitions = ModelFactoryForUser.getInstance().load(filename);
-				ISnippetCategory existingCategory = definitions.getCategory(exportCategory.getId());
-
-				if (existingCategory == null)
-					definitions.getCategories().add(exportCategory);
-				else {
-					String title = SnippetsMessages.SnippetCustomizerDialog_2; //$NON-NLS-1$
-					String message = NLS.bind(SnippetsMessages.SnippetCustomizerDialog_4, new String[]{existingCategory.getLabel()});
-					boolean answer = MessageDialog.openConfirm(getShell(), title, message);
-					if (answer) {
-						definitions.getCategories().remove(existingCategory);
-						definitions.getCategories().add(exportCategory);
+				ZipOutputStream outputStream = null;
+				try {
+					SnippetDefinitions definitions = getCategory(exportCategory, filename);
+					outputStream = new ZipOutputStream(new FileOutputStream(filename));
+					ZipEntry descriptorFile = new ZipEntry("snippets.xml");
+					outputStream.putNextEntry(descriptorFile);
+					new UserModelDumper().write(definitions, outputStream);
+					ISnippetCategory existingCategory = definitions.getCategory(exportCategory.getId());
+					ISnippetItem[] items = existingCategory.getItems();
+					for (int i = 0; i < items.length; i++) {
+						File folder = new File(SnippetManager.getInstance().getStorageLocation(items[i].getId()).toOSString());
+						if (folder.exists()) {
+							addToZip(folder.getParentFile(), folder, outputStream);
+						}
 					}
 				}
+				catch (FileNotFoundException e) {
+					// should not have problem finding the output file
+					e.printStackTrace();
+				}
+				catch (IOException e) {
+					e.printStackTrace();
+				}
+				finally {
+					if (outputStream != null) {
+						try {
+							outputStream.close();
+						}
+						catch (IOException e) {
+							// should not have problem closing the output file
+							e.printStackTrace();
+						}
+					}
+				}
+			}
+		}
 
-				OutputStream outputStream = null;
+		private void addToZip(File root, File folder, ZipOutputStream outputStream) throws IOException {
+			File[] listedFiles = folder.listFiles();
+			for (int i = 0; i < listedFiles.length; i++) {
+				if (listedFiles[i].isDirectory()) {
+					addToZip(root, listedFiles[i], outputStream);
+				}
+				else {
+					ZipEntry ze = new ZipEntry(listedFiles[i].getAbsolutePath().substring(root.getAbsolutePath().length() + 1));
+					outputStream.putNextEntry(ze);
+					BufferedInputStream bis = new BufferedInputStream(new FileInputStream(listedFiles[i]), 1024);
+					byte[] data = new byte[1024];
+					int count;
+					while ((count = bis.read(data, 0, 1024)) != -1) {
+						outputStream.write(data, 0, count);
+					}
+					bis.close();
+				}
+			}
+		}
+
+		private void exportXML(PaletteDrawer exportCategory) {
+			String filename = openFileDialog("*.xml");//$NON-NLS-1$
+
+			OutputStream outputStream = null;
+			if (filename != null) {
 				try {
+					SnippetDefinitions definitions = getCategory(exportCategory, filename);
 					outputStream = new FileOutputStream(filename);
 					new UserModelDumper().write(definitions, outputStream);
 				}
@@ -89,7 +171,7 @@
 					e.printStackTrace();
 				}
 				finally {
-					if (outputStream != null)
+					if (outputStream != null) {
 						try {
 							outputStream.close();
 						}
@@ -97,10 +179,42 @@
 							// should not have problem closing the output file
 							e.printStackTrace();
 						}
+					}
 				}
 
-				updateActions();
 			}
+
+
+		}
+
+		private SnippetDefinitions getCategory(PaletteDrawer exportCategory, String fileName) {
+			SnippetDefinitions definitions = ModelFactoryForUser.getInstance().load(fileName);
+			ISnippetCategory existingCategory = definitions.getCategory(exportCategory.getId());
+
+			if (existingCategory == null)
+				definitions.getCategories().add(exportCategory);
+			else {
+				String title = SnippetsMessages.SnippetCustomizerDialog_2; //$NON-NLS-1$
+				String message = NLS.bind(SnippetsMessages.SnippetCustomizerDialog_4, new String[]{existingCategory.getLabel()});
+				boolean answer = MessageDialog.openConfirm(getShell(), title, message);
+				if (answer) {
+					definitions.getCategories().remove(existingCategory);
+					definitions.getCategories().add(exportCategory);
+				}
+			}
+			return definitions;
+		}
+
+		private String openFileDialog(String extension) {
+			final FileDialog fileDialog = new FileDialog(getShell(), SWT.SAVE);
+			fileDialog.setText(SnippetsMessages.Export_Snippets);
+			fileDialog.setFileName("snippets"+ extension.substring(1)); //$NON-NLS-1$
+			String[] filterExtensions = new String[2];
+			filterExtensions[0] = extension;
+			filterExtensions[1] = "*.*"; //$NON-NLS-1$
+			fileDialog.setFilterExtensions(filterExtensions);
+			String filename = fileDialog.open();
+			return filename;
 		}
 
 		public void run() {
@@ -111,12 +225,12 @@
 			boolean enabled = false;
 			PaletteEntry entry = getSelectedPaletteEntry();
 			if (entry != null) {
-				if (getCustomizer() instanceof SnippetsCustomizer)
+				if (getCustomizer() instanceof SnippetsCustomizer) {
 					enabled = ((SnippetsCustomizer) getCustomizer()).canExport(entry);
+				}
 			}
 			setEnabled(enabled);
 		}
-
 	}
 
 	private class ImportAction extends PaletteCustomizationAction {
@@ -132,14 +246,40 @@
 		protected void handleImport() {
 			final FileDialog fileDialog = new FileDialog(getShell(), SWT.OPEN);
 			fileDialog.setText(SnippetsMessages.Import_Snippets);
-			fileDialog.setFileName("snippets.xml"); //$NON-NLS-1$
+//			fileDialog.setFileName("snippets.xml"); //$NON-NLS-1$
 			String[] filterExtensions = new String[2];
-			filterExtensions[0] = "*.xml"; //$NON-NLS-1$
+			filterExtensions[0] = "*.xml; *.zip"; //$NON-NLS-1$
 			filterExtensions[1] = "*.*"; //$NON-NLS-1$
 			fileDialog.setFilterExtensions(filterExtensions);
 			String filename = fileDialog.open();
-			if (filename != null) {
-				SnippetDefinitions definitions = ModelFactoryForUser.getInstance().load(filename);
+			try {
+				if (filename.toLowerCase().endsWith(".zip")) {
+					ZipFile zip = new ZipFile(new File(filename));
+					ZipEntry entry = zip.getEntry("snippets.xml");
+					loadMetadata(zip.getInputStream(entry));
+					Bundle bundle = Platform.getBundle(SnippetsPlugin.BUNDLE_ID);
+					unzip(zip, Platform.getStateLocation(bundle).toOSString());
+				}
+				else {
+					loadMetadata(new FileInputStream(filename));
+				}
+			}
+			catch (FileNotFoundException e) {
+				e.printStackTrace();
+			}
+			catch (ZipException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+			catch (IOException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+		}
+
+		private void loadMetadata(InputStream fileInputStream) {
+			if (fileInputStream != null) {
+				SnippetDefinitions definitions = ModelFactoryForUser.getInstance().load(fileInputStream);
 				List importCategories = definitions.getCategories();
 				List currentCategories = SnippetManager.getInstance().getDefinitions().getCategories();
 				PaletteEntry lastImportEntry = null;
@@ -166,8 +306,9 @@
 						lastImportEntry = (PaletteEntry) importCategories.get(i);
 					}
 				}
-				if (lastImportEntry != null)
+				if (lastImportEntry != null) {
 					fTreeviewer.setSelection(new StructuredSelection(lastImportEntry), true);
+				}
 
 				updateActions();
 			}
@@ -181,8 +322,9 @@
 			boolean enabled = false;
 			PaletteEntry entry = getSelectedPaletteEntry();
 			if (entry != null) {
-				if (getCustomizer() instanceof SnippetsCustomizer)
+				if (getCustomizer() instanceof SnippetsCustomizer) {
 					enabled = ((SnippetsCustomizer) getCustomizer()).canImport(entry);
+				}
 			}
 			setEnabled(enabled);
 		}
@@ -215,4 +357,40 @@
 
 		return super.open();
 	}
+
+	static final void copyInputStream(InputStream in, OutputStream out) throws IOException {
+		byte[] buffer = new byte[2048];
+		int len;
+
+		while ((len = in.read(buffer)) >= 0)
+			out.write(buffer, 0, len);
+
+		in.close();
+		out.close();
+	}
+
+	void unzip(ZipFile zipFile, String path) throws FileNotFoundException, IOException {
+		Enumeration entries;
+		entries = zipFile.entries();
+
+		while (entries.hasMoreElements()) {
+			ZipEntry entry = (ZipEntry) entries.nextElement();
+			File file = new File(path + File.separator + entry.getName());
+			if (entry.isDirectory()) {
+				file.mkdir();
+				continue;
+			}
+			if (!file.getParentFile().exists()) {
+				file.getParentFile().mkdirs();
+			}
+			if (entry.getName().toLowerCase().equals("snippets.xml")) {
+				continue;
+			}
+
+			copyInputStream(zipFile.getInputStream(entry), new BufferedOutputStream(new FileOutputStream(file)));
+		}
+
+		zipFile.close();
+	}
+
 }
diff --git a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/palette/SnippetPaletteItem.java b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/palette/SnippetPaletteItem.java
index 82b320b..33a0e2d 100644
--- a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/palette/SnippetPaletteItem.java
+++ b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/palette/SnippetPaletteItem.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -16,12 +16,15 @@
 import java.util.Arrays;
 import java.util.List;
 
+import org.eclipse.core.runtime.IPath;
 import org.eclipse.gef.palette.PaletteContainer;
 import org.eclipse.gef.palette.PaletteTemplateEntry;
 import org.eclipse.jface.resource.ImageDescriptor;
 import org.eclipse.wst.common.snippets.core.ISnippetCategory;
 import org.eclipse.wst.common.snippets.core.ISnippetItem;
+import org.eclipse.wst.common.snippets.core.ISnippetProvider;
 import org.eclipse.wst.common.snippets.core.ISnippetVariable;
+import org.eclipse.wst.common.snippets.internal.model.SnippetManager;
 
 public class SnippetPaletteItem extends PaletteTemplateEntry implements ISnippetItem {
 
@@ -38,6 +41,7 @@
 	protected Object fSourceDescriptor;
 	protected Object fSourceType = SNIPPET_SOURCE_USER;
 	protected List fVariables;
+	private ISnippetProvider provider;
 
 	/**
 	 * @param label
@@ -219,4 +223,17 @@
 		fVariables = new ArrayList(variables.length);
 		fVariables.addAll(Arrays.asList(variables));
 	}
+
+	public IPath getStorageLocation() {
+		return SnippetManager.getInstance().getStorageLocation(getId());
+	}
+
+
+	public ISnippetProvider getProvider() {
+		return provider;
+	}
+
+	public void setProvider(ISnippetProvider provider) {
+		this.provider = provider;
+	}
 }
diff --git a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/palette/UserModelDumper.java b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/palette/UserModelDumper.java
index 8118529..0e17e74 100644
--- a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/palette/UserModelDumper.java
+++ b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/palette/UserModelDumper.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -178,6 +178,8 @@
 			element.setAttribute(SnippetsPlugin.NAMES.CLASSNAME, ((SnippetPaletteItem) item).getClassName());
 		if (((SnippetPaletteItem) item).getEditorClassName() != null)
 			element.setAttribute(SnippetsPlugin.NAMES.EDITORCLASSNAME, ((SnippetPaletteItem) item).getEditorClassName());
+		if (((SnippetPaletteItem) item).getProvider() != null)
+			element.setAttribute(SnippetsPlugin.NAMES.PROVIDER_ID, ((SnippetPaletteItem) item).getProvider().getId());
 		element.appendChild(createContent(doc, item));
 		ISnippetVariable[] variables = item.getVariables();
 		for (int i = 0; i < variables.length; i++) {
@@ -279,13 +281,8 @@
 			Logger.log(Logger.ERROR, "could not save " + stream, e); //$NON-NLS-1$
 		}
 		finally {
-			try {
-				stream.close();
-				document = null;
-			}
-			catch (IOException e) {
-				// nothing to be done while closing
-			}
+			//				stream.close();
+			document = null;
 		}
 	}
 
diff --git a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/ui/EntryDeserializer.java b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/ui/EntryDeserializer.java
index 49d36b0..5d38303 100644
--- a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/ui/EntryDeserializer.java
+++ b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/ui/EntryDeserializer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -22,6 +22,7 @@
 import org.eclipse.wst.common.snippets.internal.palette.SnippetPaletteItem;
 import org.eclipse.wst.common.snippets.internal.palette.SnippetVariable;
 import org.eclipse.wst.common.snippets.internal.util.CommonXML;
+import org.eclipse.wst.common.snippets.internal.util.SnippetProviderManager;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
@@ -72,6 +73,7 @@
 		item.setCategoryName(element.getAttribute(SnippetsPlugin.NAMES.CATEGORY));
 		item.setClassName(element.getAttribute(SnippetsPlugin.NAMES.CLASSNAME));
 		item.setEditorClassName(element.getAttribute(SnippetsPlugin.NAMES.EDITORCLASSNAME));
+		item.setProvider(SnippetProviderManager.findProvider(element.getAttribute(SnippetsPlugin.NAMES.PROVIDER_ID)));
 		NodeList children = element.getChildNodes();
 		int length = children.getLength();
 		for (int i = 0; i < length; i++) {
diff --git a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/ui/EntrySerializer.java b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/ui/EntrySerializer.java
index 36dc1bd..b24971c 100644
--- a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/ui/EntrySerializer.java
+++ b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/ui/EntrySerializer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -116,6 +116,8 @@
 			element.setAttribute(SnippetsPlugin.NAMES.CLASSNAME, item.getClassName());
 		if (item.getEditorClassName() != null)
 			element.setAttribute(SnippetsPlugin.NAMES.EDITORCLASSNAME, item.getEditorClassName());
+		if (item.getProvider() != null)
+			element.setAttribute(SnippetsPlugin.NAMES.PROVIDER_ID, item.getProvider().getId());
 		if (item.getContentString() != null)
 			element.appendChild(createContent(doc, item));
 		ISnippetVariable[] variables = item.getVariables();
diff --git a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/ui/SnippetTemplateEntryPage.java b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/ui/SnippetTemplateEntryPage.java
index 426c5b2..1c4de6d 100644
--- a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/ui/SnippetTemplateEntryPage.java
+++ b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/ui/SnippetTemplateEntryPage.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -38,16 +38,22 @@
 			editor.addModifyListener(this);
 			editor.setItem((SnippetPaletteItem) entry);
 			editor.createContents((Composite) getControl());
-			// it can't be known in advance since the editor is unknown as
-			// well
+			/*
+			 * Can't be known in advance since the editor content is unknown
+			 */
 			((Composite) getControl()).setTabList(null);
 		}
 	}
 
 	protected ISnippetEditor getEditor(SnippetPaletteItem item) {
 		ISnippetEditor snippetEditor = null;
-		if (item.getSourceType() != ISnippetsEntry.SNIPPET_SOURCE_PLUGINS) {
-			snippetEditor = new VariableItemEditor();
+		if (item.getSourceType() == ISnippetsEntry.SNIPPET_SOURCE_USER || item.getSourceType() == ISnippetsEntry.SNIPPET_SOURCE_WORKSPACE) {
+			if (item.getProvider() == null) {
+				snippetEditor = new VariableItemEditor();
+			}
+			else {
+				snippetEditor = item.getProvider().getSnippetEditor();
+			}
 		}
 		return snippetEditor;
 	}
diff --git a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/ui/SnippetsCustomizer.java b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/ui/SnippetsCustomizer.java
index 1a30c45..20de354 100644
--- a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/ui/SnippetsCustomizer.java
+++ b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/ui/SnippetsCustomizer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -10,9 +10,11 @@
  *******************************************************************************/
 package org.eclipse.wst.common.snippets.internal.ui;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.eclipse.core.runtime.IPath;
 import org.eclipse.gef.palette.PaletteContainer;
 import org.eclipse.gef.palette.PaletteDrawer;
 import org.eclipse.gef.palette.PaletteEntry;
@@ -31,8 +33,10 @@
 
 
 public class SnippetsCustomizer extends PaletteCustomizer {
+	
 	protected List activeEditors = new ArrayList();
 	protected List factories = null;
+	private List deletedIds = new ArrayList();
 
 	public SnippetsCustomizer() {
 		super();
@@ -117,6 +121,13 @@
 				Logger.logException(e);
 			}
 		}
+		
+		for (int i = 0; i < deletedIds.size(); i++) {
+			IPath path = SnippetManager.getInstance().getStorageLocation(deletedIds.get(i).toString());
+			File folder = new File(path.toOSString());
+			deleteFolders(folder);
+		}
+		deletedIds.clear();
 
 		activeEditors = new ArrayList(0);
 
@@ -127,4 +138,26 @@
 			Logger.logException(e);
 		}
 	}
+
+	private void deleteFolders(File folder) {
+		if (!folder.exists()) {
+			return;
+		}
+		File[] listFiles = folder.listFiles();
+		for (int i = 0; i < listFiles.length; i++) {
+			if (listFiles[i].isDirectory()) {
+				deleteFolders(listFiles[i]);
+			}
+			else {
+				listFiles[i].delete();
+			}
+		}
+		folder.delete();
+	}
+
+	public void performDelete(PaletteEntry entry) {
+		deletedIds.add(entry.getId());
+		super.performDelete(entry);
+	}
+
 }
diff --git a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/ui/SnippetsView.java b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/ui/SnippetsView.java
index 0dbe494..45ceda2 100644
--- a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/ui/SnippetsView.java
+++ b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/ui/SnippetsView.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -199,8 +199,13 @@
 					}
 				}
 			}
+			 
 			if (insertion == null) {
-				insertion = new DefaultSnippetInsertion();
+				if (item.getProvider()!= null){
+					insertion = item.getProvider().getSnippetInsertion();
+				} else {
+					insertion = new DefaultSnippetInsertion();
+				}
 			}
 			return insertion;
 		}
@@ -829,6 +834,9 @@
 				insertion.setEditorPart(getSite().getPage().getActiveEditor());
 				supportedTypes = insertion.getTransfers();
 			}
+			else {
+				supportedTypes = new Transfer[]{TextTransfer.getInstance()};
+			}
 		}
 		else {
 			// Keep a transfer registered so that GEF doesn't unhook the drag
@@ -841,9 +849,11 @@
 			supportedTypes = new Transfer[]{TextTransfer.getInstance()};
 		}
 
-		// TRH suggested use of the event's doit field by the fListeners, but
-		// there's
-		// no other way to guarantee that TextTransfer is considered last
+		/*
+		 * TRH suggested use of the event's doit field by the fListeners, but
+		 * there's no other way to guarantee that TextTransfer is considered
+		 * last
+		 */
 		Iterator iterator = getTransferDragSourceListeners().iterator();
 		ArrayList oldListeners = new ArrayList();
 		while (iterator.hasNext()) {
diff --git a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/util/SnippetProviderManager.java b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/util/SnippetProviderManager.java
new file mode 100644
index 0000000..9432861
--- /dev/null
+++ b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/internal/util/SnippetProviderManager.java
@@ -0,0 +1,87 @@
+/*******************************************************************************

+ * Copyright (c) 2009 SAP AG and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *     SAP AG - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.wst.common.snippets.internal.util;

+

+import java.util.ArrayList;

+import java.util.List;

+

+import org.eclipse.core.runtime.Assert;

+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.ui.IEditorPart;

+import org.eclipse.wst.common.snippets.core.ISnippetProvider;

+import org.eclipse.wst.common.snippets.internal.SnippetContributor;

+import org.eclipse.wst.common.snippets.ui.TextSnippetProvider;

+

+

+public class SnippetProviderManager {

+

+	private static ISnippetProvider[] getProviders() {

+		IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(SnippetContributor.ID_EXTENSION_POINT_PROVIDER);

+		IExtension[] extensions = extensionPoint.getExtensions();

+		List providerList = new ArrayList();

+		for (int i = 0; i < extensions.length; i++) {

+			IConfigurationElement[] configurationElements = extensions[i].getConfigurationElements();

+			for (int j = 0; j < configurationElements.length; j++) {

+				SnippetContributor sc = new SnippetContributor(configurationElements[j]);

+				if (sc.getProvider() != null) {

+					providerList.add(sc.getProvider());

+				}

+			}

+

+		}

+		return (ISnippetProvider[]) providerList.toArray(new ISnippetProvider[providerList.size()]);

+	}

+

+	public static ISnippetProvider findProvider(String id) {

+		Assert.isNotNull(id);

+		ISnippetProvider[] providers = getProviders();

+		for (int i = 0; i < providers.length; i++) {

+			if (id.equals(providers[i].getId()))

+				return providers[i];

+		}

+

+		return new TextSnippetProvider();

+	}

+

+	public static ISnippetProvider getApplicableProvider(IEditorPart targetEditor) {

+		SnippetContributor applicableContributor = null;

+		IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(SnippetContributor.ID_EXTENSION_POINT_PROVIDER);

+		if (extensionPoint != null) {

+			IExtension[] extensions = extensionPoint.getExtensions();

+			for (int i = 0; i < extensions.length; i++) {

+				IConfigurationElement[] configurationElements = extensions[i].getConfigurationElements();

+				for (int j = 0; j < configurationElements.length; j++) {

+					SnippetContributor sc = new SnippetContributor(configurationElements[j]);

+					if (sc.isApplicable(targetEditor)) {

+						if (applicableContributor == null || applicableContributor.getPriority() > sc.getPriority()) {

+							applicableContributor = sc;

+						}

+					}

+				}

+			}

+		}

+		if (applicableContributor == null) {

+			return null;

+		}

+		ISnippetProvider provider = applicableContributor.getProvider();

+		// a null provider is an error condition

+		if (provider != null) {

+			provider.setEditor(targetEditor);

+		}

+		return provider;

+	}

+

+

+

+}

diff --git a/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/ui/TextSnippetProvider.java b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/ui/TextSnippetProvider.java
new file mode 100644
index 0000000..e46e487
--- /dev/null
+++ b/org.eclipse.wst.common.snippets/src/org/eclipse/wst/common/snippets/ui/TextSnippetProvider.java
@@ -0,0 +1,111 @@
+/*******************************************************************************

+ * Copyright (c) 2009 IBM Corporation and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *     IBM Corporation - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.wst.common.snippets.ui;

+

+import org.eclipse.core.runtime.CoreException;

+import org.eclipse.core.runtime.IPath;

+import org.eclipse.core.runtime.IStatus;

+import org.eclipse.core.runtime.Status;

+import org.eclipse.gef.palette.PaletteEntry;

+import org.eclipse.jface.text.BadLocationException;

+import org.eclipse.jface.text.IDocument;

+import org.eclipse.jface.text.ITextSelection;

+import org.eclipse.jface.viewers.ISelection;

+import org.eclipse.ui.IWorkbenchPart;

+import org.eclipse.ui.texteditor.ITextEditor;

+import org.eclipse.wst.common.snippets.core.ISnippetProvider;

+import org.eclipse.wst.common.snippets.internal.AbstractSnippetProvider;

+import org.eclipse.wst.common.snippets.internal.Logger;

+import org.eclipse.wst.common.snippets.internal.editors.ISnippetEditor;

+import org.eclipse.wst.common.snippets.internal.editors.VariableItemEditor;

+import org.eclipse.wst.common.snippets.internal.palette.SnippetPaletteItem;

+import org.eclipse.wst.common.snippets.internal.util.StringUtils;

+

+public class TextSnippetProvider extends AbstractSnippetProvider implements ISnippetProvider {

+

+	public SnippetPaletteItem createSnippet(PaletteEntry drawer) throws CoreException {

+		SnippetPaletteItem item = super.createSnippet(drawer);

+		ITextSelection selection = getTextSelection();

+		try {

+			String selectedText = getDocument().get(selection.getOffset(), selection.getLength());			

+			item.setDescription(StringUtils.firstLineOf(selectedText).trim() + "..."); //$NON-NLS-1$

+			item.setContentString(selectedText);

+		}

+		catch (BadLocationException e) {

+			Logger.logException(e);

+		}

+		return item;

+	}

+	

+

+	protected ITextSelection getTextSelection() {

+		ITextEditor editor = getTextEditor();

+		if (editor != null) {

+			ISelection selection = editor.getSelectionProvider().getSelection();

+			if (selection instanceof ITextSelection) {

+				return (ITextSelection) selection;

+			}

+		}

+		return null;

+	}

+

+	protected ITextEditor getTextEditor() {

+		ITextEditor editor = null;

+		IWorkbenchPart activePart = fEditorPart;

+		

+		if (activePart instanceof ITextEditor) {

+			editor = (ITextEditor) activePart;

+		}

+		if (editor == null) {

+			editor = (ITextEditor) activePart.getAdapter(ITextEditor.class);

+		}

+		return editor;

+	}

+

+	public boolean isActionEnabled(ISelection selection) {

+		boolean enable = false;

+		if (selection != null) {

+			if (selection instanceof ITextSelection) {

+				if (((ITextSelection) selection).getLength() > 0) {

+					enable = true;

+				}

+			}

+			else {

+				enable = !selection.isEmpty();

+			}

+		}

+		return enable;

+	}

+

+	public IDocument getDocument() {

+		return getTextEditor().getDocumentProvider().getDocument(fEditorPart.getEditorInput());

+	}

+

+	public IStatus saveAdditionalContent(IPath path) {

+		return Status.OK_STATUS;

+	}

+

+

+	public ISnippetInsertion getSnippetInsertion() {

+		return new DefaultSnippetInsertion();

+	}

+

+

+	public String getId() {

+		return TextSnippetProvider.class.getName();

+	}

+

+

+	public ISnippetEditor getSnippetEditor() {

+		return new VariableItemEditor();

+	}

+

+}