org.colombbus.tangara.io.ScriptHeaderHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.colombbus.tangara.io.ScriptHeaderHelper.java

Source

/**
 * Tangara is an educational platform to get started with programming.
 * Copyright (C) 2009 Colombbus (http://www.colombbus.org)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.colombbus.tangara.io;

import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
import java.util.regex.Pattern;

import org.apache.commons.lang.Validate;
import org.colombbus.tangara.core.Version;

public class ScriptHeaderHelper {

    private static final String VERSION_FIELD = "version"; //$NON-NLS-1$
    private static final String ENCODING_FIELD = "encoding"; //$NON-NLS-1$
    private static final Charset HEADER_CHARSET = Charset.forName("US-ASCII"); //$NON-NLS-1$
    private static final String HEADER_REGEX = "//<tangara version=\"" + Version.VERSION_REGEX //$NON-NLS-1$
            + "\" encoding=\"([a-zA-Z0-9\\- _]+)\">//"; //$NON-NLS-1$

    private static final String BYTE_HEADER_FORMAT = "//<tangara version=\"%s\" encoding=\"%s\">//"; //$NON-NLS-1$

    // TODO is it obsolete ?
    private static final byte[] HEADER_PREFIX = HEADER_CHARSET.encode("//<tangara ").array(); //$NON-NLS-1$

    private static final Version[] SUPPORTED_VERSIONS = { new Version("1.0") }; //$NON-NLS-1$

    // singleton
    private ScriptHeaderHelper() {
    }

    public static boolean containsHeader(ByteBuffer content) {
        Validate.notNull(content, "content argument is null"); //$NON-NLS-1$
        if (content.capacity() < HEADER_PREFIX.length)
            return false;
        for (int i = 0; i < HEADER_PREFIX.length; i++) {
            if (HEADER_PREFIX[i] != content.get(i))
                return false;
        }
        return true;
    }

    public static ScriptHeader extractHeader(ByteBuffer content) {
        Validate.notNull(content, "content argument is null"); //$NON-NLS-1$

        ByteBuffer byteHeader = extractHeaderAsByteBuffer(content);

        String header = HEADER_CHARSET.decode(byteHeader).toString();
        checkHeaderWellformed(header);

        String versionValue = extractFieldValue(VERSION_FIELD, header);
        Version version = new Version(versionValue);
        checkSupportedVersion(version);

        String encoding = extractFieldValue(ENCODING_FIELD, header);
        Charset charset = decodeEncodingCharset(encoding);

        ScriptHeader scriptFileHeader = new ScriptHeaderImpl(charset, version);

        return scriptFileHeader;
    }

    private static Charset decodeEncodingCharset(String encoding) {
        try {
            return Charset.forName(encoding);
        } catch (IllegalCharsetNameException nameEx) {
            String msg = String.format("Illegal charset name '%s'", encoding); //$NON-NLS-1$
            throw new MalformedScriptException(msg, nameEx);
        } catch (UnsupportedCharsetException supportEx) {
            String msg = String.format("Unsupported charset name '%s'", encoding); //$NON-NLS-1$
            throw new MalformedScriptException(msg, supportEx);
        }
    }

    private static void checkSupportedVersion(Version version) {
        for (Version supportedVersion : SUPPORTED_VERSIONS) {
            if (supportedVersion.equals(version)) {
                return;
            }
        }

        String msg = String.format("Version %s is not supported", version); //$NON-NLS-1$
        throw new MalformedScriptException(msg);
    }

    private static String extractFieldValue(String fieldName, String header) {
        int fieldStart = header.indexOf(fieldName);
        int valueBegin = fieldStart + fieldName.length() + 2;// +2 => '="'
        int valueEnd = header.indexOf('"', valueBegin);
        String value = header.substring(valueBegin, valueEnd);
        return value;
    }

    private static ByteBuffer extractHeaderAsByteBuffer(ByteBuffer content) {
        moveToHeaderEnd(content);
        int headerLength = content.position();
        content.rewind();
        ByteBuffer byteHeader = ByteBuffer.allocate(headerLength);
        content.get(byteHeader.array());
        return byteHeader;
    }

    private static void checkHeaderWellformed(String header) {
        if (Pattern.matches(HEADER_REGEX, header) == false) {
            throw new MalformedScriptException("The header is invalid"); //$NON-NLS-1$
        }
    }

    private static void moveToHeaderEnd(ByteBuffer content) throws MalformedScriptException {
        try {
            while (content.get() != '>')
                ;
            if (content.get() != '/' || content.get() != '/') {
                throw new MalformedScriptException();
            }
        } catch (BufferUnderflowException bufEx) {
            throw new MalformedScriptException(bufEx);
        }
    }

    public static byte[] toByteArray(ScriptHeader header) {
        Validate.notNull(header, "header argument is null"); //$NON-NLS-1$

        String textHeader = String.format(BYTE_HEADER_FORMAT, header.getVersion().toString(),
                header.getCharset().name());
        ByteBuffer byteHeader = HEADER_CHARSET.encode(textHeader);
        return byteHeader.array();
    }

}