/** * Copyright (c) 2012 Eclipse contributors 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 */ package org.eclipse.emf.ecore.xcore.ui.quickfix; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.util.Collections; import org.apache.log4j.Logger; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.emf.common.util.URI; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.xtext.util.MergeableManifest; import org.osgi.framework.Bundle; public class XcoreClasspathUpdater { private static final Logger LOG = Logger.getLogger(XcoreClasspathUpdater.class); private static final String PLUGIN_NATURE = "org.eclipse.pde.PluginNature"; public boolean addBundle(IJavaProject javaProject, String bundleID, IProgressMonitor monitor) { boolean result = false; try { SubMonitor progress = SubMonitor.convert(monitor, 2); IProject project = javaProject.getProject(); if (project.hasNature(PLUGIN_NATURE)) { result = addBundleToManifest(project, bundleID, progress.newChild(1)); } else { Bundle bundle = Platform.getBundle(bundleID); if (bundle != null) { URL entry = bundle.getEntry("/"); if (entry != null) { URI uri = URI.createURI(FileLocator.resolve(entry).toURI().toString()); if (uri.isArchive()) { String authority = uri.authority(); uri = URI.createURI(authority.substring(0, authority.length() - 1)); } if (uri.isFile()) { String location = uri.toFileString(); File binFolder = new File(location, "bin"); if (binFolder.isDirectory()) { location = binFolder.toString(); } if (addJarToClasspath(javaProject, new Path(location), progress.newChild(1))) { result = true; } } } } } } catch (Exception exception) { LOG.error("Error adding '" + bundleID + "' to the classpath", exception); } return result; } protected boolean addJarToClasspath(IJavaProject javaProject, IPath location, IProgressMonitor monitor) throws JavaModelException { IClasspathEntry newClasspthEntry = JavaCore.newLibraryEntry(location, null, null); IClasspathEntry[] rawClasspath = javaProject.getRawClasspath(); IClasspathEntry[] newRawClasspath = new IClasspathEntry [rawClasspath.length + 1]; for (int i = 0; i < rawClasspath.length; ++i) { IClasspathEntry entry = rawClasspath[i]; if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY && entry.getPath().equals(location)) { return false; } newRawClasspath[i + 1] = entry; } newRawClasspath[0] = newClasspthEntry; javaProject.setRawClasspath(newRawClasspath, monitor); return true; } protected boolean addBundleToManifest(IProject project, String bundleID, IProgressMonitor monitor) throws IOException, CoreException { IResource manifestResource = project.findMember("META-INF/MANIFEST.MF"); if (manifestResource != null && manifestResource.isAccessible() && !manifestResource.getResourceAttributes().isReadOnly() && manifestResource instanceof IFile) { OutputStream output = null; InputStream input = null; try { IFile manifestFile = (IFile)manifestResource; MergeableManifest manifest = new MergeableManifest(manifestFile.getContents()); manifest.addRequiredBundles(Collections.singleton(bundleID)); if (manifest.isModified()) { ByteArrayOutputStream out = new ByteArrayOutputStream(); output = new BufferedOutputStream(out); manifest.write(output); ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); input = new BufferedInputStream(in); manifestFile.setContents(input, true, true, monitor); return true; } return false; } finally { if (output != null) { output.close(); } if (input != null) { input.close(); } } } return false; } }