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.internal.builders; import java.io.File; import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Properties; import org.apache.felix.sigil.common.bnd.BundleBuilder; import org.apache.felix.sigil.common.config.IBldProject; import org.apache.felix.sigil.eclipse.SigilCore; import org.apache.felix.sigil.eclipse.model.project.ISigilProjectModel; import org.apache.felix.sigil.eclipse.model.util.JavaHelper; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.resources.IWorkspaceRoot; 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.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaModelMarker; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.ui.console.ConsolePlugin; import org.eclipse.ui.console.IConsole; import org.eclipse.ui.console.IConsoleManager; import org.eclipse.ui.console.MessageConsoleStream; public class SigilIncrementalProjectBuilder extends IncrementalProjectBuilder { @Override protected IProject[] build(int kind, @SuppressWarnings("unchecked") Map args, IProgressMonitor monitor) throws CoreException { IProject project = getProject(); if (checkOk(project)) { switch (kind) { case CLEAN_BUILD: case FULL_BUILD: fullBuild(project, monitor); break; case AUTO_BUILD: case INCREMENTAL_BUILD: autoBuild(project, monitor); break; } } return null; } /** * @param install * @param project * @param monitor * @throws CoreException */ private void autoBuild(IProject project, IProgressMonitor monitor) throws CoreException { IResourceDelta delta = getDelta(project); final boolean[] changed = new boolean[1]; ISigilProjectModel sigil = SigilCore.create(project); final IPath bldRoot = sigil.findBundleLocation().removeLastSegments(1); delta.accept(new IResourceDeltaVisitor() { public boolean visit(IResourceDelta delta) throws CoreException { if (!changed[0]) { IResource res = delta.getResource(); if (res.getType() == IResource.FILE) { changed[0] = !bldRoot.isPrefixOf(res.getLocation()); } } return !changed[0]; } }); if (changed[0]) { doBuild(project, monitor); } } /** * @param install * @param project * @param monitor * @throws CoreException */ private void fullBuild(IProject project, IProgressMonitor monitor) throws CoreException { doBuild(project, monitor); } private boolean checkOk(IProject project) throws CoreException { IMarker[] markers = project.findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE); for (IMarker m : markers) { Integer s = (Integer) m.getAttribute(IMarker.SEVERITY); if (s != null && s.equals(IMarker.SEVERITY_ERROR)) { SigilCore.log("Skipping " + project.getName() + " build due to unresolved errors"); return false; } } return true; } private void doBuild(IProject project, IProgressMonitor monitor) throws CoreException { ISigilProjectModel sigil = SigilCore.create(project); IBldProject bld = sigil.getBldProject(); File[] classpath = buildClasspath(sigil, monitor); String destPattern = buildDestPattern(sigil); Properties env = new Properties(); BundleBuilder bb = new BundleBuilder(bld, classpath, destPattern, env); for (IBldProject.IBldBundle bundle : bld.getBundles()) { String id = bundle.getId(); loginfo("creating bundle: " + id); int nWarn = 0; int nErr = 0; String msg = ""; try { boolean modified = bb.createBundle(bundle, false, new BundleBuilder.Log() { public void warn(String msg) { logwarn(msg); } public void verbose(String msg) { loginfo(msg); } }); nWarn = bb.warnings().size(); if (!modified) { msg = " (not modified)"; } } catch (Exception e) { List<String> errors = bb.errors(); if (errors != null) { nErr = errors.size(); for (String err : errors) { logerror(err); } } // FELIX-1690 - error is already logged no need to throw error as this // results in noisy error dialog box //throw SigilCore.newCoreException( "Failed to create: " + id + ": " + e, e ); } finally { loginfo(id + ": " + count(nErr, "error") + ", " + count(nWarn, "warning") + msg); } } } private static void loginfo(String message) { log("INFO: " + message); } private static void logwarn(String message) { log("WARN: " + message); } private static void logerror(String message) { log("ERROR: " + message); } private static void log(final String message) { // do this in background to avoid deadlock with ui Job job = new Job("log") { @Override protected IStatus run(IProgressMonitor arg0) { BuildConsole console = findConsole(); MessageConsoleStream stream = console.getMessageStream(); stream.println(message); return Status.OK_STATUS; } }; job.schedule(); } private static BuildConsole findConsole() { BuildConsole console = null; IConsoleManager manager = ConsolePlugin.getDefault().getConsoleManager(); for (IConsole c : manager.getConsoles()) { if (c instanceof BuildConsole) { console = (BuildConsole) c; break; } } if (console == null) { console = new BuildConsole(); manager.addConsoles(new IConsole[] { console }); } return console; } private String buildDestPattern(ISigilProjectModel sigil) throws CoreException { IPath loc = sigil.findBundleLocation().removeLastSegments(1); loc.toFile().mkdirs(); return loc.toOSString() + File.separator + "[name].jar"; } private File[] buildClasspath(ISigilProjectModel sigil, IProgressMonitor monitor) throws CoreException { LinkedList<File> files = new LinkedList<File>(); if (sigil.getBundle().getClasspathEntrys().isEmpty()) { IClasspathEntry[] entries = sigil.getJavaModel().getResolvedClasspath(true); for (IClasspathEntry cp : entries) { convert(cp, sigil, files); } } else { buildLocalClasspath(sigil, files); buildExternalClasspath(sigil, files, monitor); } return files.toArray(new File[files.size()]); } private void buildExternalClasspath(ISigilProjectModel sigil, List<File> files, IProgressMonitor monitor) throws CoreException { Collection<IClasspathEntry> entries = sigil.findExternalClasspath(monitor); for (IClasspathEntry cp : entries) { convert(cp, sigil, files); } } private void buildLocalClasspath(ISigilProjectModel sigil, List<File> files) throws CoreException { Collection<IClasspathEntry> entries = JavaHelper.findClasspathEntries(sigil.getBundle()); for (IClasspathEntry cp : entries) { convert(cp, sigil, files); } } private void convert(IClasspathEntry cp, ISigilProjectModel sigil, List<File> files) throws CoreException { switch (cp.getEntryKind()) { case IClasspathEntry.CPE_PROJECT: { convertProject(cp, files); break; } case IClasspathEntry.CPE_SOURCE: { convertSource(sigil, cp, files); break; } case IClasspathEntry.CPE_LIBRARY: { convertLibrary(sigil, cp, files); break; } case IClasspathEntry.CPE_VARIABLE: convertVariable(cp, files); break; } } private void convertVariable(IClasspathEntry cp, List<File> files) { cp = JavaCore.getResolvedClasspathEntry(cp); if (cp != null) { IPath p = cp.getPath(); files.add(p.toFile()); } } private void convertLibrary(ISigilProjectModel sigil, IClasspathEntry cp, List<File> files) { IPath p = cp.getPath(); IProject project = sigil.getProject().getWorkspace().getRoot().getProject(p.segment(0)); if (project.exists()) { p = project.getLocation().append(p.removeFirstSegments(1)); } files.add(p.toFile()); } private void convertSource(ISigilProjectModel sigil, IClasspathEntry cp, List<File> files) throws JavaModelException { IPath path = cp.getOutputLocation() == null ? sigil.getJavaModel().getOutputLocation() : cp.getOutputLocation(); IFolder buildFolder = sigil.getProject().getFolder(path.removeFirstSegments(1)); if (buildFolder.exists()) { files.add(buildFolder.getLocation().toFile()); } } private void convertProject(IClasspathEntry cp, List<File> files) throws CoreException { IProject p = findProject(cp.getPath()); ISigilProjectModel project = SigilCore.create(p); if (project.getBundle().getClasspathEntrys().isEmpty()) { // ew this is pretty messy - if a dependent bundle specifies it's dependencies // via package statements vs source directories then we need to add // the classpath path of that bundle for (IClasspathEntry rp : project.getJavaModel().getResolvedClasspath(true)) { convert(rp, project, files); } } else { for (String scp : project.getBundle().getClasspathEntrys()) { IClasspathEntry jcp = project.getJavaModel().decodeClasspathEntry(scp); convert(jcp, project, files); } } } private IProject findProject(IPath path) throws CoreException { IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); for (IProject p : root.getProjects()) { IPath projectPath = p.getFullPath(); if (projectPath.equals(path)) { return p; } } throw SigilCore.newCoreException("No such project " + path, null); } private String count(int count, String msg) { return count + " " + msg + (count == 1 ? "" : "s"); } }