Package bndtools.central

Source Code of bndtools.central.Central

package bndtools.central;

import java.io.File;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;

import org.bndtools.api.BndtoolsConstants;
import org.bndtools.api.ILogger;
import org.bndtools.api.IStartupParticipant;
import org.bndtools.api.Logger;
import org.bndtools.api.ModelListener;
import org.bndtools.utils.Function;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.Version;

import aQute.bnd.build.Project;
import aQute.bnd.build.Workspace;
import aQute.bnd.build.WorkspaceRepository;
import aQute.bnd.osgi.Constants;
import aQute.bnd.service.Refreshable;
import aQute.bnd.service.RepositoryPlugin;

public class Central implements IStartupParticipant {

    private static final ILogger logger = Logger.getLogger(Central.class);

    private static Central instance = null;

    static Workspace workspace = null;
    static final List<Function<Workspace,Void>> workspaceInitCallbackQueue = new LinkedList<Function<Workspace,Void>>();

    static WorkspaceR5Repository r5Repository = null;
    static RepositoryPlugin workspaceRepo = null;

    static final AtomicBoolean indexValid = new AtomicBoolean(false);
    static final ConcurrentMap<String,Map<String,SortedSet<Version>>> exportedPackageMap = new ConcurrentHashMap<String,Map<String,SortedSet<Version>>>();
    static final ConcurrentMap<String,Collection<String>> containedPackageMap = new ConcurrentHashMap<String,Collection<String>>();
    static final ConcurrentMap<String,Collection<IResource>> sourceFolderMap = new ConcurrentHashMap<String,Collection<IResource>>();

    private final BundleContext bundleContext;
    private final Map<IJavaProject,Project> javaProjectToModel = new HashMap<IJavaProject,Project>();
    private final List<ModelListener> listeners = new CopyOnWriteArrayList<ModelListener>();

    private RepositoryListenerPluginTracker repoListenerTracker;

    /**
     * WARNING: Do not instantiate this class. It must be public to allow instantiation by the Eclipse registry, but it
     * is not intended for direct creation by clients. Instead call Central.getInstance().
     */
    @Deprecated
    public Central() {
        bundleContext = FrameworkUtil.getBundle(Central.class).getBundleContext();
    }

    @Override
    public void start() {
        synchronized (Central.class) {
            instance = this;
        }

        repoListenerTracker = new RepositoryListenerPluginTracker(bundleContext);
        repoListenerTracker.open();
    }

    @Override
    public void stop() {
        repoListenerTracker.close();

        synchronized (Central.class) {
            instance = null;
        }
    }

    public static Central getInstance() {
        synchronized (Central.class) {
            return instance;
        }
    }

    public Project getModel(IJavaProject project) {
        try {
            Project model = javaProjectToModel.get(project);
            if (model == null) {
                File projectDir = project.getProject().getLocation().makeAbsolute().toFile();
                try {
                    model = getProject(projectDir);
                } catch (IllegalArgumentException e) {
                    // initialiseWorkspace();
                    // model = Central.getProject(projectDir);
                    return null;
                }
                if (workspace == null) {
                    model.getWorkspace();
                }
                if (model != null) {
                    javaProjectToModel.put(project, model);
                }
            }
            return model;
        } catch (Exception e) {
            // TODO do something more useful here
            throw new RuntimeException(e);
        }
    }

    /**
     * Implementation of the resource changed interface. We are checking in the POST_CHANGE phase if one of our tracked
     * models needs to be updated.
     */
    public synchronized void resourceChanged(IResourceChangeEvent event) {
        if (event.getType() != IResourceChangeEvent.POST_CHANGE)
            return;

        IResourceDelta rootDelta = event.getDelta();
        try {
            final Set<Project> changed = new HashSet<Project>();
            rootDelta.accept(new IResourceDeltaVisitor() {
                @Override
                public boolean visit(IResourceDelta delta) throws CoreException {
                    try {

                        IPath location = delta.getResource().getLocation();
                        if (location == null) {
                            System.out.println("Cannot convert resource to file: " + delta.getResource());
                        } else {
                            File file = location.toFile();
                            File parent = file.getParentFile();
                            boolean parentIsWorkspace = parent.equals(getWorkspace().getBase());

                            // file
                            // /development/osgi/svn/build/org.osgi.test.cases.distribution/bnd.bnd
                            // parent
                            // /development/osgi/svn/build/org.osgi.test.cases.distribution
                            // workspace /development/amf/workspaces/osgi
                            // false

                            if (parentIsWorkspace) {
                                // We now are on project level, we do not go
                                // deeper
                                // because projects/workspaces should check for
                                // any
                                // changes.
                                // We are careful not to create unnecessary
                                // projects
                                // here.
                                if (file.getName().equals(Workspace.CNFDIR)) {
                                    if (workspace.refresh()) {
                                        changed.addAll(workspace.getCurrentProjects());
                                    }
                                    return false;
                                }
                                if (workspace.isPresent(file.getName())) {
                                    Project project = workspace.getProject(file.getName());
                                    changed.add(project);
                                } else {
                                    // Project not created yet, so we
                                    // have
                                    // no cached results

                                }
                                return false;
                            }
                        }
                        return true;
                    } catch (Exception e) {
                        e.printStackTrace();
                        throw new CoreException(new Status(Status.ERROR, BndtoolsConstants.CORE_PLUGIN_ID, "During checking project changes", e));
                    }
                }

            });

            for (Project p : changed) {
                p.refresh();
                changed(p);

            }
        } catch (CoreException e) {
            logger.logError("While handling changes", e);
        }
    }

    public static IFile getWorkspaceBuildFile() throws Exception {
        File file = Central.getWorkspace().getPropertiesFile();
        IFile[] matches = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(file.toURI());

        if (matches == null || matches.length != 1) {
            logger.logError("Cannot find workspace location for bnd configuration file " + file, null);
            return null;
        }

        return matches[0];
    }

    public synchronized static WorkspaceR5Repository getWorkspaceR5Repository() throws Exception {
        if (r5Repository != null)
            return r5Repository;

        r5Repository = new WorkspaceR5Repository();
        r5Repository.init();

        return r5Repository;
    }

    public synchronized static RepositoryPlugin getWorkspaceRepository() throws Exception {
        if (workspaceRepo != null)
            return workspaceRepo;

        workspaceRepo = new WorkspaceRepository(getWorkspace());
        return workspaceRepo;
    }

    public synchronized static Workspace getWorkspace() throws Exception {
        if (instance == null)
            throw new IllegalStateException("Central has not been initialised");

        if (workspace != null)
            return workspace;

        Workspace newWorkspace = null;

        try {
            Workspace.setDriver(Constants.BNDDRIVER_ECLIPSE);
            newWorkspace = Workspace.getWorkspace(getWorkspaceDirectory());

            newWorkspace.addBasicPlugin(new WorkspaceListener(newWorkspace));
            newWorkspace.addBasicPlugin(instance.repoListenerTracker);
            newWorkspace.addBasicPlugin(getWorkspaceR5Repository());

            // Initialize projects in synchronized block
            newWorkspace.getBuildOrder();

            // Monitor changes in cnf so we can refresh the workspace
            addCnfChangeListener(newWorkspace);

            // The workspace has been initialized fully, set the field now
            workspace = newWorkspace;

            // Call the queued workspace init callbacks
            while (!workspaceInitCallbackQueue.isEmpty()) {
                Function<Workspace,Void> callback = workspaceInitCallbackQueue.remove(0);
                callback.run(workspace);
            }

            return workspace;
        } catch (final Exception e) {
            if (newWorkspace != null) {
                newWorkspace.close();
            }
            throw e;
        }
    }

    public synchronized static void onWorkspaceInit(Function<Workspace,Void> callback) {
        if (workspace != null)
            callback.run(workspace);
        else
            workspaceInitCallbackQueue.add(callback);
    }

    private static File getWorkspaceDirectory() throws CoreException {
        IWorkspaceRoot eclipseWorkspace = ResourcesPlugin.getWorkspace().getRoot();

        IProject cnfProject = eclipseWorkspace.getProject("bnd");
        if (!cnfProject.exists())
            cnfProject = eclipseWorkspace.getProject("cnf");

        if (cnfProject.exists()) {
            if (!cnfProject.isOpen())
                cnfProject.open(null);
            return cnfProject.getLocation().toFile().getParentFile();
        }

        // Have to assume that the eclipse workspace == the bnd workspace,
        // and cnf hasn't been imported yet.
        return eclipseWorkspace.getLocation().toFile();
    }

    private static void addCnfChangeListener(final Workspace workspace) {
        ResourcesPlugin.getWorkspace().addResourceChangeListener(new IResourceChangeListener() {

            @Override
            public void resourceChanged(IResourceChangeEvent event) {
                if (event.getType() != IResourceChangeEvent.POST_CHANGE)
                    return;

                IResourceDelta rootDelta = event.getDelta();
                if (isCnfChanged(rootDelta)) {
                    workspace.refresh();
                }
            }
        });
    }

    private static boolean isCnfChanged(IResourceDelta delta) {

        final AtomicBoolean result = new AtomicBoolean(false);
        try {
            delta.accept(new IResourceDeltaVisitor() {
                @Override
                public boolean visit(IResourceDelta delta) throws CoreException {
                    try {

                        if (!isChangeDelta(delta))
                            return false;

                        IResource resource = delta.getResource();
                        if (resource.getType() == IResource.ROOT || resource.getType() == IResource.PROJECT && resource.getName().equals(Workspace.CNFDIR))
                            return true;

                        if (resource.getType() == IResource.PROJECT)
                            return false;

                        if (resource.getType() == IResource.FOLDER && resource.getName().equals("ext")) {
                            result.set(true);
                            return false;
                        }

                        if (resource.getType() == IResource.FILE) {
                            if (Workspace.BUILDFILE.equals(resource.getName())) {
                                result.set(true);
                                return false;
                            }
                            // Check files included by the -include directive in build.bnd
                            List<File> includedFiles = workspace.getIncluded();
                            if (includedFiles == null) {
                                return false;
                            }
                            for (File includedFile : includedFiles) {
                                IPath location = resource.getLocation();
                                if (location != null && includedFile.equals(location.toFile())) {
                                    result.set(true);
                                    return false;
                                }
                            }
                        }
                        return true;
                    } catch (Exception e) {
                        throw new CoreException(new Status(Status.ERROR, BndtoolsConstants.CORE_PLUGIN_ID, "During checking project changes", e));
                    }
                }

            });
        } catch (CoreException e) {
            logger.logError("Central.isCnfChanged() failed", e);
        }
        return result.get();
    }

    public static boolean isChangeDelta(IResourceDelta delta) {
        if (IResourceDelta.MARKERS == delta.getFlags())
            return false;
        if ((delta.getKind() & (IResourceDelta.ADDED | IResourceDelta.CHANGED | IResourceDelta.REMOVED)) == 0)
            return false;
        return true;
    }

    public void changed(Project model) {
        model.setChanged();
        for (ModelListener m : listeners)
            try {
                m.modelChanged(model);
            } catch (Exception e) {
                e.printStackTrace();
            }
    }

    public void addModelListener(ModelListener m) {
        if (!listeners.contains(m)) {
            listeners.add(m);
        }
    }

    public void removeModelListener(ModelListener m) {
        listeners.remove(m);
    }

    public static IJavaProject getJavaProject(Project model) {
        for (IProject iproj : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
            if (iproj.getName().equals(model.getName())) {
                IJavaProject ij = JavaCore.create(iproj);
                if (ij != null && ij.exists()) {
                    return ij;
                }
                // current project is not a Java project
            }
        }
        return null;
    }

    public static IPath toPath(File file) throws Exception {
        IPath result = null;

        File absolute = file.getCanonicalFile();

        IWorkspaceRoot wsroot = ResourcesPlugin.getWorkspace().getRoot();
        IFile[] candidates = wsroot.findFilesForLocationURI(absolute.toURI());
        if (candidates != null && candidates.length > 0) {
            result = candidates[0].getFullPath();
        } else {
            String workspacePath = getWorkspace().getBase().getAbsolutePath();
            String absolutePath = absolute.getPath();
            if (absolutePath.startsWith(workspacePath))
                result = new Path(absolutePath.substring(workspacePath.length()));
        }

        return result;
    }

    public static void refresh(IPath path) {
        try {
            IResource r = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
            if (r != null)
                return;

            IPath p = (IPath) path.clone();
            while (p.segmentCount() > 0) {
                p = p.removeLastSegments(1);
                IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(p);
                if (resource != null) {
                    resource.refreshLocal(2, null);
                    return;
                }
            }
        } catch (Exception e) {
            logger.logError("While refreshing path " + path, e);
        }
    }

    public static void refreshPlugins() throws Exception {
        List<Refreshable> rps = getWorkspace().getPlugins(Refreshable.class);
        for (Refreshable rp : rps) {
            if (rp.refresh()) {
                File dir = rp.getRoot();
                refreshFile(dir);
            }
        }
    }

    public static void refreshFile(File f) throws Exception {
        String path = toLocal(f);
        IResource r = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
        if (r != null) {
            r.refreshLocal(IResource.DEPTH_INFINITE, null);
        }
    }

    public static void refresh(Project p) throws Exception {
        IJavaProject jp = getJavaProject(p);
        if (jp != null)
            jp.getProject().refreshLocal(IResource.DEPTH_INFINITE, null);
    }

    private static String toLocal(File f) throws Exception {
        String root = getWorkspace().getBase().getAbsolutePath();
        String path = f.getAbsolutePath().substring(root.length());
        return path;
    }

    public void close() {}

    public static void invalidateIndex() {
        indexValid.set(false);
    }

    public static boolean needsIndexing() {
        return indexValid.compareAndSet(false, true);
    }

    public static Map<String,SortedSet<Version>> getExportedPackageModel(IProject project) {
        String key = project.getFullPath().toPortableString();
        return exportedPackageMap.get(key);
    }

    public static Collection<String> getContainedPackageModel(IProject project) {
        String key = project.getFullPath().toPortableString();
        return containedPackageMap.get(key);
    }

    public static Collection<IResource> getSourceFolderModel(IProject project) {
        String key = project.getFullPath().toPortableString();
        return sourceFolderMap.get(key);
    }

    public static void setProjectPackageModel(IProject project, Map<String,SortedSet<Version>> exports, Collection<String> contained, Collection<IResource> sourceFolders) {
        String key = project.getFullPath().toPortableString();
        exportedPackageMap.put(key, exports);
        containedPackageMap.put(key, contained);
        if (sourceFolders == null) {
            sourceFolderMap.remove(key);
        } else {
            sourceFolderMap.put(key, sourceFolders);
        }
    }

    public static Project getProject(File projectDir) throws Exception {
        File projectDirAbsolute = projectDir.getAbsoluteFile();
        assert projectDirAbsolute.isDirectory();

        Workspace ws = getWorkspace();
        return ws.getProject(projectDir.getName());
    }

    public static Project getProject(IProject p) throws Exception {
        return getProject(p.getLocation().toFile());
    }
}
TOP

Related Classes of bndtools.central.Central

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.