add support for exported package refactoring (FELIX-2481)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@966522 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/sigil/eclipse/ui/plugin.properties b/sigil/eclipse/ui/plugin.properties
index 3e6d20d..532db80 100644
--- a/sigil/eclipse/ui/plugin.properties
+++ b/sigil/eclipse/ui/plugin.properties
@@ -2,4 +2,5 @@
newtonRepoPrefs=Newton Repository
librariesPrefsPage=OSGi Libraries
commandConvertProject=Convert Project To Sigil Project
-commandRefreshClasspath=Refresh bundle classpath
\ No newline at end of file
+commandRefreshClasspath=Refresh bundle classpath
+RenamePackageParticipant.name=Rename Package Participant
\ No newline at end of file
diff --git a/sigil/eclipse/ui/plugin.xml b/sigil/eclipse/ui/plugin.xml
index f0cf1a8..1a76b9f 100644
--- a/sigil/eclipse/ui/plugin.xml
+++ b/sigil/eclipse/ui/plugin.xml
@@ -264,5 +264,22 @@
</with>
</activeWhen>
</handler>
- </extension>
+ </extension>
+ <extension point="org.eclipse.ltk.core.refactoring.renameParticipants">
+ <renameParticipant
+ id="org.apache.felix.sigil.renamePackageParticipant"
+ name="%RenamePackageParticipant.name"
+ class="org.apache.felix.sigil.ui.eclipse.refactor.RenamePackageParticipant">
+ <enablement>
+ <with variable="affectedNatures">
+ <iterate operator="or">
+ <equals value="org.apache.felix.sigil.sigilnature"/>
+ </iterate>
+ </with>
+ <with variable="element">
+ <instanceof value="org.eclipse.jdt.core.IPackageFragment"/>
+ </with>
+ </enablement>
+ </renameParticipant>
+ </extension>
</plugin>
diff --git a/sigil/eclipse/ui/sigil.properties b/sigil/eclipse/ui/sigil.properties
index acfc5b8..bcce8bd 100644
--- a/sigil/eclipse/ui/sigil.properties
+++ b/sigil/eclipse/ui/sigil.properties
@@ -9,9 +9,9 @@
org.apache.felix.sigil.eclipse.ui, \
-resources: \
+ icons=icons, \
plugin.properties, \
plugin.xml, \
- icons=icons,\
schema, \
schema/org.apache.felix.sigil.ui.repositorywizard.exsd, \
@@ -48,6 +48,7 @@
org.eclipse.core.commands, \
org.eclipse.core.commands.common, \
org.eclipse.core.resources, \
+ org.eclipse.core.resources.mapping, \
org.eclipse.debug.core, \
org.eclipse.debug.ui, \
org.eclipse.draw2d, \
@@ -75,6 +76,7 @@
org.eclipse.jface.window, \
org.eclipse.jface.wizard, \
org.eclipse.ltk.core.refactoring, \
+ org.eclipse.ltk.core.refactoring.participants, \
org.eclipse.ui.editors.text, \
org.eclipse.ui.forms, \
org.eclipse.ui.forms.editor, \
diff --git a/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/refactor/ExportPackageChange.java b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/refactor/ExportPackageChange.java
new file mode 100644
index 0000000..96b8c2e
--- /dev/null
+++ b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/refactor/ExportPackageChange.java
@@ -0,0 +1,71 @@
+package org.apache.felix.sigil.ui.eclipse.refactor;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+import org.apache.felix.sigil.eclipse.SigilCore;
+import org.apache.felix.sigil.eclipse.model.project.ISigilProjectModel;
+import org.apache.felix.sigil.model.ModelElementFactory;
+import org.apache.felix.sigil.model.osgi.IBundleModelElement;
+import org.apache.felix.sigil.model.osgi.IPackageExport;
+import org.apache.felix.sigil.model.osgi.IPackageImport;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.ltk.core.refactoring.Change;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+
+public class ExportPackageChange extends Change
+{
+
+ private final ISigilProjectModel sigil;
+ private final IPackageExport oldExport;
+ private final IPackageExport newExport;
+
+ public ExportPackageChange(ISigilProjectModel sigil, IPackageExport oldExport, IPackageExport newExport)
+ {
+ this.sigil = sigil;
+ this.oldExport = oldExport;
+ this.newExport = newExport;
+ }
+
+ @Override
+ public Object getModifiedElement()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getName()
+ {
+ return "Export package update";
+ }
+
+ @Override
+ public void initializeValidationData(IProgressMonitor progress)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public RefactoringStatus isValid(IProgressMonitor progress) throws CoreException,
+ OperationCanceledException
+ {
+ // TODO check project is synchronized
+ return new RefactoringStatus();
+ }
+
+ @Override
+ public Change perform(IProgressMonitor progress) throws CoreException
+ {
+ sigil.getBundle().getBundleInfo().removeChild(oldExport);
+ sigil.getBundle().getBundleInfo().addExport(newExport);
+
+ sigil.save(progress);
+
+ return new ExportPackageChange(sigil, newExport, oldExport);
+ }
+
+}
diff --git a/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/refactor/ImportPackageChange.java b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/refactor/ImportPackageChange.java
new file mode 100644
index 0000000..289a2ac
--- /dev/null
+++ b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/refactor/ImportPackageChange.java
@@ -0,0 +1,64 @@
+package org.apache.felix.sigil.ui.eclipse.refactor;
+
+import org.apache.felix.sigil.eclipse.model.project.ISigilProjectModel;
+import org.apache.felix.sigil.model.osgi.IPackageImport;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.ltk.core.refactoring.Change;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+
+public class ImportPackageChange extends Change
+{
+
+ private final ISigilProjectModel sigil;
+ private final IPackageImport oldImport;
+ private final IPackageImport newImport;
+
+ public ImportPackageChange(ISigilProjectModel sigil, IPackageImport oldImport, IPackageImport newImport)
+ {
+ this.sigil = sigil;
+ this.oldImport = oldImport;
+ this.newImport = newImport;
+ }
+
+ @Override
+ public Object getModifiedElement()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getName()
+ {
+ return "Import package update";
+ }
+
+ @Override
+ public void initializeValidationData(IProgressMonitor arg0)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public RefactoringStatus isValid(IProgressMonitor progress) throws CoreException,
+ OperationCanceledException
+ {
+ // TODO check project is synchronized
+ return new RefactoringStatus();
+ }
+
+ @Override
+ public Change perform(IProgressMonitor progress) throws CoreException
+ {
+ sigil.getBundle().getBundleInfo().removeImport(oldImport);
+ sigil.getBundle().getBundleInfo().addImport(newImport);
+
+ sigil.save(progress);
+
+ return new ImportPackageChange(sigil, newImport, oldImport);
+ }
+
+}
diff --git a/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/refactor/RenamePackageParticipant.java b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/refactor/RenamePackageParticipant.java
new file mode 100644
index 0000000..43ff150
--- /dev/null
+++ b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/refactor/RenamePackageParticipant.java
@@ -0,0 +1,162 @@
+package org.apache.felix.sigil.ui.eclipse.refactor;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.felix.sigil.eclipse.SigilCore;
+import org.apache.felix.sigil.eclipse.model.project.ISigilProjectModel;
+import org.apache.felix.sigil.model.IModelElement;
+import org.apache.felix.sigil.model.IModelWalker;
+import org.apache.felix.sigil.model.ModelElementFactory;
+import org.apache.felix.sigil.model.osgi.IBundleModelElement;
+import org.apache.felix.sigil.model.osgi.IPackageExport;
+import org.apache.felix.sigil.model.osgi.IPackageImport;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.mapping.IResourceChangeDescriptionFactory;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.ltk.core.refactoring.Change;
+import org.eclipse.ltk.core.refactoring.CompositeChange;
+import org.eclipse.ltk.core.refactoring.NullChange;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
+import org.eclipse.ltk.core.refactoring.participants.RenameParticipant;
+import org.eclipse.ltk.core.refactoring.participants.ResourceChangeChecker;
+
+public class RenamePackageParticipant extends RenameParticipant
+{
+ private IPackageFragment packageFragment;
+ private List<Change> changes = new LinkedList<Change>();
+
+ @Override
+ public RefactoringStatus checkConditions(IProgressMonitor pm,
+ CheckConditionsContext context) throws OperationCanceledException
+ {
+ RefactoringStatus status = new RefactoringStatus();
+
+ try
+ {
+ ISigilProjectModel sigil = SigilCore.create(packageFragment.getJavaProject().getProject());
+ final String packageName = packageFragment.getElementName();
+
+ SigilCore.log("Rename checkConditions " + packageName);
+
+ final IPackageExport[] found = new IPackageExport[1];
+ sigil.visit(new IModelWalker()
+ {
+ public boolean visit(IModelElement element)
+ {
+ if (element instanceof IPackageExport) {
+ IPackageExport pe = (IPackageExport) element;
+ if (pe.getPackageName().equals(packageName)) {
+ found[0] = pe;
+ }
+ }
+ return found[0] == null;
+ }
+ });
+
+ if (found[0] != null) {
+ // record change to check if out of sync...
+ touch(context, sigil);
+
+ status = RefactoringStatus.createWarningStatus("Package " + packageName + " is exported. Renaming this package may effect bundles outside of this workspace");
+ SigilCore.log("Export Package " + packageName + " renamed to " + getArguments().getNewName());
+
+ IPackageExport oldExport = found[0];
+ IPackageExport newExport = ModelElementFactory.getInstance().newModelElement(IPackageExport.class);
+ newExport.setPackageName(getArguments().getNewName());
+ newExport.setVersion(oldExport.getVersion());
+
+ changes.add(new ExportPackageChange(sigil, oldExport, newExport));
+
+ for ( ISigilProjectModel other : SigilCore.getRoot().getProjects() ) {
+ if ( !sigil.equals(other) ) {
+ // record change to check if out of sync...
+ touch(context, other);
+ }
+ changes.add(createImportChange(status, other, oldExport, newExport));
+ }
+ }
+ }
+ catch (CoreException e)
+ {
+ SigilCore.warn("Failed to create export package refactor", e);
+ throw new OperationCanceledException("Failed to create export package refactor");
+ }
+
+ return status;
+ }
+
+ @Override
+ public Change createChange(IProgressMonitor pm) throws CoreException,
+ OperationCanceledException
+ {
+ if (changes.isEmpty()) {
+ return new NullChange();
+ }
+ else
+ {
+ CompositeChange ret = new CompositeChange("Export-Package update");
+
+ ret.addAll(changes.toArray(new Change[changes.size()]));
+
+ return ret;
+ }
+ }
+
+ @Override
+ public String getName()
+ {
+ return "Sigil export package rename participant";
+ }
+
+ @Override
+ protected boolean initialize(Object element)
+ {
+ this.packageFragment = (IPackageFragment) element;
+ return true;
+ }
+
+ private static final void touch(CheckConditionsContext context, ISigilProjectModel sigil)
+ {
+ ResourceChangeChecker checker = (ResourceChangeChecker) context.getChecker(ResourceChangeChecker.class);
+ IResourceChangeDescriptionFactory deltaFactory= checker.getDeltaFactory();
+ IFile file = sigil.getProject().getFile(SigilCore.SIGIL_PROJECT_FILE);
+ deltaFactory.change(file);
+ }
+
+ private Change createImportChange(RefactoringStatus status, ISigilProjectModel sigil, IPackageExport oldExport, IPackageExport newExport)
+ {
+ IBundleModelElement info = sigil.getBundle().getBundleInfo();
+ Collection<IPackageImport> imports = info.getImports();
+
+ for (IPackageImport oldImport : imports) {
+ if (oldImport.accepts(oldExport)) {
+ IPackageImport newImport = ModelElementFactory.getInstance().newModelElement(IPackageImport.class);
+
+ newImport.setPackageName(newExport.getPackageName());
+ newImport.setVersions(oldImport.getVersions());
+
+ status.addInfo(buildImportChangeMsg(sigil, oldImport, newImport));
+
+ return new ImportPackageChange(sigil, oldImport, newImport);
+ }
+ }
+
+ // ok no change
+ return new NullChange();
+ }
+
+ private static final String buildImportChangeMsg(ISigilProjectModel sigil,
+ IPackageImport oldImport, IPackageImport newImport)
+ {
+ return "Updating import " + oldImport.getPackageName() + " version " + oldImport.getVersions() +
+ " to " + newImport.getPackageName() + " version " + newImport.getVersions() +
+ " in project " + sigil.getSymbolicName() + " version " + sigil.getVersion();
+ }
+
+}