View | Details | Raw Unified | Return to bug 182337 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/core/internal/content/ContentTypeCatalog.java (-4 / +48 lines)
Lines 16-21 Link Here
16
import org.eclipse.core.runtime.content.*;
16
import org.eclipse.core.runtime.content.*;
17
import org.eclipse.core.runtime.content.IContentTypeManager.ISelectionPolicy;
17
import org.eclipse.core.runtime.content.IContentTypeManager.ISelectionPolicy;
18
import org.eclipse.core.runtime.preferences.IScopeContext;
18
import org.eclipse.core.runtime.preferences.IScopeContext;
19
import org.eclipse.osgi.util.NLS;
19
20
20
public final class ContentTypeCatalog {
21
public final class ContentTypeCatalog {
21
	private static final IContentType[] NO_CONTENT_TYPES = new IContentType[0];
22
	private static final IContentType[] NO_CONTENT_TYPES = new IContentType[0];
Lines 177-183 Link Here
177
		existing.add(contentType);
178
		existing.add(contentType);
178
	}
179
	}
179
180
180
	private int collectMatchingByContents(int valid, IContentType[] subset, List destination, ILazySource contents) throws IOException {
181
	private int collectMatchingByContents(int valid, IContentType[] subset, List destination, ILazySource contents, Map properties) throws IOException {
181
		for (int i = 0; i < subset.length; i++) {
182
		for (int i = 0; i < subset.length; i++) {
182
			ContentType current = (ContentType) subset[i];
183
			ContentType current = (ContentType) subset[i];
183
			IContentDescriber describer = current.getDescriber();
184
			IContentDescriber describer = current.getDescriber();
Lines 186-192 Link Here
186
				if (contents.isText() && !(describer instanceof ITextContentDescriber))
187
				if (contents.isText() && !(describer instanceof ITextContentDescriber))
187
					// for text streams we skip content types that do not provide text-based content describers
188
					// for text streams we skip content types that do not provide text-based content describers
188
					continue;
189
					continue;
189
				status = current.describe(describer, contents, null);
190
				status = describe(current, contents, null, properties);
190
				if (status == IContentDescriber.INVALID)
191
				if (status == IContentDescriber.INVALID)
191
					continue;
192
					continue;
192
			}
193
			}
Lines 198-203 Link Here
198
		return valid;
199
		return valid;
199
	}
200
	}
200
201
202
	int describe(ContentType type, ILazySource contents, ContentDescription description, Map properties) throws IOException {
203
		IContentDescriber describer = type.getDescriber();
204
		try {
205
			if (contents.isText()) {
206
				if (describer instanceof XMLRootElementContentDescriber2) {
207
					return ((XMLRootElementContentDescriber2) describer).describe((Reader) contents, description, properties);
208
				} else if (describer instanceof XMLRootElementContentDescriber) {
209
					return ((XMLRootElementContentDescriber) describer).describe((Reader) contents, description, properties);
210
				}
211
				return ((ITextContentDescriber) describer).describe((Reader) contents, description);
212
			} else {
213
				if (describer instanceof XMLRootElementContentDescriber2) {
214
					return ((XMLRootElementContentDescriber2) describer).describe((InputStream) contents, description, properties);
215
				} else if (describer instanceof XMLRootElementContentDescriber) {
216
					return ((XMLRootElementContentDescriber) describer).describe((InputStream) contents, description, properties);
217
				}
218
				return (describer).describe((InputStream) contents, description);
219
			}
220
		} catch (RuntimeException re) {
221
			// describer seems to be buggy. just disable it (logging the reason)
222
			type.invalidateDescriber(re);
223
		} catch (Error e) {
224
			// describer got some serious problem. disable it (logging the reason) and throw the error again 
225
			type.invalidateDescriber(e);
226
			throw e;
227
		} catch (LowLevelIOException llioe) {
228
			// throw the actual exception
229
			throw llioe.getActualException();
230
		} catch (IOException ioe) {
231
			// bugs 67841/ 62443  - non-low level IOException should be "ignored"
232
			if (ContentTypeManager.DEBUGGING) {
233
				String message = NLS.bind(ContentMessages.content_errorReadingContents, type.getId());
234
				ContentType.log(message, ioe);
235
			}
236
			// we don't know what the describer would say if the exception didn't occur
237
			return IContentDescriber.INDETERMINATE;
238
		} finally {
239
			contents.rewind();
240
		}
241
		return IContentDescriber.INVALID;
242
	}
243
201
	synchronized void dissociate(ContentType contentType, String text, int type) {
244
	synchronized void dissociate(ContentType contentType, String text, int type) {
202
		Map fileSpecMap = ((type & IContentType.FILE_NAME_SPEC) != 0) ? fileNames : fileExtensions;
245
		Map fileSpecMap = ((type & IContentType.FILE_NAME_SPEC) != 0) ? fileNames : fileExtensions;
203
		String mappingKey = FileSpec.getMappingKeyFor(text);
246
		String mappingKey = FileSpec.getMappingKeyFor(text);
Lines 353-362 Link Here
353
	}
396
	}
354
397
355
	private IContentType[] internalFindContentTypesFor(ILazySource buffer, IContentType[][] subset, Comparator validPolicy, Comparator indeterminatePolicy) throws IOException {
398
	private IContentType[] internalFindContentTypesFor(ILazySource buffer, IContentType[][] subset, Comparator validPolicy, Comparator indeterminatePolicy) throws IOException {
399
		Map properties = new HashMap();
356
		final List appropriate = new ArrayList(5);
400
		final List appropriate = new ArrayList(5);
357
		final int validFullName = collectMatchingByContents(0, subset[0], appropriate, buffer);
401
		final int validFullName = collectMatchingByContents(0, subset[0], appropriate, buffer, properties);
358
		final int appropriateFullName = appropriate.size();
402
		final int appropriateFullName = appropriate.size();
359
		final int validExtension = collectMatchingByContents(validFullName, subset[1], appropriate, buffer) - validFullName;
403
		final int validExtension = collectMatchingByContents(validFullName, subset[1], appropriate, buffer, properties) - validFullName;
360
		final int appropriateExtension = appropriate.size() - appropriateFullName;
404
		final int appropriateExtension = appropriate.size() - appropriateFullName;
361
		IContentType[] result = (IContentType[]) appropriate.toArray(new IContentType[appropriate.size()]);
405
		IContentType[] result = (IContentType[]) appropriate.toArray(new IContentType[appropriate.size()]);
362
		if (validFullName > 1)
406
		if (validFullName > 1)
(-)src/org/eclipse/core/internal/content/ContentType.java (-2 / +2 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2004, 2006 IBM Corporation and others.
2
 * Copyright (c) 2004, 2009 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 496-502 Link Here
496
		return false;
496
		return false;
497
	}
497
	}
498
498
499
	private IContentDescriber invalidateDescriber(Throwable reason) {
499
	public IContentDescriber invalidateDescriber(Throwable reason) {
500
		String message = NLS.bind(ContentMessages.content_invalidContentDescriber, id);
500
		String message = NLS.bind(ContentMessages.content_invalidContentDescriber, id);
501
		log(message, reason);
501
		log(message, reason);
502
		return (IContentDescriber) (describer = new InvalidDescriber());
502
		return (IContentDescriber) (describer = new InvalidDescriber());
(-)src/org/eclipse/core/runtime/content/XMLContentDescriber.java (-28 / +74 lines)
Lines 11-16 Link Here
11
package org.eclipse.core.runtime.content;
11
package org.eclipse.core.runtime.content;
12
12
13
import java.io.*;
13
import java.io.*;
14
import java.util.HashMap;
15
import java.util.Map;
14
import org.eclipse.core.internal.content.TextContentDescriber;
16
import org.eclipse.core.internal.content.TextContentDescriber;
15
import org.eclipse.core.internal.content.Util;
17
import org.eclipse.core.internal.content.Util;
16
import org.eclipse.core.runtime.QualifiedName;
18
import org.eclipse.core.runtime.QualifiedName;
Lines 49-55 Link Here
49
	private static final String XML_PREFIX = "<?xml "; //$NON-NLS-1$
51
	private static final String XML_PREFIX = "<?xml "; //$NON-NLS-1$
50
	private static final String XML_DECL_END = "?>"; //$NON-NLS-1$
52
	private static final String XML_DECL_END = "?>"; //$NON-NLS-1$
51
53
54
	private static final String BOM = "org.eclipse.core.runtime.content.XMLContentDescriber.bom"; //$NON-NLS-1$
55
	private static final String CHARSET = "org.eclipse.core.runtime.content.XMLContentDescriber.charset"; //$NON-NLS-1$
56
	private static final String FULL_XML_DECL = "org.eclipse.core.runtime.content.XMLContentDescriber.fullXMLDecl"; //$NON-NLS-1$
57
	private static final String RESULT = "org.eclipse.core.runtime.content.XMLContentDescriber.processed"; //$NON-NLS-1$
58
52
	public int describe(InputStream input, IContentDescription description) throws IOException {
59
	public int describe(InputStream input, IContentDescription description) throws IOException {
60
		return describe2(input, description, new HashMap());
61
	}
62
63
	int describe2(InputStream input, IContentDescription description, Map properties) throws IOException {
64
		if (!isProcessed(properties))
65
			fillContentProperties(input, description, properties);
66
		return internalDescribe(description, properties);
67
	}
68
69
	public int describe(Reader input, IContentDescription description) throws IOException {
70
		return describe2(input, description, new HashMap());
71
	}
72
73
	int describe2(Reader input, IContentDescription description, Map properties) throws IOException {
74
		if (!isProcessed(properties))
75
			fillContentProperties(readXMLDecl(input), description, properties);
76
		return internalDescribe(description, properties);
77
	}
78
79
	private boolean isProcessed(Map properties) {
80
		Boolean result = (Boolean) properties.get(RESULT);
81
		if (result != null)
82
			return true;
83
		return false;
84
	}
85
86
	private void fillContentProperties(InputStream input, IContentDescription description, Map properties) throws IOException {
53
		byte[] bom = Util.getByteOrderMark(input);
87
		byte[] bom = Util.getByteOrderMark(input);
54
		String xmlDeclEncoding = "UTF-8"; //$NON-NLS-1$
88
		String xmlDeclEncoding = "UTF-8"; //$NON-NLS-1$
55
		input.reset();
89
		input.reset();
Lines 60-123 Link Here
60
				xmlDeclEncoding = "UTF-16LE"; //$NON-NLS-1$
94
				xmlDeclEncoding = "UTF-16LE"; //$NON-NLS-1$
61
			// skip BOM to make comparison simpler
95
			// skip BOM to make comparison simpler
62
			input.skip(bom.length);
96
			input.skip(bom.length);
63
			// set the BOM in the description if requested
97
			properties.put(BOM, bom);
64
			if (description != null && description.isRequested(IContentDescription.BYTE_ORDER_MARK))
65
				description.setProperty(IContentDescription.BYTE_ORDER_MARK, bom);
66
		}
98
		}
67
		return internalDescribe(readXMLDecl(input, xmlDeclEncoding), description);
99
		fillContentProperties(readXMLDecl(input, xmlDeclEncoding), description, properties);
68
	}
69
	
70
	public int describe(Reader input, IContentDescription description) throws IOException {
71
		return internalDescribe(readXMLDecl(input), description);
72
	}
100
	}
73
	
101
74
	private int internalDescribe(String line, IContentDescription description) throws IOException {
102
	private void fillContentProperties(String line, IContentDescription description, Map properties) throws IOException {
75
		// end of stream
76
		if (line == null)
77
			return INDETERMINATE;
78
		// XMLDecl should be the first string (no blanks allowed)
103
		// XMLDecl should be the first string (no blanks allowed)
79
		if (!line.startsWith(XML_PREFIX))
104
		if (line != null && line.startsWith(XML_PREFIX))
105
			properties.put(FULL_XML_DECL, new Boolean(true));
106
		String charset = getCharset(line);
107
		if (charset != null)
108
			properties.put(CHARSET, charset);
109
		properties.put(RESULT, new Boolean(true));
110
	}
111
112
	private int internalDescribe(IContentDescription description, Map properties) {
113
		if (description != null) {
114
			byte[] bom = (byte[]) properties.get(BOM);
115
			if (bom != null && description.isRequested(IContentDescription.BYTE_ORDER_MARK))
116
				description.setProperty(IContentDescription.BYTE_ORDER_MARK, bom);
117
		}
118
		Boolean fullXMLDecl = (Boolean) properties.get(FULL_XML_DECL);
119
		if (fullXMLDecl == null || !fullXMLDecl.booleanValue())
80
			return INDETERMINATE;
120
			return INDETERMINATE;
81
		if (description == null)
121
		if (description == null)
82
			return VALID;
122
			return VALID;
83
		// describe charset if requested
123
		String charset = (String) properties.get(CHARSET);
84
		if ((description.isRequested(IContentDescription.CHARSET))) {
124
		if (description.isRequested(IContentDescription.CHARSET)) {
85
			String charset = getCharset(line);
86
			if (charset != null && !isCharsetValid(charset))
125
			if (charset != null && !isCharsetValid(charset))
87
				return INVALID;
126
				return INVALID;
88
			if (charset != null && !charset.equalsIgnoreCase("utf8") && !charset.equalsIgnoreCase("utf-8")) //$NON-NLS-1$ //$NON-NLS-2$
127
			if (isNonDefaultCharset(charset))
89
				// only set property if value is not default (avoid using a non-default content description)
90
				description.setProperty(IContentDescription.CHARSET, charset);
128
				description.setProperty(IContentDescription.CHARSET, charset);
91
		}
129
		}
92
		return VALID;
130
		return VALID;
93
	}
131
	}
94
	
132
133
	private boolean isNonDefaultCharset(String charset) {
134
		if (charset == null)
135
			return false;
136
		if (charset.equalsIgnoreCase("utf8") || charset.equalsIgnoreCase("utf-8")) //$NON-NLS-1$ //$NON-NLS-2$
137
			return false;
138
		return true;
139
	}
140
95
	private boolean isFullXMLDecl(String xmlDecl) {
141
	private boolean isFullXMLDecl(String xmlDecl) {
96
		return xmlDecl.endsWith(XML_DECL_END);
142
		return xmlDecl.endsWith(XML_DECL_END);
97
	}
143
	}
98
	
144
99
	private String readXMLDecl(InputStream input, String encoding) throws IOException {
145
	private String readXMLDecl(InputStream input, String encoding) throws IOException {
100
		byte[] xmlDeclEndBytes = XML_DECL_END.getBytes(encoding);
146
		byte[] xmlDeclEndBytes = XML_DECL_END.getBytes(encoding);
101
		
147
102
		// allocate an array for the input
148
		// allocate an array for the input
103
		int xmlDeclSize = 100 * xmlDeclEndBytes.length/2;
149
		int xmlDeclSize = 100 * xmlDeclEndBytes.length / 2;
104
		byte[] xmlDecl = new byte[xmlDeclSize];
150
		byte[] xmlDecl = new byte[xmlDeclSize];
105
		
151
106
		// looks for XMLDecl end (?>)
152
		// looks for XMLDecl end (?>)
107
		int c = 0;
153
		int c = 0;
108
		int read = 0;
154
		int read = 0;
109
		
155
110
		// count is incremented when subsequent read characters match the xmlDeclEnd bytes,
156
		// count is incremented when subsequent read characters match the xmlDeclEnd bytes,
111
		// the end of xmlDecl is reached, when count equals the xmlDeclEnd length
157
		// the end of xmlDecl is reached, when count equals the xmlDeclEnd length
112
		int count = 0;
158
		int count = 0;
113
	
159
114
		while (read < xmlDecl.length && (c = input.read()) != -1){
160
		while (read < xmlDecl.length && (c = input.read()) != -1) {
115
			if (c == xmlDeclEndBytes[count])
161
			if (c == xmlDeclEndBytes[count])
116
				count++;
162
				count++;
117
			else
163
			else
118
				count = 0;
164
				count = 0;
119
			xmlDecl[read++] = (byte) c;
165
			xmlDecl[read++] = (byte) c;
120
			if (count == xmlDeclEndBytes.length) 
166
			if (count == xmlDeclEndBytes.length)
121
				break;
167
				break;
122
		}
168
		}
123
		return new String(xmlDecl, 0, read, encoding);
169
		return new String(xmlDecl, 0, read, encoding);
(-)src/org/eclipse/core/runtime/content/XMLRootElementContentDescriber2.java (-26 / +77 lines)
Lines 14-20 Link Here
14
import java.io.*;
14
import java.io.*;
15
import java.util.*;
15
import java.util.*;
16
import javax.xml.parsers.ParserConfigurationException;
16
import javax.xml.parsers.ParserConfigurationException;
17
import org.eclipse.core.internal.content.*;
17
import org.eclipse.core.internal.content.ContentMessages;
18
import org.eclipse.core.internal.content.XMLRootHandler;
18
import org.eclipse.core.internal.runtime.RuntimeLog;
19
import org.eclipse.core.internal.runtime.RuntimeLog;
19
import org.eclipse.core.runtime.*;
20
import org.eclipse.core.runtime.*;
20
import org.eclipse.osgi.util.NLS;
21
import org.eclipse.osgi.util.NLS;
Lines 65-72 Link Here
65
 * @noinstantiate This class is not intended to be instantiated by clients.
66
 * @noinstantiate This class is not intended to be instantiated by clients.
66
 */
67
 */
67
public final class XMLRootElementContentDescriber2 extends XMLContentDescriber implements IExecutableExtension {
68
public final class XMLRootElementContentDescriber2 extends XMLContentDescriber implements IExecutableExtension {
69
70
	static final String DTD = "org.eclipse.core.runtime.content.XMLRootElementContentDescriber2.dtd"; //$NON-NLS-1$
71
	static final String NAMESPACE = "org.eclipse.core.runtime.content.XMLRootElementContentDescriber2.namespace"; //$NON-NLS-1$
72
	static final String ELEMENT = "org.eclipse.core.runtime.content.XMLRootElementContentDescriber2.element"; //$NON-NLS-1$
73
	static final String RESULT = "org.eclipse.core.runtime.content.XMLRootElementContentDescriber2.result"; //$NON-NLS-1$
74
68
	private static final String ELEMENT_TO_FIND = "element"; //$NON-NLS-1$
75
	private static final String ELEMENT_TO_FIND = "element"; //$NON-NLS-1$
69
	
76
70
	/* (Intentionally not included in javadoc)
77
	/* (Intentionally not included in javadoc)
71
	 * The top-level elements we are looking for. This value will be initialized
78
	 * The top-level elements we are looking for. This value will be initialized
72
	 * by the <code>setInitializationData</code> method. If no value is
79
	 * by the <code>setInitializationData</code> method. If no value is
Lines 78-100 Link Here
78
	/* (Intentionally not included in javadoc)
85
	/* (Intentionally not included in javadoc)
79
	 * Simple value holder for root element name, its namespace and dtd.
86
	 * Simple value holder for root element name, its namespace and dtd.
80
	 */
87
	 */
81
	 private class QualifiedElement {
88
	private class QualifiedElement {
82
		private String namespace;
89
		private String namespace;
83
		private String element;
90
		private String element;
84
		private String dtd;
91
		private String dtd;
85
		
92
86
		public QualifiedElement(String qualifiedElement) {
93
		public QualifiedElement(String qualifiedElement) {
87
			// Extract namespace part
94
			// Extract namespace part
88
			int openBrace = qualifiedElement.indexOf('{');
95
			int openBrace = qualifiedElement.indexOf('{');
89
			int closeBrace = qualifiedElement.indexOf('}');
96
			int closeBrace = qualifiedElement.indexOf('}');
90
			if (openBrace == 0 && closeBrace >=1 ) {
97
			if (openBrace == 0 && closeBrace >= 1) {
91
				namespace = qualifiedElement.substring(1, closeBrace);
98
				namespace = qualifiedElement.substring(1, closeBrace);
92
				qualifiedElement = qualifiedElement.substring(closeBrace+1);
99
				qualifiedElement = qualifiedElement.substring(closeBrace + 1);
93
			}
100
			}
94
			// Extract dtd part
101
			// Extract dtd part
95
			int dtdSlash = qualifiedElement.indexOf('/');
102
			int dtdSlash = qualifiedElement.indexOf('/');
96
			if (dtdSlash > 0) {
103
			if (dtdSlash > 0) {
97
				dtd = qualifiedElement.substring(dtdSlash+1);
104
				dtd = qualifiedElement.substring(dtdSlash + 1);
98
				qualifiedElement = qualifiedElement.substring(0, dtdSlash);
105
				qualifiedElement = qualifiedElement.substring(0, dtdSlash);
99
			}
106
			}
100
			// Check if the name is a wildcard
107
			// Check if the name is a wildcard
Lines 108-114 Link Here
108
			return nsMatch && elementEquals && dtdEquals;
115
			return nsMatch && elementEquals && dtdEquals;
109
		}
116
		}
110
	}
117
	}
111
	
118
112
	/* (Intentionally not included in javadoc)
119
	/* (Intentionally not included in javadoc)
113
	 * Determines the validation status for the given contents.
120
	 * Determines the validation status for the given contents.
114
	 * 
121
	 * 
Lines 120-144 Link Here
120
	 * </ul>
127
	 * </ul>
121
	 * @throws IOException
128
	 * @throws IOException
122
	 */
129
	 */
123
	private int checkCriteria(InputSource contents) throws IOException {
130
	private int checkCriteria(InputSource contents, Map properties) throws IOException {
124
		XMLRootHandler xmlHandler = new XMLRootHandler(elementsToFind != null);
131
		if (!isProcessed(properties))
125
		try {
132
			fillContentProperties(contents, properties);
126
			if (!xmlHandler.parseContents(contents))
133
		return checkCriteria(properties);
127
				return INDETERMINATE;
134
	}
128
		} catch (SAXException e) {
135
129
			// we may be handed any kind of contents... it is normal we fail to parse
136
	private int checkCriteria(Map properties) throws IOException {
137
		Boolean result = (Boolean) properties.get(RESULT);
138
		if (!result.booleanValue())
130
			return INDETERMINATE;
139
			return INDETERMINATE;
131
		} catch (ParserConfigurationException e) {
132
			// some bad thing happened - force this describer to be disabled
133
			String message = ContentMessages.content_parserConfiguration;
134
			RuntimeLog.log(new Status(IStatus.ERROR, ContentMessages.OWNER_NAME, 0, message, e));
135
			throw new RuntimeException(message);
136
		}
137
		// Check to see if we matched our criteria.
140
		// Check to see if we matched our criteria.
138
		if (elementsToFind != null) {
141
		if (elementsToFind != null) {
139
			boolean foundOne = false;
142
			boolean foundOne = false;
140
			for (int i = 0; i < elementsToFind.length && !foundOne; ++i) {
143
			for (int i = 0; i < elementsToFind.length && !foundOne; ++i) {
141
				foundOne |= elementsToFind[i].matches(xmlHandler.getRootNamespace(), xmlHandler.getRootName(), xmlHandler.getDTD());
144
				String dtd = (String) properties.get(DTD);
145
				String namespace = (String) properties.get(NAMESPACE);
146
				String element = (String) properties.get(ELEMENT);
147
				foundOne |= elementsToFind[i].matches(namespace, element, dtd);
142
			}
148
			}
143
			if (!foundOne)
149
			if (!foundOne)
144
				return INDETERMINATE;
150
				return INDETERMINATE;
Lines 151-176 Link Here
151
	 * @see IContentDescriber#describe(InputStream, IContentDescription)
157
	 * @see IContentDescriber#describe(InputStream, IContentDescription)
152
	 */
158
	 */
153
	public int describe(InputStream contents, IContentDescription description) throws IOException {
159
	public int describe(InputStream contents, IContentDescription description) throws IOException {
160
		return describe(contents, description, new HashMap());
161
	}
162
163
	public int describe(InputStream contents, IContentDescription description, Map properties) throws IOException {
154
		// call the basic XML describer to do basic recognition
164
		// call the basic XML describer to do basic recognition
155
		if (super.describe(contents, description) == INVALID)
165
		if (super.describe2(contents, description, properties) == INVALID)
156
			return INVALID;
166
			return INVALID;
157
		// super.describe will have consumed some chars, need to rewind		
167
		// super.describe will have consumed some chars, need to rewind		
158
		contents.reset();
168
		contents.reset();
159
		// Check to see if we matched our criteria.		
169
		// Check to see if we matched our criteria.		
160
		return checkCriteria(new InputSource(contents));
170
		return checkCriteria(new InputSource(contents), properties);
161
	}
171
	}
162
172
163
	/* (Intentionally not included in javadoc)
173
	/* (Intentionally not included in javadoc)
164
	 * @see IContentDescriber#describe(Reader, IContentDescription)
174
	 * @see IContentDescriber#describe(Reader, IContentDescription)
165
	 */
175
	 */
166
	public int describe(Reader contents, IContentDescription description) throws IOException {
176
	public int describe(Reader contents, IContentDescription description) throws IOException {
177
		return describe(contents, description, new HashMap());
178
	}
179
180
	public int describe(Reader contents, IContentDescription description, Map properties) throws IOException {
167
		// call the basic XML describer to do basic recognition
181
		// call the basic XML describer to do basic recognition
168
		if (super.describe(contents, description) == INVALID)
182
		if (super.describe2(contents, description, properties) == INVALID)
169
			return INVALID;
183
			return INVALID;
170
		// super.describe will have consumed some chars, need to rewind
184
		// super.describe will have consumed some chars, need to rewind
171
		contents.reset();
185
		contents.reset();
172
		// Check to see if we matched our criteria.
186
		// Check to see if we matched our criteria.
173
		return checkCriteria(new InputSource(contents));
187
		return checkCriteria(new InputSource(contents), properties);
188
	}
189
190
	static boolean isProcessed(Map properties) {
191
		Boolean result = (Boolean) properties.get(RESULT);
192
		// It can be set to false which means that content can't be parsed
193
		if (result != null)
194
			return true;
195
		return false;
196
	}
197
198
	static void fillContentProperties(InputSource input, Map properties) throws IOException {
199
		XMLRootHandler xmlHandler = new XMLRootHandler(true);
200
		try {
201
			if (!xmlHandler.parseContents(input)) {
202
				properties.put(RESULT, new Boolean(false));
203
				return;
204
			}
205
		} catch (SAXException e) {
206
			// we may be handed any kind of contents... it is normal we fail to parse
207
			properties.put(RESULT, new Boolean(false));
208
			return;
209
		} catch (ParserConfigurationException e) {
210
			// some bad thing happened - force this describer to be disabled
211
			String message = ContentMessages.content_parserConfiguration;
212
			RuntimeLog.log(new Status(IStatus.ERROR, ContentMessages.OWNER_NAME, 0, message, e));
213
			throw new RuntimeException(message);
214
		}
215
		String element = xmlHandler.getRootName();
216
		if (element != null)
217
			properties.put(ELEMENT, element);
218
		String dtd = xmlHandler.getDTD();
219
		if (dtd != null)
220
			properties.put(DTD, dtd);
221
		String namespace = xmlHandler.getRootNamespace();
222
		if (namespace != null)
223
			properties.put(NAMESPACE, namespace);
224
		properties.put(RESULT, new Boolean(true));
174
	}
225
	}
175
226
176
	/* (Intentionally not included in javadoc)
227
	/* (Intentionally not included in javadoc)
(-)src/org/eclipse/core/runtime/content/XMLRootElementContentDescriber.java (-24 / +25 lines)
Lines 11-24 Link Here
11
package org.eclipse.core.runtime.content;
11
package org.eclipse.core.runtime.content;
12
12
13
import java.io.*;
13
import java.io.*;
14
import java.util.Hashtable;
14
import java.util.*;
15
import javax.xml.parsers.ParserConfigurationException;
15
import org.eclipse.core.internal.content.ContentMessages;
16
import org.eclipse.core.internal.content.*;
17
import org.eclipse.core.internal.runtime.RuntimeLog;
18
import org.eclipse.core.runtime.*;
16
import org.eclipse.core.runtime.*;
19
import org.eclipse.osgi.util.NLS;
17
import org.eclipse.osgi.util.NLS;
20
import org.xml.sax.InputSource;
18
import org.xml.sax.InputSource;
21
import org.xml.sax.SAXException;
22
19
23
/**
20
/**
24
 * A content describer for detecting the name of the top-level element or the
21
 * A content describer for detecting the name of the top-level element or the
Lines 70-93 Link Here
70
	 * </ul>
67
	 * </ul>
71
	 * @throws IOException
68
	 * @throws IOException
72
	 */
69
	 */
73
	private int checkCriteria(InputSource contents) throws IOException {
70
	private int checkCriteria(InputSource contents, Map properties) throws IOException {
74
		XMLRootHandler xmlHandler = new XMLRootHandler(elementToFind != null);
71
		if (!XMLRootElementContentDescriber2.isProcessed(properties))
75
		try {
72
			XMLRootElementContentDescriber2.fillContentProperties(contents, properties);
76
			if (!xmlHandler.parseContents(contents))
73
		return checkCriteria(properties);
77
				return INDETERMINATE;
74
	}
78
		} catch (SAXException e) {
75
79
			// we may be handed any kind of contents... it is normal we fail to parse
76
	private int checkCriteria(Map properties) throws IOException {
77
		Boolean result = (Boolean) properties.get(XMLRootElementContentDescriber2.RESULT);
78
		if (!result.booleanValue())
80
			return INDETERMINATE;
79
			return INDETERMINATE;
81
		} catch (ParserConfigurationException e) {
82
			// some bad thing happened - force this describer to be disabled
83
			String message = ContentMessages.content_parserConfiguration;
84
			RuntimeLog.log(new Status(IStatus.ERROR, ContentMessages.OWNER_NAME, 0, message, e));
85
			throw new RuntimeException(message);
86
		}
87
		// Check to see if we matched our criteria.
80
		// Check to see if we matched our criteria.
88
		if ((elementToFind != null) && (!elementToFind.equals(xmlHandler.getRootName())))
81
		if ((dtdToFind != null) && (!dtdToFind.equals(properties.get(XMLRootElementContentDescriber2.DTD))))
89
			return INDETERMINATE;
82
			return INDETERMINATE;
90
		if ((dtdToFind != null) && (!dtdToFind.equals(xmlHandler.getDTD())))
83
		if ((elementToFind != null) && (!elementToFind.equals(properties.get(XMLRootElementContentDescriber2.ELEMENT))))
91
			return INDETERMINATE;
84
			return INDETERMINATE;
92
		// We must be okay then.		
85
		// We must be okay then.		
93
		return VALID;
86
		return VALID;
Lines 97-122 Link Here
97
	 * @see IContentDescriber#describe(InputStream, IContentDescription)
90
	 * @see IContentDescriber#describe(InputStream, IContentDescription)
98
	 */
91
	 */
99
	public int describe(InputStream contents, IContentDescription description) throws IOException {
92
	public int describe(InputStream contents, IContentDescription description) throws IOException {
93
		return describe(contents, description, new HashMap());
94
	}
95
96
	public int describe(InputStream contents, IContentDescription description, Map properties) throws IOException {
100
		// call the basic XML describer to do basic recognition
97
		// call the basic XML describer to do basic recognition
101
		if (super.describe(contents, description) == INVALID)
98
		if (super.describe2(contents, description, properties) == INVALID)
102
			return INVALID;
99
			return INVALID;
103
		// super.describe will have consumed some chars, need to rewind		
100
		// super.describe will have consumed some chars, need to rewind		
104
		contents.reset();
101
		contents.reset();
105
		// Check to see if we matched our criteria.		
102
		// Check to see if we matched our criteria.		
106
		return checkCriteria(new InputSource(contents));
103
		return checkCriteria(new InputSource(contents), properties);
107
	}
104
	}
108
105
109
	/* (Intentionally not included in javadoc)
106
	/* (Intentionally not included in javadoc)
110
	 * @see IContentDescriber#describe(Reader, IContentDescription)
107
	 * @see IContentDescriber#describe(Reader, IContentDescription)
111
	 */
108
	 */
112
	public int describe(Reader contents, IContentDescription description) throws IOException {
109
	public int describe(Reader contents, IContentDescription description) throws IOException {
110
		return describe(contents, description, new HashMap());
111
	}
112
113
	public int describe(Reader contents, IContentDescription description, Map properties) throws IOException {
113
		// call the basic XML describer to do basic recognition
114
		// call the basic XML describer to do basic recognition
114
		if (super.describe(contents, description) == INVALID)
115
		if (super.describe2(contents, description, properties) == INVALID)
115
			return INVALID;
116
			return INVALID;
116
		// super.describe will have consumed some chars, need to rewind
117
		// super.describe will have consumed some chars, need to rewind
117
		contents.reset();
118
		contents.reset();
118
		// Check to see if we matched our criteria.
119
		// Check to see if we matched our criteria.
119
		return checkCriteria(new InputSource(contents));
120
		return checkCriteria(new InputSource(contents), properties);
120
	}
121
	}
121
122
122
	/* (Intentionally not included in javadoc)
123
	/* (Intentionally not included in javadoc)

Return to bug 182337