| /******************************************************************************* |
| * Copyright (c) 2011, 2014 Sonatype Inc. and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Sonatype Inc. - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.tycho.packaging; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.Enumeration; |
| import java.util.jar.JarEntry; |
| import java.util.jar.JarFile; |
| |
| import org.apache.maven.plugin.MojoFailureException; |
| import org.codehaus.plexus.component.annotations.Component; |
| import org.codehaus.plexus.component.annotations.Requirement; |
| import org.codehaus.plexus.logging.Logger; |
| import org.eclipse.tycho.ArtifactKey; |
| import org.eclipse.tycho.ArtifactType; |
| import org.eclipse.tycho.artifacts.IllegalArtifactReferenceException; |
| import org.eclipse.tycho.artifacts.TargetPlatform; |
| import org.eclipse.tycho.locking.facade.FileLockService; |
| import org.eclipse.tycho.locking.facade.FileLocker; |
| import org.eclipse.tycho.model.Feature; |
| import org.eclipse.tycho.model.FeatureRef; |
| import org.eclipse.tycho.model.PluginRef; |
| |
| @Component(role = FeatureXmlTransformer.class) |
| public class FeatureXmlTransformer { |
| private static final int KBYTE = 1024; |
| |
| @Requirement |
| private Logger log; |
| |
| @Requirement |
| private FileLockService fileLockService; |
| |
| public FeatureXmlTransformer() { |
| } |
| |
| public FeatureXmlTransformer(Logger log, FileLockService fileLockService) { |
| this.log = log; |
| this.fileLockService = fileLockService; |
| } |
| |
| /** |
| * Replaces references in the feature model with versions from the target platform. |
| * |
| * @param feature |
| * The feature model to have plug-in and feature references completed. |
| */ |
| public Feature expandReferences(Feature feature, TargetPlatform targetPlatform) throws MojoFailureException { |
| |
| for (PluginRef pluginRef : feature.getPlugins()) { |
| ArtifactKey plugin = resolvePluginReference(targetPlatform, pluginRef); |
| pluginRef.setVersion(plugin.getVersion()); |
| |
| File location = targetPlatform.getArtifactLocation(plugin); |
| setDownloadAndInstallSize(pluginRef, location); |
| } |
| |
| for (FeatureRef featureRef : feature.getIncludedFeatures()) { |
| ArtifactKey includedFeature = resolveFeatureReference(targetPlatform, featureRef); |
| featureRef.setVersion(includedFeature.getVersion()); |
| } |
| |
| return feature; |
| } |
| |
| private ArtifactKey resolvePluginReference(TargetPlatform targetPlatform, PluginRef pluginRef) |
| throws MojoFailureException { |
| try { |
| return targetPlatform.resolveArtifact(ArtifactType.TYPE_ECLIPSE_PLUGIN, pluginRef.getId(), |
| pluginRef.getVersion()); |
| } catch (IllegalArtifactReferenceException e) { |
| throw new MojoFailureException("Invalid plugin reference with id=" + quote(pluginRef.getId()) |
| + " and version=" + quote(pluginRef.getVersion()) + ": " + e.getMessage(), e); |
| } |
| } |
| |
| private ArtifactKey resolveFeatureReference(TargetPlatform targetPlatform, FeatureRef featureRef) |
| throws MojoFailureException { |
| try { |
| return targetPlatform.resolveArtifact(ArtifactType.TYPE_ECLIPSE_FEATURE, featureRef.getId(), |
| featureRef.getVersion()); |
| } catch (IllegalArtifactReferenceException e) { |
| throw new MojoFailureException("Invalid feature reference with id=" + quote(featureRef.getId()) |
| + " and version " + quote(featureRef.getVersion()) + ": " + e.getMessage(), e); |
| } |
| } |
| |
| private static String quote(String nullableString) { |
| if (nullableString == null) |
| return null; |
| else |
| return "\"" + nullableString + "\""; |
| } |
| |
| private void setDownloadAndInstallSize(PluginRef pluginRefToEdit, File artifact) { |
| // TODO 375111 optionally disable this? |
| long downloadSize = 0; |
| long installSize = 0; |
| if (artifact.isFile()) { |
| installSize = getInstallSize(artifact); |
| downloadSize = artifact.length(); |
| } else { |
| log.info("Download/install size is not calculated for directory based bundle " + pluginRefToEdit.getId()); |
| } |
| |
| pluginRefToEdit.setDownloadSize(downloadSize / KBYTE); |
| pluginRefToEdit.setInstallSize(installSize / KBYTE); |
| } |
| |
| protected long getInstallSize(File location) { |
| long installSize = 0; |
| FileLocker locker = fileLockService.getFileLocker(location); |
| locker.lock(); |
| try { |
| try { |
| try (JarFile jar = new JarFile(location)) { |
| Enumeration<JarEntry> entries = jar.entries(); |
| while (entries.hasMoreElements()) { |
| JarEntry entry = entries.nextElement(); |
| long entrySize = entry.getSize(); |
| if (entrySize > 0) { |
| installSize += entrySize; |
| } |
| } |
| } |
| } catch (IOException e) { |
| throw new RuntimeException("Could not determine installation size of file " + location, e); |
| } |
| } finally { |
| locker.release(); |
| } |
| return installSize; |
| } |
| } |