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.compare;
011:
012: import java.io.BufferedReader;
013: import java.io.IOException;
014: import java.io.InputStream;
015: import java.io.InputStreamReader;
016:
017: import org.eclipse.compare.CompareUI;
018: import org.eclipse.compare.IEditableContent;
019: import org.eclipse.compare.IEncodedStreamContentAccessor;
020: import org.eclipse.compare.ISharedDocumentAdapter;
021: import org.eclipse.compare.IStreamContentAccessor;
022: import org.eclipse.compare.ITypedElement;
023: import org.eclipse.compare.structuremergeviewer.DocumentRangeNode;
024: import org.eclipse.compare.structuremergeviewer.IStructureComparator;
025: import org.eclipse.compare.structuremergeviewer.StructureCreator;
026: import org.eclipse.compare.structuremergeviewer.StructureRootNode;
027: import org.eclipse.core.resources.ResourcesPlugin;
028: import org.eclipse.core.runtime.CoreException;
029: import org.eclipse.core.runtime.IProgressMonitor;
030: import org.eclipse.core.runtime.IStatus;
031: import org.eclipse.core.runtime.NullProgressMonitor;
032: import org.eclipse.core.runtime.OperationCanceledException;
033: import org.eclipse.core.runtime.Status;
034: import org.eclipse.core.runtime.SubProgressMonitor;
035: import org.eclipse.jface.text.BadLocationException;
036: import org.eclipse.jface.text.IDocument;
037: import org.eclipse.jface.text.IDocumentPartitioner;
038: import org.eclipse.jface.text.rules.FastPartitioner;
039: import org.eclipse.pde.internal.ui.PDEPlugin;
040: import org.eclipse.pde.internal.ui.PDEUIMessages;
041: import org.eclipse.pde.internal.ui.editor.text.ManifestPartitionScanner;
042: import org.eclipse.swt.graphics.Image;
043:
044: public class ManifestStructureCreator extends StructureCreator {
045:
046: static class ManifestNode extends DocumentRangeNode implements
047: ITypedElement {
048:
049: public ManifestNode(DocumentRangeNode parent, int type,
050: String id, IDocument doc, int start, int length) {
051: super (parent, type, id, doc, start, length);
052: if (parent != null) {
053: parent.addChild(ManifestNode.this );
054: }
055: }
056:
057: public String getName() {
058: return this .getId();
059: }
060:
061: public String getType() {
062: return "MF2"; //$NON-NLS-1$
063: }
064:
065: public Image getImage() {
066: return CompareUI.getImage(getType());
067: }
068: }
069:
070: public String getName() {
071: return PDEUIMessages.ManifestStructureCreator_name;
072: }
073:
074: public IStructureComparator locate(Object path, Object input) {
075: return null;
076: }
077:
078: public String getContents(Object node, boolean ignoreWhitespace) {
079: if (node instanceof IStreamContentAccessor) {
080: IStreamContentAccessor sca = (IStreamContentAccessor) node;
081: try {
082: return readString(sca);
083: } catch (CoreException ex) {
084: }
085: }
086: return null;
087: }
088:
089: private void parseManifest(DocumentRangeNode root, IDocument doc,
090: IProgressMonitor monitor) throws IOException {
091: int lineStart = 0;
092: int[] args = new int[2];
093: args[0] = 0; // here we return the line number
094: args[1] = 0; // and here the offset of the first character of the line
095:
096: try {
097: String id = "Manifest"; //$NON-NLS-1$
098: ManifestNode parent = new ManifestNode(root, 0, id, doc, 0,
099: doc.getLength());
100: monitor = beginWork(monitor);
101: StringBuffer headerBuffer = new StringBuffer();
102: int headerStart = 0;
103: while (true) {
104: lineStart = args[1]; // start of current line
105: String line = readLine(args, doc);
106: if (line == null)
107: return;
108:
109: if (line.length() <= 0) {
110: saveNode(parent, doc, headerBuffer.toString(),
111: headerStart); // empty line, save buffer to node
112: continue;
113: }
114: if (line.charAt(0) == ' ') {
115: if (headerBuffer.length() > 0)
116: headerBuffer.append(line);
117: continue;
118: }
119:
120: // save old buffer and start loading again
121: saveNode(parent, doc, headerBuffer.toString(),
122: headerStart);
123:
124: headerStart = lineStart;
125: headerBuffer.replace(0, headerBuffer.length(), line);
126: worked(monitor);
127: }
128: } finally {
129: monitor.done();
130: }
131: }
132:
133: private void worked(IProgressMonitor monitor) {
134: if (monitor.isCanceled())
135: throw new OperationCanceledException();
136: monitor.worked(1);
137: }
138:
139: private IProgressMonitor beginWork(IProgressMonitor monitor) {
140: if (monitor == null)
141: return new NullProgressMonitor();
142: return new SubProgressMonitor(monitor, IProgressMonitor.UNKNOWN);
143: }
144:
145: private void saveNode(DocumentRangeNode root, IDocument doc,
146: String header, int start) {
147: if (header.length() > 0)
148: new ManifestNode(root, 1, extractKey(header), doc, start,
149: header.length());
150: }
151:
152: private String extractKey(String headerBuffer) {
153: int assign = headerBuffer.indexOf(":"); //$NON-NLS-1$
154: if (assign != -1)
155: return headerBuffer.substring(0, assign);
156: return headerBuffer;
157: }
158:
159: private String readLine(int[] args, IDocument doc) {
160: int line = args[0]++;
161: try {
162: if (line >= doc.getNumberOfLines())
163: return null;
164: int start = doc.getLineOffset(line);
165: int length = doc.getLineLength(line);
166: try {
167: args[1] = doc.getLineOffset(line + 1);
168: } catch (BadLocationException ex) {
169: args[1] = doc.getLength();
170: }
171:
172: return doc.get(start, length);
173: } catch (BadLocationException ex) {
174: }
175: return null;
176: }
177:
178: private static String readString(InputStream is, String encoding) {
179: if (is == null)
180: return null;
181: BufferedReader reader = null;
182: try {
183: StringBuffer buffer = new StringBuffer();
184: char[] part = new char[2048];
185: int read = 0;
186: reader = new BufferedReader(new InputStreamReader(is,
187: encoding));
188:
189: while ((read = reader.read(part)) != -1)
190: buffer.append(part, 0, read);
191:
192: return buffer.toString();
193:
194: } catch (IOException ex) {
195: // NeedWork
196: } finally {
197: if (reader != null) {
198: try {
199: reader.close();
200: } catch (IOException ex) {
201: // silently ignored
202: }
203: }
204: }
205: return null;
206: }
207:
208: public static String readString(IStreamContentAccessor sa)
209: throws CoreException {
210: InputStream is = sa.getContents();
211: if (is != null) {
212: String encoding = null;
213: if (sa instanceof IEncodedStreamContentAccessor) {
214: try {
215: encoding = ((IEncodedStreamContentAccessor) sa)
216: .getCharset();
217: } catch (Exception e) {
218: }
219: }
220: if (encoding == null)
221: encoding = ResourcesPlugin.getEncoding();
222: return readString(is, encoding);
223: }
224: return null;
225: }
226:
227: protected IDocumentPartitioner getDocumentPartitioner() {
228: return new FastPartitioner(new ManifestPartitionScanner(),
229: ManifestPartitionScanner.PARTITIONS);
230: }
231:
232: protected String getDocumentPartitioning() {
233: return ManifestPartitionScanner.MANIFEST_FILE_PARTITIONING;
234: }
235:
236: protected IStructureComparator createStructureComparator(
237: Object input, IDocument document,
238: ISharedDocumentAdapter adapter, IProgressMonitor monitor)
239: throws CoreException {
240:
241: final boolean isEditable;
242: if (input instanceof IEditableContent)
243: isEditable = ((IEditableContent) input).isEditable();
244: else
245: isEditable = false;
246:
247: DocumentRangeNode rootNode = new StructureRootNode(document,
248: input, this , adapter) {
249: public boolean isEditable() {
250: return isEditable;
251: }
252: };
253: try {
254: parseManifest(rootNode, document, monitor);
255: } catch (IOException ex) {
256: if (adapter != null)
257: adapter.disconnect(input);
258: throw new CoreException(
259: new Status(
260: IStatus.ERROR,
261: PDEPlugin.getPluginId(),
262: 0,
263: PDEUIMessages.ManifestStructureCreator_errorMessage,
264: ex));
265: }
266:
267: return rootNode;
268: }
269:
270: }
|