Copyright (c) 2004, 2008 IBM Corporation and others.
This program and the accompanying materials
are made available under the terms of the Eclipse Public License 2.0
which accompanies this distribution, and is available at
https://www.eclipse.org/legal/epl-2.0/
SPDX-License-Identifier: EPL-2.0
Contributors:
IBM Corporation - initial API and implementation
/*******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.core.runtime.content;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import org.eclipse.core.internal.content.ContentMessages;
import org.eclipse.core.runtime.*;
import org.eclipse.osgi.util.NLS;
A content describer for binary formats that present some
simple signature at a known, fixed offset.
This executable extension supports three parameters:
"signature", "offset" and "required", the first one being mandatory.
If the
":-"
method is used, then the value is treated as the
"signature".
The "signature" parameter is a sequence of hex codes, one for each byte in
the signature. For example, "CA FE BA BE" would be a signature for Java
class files.
The "offset" parameter is an integer indicating the offset where the
signature's first byte is found.
The "required" parameter is a boolean (default is " true") indicating whether
the absence of a signature should deem the contents validity status as
IContentDescriber.INVALID or IContentDescriber.INDETERMINATE.
This class is not intended to be subclassed or instantiated by clients,
only to be referenced by the "describer" configuration element in
extensions to the org.eclipse.core.runtime.contentTypes
extension point.
Since: 3.0
/**
* A content describer for binary formats that present some
* simple signature at a known, fixed offset.
* <p>
* This executable extension supports three parameters:
* "signature", "offset" and "required", the first one being mandatory.
* If the
* <code>":-"</code> method is used, then the value is treated as the
* "signature".
* </p>
* <p>
* The "signature" parameter is a sequence of hex codes, one for each byte in
* the signature. For example, "CA FE BA BE" would be a signature for Java
* class files.
* </p>
* <p>
* The "offset" parameter is an integer indicating the offset where the
* signature's first byte is found.
* </p>
* <p>
* The "required" parameter is a boolean (default is " true") indicating whether
* the absence of a signature should deem the contents validity status as
* IContentDescriber.INVALID or IContentDescriber.INDETERMINATE.
* </p>
* <p>
* This class is not intended to be subclassed or instantiated by clients,
* only to be referenced by the "describer" configuration element in
* extensions to the <code>org.eclipse.core.runtime.contentTypes</code>
* extension point.
* </p>
*
* @since 3.0
*/
public final class BinarySignatureDescriber implements IContentDescriber, IExecutableExtension {
private final static String SIGNATURE = "signature"; //$NON-NLS-1$
private final static String OFFSET = "offset"; //$NON-NLS-1$
private static final Object REQUIRED = "required"; //$NON-NLS-1$
private byte[] signature;
private int offset;
private boolean required = true;
/* (Intentionally not included in javadoc)
* @see IContentDescriber#describe(InputStream, IContentDescription)
*/
@Override
public int describe(InputStream contents, IContentDescription description) throws IOException {
byte[] buffer = new byte[signature.length];
int notValid = required ? INVALID : INDETERMINATE;
if (contents.skip(offset) < offset)
return notValid;
if (contents.read(buffer) != buffer.length)
return notValid;
for (int i = 0; i < signature.length; i++)
if (signature[i] != buffer[i])
return notValid;
return VALID;
}
@Override
public QualifiedName[] getSupportedOptions() {
return new QualifiedName[0];
}
@Override
public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
try {
if (data instanceof String)
signature = parseSignature((String) data);
else if (data instanceof Hashtable) {
Hashtable<?,?> parameters = (Hashtable<?,?>) data;
if (!parameters.containsKey(SIGNATURE)) {
String message = NLS.bind(ContentMessages.content_badInitializationData, BinarySignatureDescriber.class.getName());
throw new CoreException(new Status(IStatus.ERROR, ContentMessages.OWNER_NAME, 0, message, null));
}
signature = parseSignature((String) parameters.get(SIGNATURE));
if (parameters.containsKey(OFFSET))
offset = Integer.parseInt((String) parameters.get(OFFSET));
if (parameters.containsKey(REQUIRED))
required = Boolean.valueOf((String) parameters.get(REQUIRED)).booleanValue();
}
} catch (NumberFormatException nfe) {
String message = NLS.bind(ContentMessages.content_badInitializationData, BinarySignatureDescriber.class.getName());
throw new CoreException(new Status(IStatus.ERROR, ContentMessages.OWNER_NAME, 0, message, nfe));
}
}
private static byte[] parseSignature(String data) {
List<Byte> bytes = new ArrayList<>();
StringTokenizer tokenizer = new StringTokenizer(data, " \t\n\r\f,"); //$NON-NLS-1$
while (tokenizer.hasMoreTokens())
bytes.add(Byte.valueOf((byte) Integer.parseInt(tokenizer.nextToken().trim(), 16)));
byte[] signature = new byte[bytes.size()];
for (int i = 0; i < signature.length; i++)
signature[i] = bytes.get(i).byteValue();
return signature;
}
}