fr.obeo.acceleo.tools.resources.Resources.java Source code

Java tutorial

Introduction

Here is the source code for fr.obeo.acceleo.tools.resources.Resources.java

Source

/*
 * Copyright (c) 2005-2008 Obeo
 * 
 * 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:
 *    Obeo - initial API and implementation
 */

package fr.obeo.acceleo.tools.resources;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.osgi.framework.Constants;

import fr.obeo.acceleo.tools.AcceleoToolsPlugin;

/**
 * It helps to use workspace resources.
 * 
 * @author www.obeo.fr
 */
public class Resources {

    private static final String INSTALL_LOCATION_TAG = "INSTALL_LOCATION"; //$NON-NLS-1$

    private static final String WORKSPACE_LOCATION_TAG = "WORKSPACE_LOCATION"; //$NON-NLS-1$

    private static final int BOM_SIZE = 3;

    /**
     * Returns the content of the file.
     * 
     * @param file
     *            is the file
     * @return the content of the file, or an empty buffer if the file doesn't
     *         exist
     */
    public static StringBuffer getFileContent(IFile file) {
        return Resources.getFileContent(file, true);
    }

    /**
     * Returns the content of the file.
     * 
     * @param file
     *            is the file
     * @param report
     *            indicates if an error is reported when the file doesn't exist
     * @return the content of the file, or an empty buffer if the file doesn't
     *         exist
     */
    public static StringBuffer getFileContent(IFile file, boolean report) {
        StringBuffer buffer = Resources.doGetFileContent(file, report);
        if (file != null && Resources.isTemplateFile(file.getName()) && Resources.getEncoding(buffer) != null) {
            buffer = Resources.getEncodedFileContent(file, report, Resources.getEncoding(buffer));
        }
        return buffer;
    }

    /**
     * Returns the content of the file.
     * 
     * @param file
     *            is the file
     * @param report
     *            indicates if an error is reported when the file doesn't exist
     * @return the content of the file, or an empty buffer if the file doesn't
     *         exist
     */
    private static StringBuffer doGetFileContent(IFile file, boolean report) {
        StringBuffer buffer = new StringBuffer();
        if (file != null) {

            UnicodeBOMInputStream ubis = null;
            InputStream content = null;
            try {
                content = file.getContents(false);
                ubis = new UnicodeBOMInputStream(content);
                ubis.skipBOM();
                byte[] readBuffer = new byte[ubis.available()];
                int n = ubis.read(readBuffer);
                while (n > 0) {
                    buffer.append(new String(readBuffer));
                    n = ubis.read(readBuffer);
                }
            } catch (Exception e) {
                if (report) {
                    AcceleoToolsPlugin.getDefault().log(e, true);
                }
            } finally {
                if (ubis != null) {
                    try {
                        ubis.close();
                    } catch (IOException e) {
                        if (report) {
                            AcceleoToolsPlugin.getDefault().log(e, true);
                        }
                    }
                }
                if (content != null) {
                    try {
                        content.close();
                    } catch (IOException e) {
                        if (report) {
                            AcceleoToolsPlugin.getDefault().log(e, true);
                        }
                    }
                }
            }
        }
        return buffer;
    }

    /**
     * Returns the content of the file.
     * 
     * @param file
     *            is the file
     * @return the content of the file, or an empty buffer if the file doesn't
     *         exist
     */
    public static StringBuffer getFileContent(File file) {
        return Resources.getFileContent(file, true);
    }

    /**
     * Returns the content of the file.
     * 
     * @param file
     *            is the file
     * @param report
     *            indicates if an error is reported when the file doesn't exist
     * @return the content of the file, or an empty buffer if the file doesn't
     *         exist
     */
    public static StringBuffer getFileContent(File file, boolean report) {
        StringBuffer buffer = Resources.doGetFileContent(file, report);
        String encoding = Resources.getEncoding(buffer);
        if (file != null && Resources.isTemplateFile(file.getName()) && encoding != null) {
            buffer = Resources.getEncodedFileContent(file, report, encoding);
        }
        return buffer;
    }

    /**
     * @param file
     *            any file (existing or not).
     * @return true if this file is an Acceleo Template file, false otherwise.
     */
    private static boolean isTemplateFile(String filename) {
        if (filename != null) {
            if (filename.toLowerCase().endsWith("mt")) { //$NON-NLS-1$
                return true;
            }
            if (filename.toLowerCase().endsWith("tr")) { //$NON-NLS-1$
                return true;
            }
        }
        return false;
    }

    /**
     * Return the content of an {@link IFile} using the specified encoding.
     * 
     * @param file
     *            file to read.
     * @param report
     *            if it's set to true, any error will get reported, otherwise
     *            some errors may appear silently.
     * @param encodingCode
     *            encodingCode to use in order to read the file.
     * @return an unicode {@link StringBuffer} of the file content.
     */
    public static StringBuffer getEncodedFileContent(File file, boolean report, String encodingCode) {
        StringBuffer buffer = new StringBuffer();
        FileInputStream fiss;
        UnicodeBOMInputStream fis;
        try {
            fiss = new FileInputStream(file);
            fis = new UnicodeBOMInputStream(fiss);
            fis.skipBOM();
            InputStreamReader in = new InputStreamReader(fis, encodingCode);
            try {
                char[] buff = new char[512];
                int size = in.read(buff);
                while (size > 0) {
                    buffer.append(buff, 0, size);
                    size = in.read(buff);
                }
            } finally {
                if (in != null) {
                    in.close();
                }
                if (fiss != null) {
                    fiss.close();
                }
                if (fis != null) {
                    fis.close();
                }
            }
        } catch (IOException e) {
            if (report && !(e instanceof UnsupportedEncodingException)) {
                AcceleoToolsPlugin.getDefault().log(e, true);
            }
        }

        return buffer;
    }

    /**
     * Return the content of an {@link IFile} using the specified encoding.
     * 
     * @param file
     *            file to read.
     * @param report
     *            if it's set to true, any error will get reported, otherwise
     *            some errors may appear silently.
     * @param encodingCode
     *            encodingCode to use in order to read the file.
     * @return an unicode {@link StringBuffer} of the file content.
     */
    public static StringBuffer getEncodedFileContent(IFile file, boolean report, String encodingCode) {
        StringBuffer buffer = new StringBuffer();
        if (file != null) {
            UnicodeBOMInputStream content = null;
            try {
                content = new UnicodeBOMInputStream(file.getContents(false));
                content.skipBOM();
                /*
                 * create an InputStreamReader specifying an encoding.
                 */
                InputStreamReader in = new InputStreamReader(content, encodingCode);
                try {
                    char[] buff = new char[content.available()];
                    int size = in.read(buff);
                    while (size > 0) {
                        buffer.append(buff, 0, size);
                        size = in.read(buff);
                    }
                } finally {
                    if (in != null) {
                        in.close();
                    }
                }
            } catch (Exception e) {
                if (report) {
                    AcceleoToolsPlugin.getDefault().log(e, true);
                }
            } finally {
                if (content != null) {
                    try {
                        content.close();
                    } catch (IOException e) {
                        if (report && !(e instanceof UnsupportedEncodingException)) {
                            AcceleoToolsPlugin.getDefault().log(e, true);
                        }
                    }
                }
            }
        }
        return buffer;
    }

    /**
     * Returns the content of the file.
     * 
     * @param file
     *            is the file
     * @param report
     *            indicates if an error is reported when the file doesn't exist
     * @return the content of the file, or an empty buffer if the file doesn't
     *         exist
     */
    private static StringBuffer doGetFileContent(File file, boolean report) {
        StringBuffer buffer = new StringBuffer();
        try {
            FileInputStream fis = new FileInputStream(file);
            UnicodeBOMInputStream ubis = new UnicodeBOMInputStream(fis);
            ubis.skipBOM();
            BufferedReader in = new BufferedReader(new InputStreamReader(ubis));
            try {
                char[] buff = new char[512];
                int size = in.read(buff);
                while (size > 0) {
                    buffer.append(buff, 0, size);
                    size = in.read(buff);
                }
            } finally {
                if (in != null) {
                    in.close();
                }
                if (fis != null) {
                    fis.close();
                }
                if (ubis != null) {
                    ubis.close();
                }
            }
        } catch (IOException e) {
            if (report) {
                AcceleoToolsPlugin.getDefault().log(e, true);
            }
        }
        return buffer;
    }

    /**
     * Gets the default output of the project.
     * 
     * @param project
     *            is the project
     * @return the default output of the project, or null if it doesn't exist
     */
    public static IFolder getOutputFolder(IProject project) {
        final IJavaProject projet = JavaCore.create(project);
        try {
            IPath output = projet.getOutputLocation();
            if (output != null && output.segmentCount() > 1) {
                IFolder folder = project.getWorkspace().getRoot().getFolder(output);
                if (folder.exists()) {
                    return folder;
                } else {
                    return null;
                }
            } else {
                return null;
            }
        } catch (JavaModelException e) {
            return null;
        }
    }

    /**
     * Creates and load a persistent EMF document for a resource in the
     * workspace.
     * 
     * @param resource
     *            is the resource in the workspace
     * @param load
     *            indicates if the persistent EMF document is loaded
     * @return the persistent EMF document
     */
    public static Resource getResource(IResource resource, boolean load) {
        ResourceSetImpl resourceSet = new ResourceSetImpl();
        Resource result = resourceSet
                .getResource(Resources.createPlatformResourceURI(resource.getFullPath().toString()), load);
        // EcoreUtil.resolveAll(resourceSet);
        return result;
    }

    /**
     * Gets the resource in the workspace for a persistent EMF document.
     * 
     * @param resource
     *            is the persistent EMF document
     * @return the resource in the workspace
     */
    public static IFile getIFile(Resource resource) {
        URI uri = resource.getURI();
        if ("cdo".equals(uri.scheme())) { //$NON-NLS-1$
            if (resource.getURI().path() != null) {
                if (resource.getURI().path() != null) {
                    IPath path = Path.fromPortableString(resource.getURI().path());
                    IContainer folder = (IContainer) ResourcesPlugin.getWorkspace().getRoot()
                            .findMember(path.removeLastSegments(1));
                    if (folder != null) {
                        path = path.removeFirstSegments(path.segmentCount() - 1);
                        if ("system".equals(path.getFileExtension())) { //$NON-NLS-1$
                            path = path.removeFileExtension().removeFileExtension().addFileExtension("system") //$NON-NLS-1$
                                    .addFileExtension("ost"); //$NON-NLS-1$
                        } else if ("xmi".equals(path.getFileExtension())) { //$NON-NLS-1$
                            path = path.removeFileExtension().addFileExtension("ost"); //$NON-NLS-1$
                        }
                        return folder.getFile(path);
                    }
                }
            }
        } else {
            String path = uri.path();
            if (path != null) {
                if (path.startsWith("/resource")) { //$NON-NLS-1$
                    path = path.substring("/resource".length()); //$NON-NLS-1$
                }
                IResource member = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
                if (member instanceof IFile) {
                    return (IFile) member;
                }
            }
        }
        return null;
    }

    /**
     * Finds and returns the member resource identified by the given path in the
     * workspace, or null if no such resource exists.
     * 
     * @param path
     *            is the path of the desired resource
     * @return the member resource, or null if no such resource exists
     */
    public static IResource findResource(IPath path) {
        IWorkspace workspace = ResourcesPlugin.getWorkspace();
        if (workspace.getRoot().exists(path)) {
            return workspace.getRoot().findMember(path);
        } else {
            return null;
        }
    }

    /**
     * Finds and returns the file identified by the given path in the workspace,
     * or null if no such file exists.
     * 
     * @param path
     *            is the path of the desired resource
     * @return the member file, or null if no such resource exists
     */
    public static IFile findFile(IPath path) {
        IResource resource = Resources.findResource(path);
        if (resource instanceof IFile) {
            return (IFile) resource;
        } else {
            return null;
        }
    }

    /**
     * Creates a platform-relative path URI.
     * 
     * @param path
     *            is the path of the URI to create
     * @return the new URI
     * @see org.eclipse.emf.common.util.URI#createPlatformResourceURI
     */
    public static URI createPlatformResourceURI(String path) {
        if (path.startsWith("platform:/plugin")) { //$NON-NLS-1$
            return URI.createURI(path, true);
        } else {
            return URI.createPlatformResourceURI(path, true);
        }
    }

    /**
     * Creates relative path from absolute. Resolve relative pathnames against
     * workspace directory.
     * 
     * @param absolutePath
     *            absolute file path (directory or file).
     * @return relative path if workspace directory is included in absolutePath,
     *         otherwise return absolute path.
     */
    public static String makeWorkspaceRelativePath(String absolutePath) {
        return Resources.makeRelativePath(ResourcesPlugin.getWorkspace().getRoot().getLocation().toOSString(),
                absolutePath);
    }

    /**
     * Creates relative path from absolute. Resolve relative pathnames against
     * parent directory.
     * 
     * @param parentPath
     *            parent directory path.
     * @param absolutePath
     *            absolute file path (directory or file).
     * @return relative path if parent directory is included in absolutePath,
     *         otherwise return absolute path.
     */
    public static String makeRelativePath(String parentPath, String absolutePath) {
        String relativePath = null;
        if (parentPath != null && absolutePath != null && parentPath.length() < absolutePath.length()) {
            File absoluteFile = new File(absolutePath);
            if (absoluteFile.isAbsolute()) {
                File parentFile = new File(parentPath);
                if (parentFile.isAbsolute()) {
                    String dirPath = parentFile.getAbsolutePath().replace('\\', '/');
                    absolutePath = absolutePath.replace('\\', '/');
                    int dirLength = dirPath.length();
                    if (absolutePath.substring(0, dirLength).equalsIgnoreCase(dirPath)) {
                        relativePath = absolutePath.substring(dirLength);
                        if (relativePath.startsWith("/")) { //$NON-NLS-1$
                            relativePath = relativePath.substring(1);
                        }
                    }
                } else {
                    relativePath = absoluteFile.getPath().replace('\\', '/');
                }
            } else {
                relativePath = absoluteFile.getPath().replace('\\', '/');
            }
        } else {
            if (absolutePath != null) {
                relativePath = absolutePath.replace('\\', '/');
            }
        }
        return relativePath;
    }

    /**
     * Creates the absolute path.
     * 
     * @param url
     *            is the relative path
     * @return the absolute file path
     */
    public static String transformToAbsolutePath(URL url) {
        String absolutePath;
        try {
            URL transformedUrl = FileLocator.toFileURL(url);
            File file = new File(transformedUrl.getFile());
            absolutePath = file.getAbsolutePath();
        } catch (IOException e) {
            absolutePath = ""; //$NON-NLS-1$
            AcceleoToolsPlugin.getDefault().log(e, true);
        }
        return absolutePath;
    }

    /**
     * Get the IFile for the URI.
     * 
     * @param uri
     *            is the URI
     * @return the IFile if the URI is a project form, or null if not a project
     *         form, OR the project doesn't exist.The IFile returned doesn't
     *         necessarily exist.
     */
    public static IFile getIFile(URI uri) {
        IProject project = Resources.getProject(uri);
        if (project != null) {
            IPath path;
            if (Resources.isPlatformResourceURI(uri)) {
                // remove /resource/project name/
                path = new Path(URI.decode(uri.path())).removeFirstSegments(2);
            } else {
                // remove /project name/
                path = new Path(URI.decode(uri.path())).removeFirstSegments(1);
            }
            return project.getFile(path);
        } else {
            return null;
        }
    }

    private static IProject getProject(URI uri) {
        String projectName;
        if (Resources.isPlatformResourceURI(uri)) {
            projectName = uri.segment(1);
        } else if (uri.scheme() == null) {
            projectName = new Path(uri.path()).segment(0); // project name is
            // first in the URI
        } else {
            return null;
        }
        IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(URI.decode(projectName));
        if (project != null && project.isAccessible()) {
            return project;
        } else {
            return null;
        }
    }

    private static boolean isPlatformResourceURI(URI uri) {
        return "platform".equals(uri.scheme()) && "resource".equals(uri.segment(0)); //$NON-NLS-1$ //$NON-NLS-2$
    }

    /**
     * Gets the required plugins for the given project.
     * 
     * @param project
     *            is the project
     * @return the IDs of the required plugins
     */
    public static String[] getRequiredPluginIDs(IProject project) {
        List IDs = new ArrayList();
        IFile file = project.getFile(JarFile.MANIFEST_NAME);
        Double cachedTimestamp = (Double) Resources.fileTimestamp.get(file);
        if (cachedTimestamp != null
                && file.getModificationStamp() + file.getLocalTimeStamp() == cachedTimestamp.longValue()) {
            IDs = (List) Resources.fileRequired.get(file);
        } else {
            if (file.exists()) {
                InputStream manifestStream = null;
                try {
                    manifestStream = new FileInputStream(file.getLocation().toFile());
                    Manifest manifest = new Manifest(manifestStream);
                    Properties prop = Resources.manifestToProperties(manifest.getMainAttributes());
                    String requiredBundles = (String) prop.get(Constants.REQUIRE_BUNDLE);
                    if (requiredBundles != null) {
                        StringTokenizer st = new StringTokenizer(requiredBundles, ","); //$NON-NLS-1$
                        while (st.hasMoreTokens()) {
                            String id = st.nextToken().trim();
                            int iDot = id.indexOf(';');
                            if (iDot > -1) {
                                id = id.substring(0, iDot).trim();
                            }
                            if (id.length() > 0) {
                                IDs.add(id);
                            }
                        }
                    }
                } catch (FileNotFoundException e) {
                } catch (IOException e) {
                } finally {
                    try {
                        if (manifestStream != null) {
                            manifestStream.close();
                        }
                    } catch (IOException e) {
                    }
                }
            }
            Resources.fileTimestamp.put(file, new Double(file.getModificationStamp() + file.getLocalTimeStamp()));
            Resources.fileRequired.put(file, IDs);
        }
        return (String[]) IDs.toArray(new String[IDs.size()]);
    }

    /**
     * Cache map File -> time stamp.
     */
    private static Map fileTimestamp = new HashMap();

    /**
     * Cache file -> required plug-in.
     */
    private static Map fileRequired = new HashMap();

    private static Properties manifestToProperties(Attributes d) {
        Iterator iter = d.keySet().iterator();
        Properties result = new Properties();
        while (iter.hasNext()) {
            Attributes.Name key = (Attributes.Name) iter.next();
            result.put(key.toString(), d.get(key));
        }
        return result;
    }

    /**
     * Decodes an acceleo path, it replaces the acceleo tags by the workspace
     * location or the platform location.
     * 
     * @param path
     *            is the path to decode
     * @return the absolute path
     * @see encodeAcceleoAbsolutePath
     */
    public static String decodeAcceleoAbsolutePath(String path) {
        if (path == null) {
            return path;
        } else {
            if (path.startsWith(Resources.WORKSPACE_LOCATION_TAG)) {
                String workspaceLocation;
                if (ResourcesPlugin.getWorkspace().getRoot().getLocation() != null) {
                    workspaceLocation = ResourcesPlugin.getWorkspace().getRoot().getLocation().toString();
                } else {
                    workspaceLocation = ""; //$NON-NLS-1$
                }
                return workspaceLocation + path.substring(Resources.WORKSPACE_LOCATION_TAG.length());
            } else if (path.startsWith(Resources.INSTALL_LOCATION_TAG)) {
                String installLocation;
                if (Platform.getInstallLocation() != null) {
                    installLocation = new Path(
                            Resources.transformToAbsolutePath(Platform.getInstallLocation().getURL())).toString();
                } else {
                    installLocation = ""; //$NON-NLS-1$
                }
                return installLocation + path.substring(Resources.INSTALL_LOCATION_TAG.length());
            } else {
                return path;
            }
        }
    }

    /**
     * Encodes an absolute path, it replaces the workspace location or the
     * platform location by an acceleo tag.
     * 
     * @param path
     *            is the path to encode
     * @return the acceleo path
     * @see decodeAcceleoAbsolutePath
     */
    public static String encodeAcceleoAbsolutePath(String path) {
        if (path == null) {
            return path;
        } else {
            path = new Path(path).toString();
            String workspaceLocation = null;
            if (ResourcesPlugin.getWorkspace().getRoot().getLocation() != null) {
                workspaceLocation = ResourcesPlugin.getWorkspace().getRoot().getLocation().toString();
            }
            if (workspaceLocation != null && path.startsWith(workspaceLocation)) {
                return Resources.WORKSPACE_LOCATION_TAG + path.substring(workspaceLocation.length());
            } else {
                String installLocation = null;
                if (Platform.getInstallLocation() != null) {
                    installLocation = new Path(
                            Resources.transformToAbsolutePath(Platform.getInstallLocation().getURL())).toString();
                }
                if (installLocation != null && path.startsWith(installLocation)) {
                    return Resources.INSTALL_LOCATION_TAG + path.substring(installLocation.length());
                } else {
                    return path;
                }
            }
        }
    }

    /**
     * Encoding specification start marker, used in MT templates to indicate to
     * Acceleo in which encoding the file should be loaded.
     */
    private static final String ENCODING_START = "encoding=";//$NON-NLS-1$

    /**
     * @param buffer
     *            buffer in which we want to look for an encoding code.
     * @return a {@link String} having an encoding code as value (be carefull it
     *         may be a wrong code, you'll have to check by yourself). It may
     *         return null if no encoding code is found.
     */
    public static String getEncoding(StringBuffer buffer) {
        String startMarker = "<%--"; //$NON-NLS-1$
        String endMarker = "--%>"; //$NON-NLS-1$
        String result = Resources.doGetEncoding(buffer, startMarker, endMarker);
        if (result == null) {
            startMarker = "[%--"; //$NON-NLS-1$
            endMarker = "--%]"; //$NON-NLS-1$
            result = Resources.doGetEncoding(buffer, startMarker, endMarker);
        }
        return result;
    }

    /**
     * Look for an encoding specification in a buffer using start and end
     * markers.
     * 
     * @param buffer
     *            buffer in which we want to look for an encoding code.
     * @param startMarker
     *            start marker of the language.
     * @param endMarker
     *            end marker of the language.
     * @return the found encoding code or null.
     */
    private static String doGetEncoding(StringBuffer buffer, String startMarker, String endMarker) {
        int start = buffer.indexOf(startMarker + Resources.ENCODING_START);
        if (start != -1) {
            int end = buffer.indexOf(endMarker, start);
            if (end != -1) {
                String encoding = buffer.substring(start + (startMarker + Resources.ENCODING_START).length(), end);
                return encoding.trim().toUpperCase();
            }
        }
        return null;
    }
}