org.eclipse.xtend.expression.ResourceManagerDefaultImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.xtend.expression.ResourceManagerDefaultImpl.java

Source

/*******************************************************************************
 * Copyright (c) 2005, 2007 committers of openArchitectureWare and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     committers of openArchitectureWare - initial API and implementation
 *******************************************************************************/

package org.eclipse.xtend.expression;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.emf.mwe.core.resources.ResourceLoaderFactory;
import org.eclipse.internal.xtend.expression.parser.SyntaxConstants;
import org.eclipse.internal.xtend.util.internal.icu.CharsetDetector;
import org.eclipse.internal.xtend.util.internal.icu.CharsetMatch;
import org.eclipse.internal.xtend.xtend.XtendFile;
import org.eclipse.internal.xtend.xtend.XtendResourceParser;
import org.eclipse.xtend.check.CheckUtils;

public class ResourceManagerDefaultImpl implements ResourceManager {

    private final Log log = LogFactory.getLog(getClass());

    private String fileEncoding = null;

    private final Map<String, Resource> resources = new HashMap<String, Resource>();

    public ResourceManagerDefaultImpl() {
        XtendResourceParser xtendResourceParser = new XtendResourceParser();
        registeredParsers.put(XtendFile.FILE_EXTENSION, xtendResourceParser);
        registeredParsers.put(CheckUtils.FILE_EXTENSION, xtendResourceParser);
    }

    public Resource loadResource(final String fullyQualifiedName, final String extension) {
        final String resourceName = fullyQualifiedName.replace(SyntaxConstants.NS_DELIM, "/") + "." + extension;
        if (resources.containsKey(resourceName))
            return resources.get(resourceName);
        final InputStream in = ResourceLoaderFactory.createResourceLoader().getResourceAsStream(resourceName);

        if (in == null)
            return null;
        else {
            Reader reader = createReader(in);
            final ResourceParser parser = registeredParsers.get(extension);
            if (parser == null)
                throw new RuntimeException("No Parser registered for extension '" + extension
                        + "'! Known extensions are '" + registeredParsers.keySet() + "'");
            final Resource res = parser.parse(reader, resourceName);
            res.setFullyQualifiedName(fullyQualifiedName);
            resources.put(resourceName, res);
            return res;
        }
    }

    /**
     * Creates a Reader for the given InputStream. If no explicit file encoding
     * is set this method will try to autodetect the file's encoding.
     * 
     * @param in
     *            Some resource input stream
     * @return A Reader for the stream
     * @since 4.2
     */
    protected Reader createReader(final InputStream in) {
        Reader reader = null;
        if (fileEncoding != null) {
            try {
                reader = new InputStreamReader(in, fileEncoding);
            } catch (final UnsupportedEncodingException e) {
                log.error("Unsupported encoding falling back to default...", e);
                reader = new InputStreamReader(in);
            }
        } else {
            Charset encoding = null;
            // Buffer the original stream since we want to re-read it
            BufferedInputStream is = new BufferedInputStream(in);

            try {
                // Read some bytes from the stream
                is.mark(65);
                byte[] buf = new byte[64];
                is.read(buf);
                // reset the stream
                is.reset();

                // Special handling for Xpand files on Mac: Try to detect
                // the opening Guillemot bracket for MacRoman encoding
                for (int i = 0; i < buf.length; i++) {
                    if (buf[i] == -57) { // opening Guillemot bracket
                        encoding = Charset.forName("MacRoman");
                        break;
                    }
                }
                // Use com.ibm.icu for autodetection
                if (encoding == null) {
                    CharsetDetector det = new CharsetDetector();
                    det.setText(buf);
                    CharsetMatch match = det.detect();
                    if (match != null) {
                        encoding = Charset.forName(match.getName());
                    }
                }

                // Create the reader with the detected encoding
                if (encoding != null) {
                    reader = new InputStreamReader(is, encoding);
                } else {
                    log.warn("Failed autodetecting encoding. Falling back to default...");
                    reader = new InputStreamReader(is);
                }
            } catch (IOException e) {
                log.warn("Failed autodetecting encoding. Falling back to default...", e);
                reader = new InputStreamReader(in);
            }
        }
        return reader;
    }

    public void setFileEncoding(final String fileEncoding) {
        this.fileEncoding = fileEncoding;
    }

    protected Map<String, ResourceParser> registeredParsers = new HashMap<String, ResourceParser>();

    public void registerParser(final String extension, final ResourceParser parser) {
        registeredParsers.put(extension, parser);
    }

}