fr.obeo.releng.targetplatform.pde.Converter.java Source code

Java tutorial

Introduction

Here is the source code for fr.obeo.releng.targetplatform.pde.Converter.java

Source

/*******************************************************************************
 * Copyright (c) 2012 Obeo.
 * 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:
 *     Mikael Barbero (Obeo) - initial API and implementation
 *******************************************************************************/
package fr.obeo.releng.targetplatform.pde;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.DiagnosticChain;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.Diagnostician;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
import org.eclipse.xtext.resource.XtextResourceSet;

import com.google.common.base.Charsets;
import com.google.common.io.Closeables;
import com.google.common.io.Files;
import com.google.inject.Inject;
import com.google.inject.Provider;

import fr.obeo.releng.targetplatform.TargetPlatform;
import fr.obeo.releng.targetplatform.TargetPlatformBundleActivator;
import fr.obeo.releng.targetplatform.TargetPlatformPackage;
import fr.obeo.releng.targetplatform.resolved.ResolvedTargetPlatform;
import fr.obeo.releng.targetplatform.util.LocationIndexBuilder;

/**
 * @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a>
 *
 */
public class Converter {

    private static final Pattern SEQUENCE_NUMBER__PATTERN = Pattern.compile("sequenceNumber\\s*=\\s*\"[0-9]+\"");

    @Inject
    private Provider<XtextResourceSet> resourceSetProvider;

    @Inject
    private LocationIndexBuilder indexBuilder;

    @Inject
    private IProvisioningAgent agent;

    public Diagnostic generateTargetDefinitionFile(URI uri, IProgressMonitor monitor) {
        BasicDiagnostic ret = new BasicDiagnostic(TargetPlatformBundleActivator.PLUGIN_ID, 0,
                "Diagnostic of the generation of the target platform.", null);
        if (!"targetplatform".equals(uri.fileExtension()) && !"tpd".equals(uri.fileExtension())) {
            ret.merge(new BasicDiagnostic(Diagnostic.ERROR, TargetPlatformBundleActivator.PLUGIN_ID, -1,
                    "The target platform file '" + uri + "' must ends with '.tpd' or '.targetplatform' extensions.",
                    null));
        } else {
            Diagnostic diagnostic = doGenerateTargetDefinitionFile(uri, monitor);
            if (diagnostic.getSeverity() >= Diagnostic.WARNING) {
                ret.merge(diagnostic);
            }
        }
        return ret;
    }

    private Diagnostic doGenerateTargetDefinitionFile(URI uri, IProgressMonitor monitor) {
        BasicDiagnostic ret = new BasicDiagnostic();
        SubMonitor subMonitor = SubMonitor.convert(monitor, 100);

        try {
            Resource resource = loadTargetPlatform(uri);
            subMonitor.worked(2);

            Diagnostic resourceDiagnostic = EcoreUtil.computeDiagnostic(resource, true);
            if (resourceDiagnostic.getSeverity() >= Diagnostic.WARNING) {
                ret.merge(resourceDiagnostic);
            }

            if (resourceDiagnostic.getSeverity() < Diagnostic.ERROR) {
                TargetPlatform targetPlatform = null;
                if (resource != null && !resource.getContents().isEmpty()) {
                    targetPlatform = (TargetPlatform) resource.getContents().get(0);
                }
                if (targetPlatform == null) {
                    ret.merge(new BasicDiagnostic(Diagnostic.ERROR, TargetPlatformBundleActivator.PLUGIN_ID, -1,
                            "Error occured while loading the file " + uri + ".", null));
                } else if (subMonitor.isCanceled()) {
                    ret.merge(Diagnostic.CANCEL_INSTANCE);
                } else {
                    SubMonitor diagnosticianMonitor = subMonitor.newChild(90)
                            .setWorkRemaining(targetPlatform.getLocations().size());
                    Diagnostic validation = new CustomDiagnostician(diagnosticianMonitor).validate(targetPlatform);
                    if (validation.getSeverity() >= Diagnostic.WARNING) {
                        ret.merge(validation);
                    } else if (subMonitor.isCanceled()) {
                        ret.merge(Diagnostic.CANCEL_INSTANCE);
                    }

                    if (validation.getSeverity() < Diagnostic.ERROR) {
                        Diagnostic diagnostic = doGenerateTargetDefinitionFile(uri, targetPlatform,
                                subMonitor.newChild(8));
                        if (diagnostic.getSeverity() >= Diagnostic.WARNING) {
                            ret.merge(diagnostic);
                        }
                    }
                    subMonitor.setWorkRemaining(0);
                }
            }
        } catch (Exception e) {
            ret.merge(BasicDiagnostic.toDiagnostic(e));
        }
        return ret;
    }

    private Diagnostic doGenerateTargetDefinitionFile(URI uri, TargetPlatform targetPlatform,
            IProgressMonitor monitor) {
        final BasicDiagnostic ret = new BasicDiagnostic();
        SubMonitor subMonitor = SubMonitor.convert(monitor, 100);

        try {
            IMetadataRepositoryManager repositoryManager = (IMetadataRepositoryManager) agent
                    .getService(IMetadataRepositoryManager.SERVICE_NAME);
            ResolvedTargetPlatform resolvedTargetPlatform = ResolvedTargetPlatform.create(targetPlatform,
                    indexBuilder);
            subMonitor.worked(5);

            if (subMonitor.isCanceled()) {
                ret.merge(Diagnostic.CANCEL_INSTANCE);
            } else {
                Diagnostic diagnostic = resolvedTargetPlatform.resolve(repositoryManager, subMonitor.newChild(90));
                if (diagnostic.getSeverity() >= Diagnostic.WARNING) {
                    ret.merge(diagnostic);
                }
                if (subMonitor.isCanceled()) {
                    ret.merge(Diagnostic.CANCEL_INSTANCE);
                } else if (ret.getSeverity() < Diagnostic.ERROR) {
                    diagnostic = doGenerateTargetDefinitionFile(uri, resolvedTargetPlatform);
                    if (diagnostic.getSeverity() >= Diagnostic.WARNING) {
                        ret.merge(diagnostic);
                    }
                    subMonitor.worked(5);
                }
            }
        } catch (Exception e) {
            ret.merge(BasicDiagnostic.toDiagnostic(e));
        }

        return ret;
    }

    private Diagnostic doGenerateTargetDefinitionFile(URI uri, ResolvedTargetPlatform resolvedTargetPlatform) {
        BasicDiagnostic ret = new BasicDiagnostic();
        TargetDefinitionGenerator generator = new TargetDefinitionGenerator();
        String xml = generator.generate(resolvedTargetPlatform,
                (int) TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()));
        final URI targetDefinitionLocation = uri.trimFileExtension().appendFileExtension("target");

        Diagnostic diagnostic = serialize(targetDefinitionLocation, xml);
        if (diagnostic.getSeverity() >= Diagnostic.WARNING) {
            ret.merge(diagnostic);
        }

        return ret;
    }

    private Diagnostic serialize(URI targetPlatformLocation, String xml) {
        BasicDiagnostic ret = new BasicDiagnostic();
        URI targetDefinitionLocation = targetPlatformLocation.trimFileExtension().appendFileExtension("target");

        if (hasContentDifferencesOtherThanSequenceNumber(targetDefinitionLocation, xml)) {
            OutputStream outputStream = null;
            try {
                outputStream = new BufferedOutputStream(
                        new FileOutputStream(new File(targetDefinitionLocation.toFileString())));
                outputStream.write(xml.getBytes());
            } catch (Exception e) {
                ret.merge(BasicDiagnostic.toDiagnostic(e));
            } finally {
                try {
                    Closeables.close(outputStream, true);
                } catch (IOException e) {
                    // swallowed
                }
            }
        } else {
            ret.merge(
                    new BasicDiagnostic(Diagnostic.INFO, TargetPlatformBundleActivator.PLUGIN_ID, -1,
                            "The target definition '" + targetDefinitionLocation
                                    + "' did not changed since previous generation, we did not overwrote it.",
                            null));
        }

        return ret;
    }

    private boolean hasContentDifferencesOtherThanSequenceNumber(URI targetDefinitionLocation, String xml) {
        try {
            File targetDefinition = new File(targetDefinitionLocation.toFileString());
            if (targetDefinition.exists()) {
                String oldXml = Files.toString(targetDefinition, Charsets.UTF_8);
                oldXml = SEQUENCE_NUMBER__PATTERN.matcher(oldXml).replaceFirst("");
                String newXml = SEQUENCE_NUMBER__PATTERN.matcher(xml).replaceFirst("");
                return !oldXml.equals(newXml);
            }
        } catch (IOException e) {
            TargetPlatformBundleActivator.getInstance().getLog()
                    .log(new Status(IStatus.ERROR, TargetPlatformBundleActivator.PLUGIN_ID, e.getMessage()));
        }
        return true;
    }

    private Resource loadTargetPlatform(URI fileLocation) {
        ResourceSet resourceSet = resourceSetProvider.get();
        return resourceSet.getResource(fileLocation, true);
    }

    private static class CustomDiagnostician extends Diagnostician {

        private final SubMonitor monitor;

        public CustomDiagnostician(SubMonitor monitor) {
            this.monitor = monitor;
        }

        @Override
        public boolean validate(EClass eClass, EObject eObject, DiagnosticChain diagnostics,
                Map<Object, Object> context) {
            if (monitor.isCanceled()) {
                return true;
            }

            if (eClass == TargetPlatformPackage.Literals.LOCATION) {
                context.put(IProgressMonitor.class, monitor.newChild(1));
            }

            return super.validate(eClass, eObject, diagnostics, context);
        }
    }
}