org.bimserver.plugins.VirtualFile.java Source code

Java tutorial

Introduction

Here is the source code for org.bimserver.plugins.VirtualFile.java

Source

package org.bimserver.plugins;

/******************************************************************************
 * Copyright (C) 2009-2016  BIMserver.org
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero 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 Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see {@literal<http://www.gnu.org/licenses/>}.
 *****************************************************************************/

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;

import javax.lang.model.element.Modifier;
import javax.lang.model.element.NestingKind;
import javax.tools.JavaFileObject;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Charsets;

public class VirtualFile implements JavaFileObject {

    private static final Logger LOGGER = LoggerFactory.getLogger(VirtualFile.class);
    private final Map<String, VirtualFile> files = new HashMap<String, VirtualFile>();
    private final String name;
    private byte[] data = new byte[0];
    private VirtualFile parent;
    private URI uri;
    private final Set<VirtualFile> sourceFiles = new HashSet<VirtualFile>();

    public VirtualFile() {
        this.parent = null;
        this.name = null;
    }

    public VirtualFile(VirtualFile parent, String name) {
        this.parent = parent;
        this.name = name;
        if (name != null & parent != null) {
            try {
                if (parent.toUri() != null) {
                    this.uri = new URI(parent.toUri() + "/" + name);
                } else {
                    this.uri = new URI(name.replace("\\", "/"));
                }
            } catch (URISyntaxException e) {
                LOGGER.error("", e);
            }
        } else {
            uri = null;
        }
    }

    public VirtualFile(File file) throws IOException {
        this(null, file);
    }

    public VirtualFile(VirtualFile parent, File file) throws IOException {
        this.parent = parent;
        this.name = file.getName();
        if (file.isDirectory()) {
            for (File f : file.listFiles()) {
                files.put(f.getName(), new VirtualFile(this, f));
            }
        } else {
            setData(FileUtils.readFileToByteArray(file));
        }
    }

    public VirtualFile createFile(String path) {
        if (path.startsWith("/")) {
            path = path.substring(1);
        }
        if (path.contains(File.separator)) {
            String newName = path.substring(0, path.indexOf(File.separator));
            if (files.containsKey(newName)) {
                VirtualFile virtualFile = files.get(newName);
                return virtualFile.createFile(path.substring(path.indexOf(File.separator) + 1));
            } else {
                VirtualFile virtualFile = new VirtualFile(this, newName);
                files.put(newName, virtualFile);
                return virtualFile.createFile(path.substring(path.indexOf(File.separator) + 1));
            }
        } else {
            VirtualFile virtualFile = new VirtualFile(this, path);
            if (path.endsWith(".java")) {
                sourceFiles.add(virtualFile);
            }
            files.put(path, virtualFile);
            return virtualFile;
        }
    }

    public void setStringContent(String content) {
        data = content.getBytes(Charsets.UTF_8);
    }

    public OutputStream openOutputStream() {
        return new ByteArrayOutputStream() {
            @Override
            public void close() throws IOException {
                super.close();
                data = this.toByteArray();
            }
        };
    }

    public void createJar(OutputStream outputStream) {
        try {
            JarOutputStream jarOutputStream = new JarOutputStream(outputStream);
            createJar(jarOutputStream);
            jarOutputStream.finish();
        } catch (IOException e) {
            LOGGER.error("", e);
        }
    }

    public void dumpToDir(File dir) {
        if (isDirectory()) {
            dir.mkdir();
            for (VirtualFile virtualFile : files.values()) {
                virtualFile.dumpToDir(new File(dir, virtualFile.name));
            }
        } else {
            try {
                FileOutputStream fos = new FileOutputStream(dir);
                ByteArrayInputStream bais = new ByteArrayInputStream(data);
                IOUtils.copy(bais, fos);
                fos.close();
            } catch (FileNotFoundException e) {
                LOGGER.error("", e);
            } catch (IOException e) {
                LOGGER.error("", e);
            }
        }
    }

    private void createJar(JarOutputStream jarOutputStream) throws IOException {
        for (VirtualFile virtualFile : files.values()) {
            if (virtualFile.isDirectory()) {
                virtualFile.createJar(jarOutputStream);
            } else {
                JarEntry jarEntry = new JarEntry(virtualFile.getName().replace(File.separator, "/"));
                jarOutputStream.putNextEntry(jarEntry);
                InputStream inputStream = virtualFile.openInputStream();
                IOUtils.copy(inputStream, jarOutputStream);
                inputStream.close();
            }
        }
    }

    public InputStream openInputStream() {
        return new ByteArrayInputStream(data);
    }

    public Collection<VirtualFile> listFiles() {
        return files.values();
    }

    public boolean isDirectory() {
        return files.size() != 0;
    }

    public String getName() {
        if (parent != null && parent.getName() != null) {
            return parent.getName() + "/" + name;
        } else {
            return name;
        }
    }

    public List<VirtualFile> getAllJavaFileObjects() {
        List<VirtualFile> list = new ArrayList<VirtualFile>(sourceFiles);
        for (VirtualFile virtualFile : files.values()) {
            if (virtualFile.isDirectory()) {
                list.addAll(virtualFile.getAllJavaFileObjects());
            }
        }
        return list;
    }

    @Override
    public Modifier getAccessLevel() {
        return Modifier.PUBLIC;
    }

    @Override
    public Kind getKind() {
        if (name.endsWith(".java")) {
            return Kind.SOURCE;
        } else if (name.endsWith(".class")) {
            return Kind.CLASS;
        } else if (name.endsWith(".html")) {
            return Kind.HTML;
        } else {
            return Kind.OTHER;
        }
    }

    @Override
    public NestingKind getNestingKind() {
        return NestingKind.TOP_LEVEL;
    }

    @Override
    public boolean isNameCompatible(String simpleName, Kind kind) {
        return true;
    }

    @Override
    public boolean delete() {
        return parent.remove(this);
    }

    private boolean remove(VirtualFile virtualFile) {
        return files.remove(virtualFile.getName()) != null;
    }

    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors) {
        return new String(data, Charsets.UTF_8);
    }

    @Override
    public long getLastModified() {
        return 0;
    }

    @Override
    public Reader openReader(boolean ignoreEncodingErrors) {
        return new StringReader(new String(data, Charsets.UTF_8));
    }

    @Override
    public Writer openWriter() throws IOException {
        return new StringWriter() {
            @Override
            public void close() throws IOException {
                super.close();
                data = this.toString().getBytes(Charsets.UTF_8);
            }
        };
    }

    @Override
    public URI toUri() {
        return uri;
    }

    public String getPackageName() {
        String name = getName();
        return name.replace("/", ".");
    }

    public Collection<VirtualFile> getFiles() {
        return files.values();
    }

    public Collection<VirtualFile> getFiles(Set<Kind> kinds) {
        ArrayList<VirtualFile> list = new ArrayList<VirtualFile>();
        for (VirtualFile f : files.values()) {
            for (Kind kind : kinds) {
                if (f.name.endsWith(kind.extension.toLowerCase())) {
                    if (f.name.endsWith(".class")) {
                        list.add(f);
                    }
                }
            }
        }
        return list;
    }

    public void integrate(VirtualFile baseDir) {
        if (baseDir.isDirectory()) {
            for (VirtualFile file : baseDir.getFiles()) {
                if (files.containsKey(file.name)) {
                    if (file.isDirectory()) {
                        files.get(file.name).integrate(file);
                    } else {
                        files.get(file.name).add(file);
                    }
                } else {
                    files.put(file.name, file);
                    file.parent = this;
                }
            }
        }
    }

    private void add(VirtualFile file) {
        files.put(file.name, file);
    }

    @Override
    public String toString() {
        return uri.toString();
    }

    public Collection<VirtualFile> getFiles(Set<Kind> kinds, String path) {
        if (path.contains("/")) {
            String substring = path.substring(0, path.indexOf("/"));
            if (files.containsKey(substring)) {
                return files.get(substring).getFiles(kinds, path.substring(path.indexOf("/") + 1));
            }
        } else {
            if (files.containsKey(path)) {
                return files.get(path).getFiles(kinds);
            }
        }
        return new ArrayList<VirtualFile>();
    }

    public String getSimpleName() {
        return name;
    }

    public String getCleanName() {
        String name = getName();
        if (name.contains(".")) {
            name = name.substring(0, name.indexOf("."));
        }
        return name.replace("/", ".");
    }

    public boolean containsType(String path) {
        if (path.contains("/")) {
            String newName = path.substring(0, path.indexOf("/"));
            if (files.containsKey(newName)) {
                return files.get(newName).containsType(path.substring(path.indexOf("/") + 1));
            } else {
                return false;
            }
        } else {
            return files.containsKey(path);
        }
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((uri == null) ? 0 : uri.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        VirtualFile other = (VirtualFile) obj;
        if (uri == null) {
            if (other.uri != null)
                return false;
        } else if (!uri.equals(other.uri))
            return false;
        return true;
    }

    public VirtualFile get(String name) {
        return files.get(name);
    }

    public VirtualFile getClass(String name) {
        if (name.contains(".")) {
            VirtualFile virtualFile = files.get(name.substring(0, name.indexOf(".")));
            if (virtualFile == null) {
                throw new RuntimeException("Not found: " + name);
            }
            return virtualFile.getClass(name.substring(name.indexOf(".") + 1));
        }
        return files.get(name + ".class");
    }

    public byte[] getData() {
        return data;
    }

    public static VirtualFile fromJar(File file) throws IOException {
        return fromJar(new FileInputStream(file));
    }

    public static VirtualFile fromJar(InputStream inputStream) throws IOException {
        VirtualFile result = new VirtualFile();
        JarInputStream jarInputStream = new JarInputStream(inputStream);
        JarEntry jarEntry = jarInputStream.getNextJarEntry();
        while (jarEntry != null) {
            String n = jarEntry.getName();
            n = n.replace("/", File.separator);
            n = n.replace("\\", File.separator);
            VirtualFile newFile = result.createFile(n);
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            IOUtils.copy(jarInputStream, byteArrayOutputStream);
            newFile.setData(byteArrayOutputStream.toByteArray());
            jarEntry = jarInputStream.getNextJarEntry();
        }
        return result;
    }

    public void setData(byte[] data) {
        this.data = data;
    }

    public void add(File file) {

    }

    public static VirtualFile fromDirectory(File file) throws IOException {
        return new VirtualFile(file);
    }

    public void copyTo(VirtualFile virtualFile) {
        // TODO
    }

    public void setData(InputStream inputStream) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        IOUtils.copy(inputStream, output);
        setData(output.toByteArray());
        inputStream.close();
    }
}