You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ri...@apache.org on 2009/07/13 15:26:06 UTC

svn commit: r793581 [12/23] - in /felix/trunk/sigil: ./ bld-ivy/ bld-ivy/example/ bld-ivy/example/dependence/ bld-ivy/example/dependence/dependee/ bld-ivy/example/dependence/dependee/src/ bld-ivy/example/dependence/dependee/src/standalone/ bld-ivy/exam...

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/SigilCore.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/SigilCore.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/SigilCore.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/SigilCore.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,570 @@
+/*
+ * 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.cauldron.sigil;
+
+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.HashMap;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.cauldron.bld.config.IBldProject;
+import org.cauldron.bld.core.BldCore;
+import org.cauldron.sigil.install.IOSGiInstallManager;
+import org.cauldron.sigil.internal.install.OSGiInstallManager;
+import org.cauldron.sigil.internal.model.project.SigilModelRoot;
+import org.cauldron.sigil.internal.model.project.SigilProject;
+import org.cauldron.sigil.internal.model.repository.RepositoryConfiguration;
+import org.cauldron.sigil.internal.repository.eclipse.GlobalRepositoryManager;
+import org.cauldron.sigil.internal.repository.eclipse.SigilRepositoryManager;
+import org.cauldron.sigil.model.ModelElementFactory;
+import org.cauldron.sigil.model.eclipse.ISigilBundle;
+import org.cauldron.sigil.model.project.ISigilModelRoot;
+import org.cauldron.sigil.model.project.ISigilProjectModel;
+import org.cauldron.sigil.model.repository.IRepositoryConfiguration;
+import org.cauldron.sigil.model.util.JavaHelper;
+import org.cauldron.sigil.repository.IBundleRepository;
+import org.cauldron.sigil.repository.IRepositoryManager;
+import org.cauldron.sigil.repository.IRepositoryVisitor;
+import org.cauldron.sigil.repository.ResolutionConfig;
+import org.eclipse.core.resources.ICommand;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+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.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;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class SigilCore extends AbstractUIPlugin {
+
+	// The plug-in ID
+	public static final String PLUGIN_ID = "org.cauldron.sigil.core";
+    public static final String NATURE_ID = PLUGIN_ID + ".sigilnature";
+    public static final String PREFERENCES_ID = "org.cauldron.sigil.ui.preferences.SigilPreferencePage";
+    public static final String OSGI_INSTALLS_PREFERENCES_ID = "org.cauldron.sigil.ui.preferences.osgiInstalls";
+    public static final String EXCLUDED_RESOURCES_PREFERENCES_ID = "org.cauldron.sigil.ui.preferences.excludedResources";
+	public static final String REPOSITORIES_PREFERENCES_ID = "org.cauldron.sigil.ui.preferences.repositoriesPreferencePage";
+    public static final String OSGI_SCRIPT_TYPE = "org.cauldron.sigil.content.OSGiScriptType";
+    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 = PLUGIN_ID + ".classpathContainer";
+
+    public static final String OSGI_INSTALLS = "org.cauldron.osgi.installs";
+	public static final String OSGI_DEFAULT_INSTALL_ID = "org.cauldron.osgi.default.install.id";
+	public static final String OSGI_INSTALL_PREFIX = "org.cauldron.osgi.install.";
+	public static final String OSGI_SOURCE_LOCATION = "org.cauldron.osgi.source.location";
+	public static final String OSGI_INSTALL_CHECK_PREFERENCE = "org.cauldron.osgi.install.check";
+	public static final String LIBRARY_KEYS_PREF = "org.cauldron.osgi.library.keys";
+	public static final String PREFERENCES_REBUILD_PROJECTS = "org.cauldron.sigil.rebuild.projects";
+	public static final String QUALIFY_VERSIONS = "org.cauldron.sigil.qualify.versions";
+	
+	public static final String DEFAULT_VERSION_LOWER_BOUND = "org.cauldron.sigil.versionLowerBound";
+	public static final String DEFAULT_VERSION_UPPER_BOUND = "org.cauldron.sigil.versionUpperBound";
+
+	public static final String DEFAULT_EXCLUDED_RESOURCES = "org.cauldron.sigil.excludedResources";
+	public static final String PREFERENCES_NOASK_OSGI_INSTALL = "org.cauldron.sigil.noAskOSGIHome";
+	public static final String PREFERENCES_ADD_IMPORT_FOR_EXPORT = "org.cauldron.sigil.addImportForExport";
+	public static final String INCLUDE_OPTIONAL_DEPENDENCIES = "org.cauldron.sigil.includeOptionalDependencies";
+
+	public static final String INSTALL_BUILDER_EXTENSION_POINT_ID = "org.cauldron.sigil.installbuilder";
+	public static final String REPOSITORY_PROVIDER_EXTENSION_POINT_ID = "org.cauldron.sigil.repositoryprovider";
+	
+	public static final String MARKER_UNRESOLVED_DEPENDENCY = "org.cauldron.sigil.unresolvedDependencyMarker";
+	public static final String MARKER_UNRESOLVED_IMPORT_PACKAGE = "org.cauldron.sigil.unresolvedDependencyMarker.importPackage";
+	public static final String MARKER_UNRESOLVED_REQUIRE_BUNDLE = "org.cauldron.sigil.unresolvedDependencyMarker.requireBundle";
+	public static final String REPOSITORY_SET = PLUGIN_ID + ".repository.set";
+	public static final String PREFERENCES_INCLUDE_OPTIONAL = PLUGIN_ID + ".include.optional";
+	
+	private static final Object NULL = new Object();
+
+	// The shared instance
+	private static SigilCore plugin;
+
+	private ServiceTracker descriptorTracker;
+	private ServiceTracker registryTracker;
+	private ServiceTracker serializerTracker;
+
+	private static IRepositoryConfiguration repositoryConfig;
+	private static OSGiInstallManager installs;
+	private static ISigilModelRoot modelRoot;
+	private static HashMap<Object, SigilRepositoryManager> repositoryManagers = new HashMap<Object, SigilRepositoryManager>();
+	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 {
+		if (project.hasNature(NATURE_ID)) {
+			return new SigilProject(project);
+		} else {
+			throw newCoreException("Project " + project.getName()
+					+ " is not a sigil project", null);
+		}
+	}
+
+	/**
+	 * 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);
+
+		modelRoot = new SigilModelRoot();
+		
+		repositoryConfig = new RepositoryConfiguration();
+
+		installs = new OSGiInstallManager();
+		
+		globalRepositoryManager = new GlobalRepositoryManager();
+
+		registerModelElements(context);
+		registerResourceListeners();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext
+	 * )
+	 */
+	public void stop(BundleContext context) throws Exception {
+		if (descriptorTracker != null) {
+			descriptorTracker.close();
+			descriptorTracker = null;
+		}
+
+		if (registryTracker != null) {
+			registryTracker.close();
+			registryTracker = null;
+		}
+
+		if (serializerTracker != null) {
+			serializerTracker.close();
+			serializerTracker = null;
+		}
+		
+		for ( SigilRepositoryManager m : repositoryManagers.values() ) {
+			m.destroy();
+		}
+		
+		repositoryManagers.clear();
+		
+		globalRepositoryManager.destroy();
+		globalRepositoryManager = 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) {
+				IPath path = b.getLocation();
+				if (path != null && path.toOSString().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() {
+		final IResourceChangeListener listener = new IResourceChangeListener() {
+			public void resourceChanged(IResourceChangeEvent event) {
+				IResourceDelta delta = event.getDelta();
+				if ( delta != null ) {
+					try {
+						delta.accept(new IResourceDeltaVisitor() {
+							public boolean visit(IResourceDelta delta) throws CoreException {
+								IResource resource = delta.getResource();
+								if(resource instanceof IProject) {
+									IProject project = (IProject) resource;
+									if ( SigilCore.isSigilProject(project) ) {
+										switch (delta.getKind()) {
+										case IResourceDelta.REMOVED:
+										case IResourceDelta.ADDED:
+											rebuildAllBundleDependencies(Job.getJobManager().createProgressGroup());
+											break;
+										}									
+									}
+									// Recurse no more
+									return false;
+								}							
+								return true;
+							}
+						});
+					} catch (CoreException e) {
+						error("Failed to update after change", e);
+					}
+				}
+			}
+		};
+		
+		Job job = new Job("Initialising sigil resource listeners") {
+			@Override
+			protected IStatus run(IProgressMonitor monitor) {
+				ResourcesPlugin.getWorkspace().addResourceChangeListener(listener, IResourceChangeEvent.PRE_DELETE | IResourceChangeEvent.POST_CHANGE);
+				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();
+		String uri = "http://sigil.codecauldron.org/xml/sigil-namespace";
+		ModelElementFactory.getInstance().register(ISigilProjectModel.class,
+				SigilProject.class, "project", "sigil", uri);
+	}
+
+	public static IOSGiInstallManager getInstallManager() {
+		return installs;
+	}
+
+	public static ISigilModelRoot getRoot() {
+		return modelRoot;
+	}
+	
+	public static IRepositoryManager getGlobalRepositoryManager() {
+		return globalRepositoryManager;
+	}
+
+	public static IRepositoryManager getRepositoryManager(String set) {
+		SigilRepositoryManager manager = null;
+		
+		if ( set == null ) {
+			manager = repositoryManagers.get( NULL );
+			if ( manager == null ) {
+				manager = new SigilRepositoryManager(null);
+				manager.initialise();
+				repositoryManagers.put( NULL, manager );
+			}
+		}
+		else {
+			manager = repositoryManagers.get(set);
+			
+			if ( manager == null ) {
+				manager = new SigilRepositoryManager(set);
+				manager.initialise();
+				repositoryManagers.put( set, manager );
+			}			
+		}
+		
+		return manager;
+	}
+	public static IRepositoryManager getRepositoryManager(ISigilProjectModel model) {
+		return getRepositoryManager(loadProjectRepositorySet(model));
+	}
+	
+	private static String loadProjectRepositorySet(ISigilProjectModel model) {
+		if ( model == null ) {
+			return null;
+		}
+		
+		return model.getPreferences().get(REPOSITORY_SET, null );
+	}		
+
+
+	public static IRepositoryConfiguration getRepositoryConfiguration() {
+		return repositoryConfig;
+	}	
+
+	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, IProgressMonitor monitor) {
+		HashSet<ISigilProjectModel> affected = new HashSet<ISigilProjectModel>(project.findDependentProjects(monitor));
+		affected.add(project);
+
+		SubMonitor progress = SubMonitor.convert(monitor, affected.size()*20);
+		for (ISigilProjectModel dependent : affected) {
+			rebuild(dependent, progress);
+		}
+	}	
+	
+	
+	private static void rebuild(ISigilProjectModel dependent, SubMonitor progress) {
+		try {
+			dependent.resetClasspath(progress.newChild(10));
+			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();
+			// XXX fix for http://jira.codecauldron.org/browse/SIGIL-304
+			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 );
+				}
+			}
+		}
+	}
+
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/IOSGiInstall.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/IOSGiInstall.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/IOSGiInstall.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/IOSGiInstall.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,65 @@
+/*
+ * 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.cauldron.sigil.install;
+
+import java.util.Map;
+
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * Encapsulates all information about a particular OSGi install.
+ * 
+ * @author dave
+ *
+ */
+public interface IOSGiInstall {
+	
+	/**
+	 * A unique id which can be used to refer to this install within the eclipse runtime.
+	 * @return
+	 */
+	String getId();
+	
+	/**
+	 * Where this install is located
+	 * @return
+	 */
+	IPath getInstallLocation();
+
+	/**
+	 * @return
+	 */
+	Map<String, String> getProperties();
+	
+	/**
+	 * @return
+	 */
+	String[] getLaunchArguments();	
+	
+	/**
+	 * @return
+	 */
+	IPath getVarDirectory();
+	
+	/**
+	 * @return
+	 */
+	IOSGiInstallType getType();
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/IOSGiInstallBuilder.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/IOSGiInstallBuilder.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/IOSGiInstallBuilder.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/IOSGiInstallBuilder.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,27 @@
+/*
+ * 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.cauldron.sigil.install;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+
+public interface IOSGiInstallBuilder {
+	IOSGiInstall build(String id, IPath path) throws CoreException;
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/IOSGiInstallManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/IOSGiInstallManager.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/IOSGiInstallManager.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/IOSGiInstallManager.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,28 @@
+/*
+ * 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.cauldron.sigil.install;
+
+public interface IOSGiInstallManager {
+	IOSGiInstall findInstall(String id);
+	String[] getInstallIDs();
+	IOSGiInstall[] getInstalls();
+	IOSGiInstall getDefaultInstall();
+	IOSGiInstallType findInstallType(String location);
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/IOSGiInstallType.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/IOSGiInstallType.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/IOSGiInstallType.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/IOSGiInstallType.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,68 @@
+/*
+ * 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.cauldron.sigil.install;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.swt.graphics.Image;
+
+//import org.eclipse.swt.graphics.Image;
+
+public interface IOSGiInstallType {
+	/**
+	 * @return
+	 */
+	String getName();
+
+	/**
+	 * 
+	 * @return
+	 */
+	String getVersion();
+	
+	/**
+	 * @return
+	 */
+	String getMainClass();
+	
+	/**
+	 * @return
+	 */
+	String[] getClassPath();
+
+	/**
+	 * @return
+	 */
+	IPath getSourceLocation();
+	
+	/**
+	 * @return
+	 */
+	IPath getJavaDocLocation();
+	
+	/**
+	 * Return the paths of any bundles that are started by default in this OSGi instance.
+	 * @return
+	 */
+	IPath[] getDefaultBundleLocations();
+
+	String getId();
+
+	Image getIcon();
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/OSGiInstall.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/OSGiInstall.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/OSGiInstall.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/OSGiInstall.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,93 @@
+/*
+ * 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.cauldron.sigil.install;
+
+import java.util.Arrays;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IPath;
+
+public class OSGiInstall implements IOSGiInstall {
+
+	private String id;
+	private IPath installLocation;
+	private String[] launchArgs;
+	private Map<String, String> properties;
+	private IPath varDirectory;
+	private IOSGiInstallType type;
+	
+	public IPath getVarDirectory() {
+		return varDirectory;
+	}
+
+	public void setVarDirectory(IPath varDirectory) {
+		this.varDirectory = varDirectory;
+	}
+
+	public OSGiInstall(String id) {
+		this.id = id;
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	public IPath getInstallLocation() {
+		return installLocation;
+	}
+
+	public void setInstallLocation(IPath installLocation) {
+		this.installLocation = installLocation;
+	}
+
+	public String[] getLaunchArguments() {
+		return launchArgs;
+	}
+	
+	public void setLaunchArguments(String[] launchArgs) {
+		this.launchArgs = launchArgs;
+	}
+
+	public Map<String, String> getProperties() {
+		return properties;
+	}
+	
+	public void setProperties(Map<String,String> properties) {
+		this.properties = properties;
+	}
+
+	public String toString() {
+		return "OSGiInstall[\n" + 
+			"id=" + id + "\n" +
+			"type=" + type + "\n" +
+			"installLocation=" + installLocation + "\n" +
+			"launchArgs=" + Arrays.asList(launchArgs) + "\n" +
+			"properties=" + properties + "\n" +
+			"]";
+	}
+
+        public IOSGiInstallType getType() {
+                return type;
+        }
+        
+        public void setType(IOSGiInstallType type) {
+                this.type = type;
+        }
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/OSGiInstallType.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/OSGiInstallType.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/OSGiInstallType.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/install/OSGiInstallType.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,122 @@
+/*
+ * 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.cauldron.sigil.install;
+
+import java.util.Arrays;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.swt.graphics.Image;
+
+public class OSGiInstallType implements IOSGiInstallType {
+
+	private String id;
+	private String name;
+	private String version;
+	private String mainClass;
+	private String[] classPath;
+	private IPath javaDocLocation;
+	private IPath sourceLocation;
+	private IPath[] defaultBundleLocations;
+	private Image icon;
+	
+	public Image getIcon() {
+		return icon;
+	}
+
+	public void setIcon(Image icon) {
+		this.icon = icon;
+	}
+
+	public String getId() {
+		return id;
+	}
+	
+	public String[] getClassPath() {
+		return classPath;
+	}
+
+	public IPath[] getDefaultBundleLocations() {
+		return defaultBundleLocations;
+	}
+
+	public IPath getJavaDocLocation() {
+		return javaDocLocation;
+	}
+
+	public String getMainClass() {
+		return mainClass;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public IPath getSourceLocation() {
+		return sourceLocation;
+	}
+
+	public String getVersion() {
+		return version;
+	}
+	
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public void setVersion(String version) {
+		this.version = version;
+	}
+
+	public void setMainClass(String mainClass) {
+		this.mainClass = mainClass;
+	}
+
+	public void setClassPath(String[] classPath) {
+		this.classPath = classPath;
+	}
+
+	public void setJavaDocLocation(IPath javaDocLocation) {
+		this.javaDocLocation = javaDocLocation;
+	}
+
+	public void setSourceLocation(IPath sourceLocation) {
+		this.sourceLocation = sourceLocation;
+	}
+
+	public void setDefaultBundleLocations(IPath[] defaultBundleLocations) {
+		this.defaultBundleLocations = defaultBundleLocations;
+	}
+	
+	public String toString() {
+		return "OSGiInstallType[\n" + 
+			"name=" + name + "\n" +
+			"version=" + version + "\n" +
+			"mainClass=" + mainClass + "\n" +
+			"classPath=" + Arrays.asList(classPath) + "\n" +
+			"javaDocLocation=" + javaDocLocation + "\n" +
+			"sourceLocation=" + sourceLocation + "\n" +
+			"defaultBundleLocations=" + Arrays.asList(defaultBundleLocations) + "\n" +
+			"]";
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/adapter/FileAdaptorFactory.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/adapter/FileAdaptorFactory.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/adapter/FileAdaptorFactory.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/adapter/FileAdaptorFactory.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,86 @@
+/*
+ * 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.cauldron.sigil.internal.adapter;
+
+import org.cauldron.sigil.SigilCore;
+import org.cauldron.sigil.model.ModelElementFactory;
+import org.cauldron.sigil.model.ModelElementFactoryException;
+import org.cauldron.sigil.model.eclipse.ISigilBundle;
+import org.cauldron.sigil.model.project.ISigilProjectModel;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdapterFactory;
+
+/**
+ * @author savage
+ *
+ */
+public class FileAdaptorFactory implements IAdapterFactory {
+
+	public FileAdaptorFactory() {
+		
+	}
+	private Class<?>[] types = new Class<?>[] { ISigilBundle.class };
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.core.runtime.IAdapterFactory#getAdapter(java.lang.Object, java.lang.Class)
+	 */
+	@SuppressWarnings("unchecked")
+	public Object getAdapter( Object adaptableObject, Class adapterType ) {
+        Object adapted = null;
+        
+        IFile file = (IFile) adaptableObject;
+        
+        if ( ISigilBundle.class.equals( adapterType ) ) {
+        	adapted = adaptBundle(file);
+        }
+		
+		return adapted;
+	}
+    
+    private Object adaptBundle(IFile file) {
+        Object adapted = null;
+        IProject project = file.getProject();
+        try {
+            if ( SigilCore.hasProjectNature( project ) ) {
+                ISigilProjectModel sigil = SigilCore.create( project );
+                ISigilBundle bundle = ModelElementFactory.getInstance().newModelElement( ISigilBundle.class );
+                bundle.setParent( sigil );
+                adapted = bundle;
+            }
+        }
+        catch ( CoreException e ) {
+			SigilCore.error( "Failed to construct bundle", e );
+        } catch (ModelElementFactoryException e) {
+			SigilCore.error( "Failed to construct bundle", e );
+		}
+        
+        return adapted;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.core.runtime.IAdapterFactory#getAdapterList()
+	 */
+	@SuppressWarnings("unchecked")
+	public Class[] getAdapterList() {
+		return types;
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/adapter/ProjectAdaptorFactory.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/adapter/ProjectAdaptorFactory.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/adapter/ProjectAdaptorFactory.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/adapter/ProjectAdaptorFactory.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,71 @@
+/*
+ * 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.cauldron.sigil.internal.adapter;
+
+import org.cauldron.sigil.SigilCore;
+import org.cauldron.sigil.model.project.ISigilProjectModel;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdapterFactory;
+
+/**
+ * @author savage
+ *
+ */
+public class ProjectAdaptorFactory implements IAdapterFactory {
+
+	private Class<?>[] types = new Class<?>[] { ISigilProjectModel.class };
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.core.runtime.IAdapterFactory#getAdapter(java.lang.Object, java.lang.Class)
+	 */
+	@SuppressWarnings("unchecked")
+	public Object getAdapter( Object adaptableObject, Class adapterType ) {
+        Object adapted = null;
+        
+        IProject project = (IProject) adaptableObject;
+        
+		if ( ISigilProjectModel.class.equals( adapterType ) ) {
+			adapted = adaptProject(project);
+		}
+		
+		return adapted;
+	}
+    
+    private Object adaptProject(IProject project) {
+    	try {
+			if ( SigilCore.isSigilProject(project) ) {
+				return SigilCore.create(project);
+			}
+		} catch (CoreException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.core.runtime.IAdapterFactory#getAdapterList()
+	 */
+	@SuppressWarnings("unchecked")
+	public Class[] getAdapterList() {
+		return types;
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/builders/BuildConsole.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/builders/BuildConsole.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/builders/BuildConsole.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/builders/BuildConsole.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,42 @@
+/*
+ * 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.cauldron.sigil.internal.builders;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.console.MessageConsole;
+import org.eclipse.ui.console.MessageConsoleStream;
+
+public class BuildConsole extends MessageConsole {
+
+	private static final ImageDescriptor imageDescriptor = null;
+	private MessageConsoleStream stream;
+
+	public BuildConsole() {
+		super("Sigil Build", imageDescriptor, true);
+	}
+
+	public synchronized MessageConsoleStream getMessageStream() {
+		if ( stream == null ) {
+			stream = newMessageStream();
+		}
+		return stream;
+	}
+
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/builders/SigilIncrementalProjectBuilder.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/builders/SigilIncrementalProjectBuilder.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/builders/SigilIncrementalProjectBuilder.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/builders/SigilIncrementalProjectBuilder.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,312 @@
+/*
+ * 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.cauldron.sigil.internal.builders;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.cauldron.bld.bnd.BundleBuilder;
+import org.cauldron.bld.config.IBldProject;
+import org.cauldron.sigil.SigilCore;
+import org.cauldron.sigil.model.project.ISigilProjectModel;
+import org.cauldron.sigil.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.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaModelMarker;
+import org.eclipse.jdt.core.JavaCore;
+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);
+    				}
+    			}
+    			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) {
+		BuildConsole console = findConsole();
+		MessageConsoleStream stream = console.getMessageStream();
+		stream.println("INFO: " + message);
+	}
+
+	private static void logwarn(String message) {
+		BuildConsole console = findConsole();
+		MessageConsoleStream stream = console.getMessageStream();
+		stream.println("WARN: " + message);
+	}
+	
+	private static void logerror(String message) {
+		BuildConsole console = findConsole();
+		MessageConsoleStream stream = console.getMessageStream();
+		stream.println("ERROR: " + message);
+	}
+	
+	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 {
+		ArrayList<File> files = new ArrayList<File>();
+		
+		buildLocalClasspath(sigil, files);
+		buildExternalClasspath(sigil, files, monitor);
+			
+		return files.toArray( new File[files.size()] );
+	}
+
+	private void buildExternalClasspath(ISigilProjectModel sigil,
+			ArrayList<File> files, IProgressMonitor monitor) throws CoreException {
+		Collection<IClasspathEntry> entries = sigil.findExternalClasspath(monitor);
+		files.ensureCapacity(files.size() + entries.size());
+		
+		for ( IClasspathEntry cp : entries ) {
+			convert(cp, sigil, files);
+		}
+	}
+
+	private void buildLocalClasspath(ISigilProjectModel sigil, ArrayList<File> files) throws CoreException {
+		Collection<IClasspathEntry> entries = JavaHelper.findClasspathEntries(sigil.getBundle());
+		files.ensureCapacity(files.size() + entries.size());
+		for ( IClasspathEntry cp : entries ) {
+			convert(cp, sigil, files);
+		}
+		
+		if ( !sigil.getBundle().getComposites().isEmpty() ) {
+			throw new IllegalStateException("XXX-FIXME-XXX");
+		}
+	}
+
+	private void convert(IClasspathEntry cp, ISigilProjectModel sigil, ArrayList<File> files) throws CoreException {
+		switch( cp.getEntryKind() ) {
+		case IClasspathEntry.CPE_PROJECT: {
+			IProject p = findProject(cp.getPath());
+			ISigilProjectModel project = SigilCore.create(p);
+			for ( String scp : project.getBundle().getClasspathEntrys() ) {
+				IClasspathEntry jcp = project.getJavaModel().decodeClasspathEntry(scp);
+				convert( jcp, project, files );
+			}
+			break;
+		}
+		case IClasspathEntry.CPE_SOURCE : {
+			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());
+			}
+			break;
+		}
+		case IClasspathEntry.CPE_LIBRARY: {
+			IPath p = cp.getPath();
+			
+			IPath ppath = sigil.getProject().getFullPath();
+			
+			if ( ppath.isPrefixOf(p) ) {
+				p = sigil.getProject().getLocation().append( p.removeFirstSegments(1) );
+			}
+			
+			files.add( p.toFile() );
+			break;
+		}
+		case IClasspathEntry.CPE_VARIABLE:
+			cp = JavaCore.getResolvedClasspathEntry(cp);
+			if ( cp != null ) {
+				IPath p = cp.getPath();
+				files.add( p.toFile() );
+			}
+			break;
+		}
+	}
+
+	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");
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/install/OSGiInstallManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/install/OSGiInstallManager.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/install/OSGiInstallManager.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/install/OSGiInstallManager.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,267 @@
+/*
+ * 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.cauldron.sigil.internal.install;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+
+import org.cauldron.sigil.SigilCore;
+import org.cauldron.sigil.install.IOSGiInstall;
+import org.cauldron.sigil.install.IOSGiInstallBuilder;
+import org.cauldron.sigil.install.IOSGiInstallManager;
+import org.cauldron.sigil.install.IOSGiInstallType;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialogWithToggle;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceDialog;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.PreferencesUtil;
+
+public class OSGiInstallManager implements IOSGiInstallManager, IPropertyChangeListener {
+	private static final int NORMAL_PRIORITY = 0;
+	
+	private LinkedList<IOSGiInstallBuilder> builders = new LinkedList<IOSGiInstallBuilder>();
+
+	private HashMap<IPath, IOSGiInstall> pathToinstall = new HashMap<IPath, IOSGiInstall>();
+	private HashMap<String, IOSGiInstall> idToInstall = new HashMap<String, IOSGiInstall>();
+	
+	private String defaultId;
+	
+	private boolean initialised;
+		
+	public IOSGiInstall findInstall(String id) {
+		init();
+		return idToInstall.get(id);
+	}
+
+	public String[] getInstallIDs() {
+		init();
+		return idToInstall.keySet().toArray( new String[idToInstall.size()] );
+	}
+
+	public IOSGiInstall[] getInstalls() {
+		init();
+		return idToInstall.values().toArray( new IOSGiInstall[idToInstall.size()] );
+	}
+
+	public IOSGiInstall getDefaultInstall() {
+		init();
+		return findInstall(defaultId);
+	}
+
+	public IOSGiInstallType findInstallType(String location) {
+		IOSGiInstallType type = null;
+		
+		try {
+			IOSGiInstall install = buildInstall("tmp", new Path( location ) );
+			type = install == null ? null : install.getType();
+		} catch (CoreException e) {
+			SigilCore.error( "Failed to build install", e);
+		}
+		
+		return type;
+	}
+	
+	public void propertyChange(PropertyChangeEvent event) {
+		synchronized( this ) {
+			if ( event.getProperty().equals(SigilCore.OSGI_INSTALLS) ) {
+				clearInstalls();
+				String val = (String) event.getNewValue();
+				addInstalls(val);
+			}
+			else if ( event.getProperty().equals( SigilCore.OSGI_DEFAULT_INSTALL_ID ) ) {
+				defaultId = (String) event.getNewValue();
+			}
+		}
+	}
+
+	private void init() {
+		boolean show = false;
+		
+		IPreferenceStore prefs = getPreferenceStore(); 
+		
+		synchronized( this ) {
+			if ( !initialised ) {
+				initialised = true;
+				
+				prefs.addPropertyChangeListener(this);
+				
+				String val = prefs.getString(SigilCore.OSGI_INSTALLS);
+				
+				boolean noAsk = prefs.getBoolean(SigilCore.PREFERENCES_NOASK_OSGI_INSTALL);
+				if(val == null || val.trim().length() == 0) {
+					show = !noAsk;
+				}
+				else {
+					addInstalls(val);
+					defaultId = prefs.getString(SigilCore.OSGI_DEFAULT_INSTALL_ID);
+				}
+			}
+		}
+		
+		if ( show ) {
+			showInstallPrefs(prefs);
+		}		
+	}
+	
+	private void addInstalls(String prop) {
+		if ( prop != null && prop.trim().length() > 0 ) {
+			IPreferenceStore prefs = getPreferenceStore();
+			
+			for (String id : prop.split(",")) {
+				String path = prefs.getString( SigilCore.OSGI_INSTALL_PREFIX + id );
+				addInstall(id, new Path( path ) );
+			}
+		}				
+	}
+
+	private IPreferenceStore getPreferenceStore() {
+		return SigilCore.getDefault().getPreferenceStore();
+	}
+
+	private void showInstallPrefs(final IPreferenceStore prefs) {
+		Runnable r = new Runnable() {
+			public void run() {
+				MessageDialogWithToggle questionDialog = MessageDialogWithToggle.openYesNoQuestion(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Sigil Configuration", "Missing OSGi installation. Open preferences to configure it now?", "Do not show this message again", false, null, null);
+				prefs.setValue(SigilCore.PREFERENCES_NOASK_OSGI_INSTALL, questionDialog.getToggleState());
+				if(questionDialog.getReturnCode() == IDialogConstants.YES_ID) {
+					PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(null, SigilCore.OSGI_INSTALLS_PREFERENCES_ID, null, null);
+					dialog.open();
+				}
+			}
+		};
+		Display d = Display.getCurrent();
+		if ( d == null ) {
+			d = Display.getDefault();
+			d.asyncExec(r);
+		}
+		else {
+			d.syncExec(r);
+		}
+	}
+
+	private IOSGiInstall addInstall(String id, IPath path) {
+		IOSGiInstall install = pathToinstall.get(path);
+		
+		if ( install == null ) {
+			try {
+				install = buildInstall(id, path);
+				if ( install != null ) {
+					pathToinstall.put( path, install );
+					idToInstall.put( install.getId(), install );
+				}
+			}
+			catch (CoreException e) {
+				SigilCore.error( "Failed to build install for " + path, e);
+			}
+		}
+		
+		return install;
+	}
+	
+	private IOSGiInstall buildInstall(String id, IPath path) throws CoreException {
+		initBuilders();
+		IOSGiInstall install = null;
+		
+		for ( IOSGiInstallBuilder b : builders ) {
+			install = b.build(id, path);
+
+			if ( install != null ) {
+				break;
+			}
+		}
+		
+		return install;
+	}
+
+	private void clearInstalls() {
+		idToInstall.clear();
+		pathToinstall.clear();
+	}
+
+	private void initBuilders() {
+		synchronized( builders ) {
+			if ( builders.isEmpty() ) {
+				final HashMap<IOSGiInstallBuilder, Integer> tmp = new HashMap<IOSGiInstallBuilder, Integer>();
+				
+				IExtensionRegistry registry = Platform.getExtensionRegistry();
+				IExtensionPoint p = registry.getExtensionPoint(SigilCore.INSTALL_BUILDER_EXTENSION_POINT_ID);
+				for ( IExtension e : p.getExtensions() ) {
+					for ( IConfigurationElement c : e.getConfigurationElements() ) {
+						createBuilderFromElement(c, tmp);
+					}
+				}
+				
+				builders = new LinkedList<IOSGiInstallBuilder>(tmp.keySet());
+				Collections.sort(builders, new Comparator<IOSGiInstallBuilder>() {
+					public int compare(IOSGiInstallBuilder o1, IOSGiInstallBuilder o2) {
+						int p1 = tmp.get(o1);
+						int p2 = tmp.get(o2);
+						
+						if ( p1 == p2 ) {
+							return 0;
+						}
+						else if ( p1 > p2 ) {
+							return -1;
+						}
+						else {
+							return 1;
+						}
+					}
+				});
+			}
+		}
+	}
+
+	private void createBuilderFromElement(IConfigurationElement c, Map<IOSGiInstallBuilder, Integer> builder) {
+		try {
+			IOSGiInstallBuilder b = (IOSGiInstallBuilder) c.createExecutableExtension("class");
+			int priority = parsePriority( c );
+			builder.put(b, priority);
+		} catch (CoreException e) {
+			SigilCore.error("Failed to create builder", e);
+		}
+	}
+	
+	private int parsePriority(IConfigurationElement c) {
+		String str = c.getAttribute("priority");
+		
+		if ( str == null ) {
+			return NORMAL_PRIORITY;
+		}
+		else {
+			return Integer.parseInt(str);
+		}
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/model/project/SigilModelRoot.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/model/project/SigilModelRoot.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/model/project/SigilModelRoot.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/model/project/SigilModelRoot.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,126 @@
+/*
+ * 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.cauldron.sigil.internal.model.project;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+
+import org.cauldron.sigil.SigilCore;
+import org.cauldron.sigil.model.IModelElement;
+import org.cauldron.sigil.model.eclipse.ILibrary;
+import org.cauldron.sigil.model.eclipse.ILibraryImport;
+import org.cauldron.sigil.model.eclipse.ISigilBundle;
+import org.cauldron.sigil.model.osgi.IPackageExport;
+import org.cauldron.sigil.model.osgi.IPackageImport;
+import org.cauldron.sigil.model.osgi.IRequiredBundle;
+import org.cauldron.sigil.model.project.ISigilModelRoot;
+import org.cauldron.sigil.model.project.ISigilProjectModel;
+import org.cauldron.sigil.repository.IBundleResolver;
+import org.cauldron.sigil.repository.IResolution;
+import org.cauldron.sigil.repository.ResolutionConfig;
+import org.cauldron.sigil.repository.ResolutionException;
+import org.cauldron.sigil.repository.ResolutionMonitorAdapter;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+public class SigilModelRoot implements ISigilModelRoot {
+	public List<ISigilProjectModel> getProjects() {
+		IProject[] all = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+		ArrayList<ISigilProjectModel> projects = new ArrayList<ISigilProjectModel>(all.length);
+		for (IProject p : all) {
+			try {
+				if (p.isOpen() && p.hasNature(SigilCore.NATURE_ID)) {
+					ISigilProjectModel n = SigilCore.create(p);
+					projects.add(n);
+				}
+			} catch (CoreException e) {
+				SigilCore.error("Failed to build model element", e);
+			}
+		}
+
+		return projects;
+	}
+
+	public Collection<ISigilProjectModel> resolveDependentProjects(
+			ISigilProjectModel sigil, IProgressMonitor monitor) {
+		HashSet<ISigilProjectModel> dependents = new HashSet<ISigilProjectModel>();
+
+		for (ISigilProjectModel n : getProjects()) {
+			if (!sigil.equals(n)) {
+				for (IPackageExport pe : sigil.getBundle().getBundleInfo().getExports()) {
+					for (IPackageImport i : n.getBundle().getBundleInfo()
+							.getImports()) {
+						if (pe.getPackageName().equals(i.getPackageName())
+								&& i.getVersions().contains(pe.getVersion())) {
+							dependents.add(n);
+						}
+					}
+
+					for (ILibraryImport l : n.getBundle().getBundleInfo().getLibraryImports()) {
+						ILibrary lib = SigilCore.getRepositoryManager(sigil).resolveLibrary(l);
+
+						if (lib != null) {
+							for (IPackageImport i : lib.getImports()) {
+								if (pe.getPackageName().equals(
+										i.getPackageName())
+										&& i.getVersions().contains(
+												pe.getVersion())) {
+									dependents.add(n);
+								}
+							}
+						} else {
+							SigilCore.error("No library found for " + l);
+						}
+					}
+				}
+
+				for (IRequiredBundle r : n.getBundle().getBundleInfo().getRequiredBundles()) {
+					if (sigil.getSymbolicName().equals(r.getSymbolicName())
+							&& r.getVersions().contains(sigil.getVersion())) {
+						dependents.add(n);
+					}
+				}
+			}
+		}
+
+		return dependents;
+	}
+
+	public Collection<ISigilBundle> resolveBundles(ISigilProjectModel sigil, IModelElement element, boolean includeOptional, IProgressMonitor monitor) throws CoreException {
+		int options = ResolutionConfig.INCLUDE_DEPENDENTS;
+		if ( includeOptional ) {
+			options |= ResolutionConfig.INCLUDE_OPTIONAL;
+		}
+		
+		ResolutionConfig config = new ResolutionConfig(options);
+		try {
+			IBundleResolver resolver = SigilCore.getRepositoryManager(sigil).getBundleResolver();
+			IResolution resolution = resolver.resolve(element, config, new ResolutionMonitorAdapter(monitor));
+			resolution.synchronize(monitor);
+			return resolution.getBundles();
+		} catch (ResolutionException e) {
+			throw SigilCore.newCoreException(e.getMessage(), e);
+		}
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/model/project/SigilProject.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/model/project/SigilProject.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/model/project/SigilProject.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/model/project/SigilProject.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,460 @@
+/*
+ * 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.cauldron.sigil.internal.model.project;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.cauldron.bld.config.BldFactory;
+import org.cauldron.bld.config.IBldProject;
+import org.cauldron.sigil.SigilCore;
+import org.cauldron.sigil.job.ThreadProgressMonitor;
+import org.cauldron.sigil.model.AbstractCompoundModelElement;
+import org.cauldron.sigil.model.IModelElement;
+import org.cauldron.sigil.model.IModelWalker;
+import org.cauldron.sigil.model.ModelElementFactory;
+import org.cauldron.sigil.model.eclipse.ISigilBundle;
+import org.cauldron.sigil.model.osgi.IBundleModelElement;
+import org.cauldron.sigil.model.osgi.IPackageExport;
+import org.cauldron.sigil.model.osgi.IPackageImport;
+import org.cauldron.sigil.model.osgi.IRequiredBundle;
+import org.cauldron.sigil.model.project.ISigilProjectModel;
+import org.cauldron.sigil.model.util.JavaHelper;
+import org.cauldron.sigil.repository.IRepositoryManager;
+import org.cauldron.sigil.repository.IResolution;
+import org.cauldron.sigil.repository.ResolutionConfig;
+import org.cauldron.sigil.repository.ResolutionException;
+import org.cauldron.sigil.repository.ResolutionMonitorAdapter;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.INodeChangeListener;
+import org.eclipse.jdt.core.ClasspathContainerInitializer;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.IParent;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.osgi.framework.Version;
+import org.osgi.service.prefs.Preferences;
+
+/**
+ * @author dave
+ *
+ */
+public class SigilProject extends AbstractCompoundModelElement implements ISigilProjectModel {
+
+	private static final long serialVersionUID = 1L;
+	
+	private IFile bldProjectFile;
+    private IProject project;
+    private IBldProject bldProject;
+    
+    private ISigilBundle bundle;
+
+	private IEclipsePreferences preferences;
+
+    public SigilProject() {
+    	super( "Sigil Project" );
+    }
+    
+    public SigilProject(IProject project) throws CoreException {
+    	this();
+        this.project = project;
+        bldProjectFile = project.getFile( new Path( SigilCore.SIGIL_PROJECT_FILE) );
+    }
+    
+    // to aid testing conversion between project file formats
+    public InputStream saveBundle(ISigilBundle b) throws CoreException {
+    	setBundle(b);
+    	// FIXME causes NPE in JavaHelper
+    	// calculateUses();
+    	return buildContents();
+    }
+    
+	public void save(IProgressMonitor monitor) throws CoreException {
+		SubMonitor progress = SubMonitor.convert(monitor, 100);
+		
+    	calculateUses();
+    	
+    	bldProjectFile.setContents( buildContents(), IFile.KEEP_HISTORY, progress.newChild(10));
+    	
+		IRepositoryManager manager = SigilCore.getRepositoryManager(this);
+		ResolutionConfig config = new ResolutionConfig(ResolutionConfig.INCLUDE_OPTIONAL);
+		
+		try {
+			IResolution res = manager.getBundleResolver().resolve(this, config, new ResolutionMonitorAdapter(progress.newChild(10)));
+			if ( !res.isSynchronized() ) {
+				res.synchronize(progress.newChild(60));
+			}
+		} catch (ResolutionException e) {
+			throw SigilCore.newCoreException("Failed to synchronize dependencies", e);
+		}
+		
+		
+		progress.setWorkRemaining(40);
+		
+    	SigilCore.rebuildBundleDependencies( this, progress.newChild(20) );
+    }
+	
+	/**
+	 * Returns the project custom preference pool.
+	 * Project preferences may include custom encoding.
+	 * @return IEclipsePreferences or <code>null</code> if the project
+	 * 	does not have a java nature.
+	 */
+	public Preferences getPreferences(){
+		synchronized(this) {
+			if ( preferences == null ) {
+				preferences = loadPreferences();
+			}
+			
+			return preferences;
+		}
+	}
+	
+	
+	/**
+	 * @return
+	 */
+	private synchronized IEclipsePreferences loadPreferences() {
+		IScopeContext context = new ProjectScope(getProject());
+		final IEclipsePreferences eclipsePreferences = context.getNode(SigilCore.PLUGIN_ID);
+		
+		// Listen to node removal from parent in order to reset cache
+		INodeChangeListener nodeListener = new IEclipsePreferences.INodeChangeListener() {
+			public void added(IEclipsePreferences.NodeChangeEvent event) {
+				// do nothing
+			}
+			
+			public void removed(IEclipsePreferences.NodeChangeEvent event) {
+				if (event.getChild() == eclipsePreferences) {
+					synchronized( SigilProject.this ) {
+						preferences = null;
+					}
+					((IEclipsePreferences) eclipsePreferences.parent()).removeNodeChangeListener(this);
+				}
+			}
+		};
+
+		((IEclipsePreferences) eclipsePreferences.parent()).addNodeChangeListener(nodeListener);
+		
+		return eclipsePreferences;
+	}
+
+	public Collection<IClasspathEntry> findExternalClasspath(IProgressMonitor monitor) throws CoreException {
+		return JavaHelper.resolveClasspathEntrys(this, monitor);
+	}
+
+	private void calculateUses() {
+		visit( new IModelWalker() {
+			public boolean visit(IModelElement element) {
+				if ( element instanceof IPackageExport ) {
+					IPackageExport pe = (IPackageExport) element;
+					try {
+						pe.setUses( Arrays.asList( JavaHelper.findUses(pe.getPackageName(), SigilProject.this ) ) );
+					} catch (CoreException e) {
+						SigilCore.error( "Failed to build uses list for " + pe, e );
+					}
+				}
+				return true;
+			} 
+		} );
+	}
+
+    public Collection<ISigilProjectModel> findDependentProjects(IProgressMonitor monitor) {
+		return SigilCore.getRoot().resolveDependentProjects(this, monitor);
+	}
+
+	public Version getVersion() {
+		ISigilBundle bundle = getBundle();
+		return bundle == null ? null : bundle.getBundleInfo() == null ? null :  bundle.getBundleInfo().getVersion();
+	}
+
+    public String getSymbolicName() {
+		ISigilBundle bundle = getBundle();
+    	return bundle == null ? null : bundle.getBundleInfo() == null ? null : bundle.getBundleInfo().getSymbolicName();
+	}
+
+    public IProject getProject() {
+        return project;
+    }
+
+	public ISigilBundle getBundle() {
+		if ( bundle == null && bldProjectFile != null ) {
+			synchronized( bldProjectFile ) {
+				try {
+			        if ( bldProjectFile.getLocation().toFile().exists() ) {
+			        	bundle = parseContents(bldProjectFile);
+			        }
+			        else {
+			        	bundle = setupDefaults();
+			        	NullProgressMonitor npm = new NullProgressMonitor();
+			        	bldProjectFile.create( buildContents(), true /* force */, npm);
+			        	project.refreshLocal( IResource.DEPTH_INFINITE, npm );
+			        }
+				} catch (CoreException e) {
+					SigilCore.error( "Failed to build bundle", e);
+				}
+			}
+		}
+		return bundle;
+	}
+	
+	public void setBundle(ISigilBundle bundle) {
+		this.bundle = bundle;
+	}
+	
+	public IJavaProject getJavaModel() {
+		return JavaCore.create( project );
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if ( obj == null ) return false;
+		
+		if ( obj == this ) return true;
+		
+		try {
+			SigilProject p = (SigilProject) obj;
+			return getSymbolicName().equals( p.getSymbolicName() ) && (getVersion() == null ? p.getVersion() == null : getVersion().equals( p.getVersion() ));
+		}
+		catch (ClassCastException e) {
+			return false;
+		}
+	}
+
+	@Override
+	public int hashCode() {
+		// TODO Auto-generated method stub
+		return super.hashCode();
+	}
+
+	@Override
+	public String toString() {
+		return "SigilProject[" + getSymbolicName() + ":" + getVersion() + "]";
+	}
+
+	public void resetClasspath(IProgressMonitor monitor) throws CoreException {
+    	Path containerPath = new Path( SigilCore.CLASSPATH_CONTAINER_PATH );
+    	IJavaProject java = getJavaModel();
+		ClasspathContainerInitializer init = JavaCore.getClasspathContainerInitializer(SigilCore.CLASSPATH_CONTAINER_PATH);
+		ThreadProgressMonitor.setProgressMonitor(monitor);
+		try {
+			init.requestClasspathContainerUpdate(containerPath, java, null);
+		}
+		finally {
+			ThreadProgressMonitor.setProgressMonitor(null);
+		}
+	}
+
+	public IPath findBundleLocation() throws CoreException {
+		IPath p = getBundle().getLocation();
+		if ( p == null ) {
+			p = SigilCore.getDefault().findDefaultBundleLocation(this);
+		}
+		return p;
+	}
+
+    public IModelElement findImport(final String packageName, final IProgressMonitor monitor) {
+    	final IModelElement[] found = new IModelElement[1];
+    	
+    	visit( new IModelWalker() {
+			public boolean visit(IModelElement element) {
+				if ( element instanceof IPackageImport ) {
+					IPackageImport pi = (IPackageImport) element;
+					if ( pi.getPackageName().equals( packageName ) ) {
+						found[0] = pi;
+						return false;
+					}
+				}
+				else if ( element instanceof IRequiredBundle ) {
+					IRequiredBundle rb = (IRequiredBundle) element;
+					try {
+						IRepositoryManager manager = SigilCore.getRepositoryManager(SigilProject.this);
+						ResolutionConfig config = new ResolutionConfig(ResolutionConfig.IGNORE_ERRORS);
+						IResolution res = manager.getBundleResolver().resolve(rb, config, new ResolutionMonitorAdapter(monitor));
+						ISigilBundle b = res.getProvider(rb);
+						for ( IPackageExport pe : b.getBundleInfo().getExports() ) {
+							if ( pe.getPackageName().equals( packageName ) ) {
+								found[0] = rb;
+								return false;
+							}
+						}
+					} catch (ResolutionException e) {
+						SigilCore.error( "Failed to resolve " + rb, e );
+					}
+				}
+				return true;
+			}
+    		
+    	});
+    	
+    	return found[0];
+	}
+
+	public boolean isInClasspath(String packageName, IProgressMonitor monitor) throws CoreException {
+		if ( findImport(packageName, monitor) != null ) {
+			return true;
+		}
+		
+		for ( String path : getBundle().getClasspathEntrys() ) {
+			IClasspathEntry cp = getJavaModel().decodeClasspathEntry(path);
+			for ( IPackageFragmentRoot root : getJavaModel().findPackageFragmentRoots(cp) ) {
+				if ( findPackage( packageName, root ) ) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+	
+	public boolean isInClasspath(ISigilBundle bundle) {
+		for ( String path : getBundle().getClasspathEntrys() ) {
+			IClasspathEntry cp = getJavaModel().decodeClasspathEntry(path);
+			switch ( cp.getEntryKind() ) {
+			case IClasspathEntry.CPE_PROJECT:
+				ISigilProjectModel p = bundle.getAncestor(ISigilProjectModel.class);
+				return p != null && cp.getPath().equals(p.getProject().getFullPath());
+			case IClasspathEntry.CPE_LIBRARY:
+				return cp.getPath().equals(bundle.getLocation());
+			}
+		}	
+		
+		return false;
+	}
+
+	private boolean findPackage(String packageName, IParent parent) throws JavaModelException {
+		for ( IJavaElement e : parent.getChildren() ) {
+			if ( e.getElementType() == IJavaElement.PACKAGE_FRAGMENT ) {
+				return e.getElementName().equals( packageName );
+			}
+			
+			if ( e instanceof IParent ) {
+				if ( findPackage(packageName, (IParent) e) ) {
+					return true;
+				}
+			}
+		}
+		
+		return false;
+	}
+
+	private ISigilBundle setupDefaults() {
+    	ISigilBundle bundle = ModelElementFactory.getInstance().newModelElement(ISigilBundle.class);
+    	IBundleModelElement info = ModelElementFactory.getInstance().newModelElement( IBundleModelElement.class );
+    	info.setSymbolicName(project.getName());
+    	bundle.setBundleInfo(info);
+    	bundle.setParent(this);
+    	return bundle;
+    }
+
+	
+	private ISigilBundle parseContents(IFile projectFile) throws CoreException {
+		/*if ( !projectFile.isSynchronized(IResource.DEPTH_ONE) ) {
+			projectFile.refreshLocal(IResource.DEPTH_ONE, new NullProgressMonitor());
+		}*/
+		
+		if ( projectFile.getName().equals( SigilCore.SIGIL_PROJECT_FILE) ) {
+			return parseBldContents(projectFile.getLocationURI());
+		}
+		else {
+			throw SigilCore.newCoreException("Unexpected project file: " + projectFile.getName(), null );
+		}
+	}
+	
+    private ISigilBundle parseBldContents(URI uri) throws CoreException {
+		try {
+			bldProject = BldFactory.getProject(uri, true);
+			ISigilBundle bundle = bldProject.getDefaultBundle();
+			bundle.setParent(this);
+			return bundle;
+		} catch (IOException e) {
+			throw SigilCore.newCoreException( "Failed to parse " + uri, e);
+		}
+	}
+
+	private InputStream buildContents() throws CoreException {
+    	ByteArrayOutputStream buf = new ByteArrayOutputStream();    	
+    	try {
+    		if (bldProject == null) {
+            	bldProject = BldFactory.newProject(bldProjectFile.getLocationURI(), null);
+    		}
+        	bldProject.setDefaultBundle(getBundle());
+			bldProject.saveTo(buf);
+		} catch (IOException e) {
+			throw SigilCore.newCoreException("Failed to save project file", e);
+		}
+    	return new ByteArrayInputStream(buf.toByteArray());
+    }
+    
+//    private InputStream buildXMLContents() throws CoreException {
+//    	Serializer serializer = SigilCore.getDefault().getDescriptorSerializer();
+//    	
+//    	ByteArrayOutputStream buf = new ByteArrayOutputStream();
+//    	
+//    	try {
+//    		serializer.serialize(getBundle(), buf);
+//    	} catch (SerializingException e) {
+//			throw SigilCore.newCoreException("Failed to serialize " + this, e);
+//    	}
+//    	
+//        return new ByteArrayInputStream(buf.toByteArray());
+//    }
+
+	public String getName() {
+		return getProject().getName();
+	}
+
+	public IPath findOutputLocation() throws CoreException {
+		return getProject().getLocation().append(
+				getJavaModel().getOutputLocation()
+				.removeFirstSegments(1));
+	}
+
+	public IBldProject getBldProject() throws CoreException {
+		try {
+			return BldFactory.getProject(project.getFile(IBldProject.PROJECT_FILE).getLocationURI());
+		} catch (IOException e) {
+			throw SigilCore.newCoreException("Failed to get project file: ",e);
+		}
+	}
+
+	public boolean isInBundleClasspath(IPackageFragmentRoot root) throws JavaModelException {
+		String enc = getJavaModel().encodeClasspathEntry(root.getRawClasspathEntry());
+		return getBundle().getClasspathEntrys().contains( enc.trim() );
+	}
+}