Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 org.apache.felix.sigil.eclipse; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Locale; import java.util.ResourceBundle; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.felix.sigil.common.config.IBldProject; import org.apache.felix.sigil.common.core.BldCore; import org.apache.felix.sigil.common.model.ICapabilityModelElement; import org.apache.felix.sigil.common.model.eclipse.ISigilBundle; import org.apache.felix.sigil.common.repository.IBundleRepository; import org.apache.felix.sigil.common.repository.IRepositoryManager; import org.apache.felix.sigil.common.repository.IRepositoryVisitor; import org.apache.felix.sigil.common.repository.ResolutionConfig; import org.apache.felix.sigil.eclipse.install.IOSGiInstallManager; import org.apache.felix.sigil.eclipse.internal.install.OSGiInstallManager; import org.apache.felix.sigil.eclipse.internal.model.project.SigilModelRoot; import org.apache.felix.sigil.eclipse.internal.model.repository.RepositoryPreferences; import org.apache.felix.sigil.eclipse.internal.repository.manager.GlobalRepositoryManager; import org.apache.felix.sigil.eclipse.internal.repository.manager.IEclipseBundleRepository; import org.apache.felix.sigil.eclipse.internal.repository.manager.RepositoryCache; import org.apache.felix.sigil.eclipse.internal.resources.ProjectResourceListener; import org.apache.felix.sigil.eclipse.internal.resources.SigilProjectManager; import org.apache.felix.sigil.eclipse.model.project.ISigilModelRoot; import org.apache.felix.sigil.eclipse.model.project.ISigilProjectModel; import org.apache.felix.sigil.eclipse.model.repository.IRepositoryModel; import org.apache.felix.sigil.eclipse.model.repository.IRepositoryPreferences; import org.apache.felix.sigil.eclipse.model.util.JavaHelper; import org.eclipse.core.resources.ICommand; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IncrementalProjectBuilder; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jface.resource.ImageRegistry; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.osgi.framework.BundleContext; /** * The activator class controls the plug-in life cycle */ public class SigilCore extends AbstractUIPlugin { private static final String BASE = "org.apache.felix.sigil"; // The plug-in ID public static final String PLUGIN_ID = BASE + ".eclipse.core"; public static final String NATURE_ID = BASE + ".sigilnature"; public static final String PREFERENCES_ID = BASE + ".ui.preferences.SigilPreferencePage"; public static final String OSGI_INSTALLS_PREFERENCES_ID = BASE + ".ui.preferences.osgiInstalls"; public static final String EXCLUDED_RESOURCES_PREFERENCES_ID = BASE + ".ui.preferences.excludedResources"; public static final String REPOSITORIES_PREFERENCES_ID = BASE + ".ui.preferences.repositoriesPreferencePage"; public static final String SIGIL_PROJECT_FILE = IBldProject.PROJECT_FILE; public static final String BUILDER_ID = PLUGIN_ID + ".sigilBuilder"; public static final String CLASSPATH_CONTAINER_PATH = BASE + ".classpathContainer"; public static final String OSGI_INSTALLS = BASE + ".osgi.installs"; public static final String OSGI_DEFAULT_INSTALL_ID = BASE + ".osgi.default.install.id"; public static final String OSGI_INSTALL_PREFIX = BASE + ".osgi.install."; public static final String OSGI_SOURCE_LOCATION = BASE + ".osgi.source.location"; public static final String OSGI_INSTALL_CHECK_PREFERENCE = BASE + ".osgi.install.check"; public static final String LIBRARY_KEYS_PREF = BASE + ".library.keys"; public static final String PREFERENCES_REBUILD_PROJECTS = BASE + ".rebuild.projects"; public static final String QUALIFY_VERSIONS = BASE + ".qualify.versions"; public static final String DEFAULT_VERSION_LOWER_BOUND = BASE + ".versionLowerBound"; public static final String DEFAULT_VERSION_UPPER_BOUND = BASE + ".versionUpperBound"; public static final String DEFAULT_EXCLUDED_RESOURCES = BASE + ".excludedResources"; public static final String INCLUDE_OPTIONAL_DEPENDENCIES = BASE + ".includeOptionalDependencies"; public static final String INSTALL_BUILDER_EXTENSION_POINT_ID = BASE + ".installbuilder"; public static final String REPOSITORY_PROVIDER_EXTENSION_POINT_ID = BASE + ".repositoryprovider"; public static final String MARKER_UNRESOLVED_DEPENDENCY = BASE + ".unresolvedDependencyMarker"; public static final String MARKER_UNRESOLVED_IMPORT_PACKAGE = BASE + ".unresolvedDependencyMarker.importPackage"; public static final String MARKER_UNRESOLVED_REQUIRE_BUNDLE = BASE + ".unresolvedDependencyMarker.requireBundle"; public static final String REPOSITORY_SET = PLUGIN_ID + ".repository.set"; public static final String PREFERENCES_NOASK_OSGI_INSTALL = BASE + ".noAskOSGIHome"; public static final String PREFERENCES_ADD_IMPORT_FOR_EXPORT = BASE + ".addImportForExport"; public static final String PREFERENCES_INCLUDE_OPTIONAL = PLUGIN_ID + ".include.optional"; public static final String PREFERENCES_REMOVE_IMPORT_FOR_EXPORT = BASE + ".removeImportForExport"; // The shared instance private static SigilCore plugin; private static RepositoryPreferences repositoryPrefs; private static SigilProjectManager projectManager; private static OSGiInstallManager installs; private static ISigilModelRoot modelRoot; private static GlobalRepositoryManager globalRepositoryManager; /** * Returns the shared instance * * @return the shared instance */ public static SigilCore getDefault() { return plugin; } public static CoreException newCoreException(String msg, Throwable t) { return new CoreException(makeStatus(msg, t, IStatus.ERROR)); } public static void log(String msg) { DebugPlugin.log(makeStatus(msg, null, IStatus.INFO)); } public static void error(String msg) { DebugPlugin.log(makeStatus(msg, null, IStatus.ERROR)); } public static void error(String msg, Throwable t) { DebugPlugin.log(makeStatus(msg, t, IStatus.ERROR)); } public static void warn(String msg) { DebugPlugin.log(makeStatus(msg, null, IStatus.WARNING)); } public static void warn(String msg, Throwable t) { DebugPlugin.log(makeStatus(msg, t, IStatus.WARNING)); } private static IStatus makeStatus(String msg, Throwable t, int status) { if (t instanceof CoreException) { CoreException c = (CoreException) t; return c.getStatus(); } else { return new Status(status, SigilCore.PLUGIN_ID, status, msg, t); } } public static boolean isSigilProject(IProject resource) { if (resource == null) return false; if (resource.isAccessible() && resource instanceof IProject) { IProject project = (IProject) resource; try { return project.hasNature(NATURE_ID); } catch (CoreException e) { error(e.getMessage(), e); return false; } } else { return false; } } public static boolean hasProjectNature(IProject project) throws CoreException { return project.getNature(NATURE_ID) != null; } public static ResourceBundle getResourceBundle() { return ResourceBundle.getBundle("resources." + SigilCore.class.getName(), Locale.getDefault(), SigilCore.class.getClassLoader()); } public static ISigilProjectModel create(IProject project) throws CoreException { return projectManager.getSigilProject(project); } /** * The constructor */ public SigilCore() { plugin = this; } public void earlyStartup() { } /* * (non-Javadoc) * * @see * org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext * ) */ public void start(final BundleContext context) throws Exception { super.start(context); RepositoryCache repositoryCache = new RepositoryCache(); projectManager = new SigilProjectManager(repositoryCache); modelRoot = new SigilModelRoot(); installs = new OSGiInstallManager(); repositoryPrefs = new RepositoryPreferences(); globalRepositoryManager = new GlobalRepositoryManager(repositoryCache); globalRepositoryManager.initialise(); registerModelElements(context); registerResourceListeners(); } /* * (non-Javadoc) * * @see * org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext * ) */ public void stop(BundleContext context) throws Exception { globalRepositoryManager.destroy(); globalRepositoryManager = null; projectManager.destroy(); projectManager = null; plugin = null; super.stop(context); } public static boolean isBundledPath(String bp) throws CoreException { boolean bundle = JavaHelper.isCachedBundle(bp); if (!bundle) { bundle = isProjectPath(bp); if (!bundle) { for (IBundleRepository r : getGlobalRepositoryManager().getRepositories()) { bundle = isBundlePath(bp, r); if (bundle) break; } } } return bundle; } private static boolean isBundlePath(final String bp, IBundleRepository r) { final AtomicBoolean flag = new AtomicBoolean(); IRepositoryVisitor visitor = new IRepositoryVisitor() { public boolean visit(ISigilBundle b) { File path = b.getLocation(); if (path != null && path.getAbsolutePath().equals(bp)) { flag.set(true); return false; } else { return true; } } }; r.accept(visitor, ResolutionConfig.INDEXED_ONLY | ResolutionConfig.LOCAL_ONLY); return flag.get(); } private static boolean isProjectPath(String bp) throws CoreException { for (ISigilProjectModel p : SigilCore.getRoot().getProjects()) { IPath path = p.findOutputLocation(); if (path.toOSString().equals(bp)) { return true; } } return false; } private void registerResourceListeners() { Job job = new Job("Initialising sigil resource listeners") { @Override protected IStatus run(IProgressMonitor monitor) { ResourcesPlugin.getWorkspace().addResourceChangeListener( new ProjectResourceListener(projectManager), ProjectResourceListener.EVENT_MASKS); return Status.OK_STATUS; } }; job.setSystem(true); job.schedule(); } private void registerModelElements(BundleContext context) { // trick to get eclipse to lazy load BldCore for model elements BldCore.getLicenseManager(); } public static IOSGiInstallManager getInstallManager() { return installs; } public static ISigilModelRoot getRoot() { return modelRoot; } public static IRepositoryManager getGlobalRepositoryManager() { return globalRepositoryManager; } public static IRepositoryManager getRepositoryManager(ISigilProjectModel model) { if (model == null) return globalRepositoryManager; try { return projectManager.getRepositoryManager(model); } catch (CoreException e) { SigilCore.error("Failed to read repository config", e); return globalRepositoryManager; } } /** * @param rep * @return */ public static IRepositoryModel getRepositoryModel(IBundleRepository rep) { IEclipseBundleRepository cast = (IEclipseBundleRepository) rep; return cast.getModel(); } public static IRepositoryPreferences getRepositoryPreferences() { return repositoryPrefs; } public static void rebuildAllBundleDependencies(IProgressMonitor monitor) { Collection<ISigilProjectModel> projects = getRoot().getProjects(); if (!projects.isEmpty()) { SubMonitor progress = SubMonitor.convert(monitor, projects.size() * 20); for (ISigilProjectModel p : projects) { rebuild(p, progress); } } monitor.done(); } public static void rebuildBundleDependencies(ISigilProjectModel project, Collection<ICapabilityModelElement> caps, IProgressMonitor monitor) { Set<ISigilProjectModel> affected = SigilCore.getRoot().resolveDependentProjects(caps, monitor); if (project != null) { affected.remove(project); } SubMonitor progress = SubMonitor.convert(monitor, affected.size() * 20); for (ISigilProjectModel dependent : affected) { //dependent.flushDependencyState(); rebuild(dependent, progress); } } public static void rebuild(ISigilProjectModel dependent, SubMonitor progress) { try { dependent.resetClasspath(progress.newChild(10), false); dependent.getProject().build(IncrementalProjectBuilder.FULL_BUILD, progress.newChild(10)); } catch (CoreException e) { SigilCore.error("Failed to rebuild " + dependent, e); } } public IPath findDefaultBundleLocation(ISigilProjectModel m) throws CoreException { IPath loc = m.getProject().getLocation(); loc = loc.append(m.getJavaModel().getOutputLocation().removeFirstSegments(1)); loc = loc.removeLastSegments(1).append("lib"); return loc.append(m.getSymbolicName() + ".jar"); } public static void makeSigilProject(IProject project, IProgressMonitor monitor) throws CoreException { IProjectDescription description = project.getDescription(); String[] natures = description.getNatureIds(); String[] newNatures = new String[natures.length + 1]; System.arraycopy(natures, 0, newNatures, 0, natures.length); newNatures[natures.length] = SigilCore.NATURE_ID; description.setNatureIds(newNatures); ICommand sigilBuild = description.newCommand(); sigilBuild.setBuilderName(SigilCore.BUILDER_ID); ICommand javaBuild = description.newCommand(); javaBuild.setBuilderName(JavaCore.BUILDER_ID); description.setBuildSpec(new ICommand[] { javaBuild, sigilBuild }); project.setDescription(description, new SubProgressMonitor(monitor, 2)); IJavaProject java = JavaCore.create(project); if (java.exists()) { IClasspathEntry[] cp = java.getRawClasspath(); // check if sigil container is already on classpath - if not add it if (!isSigilOnClasspath(cp)) { ArrayList<IClasspathEntry> entries = new ArrayList<IClasspathEntry>(Arrays.asList(cp)); entries.add(JavaCore.newContainerEntry(new Path(SigilCore.CLASSPATH_CONTAINER_PATH))); java.setRawClasspath(entries.toArray(new IClasspathEntry[entries.size()]), monitor); } } } /** * @param cp * @return */ private static boolean isSigilOnClasspath(IClasspathEntry[] cp) { for (IClasspathEntry e : cp) { if (e.getEntryKind() == IClasspathEntry.CPE_CONTAINER && e.getPath().segment(0).equals(SigilCore.CLASSPATH_CONTAINER_PATH)) { return true; } } return false; } public static Image loadImage(URL url) throws IOException { ImageRegistry registry = getDefault().getImageRegistry(); String key = url.toExternalForm(); Image img = registry.get(key); if (img == null) { img = openImage(url); registry.put(key, img); } return img; } private static Image openImage(URL url) throws IOException { Display display = Display.getCurrent(); if (display == null) { display = Display.getDefault(); } InputStream in = null; try { in = url.openStream(); return new Image(display, in); } finally { if (in != null) { try { in.close(); } catch (IOException e) { error("Failed to close stream", e); } } } } }