Package ceylon.modules.jboss.repository

Source Code of ceylon.modules.jboss.repository.SourceResourceLoader

/*
* Copyright 2011 Red Hat inc. and third party contributors as noted
* by the author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package ceylon.modules.jboss.repository;

import ceylon.modules.api.compiler.CompilerAdapterFactory;
import org.jboss.modules.ClassSpec;
import org.jboss.modules.PackageSpec;
import org.jboss.modules.Resource;
import org.jboss.modules.ResourceLoader;

import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

/**
* Source resource loader.
*
* @author <a href="mailto:ales.justin@jboss.org">Ales Justin</a>
*/
class SourceResourceLoader implements ResourceLoader {
    private File sourcesRoot;
    private File classesRoot;
    private String rootName;
    private Manifest manifest;

    SourceResourceLoader(File sourcesRoot, File classesRoot, String rootName) {
        if (sourcesRoot == null)
            throw new IllegalArgumentException("Null sources root");
        if (classesRoot == null)
            throw new IllegalArgumentException("Null classes root");
        if (rootName == null)
            throw new IllegalArgumentException("Null root name");

        this.sourcesRoot = sourcesRoot;
        this.classesRoot = classesRoot;
        this.rootName = rootName;

        final File manifestFile = new File(sourcesRoot, "META-INF" + File.separator + "MANIFEST.MF");
        manifest = readManifestFile(manifestFile);
    }

    private static Manifest readManifestFile(final File manifestFile) {
        try {
            InputStream is = new FileInputStream(manifestFile);
            try {
                return new Manifest(is);
            } finally {
                safeClose(is);
            }
        } catch (IOException e) {
            return null;
        }
    }

    public String getRootName() {
        return rootName;
    }

    public ClassSpec getClassSpec(String name) throws IOException {
        File file = new File(classesRoot, name);
        if (file.exists()) {
            return toClassSpec(file);
        } else {
            CompilerAdapterFactory factory = CompilerAdapterFactory.getInstance();
            file = factory.findAndCompile(sourcesRoot, name, classesRoot);
            return file != null ? toClassSpec(file) : null;
        }
    }

    /**
     * To class spec.
     *
     * @param file the file
     * @return new class spec instance
     * @throws IOException for any I/O error
     */
    protected ClassSpec toClassSpec(File file) throws IOException {
        final long size = file.length();
        final ClassSpec spec = new ClassSpec();
        final InputStream is = new FileInputStream(file);
        try {
            if (size <= (long) Integer.MAX_VALUE) {
                final int castSize = (int) size;
                byte[] bytes = new byte[castSize];
                int a = 0, res;
                while ((res = is.read(bytes, a, castSize - a)) > 0) {
                    a += res;
                }
                // done
                is.close();
                spec.setBytes(bytes);
                return spec;
            } else {
                throw new IOException("Resource is too large to be a valid class file");
            }
        } finally {
            safeClose(is);
        }
    }

    private static void safeClose(final Closeable closeable) {
        if (closeable != null) try {
            closeable.close();
        } catch (IOException e) {
            // ignore
        }
    }

    /**
     * Get the file name of a class.
     *
     * @param className  the class name
     * @param typeSuffix the language type suffix
     * @return the name of the corresponding class file
     */
    static String fileNameOfClass(final String className, String typeSuffix) {
        return className.replace('.', '/') + "." + typeSuffix;
    }

    public PackageSpec getPackageSpec(String name) throws IOException {
        final PackageSpec spec = new PackageSpec();
        final Manifest manifest = this.manifest;
        if (manifest == null) {
            return spec;
        }

        final Attributes mainAttribute = manifest.getAttributes(name);
        final Attributes entryAttribute = manifest.getAttributes(name);
        spec.setSpecTitle(getDefinedAttribute(Attributes.Name.SPECIFICATION_TITLE, entryAttribute, mainAttribute));
        spec.setSpecVersion(getDefinedAttribute(Attributes.Name.SPECIFICATION_VERSION, entryAttribute, mainAttribute));
        spec.setSpecVendor(getDefinedAttribute(Attributes.Name.SPECIFICATION_VENDOR, entryAttribute, mainAttribute));
        spec.setImplTitle(getDefinedAttribute(Attributes.Name.IMPLEMENTATION_TITLE, entryAttribute, mainAttribute));
        spec.setImplVersion(getDefinedAttribute(Attributes.Name.IMPLEMENTATION_VERSION, entryAttribute, mainAttribute));
        spec.setImplVendor(getDefinedAttribute(Attributes.Name.IMPLEMENTATION_VENDOR, entryAttribute, mainAttribute));
        if (Boolean.parseBoolean(getDefinedAttribute(Attributes.Name.SEALED, entryAttribute, mainAttribute))) {
            spec.setSealBase(classesRoot.toURI().toURL());
        }
        return spec;
    }

    private static String getDefinedAttribute(Attributes.Name name, Attributes entryAttribute, Attributes mainAttribute) {
        final String value = entryAttribute == null ? null : entryAttribute.getValue(name);
        return value == null ? mainAttribute == null ? null : mainAttribute.getValue(name) : value;
    }

    public Resource getResource(String name) {
        try {
            File file = new File(classesRoot, name);
            if (file.exists()) {
                return new FileEntryResource(name, file, file.toURI().toURL());
            } else {
                file = new File(sourcesRoot, name);
                if (file.exists() == false)
                    return null;

                // TODO -- fix url!
                return new SourceEntryResource(name, file, file.toURI().toURL(), classesRoot);
            }
        } catch (MalformedURLException e) {
            // must be invalid...?  (TODO: check this out)
            return null;
        }
    }

    public String getLibrary(String name) {
        // Source cannot have lib
        return null;
    }

    public Collection<String> getPaths() {
        List<String> paths = new ArrayList<String>();
        buildIndex(paths, sourcesRoot, "");
        return paths;
    }

    private void buildIndex(final List<String> index, final File root, final String pathBase) {
        for (File file : root.listFiles()) {
            if (file.isDirectory()) {
                index.add(pathBase + file.getName());
                buildIndex(index, file, pathBase + file.getName() + File.separator);
            }
        }
    }
}
TOP

Related Classes of ceylon.modules.jboss.repository.SourceResourceLoader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.