/***************************************************************************** * Copyright (c) 2006-2013, Cloudsmith Inc. * The code, documentation and other materials contained herein have been * licensed under the Eclipse Public License - v 1.0 by the copyright holder * listed above, as the Initial Contributor under such license. The text of * such license is available at www.eclipse.org. *****************************************************************************/ package org.eclipse.buckminster.core.materializer; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; import org.eclipse.buckminster.core.CorePlugin; import org.eclipse.buckminster.core.Messages; import org.eclipse.buckminster.core.actor.IPerformManager; import org.eclipse.buckminster.core.cspec.model.Attribute; import org.eclipse.buckminster.core.cspec.model.CSpec; import org.eclipse.buckminster.core.helpers.AbstractExtension; import org.eclipse.buckminster.core.helpers.FileUtils; import org.eclipse.buckminster.core.metadata.ModelCache; import org.eclipse.buckminster.core.metadata.StorageManager; import org.eclipse.buckminster.core.metadata.model.BOMNode; import org.eclipse.buckminster.core.metadata.model.BillOfMaterials; import org.eclipse.buckminster.core.metadata.model.GeneratorNode; import org.eclipse.buckminster.core.metadata.model.Resolution; import org.eclipse.buckminster.core.mspec.model.MaterializationSpec; import org.eclipse.buckminster.core.reader.IReaderType; import org.eclipse.buckminster.runtime.BuckminsterException; import org.eclipse.buckminster.runtime.MonitorUtils; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtensionRegistry; 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.Platform; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.osgi.service.datalocation.Location; /** * @author Thomas Hallgren */ public abstract class AbstractMaterializer extends AbstractExtension implements IMaterializer { private static IConfigurationElement[] getElements() { IExtensionRegistry exReg = Platform.getExtensionRegistry(); return exReg.getConfigurationElementsFor(MATERIALIZERS_POINT); } public static String[] getMaterializerIDs(boolean includeEmptyEntry) { IConfigurationElement[] elems = getElements(); int idx = elems.length; ArrayList<String> names = new ArrayList<String>(idx + 1); if (includeEmptyEntry) names.add(""); //$NON-NLS-1$ while (--idx >= 0) names.add(elems[idx].getAttribute("id")); //$NON-NLS-1$ Collections.sort(names); return names.toArray(new String[names.size()]); } public static void performInstallActions(BillOfMaterials bom, MaterializationContext context, IProgressMonitor monitor) throws CoreException { monitor.beginTask(null, bom.uniqueNodeCount() * 100); try { Resolution resolution = bom.getResolution(); MaterializationSpec mspec = context.getMaterializationSpec(); IMaterializer materializer = mspec.getMaterializer(resolution); Set<Resolution> perused = new LinkedHashSet<Resolution>(); materializer.installRecursive(bom, context, new HashSet<String>(), perused, monitor); IStatus status = context.getStatus(); if (status.getSeverity() == IStatus.ERROR) return; // Collect the reader types in the order they were perused // Set<String> readerTypes = new LinkedHashSet<String>(); for (Resolution res : perused) { if (!mspec.isExcluded(res)) readerTypes.add(mspec.getMaterializer(res).getMaterializationReaderType(res).getId()); } CorePlugin plugin = CorePlugin.getDefault(); for (String readerTypeId : readerTypes) { IReaderType readerType = plugin.getReaderType(readerTypeId); readerType.postMaterialization(context, new SubProgressMonitor(monitor, 1)); } for (Resolution res : perused) mspec.getMaterializer(resolution).performPostInstallAction(res, context, new SubProgressMonitor(monitor, 1)); } finally { monitor.done(); } } @Override public boolean canWorkInParallel() { // Most materializers should be able to do this. // return true; } private void delegateAndInstallRecursive(BOMNode node, MaterializationContext context, Set<String> generated, Set<Resolution> perused, IProgressMonitor monitor) throws CoreException { Resolution res = node.getResolution(); if (res == null) return; IMaterializer materializer; if (node instanceof GeneratorNode) materializer = this; else materializer = getMaterializer(context, res); ((AbstractMaterializer) materializer).installRecursive(node, context, generated, perused, monitor); } private boolean generateResolution(GeneratorNode generatorNode, MaterializationContext context, IProgressMonitor monitor) throws CoreException { CSpec cspec = generatorNode.getDeclaringCSpec(); try { IPerformManager performManager = CorePlugin.getPerformManager(); Attribute generatorAttribute = cspec.getReferencedAttribute(generatorNode.getComponent(), null, null, generatorNode.getAttribute(), new ModelCache()); if (generatorAttribute != null) { performManager.perform(Collections.singletonList(generatorAttribute), context, false, false, monitor); return true; } } catch (CoreException e) { if (!context.isContinueOnError()) throw e; context.addRequestStatus(generatorNode.getRequest(), e.getStatus()); } return false; } @Override public IPath getDefaultInstallRoot(MaterializationContext context, Resolution resolution) throws CoreException { IPath rootDir = Path.fromOSString(getMaterializerRootDir()); if (rootDir.isAbsolute()) return rootDir; if (Platform.OS_WIN32.equals(Platform.getOS())) { File userDir = null; String appDataEnv = System.getenv("APPDATA"); //$NON-NLS-1$ if (appDataEnv != null) { userDir = new File(appDataEnv + "\\buckminster"); //$NON-NLS-1$ return Path.fromOSString(new File(userDir, rootDir.toOSString()).toString()); } } Location userLocation = Platform.getUserLocation(); if (userLocation != null) { File userDir = FileUtils.getFile(userLocation.getURL()); if (userDir != null) { if (Platform.OS_WIN32.equals(Platform.getOS())) userDir = new File(userDir, "Application Data\\buckminster"); //$NON-NLS-1$ else userDir = new File(userDir, "buckminster"); //$NON-NLS-1$ return Path.fromOSString(new File(userDir, rootDir.toOSString()).toString()); } } throw BuckminsterException.fromMessage(Messages.Unable_to_determine_users_home_directory); } @Override public IReaderType getMaterializationReaderType(Resolution resolution) throws CoreException { return resolution.getProvider().getReaderType(); } private IMaterializer getMaterializer(MaterializationContext context, Resolution res) throws CoreException { String materializerId = context.getMaterializationSpec().getMaterializerID(res); return materializerId.equals(getId()) ? this : CorePlugin.getDefault().getMaterializer(materializerId); } public abstract String getMaterializerRootDir() throws CoreException; @Override public void installRecursive(BOMNode node, MaterializationContext context, Set<String> generated, Set<Resolution> perused, IProgressMonitor monitor) throws CoreException { if (node instanceof GeneratorNode) { GeneratorNode generatorNode = (GeneratorNode) node; String generates = generatorNode.getGeneratesId().toString(); if (!generated.contains(generates)) { if (generateResolution(generatorNode, context, MonitorUtils.subMonitor(monitor, 100))) generated.add(generates); } } else { Resolution resolution = node.getResolution(); if (resolution == null || perused.contains(resolution)) return; perused.add(resolution); for (BOMNode child : node.getChildren()) delegateAndInstallRecursive(child, context, generated, perused, monitor); if (!context.getMaterializationSpec().isExcluded(resolution)) { // The local reader might create resolutions that are not // materialized and // hence not stored so we must make sure it's stored here. // resolution.store(StorageManager.getDefault()); performInstallAction(resolution, context, MonitorUtils.subMonitor(monitor, 100)); } } } @Override public void performInstallAction(Resolution resolution, MaterializationContext context, IProgressMonitor monitor) throws CoreException { // The AbstractMaterializer will not perform any install actions // MonitorUtils.complete(monitor); } @Override public void performPostInstallAction(Resolution resolution, MaterializationContext context, IProgressMonitor monitor) throws CoreException { } }