001: /*******************************************************************************
002: * Copyright (c) 2005, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.pde.internal.ui.refactoring;
011:
012: import java.util.ArrayList;
013:
014: import org.eclipse.core.filebuffers.FileBuffers;
015: import org.eclipse.core.filebuffers.ITextFileBufferManager;
016: import org.eclipse.core.filebuffers.LocationKind;
017: import org.eclipse.core.resources.IFile;
018: import org.eclipse.core.runtime.CoreException;
019: import org.eclipse.core.runtime.IProgressMonitor;
020: import org.eclipse.jdt.core.IJavaElement;
021: import org.eclipse.jdt.core.IPackageFragment;
022: import org.eclipse.jdt.core.IType;
023: import org.eclipse.jface.text.BadLocationException;
024: import org.eclipse.jface.text.IDocument;
025: import org.eclipse.ltk.core.refactoring.Change;
026: import org.eclipse.ltk.core.refactoring.TextFileChange;
027: import org.eclipse.osgi.util.ManifestElement;
028: import org.eclipse.pde.internal.core.ICoreConstants;
029: import org.eclipse.pde.internal.core.bundle.BundlePluginBase;
030: import org.eclipse.pde.internal.core.ibundle.IBundle;
031: import org.eclipse.pde.internal.core.ibundle.IManifestHeader;
032: import org.eclipse.pde.internal.core.text.bundle.BasePackageHeader;
033: import org.eclipse.pde.internal.core.text.bundle.Bundle;
034: import org.eclipse.pde.internal.core.text.bundle.BundleModel;
035: import org.eclipse.pde.internal.core.text.bundle.BundleTextChangeListener;
036: import org.eclipse.pde.internal.core.text.bundle.ExportPackageHeader;
037: import org.eclipse.pde.internal.core.text.bundle.ExportPackageObject;
038: import org.eclipse.pde.internal.core.text.bundle.PDEManifestElement;
039: import org.eclipse.pde.internal.core.text.bundle.PackageObject;
040: import org.eclipse.pde.internal.ui.util.PDEModelUtility;
041: import org.eclipse.text.edits.MalformedTreeException;
042: import org.eclipse.text.edits.MultiTextEdit;
043: import org.eclipse.text.edits.TextEdit;
044: import org.osgi.framework.Constants;
045:
046: public class BundleManifestChange {
047:
048: public static Change createMoveToPackageChange(IFile file,
049: MoveFromChange change, IProgressMonitor monitor)
050: throws CoreException {
051: try {
052: Bundle bundle = getBundle(file, monitor);
053: if (bundle == null)
054: return null;
055:
056: BundleModel model = (BundleModel) bundle.getModel();
057: BundleTextChangeListener listener = new BundleTextChangeListener(
058: model.getDocument());
059: bundle.getModel().addModelChangedListener(listener);
060: addPackage(bundle, change);
061: return createChange(listener, file);
062: } catch (CoreException e) {
063: } catch (MalformedTreeException e) {
064: } catch (BadLocationException e) {
065: } finally {
066: FileBuffers.getTextFileBufferManager()
067: .disconnect(file.getFullPath(),
068: LocationKind.NORMALIZE, monitor);
069: }
070: return null;
071: }
072:
073: public static MoveFromChange createMovePackageChange(IFile file,
074: Object[] elements, IProgressMonitor monitor)
075: throws CoreException {
076: try {
077: Bundle bundle = getBundle(file, monitor);
078: if (bundle == null)
079: return null;
080:
081: BundleModel model = (BundleModel) bundle.getModel();
082: BundleTextChangeListener listener = new BundleTextChangeListener(
083: model.getDocument());
084: bundle.getModel().addModelChangedListener(listener);
085:
086: ArrayList list = new ArrayList();
087: for (int i = 0; i < elements.length; i++) {
088: if (elements[i] instanceof IJavaElement) {
089: String packageName = ((IJavaElement) elements[i])
090: .getElementName();
091: PDEManifestElement export = removePackage(
092: bundle
093: .getManifestHeader(Constants.EXPORT_PACKAGE),
094: packageName);
095: if (export != null)
096: list.add(export);
097: }
098: }
099:
100: TextEdit[] operations = listener.getTextOperations();
101: if (operations.length > 0) {
102: MoveFromChange change = new MoveFromChange("", file); //$NON-NLS-1$
103: MultiTextEdit edit = new MultiTextEdit();
104: edit.addChildren(operations);
105: change.setEdit(edit);
106: PDEModelUtility.setChangeTextType(change, file);
107: if (list.size() > 0)
108: change
109: .setMovedElements((PDEManifestElement[]) list
110: .toArray(new PDEManifestElement[list
111: .size()]));
112: return change;
113: }
114: } catch (CoreException e) {
115: } catch (MalformedTreeException e) {
116: } catch (BadLocationException e) {
117: } finally {
118: FileBuffers.getTextFileBufferManager()
119: .disconnect(file.getFullPath(),
120: LocationKind.NORMALIZE, monitor);
121: }
122: return null;
123: }
124:
125: public static Change createRenameChange(IFile file,
126: Object[] elements, String[] newTexts,
127: IProgressMonitor monitor) throws CoreException {
128: try {
129: Bundle bundle = getBundle(file, monitor);
130: if (bundle == null)
131: return null;
132:
133: BundleModel model = (BundleModel) bundle.getModel();
134: BundleTextChangeListener listener = new BundleTextChangeListener(
135: model.getDocument());
136: bundle.getModel().addModelChangedListener(listener);
137: for (int i = 0; i < elements.length; i++) {
138: Object element = elements[i];
139: String newText = newTexts[i];
140: if (element instanceof IType) {
141: String oldText = ((IType) element)
142: .getFullyQualifiedName('$');
143: resetHeaderValue(
144: bundle
145: .getManifestHeader(Constants.BUNDLE_ACTIVATOR),
146: false, oldText, newText);
147: resetHeaderValue(
148: bundle
149: .getManifestHeader(ICoreConstants.PLUGIN_CLASS),
150: false, oldText, newText);
151: } else if (element instanceof IPackageFragment) {
152: String oldText = ((IPackageFragment) element)
153: .getElementName();
154: resetHeaderValue(
155: bundle
156: .getManifestHeader(Constants.BUNDLE_ACTIVATOR),
157: true, oldText, newText);
158: resetHeaderValue(
159: bundle
160: .getManifestHeader(ICoreConstants.PLUGIN_CLASS),
161: true, oldText, newText);
162: renamePackage(
163: bundle
164: .getManifestHeader(Constants.EXPORT_PACKAGE),
165: oldText, newText);
166: renamePackage(
167: bundle
168: .getManifestHeader(ICoreConstants.PROVIDE_PACKAGE),
169: oldText, newText);
170: renamePackage(
171: bundle
172: .getManifestHeader(Constants.IMPORT_PACKAGE),
173: oldText, newText);
174: }
175: }
176: return createChange(listener, file);
177: } catch (CoreException e) {
178: } catch (MalformedTreeException e) {
179: } catch (BadLocationException e) {
180: } finally {
181: FileBuffers.getTextFileBufferManager()
182: .disconnect(file.getFullPath(),
183: LocationKind.NORMALIZE, monitor);
184: }
185: return null;
186: }
187:
188: private static Change createChange(
189: BundleTextChangeListener listener, IFile file) {
190: TextEdit[] operations = listener.getTextOperations();
191: if (operations.length > 0) {
192: TextFileChange change = new TextFileChange("", file); //$NON-NLS-1$
193: MultiTextEdit edit = new MultiTextEdit();
194: edit.addChildren(operations);
195: change.setEdit(edit);
196: PDEModelUtility.setChangeTextType(change, file);
197: return change;
198: }
199: return null;
200: }
201:
202: private static void resetHeaderValue(IManifestHeader header,
203: boolean isPackage, String oldText, String newText) {
204: if (header != null) {
205: String value = header.getValue();
206: if (oldText.equals(value)
207: || isGoodMatch(value, oldText, isPackage)) {
208: StringBuffer buffer = new StringBuffer(newText);
209: buffer.append(value.substring(oldText.length()));
210: header.setValue(buffer.toString());
211: }
212: }
213: }
214:
215: private static boolean isGoodMatch(String value, String oldName,
216: boolean isPackage) {
217: if (value == null || value.length() <= oldName.length())
218: return false;
219: boolean goodLengthMatch = isPackage ? value.lastIndexOf('.') <= oldName
220: .length()
221: : value.charAt(oldName.length()) == '$';
222: return value.startsWith(oldName) && goodLengthMatch;
223: }
224:
225: private static void renamePackage(IManifestHeader header,
226: String oldName, String newName) {
227: if (header instanceof BasePackageHeader) {
228: BasePackageHeader bHeader = (BasePackageHeader) header;
229: bHeader.renamePackage(oldName, newName);
230: }
231: }
232:
233: private static PDEManifestElement removePackage(
234: IManifestHeader header, String name) {
235: PDEManifestElement result = null;
236: if (header instanceof BasePackageHeader) {
237: BasePackageHeader bHeader = (BasePackageHeader) header;
238: result = ((PackageObject) bHeader.removePackage(name));
239: }
240: return result;
241: }
242:
243: private static void addPackage(Bundle bundle, MoveFromChange change) {
244: String headerName = getExportedPackageHeader(bundle);
245: ExportPackageHeader header = (ExportPackageHeader) bundle
246: .getManifestHeader(headerName);
247: ManifestElement[] elements = change.getMovedElements();
248: for (int i = 0; i < elements.length; i++) {
249: if (header != null) {
250: if (!header.hasPackage(change.getPackageName(i))) {
251: header.addPackage(new ExportPackageObject(header,
252: elements[i], getVersionAttribute(header
253: .getBundle())));
254: }
255: } else {
256: bundle.setHeader(headerName, change.getMovedText(i));
257: header = (ExportPackageHeader) bundle
258: .getManifestHeader(headerName);
259: }
260: }
261: }
262:
263: private static String getVersionAttribute(IBundle bundle) {
264: int manifestVersion = BundlePluginBase
265: .getBundleManifestVersion(bundle);
266: return (manifestVersion < 2) ? ICoreConstants.PACKAGE_SPECIFICATION_VERSION
267: : Constants.VERSION_ATTRIBUTE;
268: }
269:
270: private static String getExportedPackageHeader(IBundle bundle) {
271: int manifestVersion = BundlePluginBase
272: .getBundleManifestVersion(bundle);
273: return (manifestVersion < 2) ? ICoreConstants.PROVIDE_PACKAGE
274: : Constants.EXPORT_PACKAGE;
275: }
276:
277: public static Bundle getBundle(IFile file, IProgressMonitor monitor)
278: throws CoreException, MalformedTreeException,
279: BadLocationException {
280: ITextFileBufferManager manager = FileBuffers
281: .getTextFileBufferManager();
282: manager.connect(file.getFullPath(), LocationKind.NORMALIZE,
283: monitor);
284:
285: IDocument document = manager.getTextFileBuffer(
286: file.getFullPath(), LocationKind.NORMALIZE)
287: .getDocument();
288: BundleModel model = new BundleModel(document, false);
289: model.load();
290: return model.isLoaded() ? (Bundle) model.getBundle() : null;
291: }
292:
293: }
|