Java tutorial
/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation 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: * IBM Corporation - initial API and implementation * Code 9 Corporation - ongoing enhancements * Bartosz Michalik <bartosz.michalik@gmail.com> - bug 109440 * Benjamin Cabe <benjamin.cabe@anyware-tech.com> - bug 248852, bug 247553 *******************************************************************************/ package com.siteview.mde.internal.ui.wizards.plugin; import com.siteview.mde.internal.core.monitor.WorkspaceMonitorModelBase; import com.siteview.mde.core.monitor.*; import java.io.*; import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.jar.JarFile; import java.util.jar.Manifest; import java.util.zip.ZipFile; import org.eclipse.core.resources.*; import org.eclipse.core.runtime.*; import org.eclipse.jdt.core.*; import org.eclipse.osgi.service.resolver.BundleDescription; import org.eclipse.osgi.util.ManifestElement; import org.eclipse.osgi.util.NLS; import com.siteview.mde.core.build.IBuildEntry; import com.siteview.mde.core.build.IBuildModelFactory; import com.siteview.mde.internal.core.ICoreConstants; import com.siteview.mde.internal.core.build.WorkspaceBuildModel; import com.siteview.mde.internal.core.bundle.BundlePluginBase; import com.siteview.mde.internal.core.converter.MonitorConverter; import com.siteview.mde.internal.core.ibundle.IBundle; import com.siteview.mde.internal.core.ibundle.IBundlePluginModelBase; import com.siteview.mde.internal.core.natures.MDE; import com.siteview.mde.internal.core.project.PDEProject; import com.siteview.mde.internal.ui.*; import com.siteview.mde.internal.ui.search.dependencies.AddNewBinaryDependenciesOperation; import com.siteview.mde.internal.ui.wizards.IProjectProvider; import com.siteview.mde.ui.IFieldData; import com.siteview.mde.ui.IPluginContentWizard; import org.eclipse.ui.dialogs.IOverwriteQuery; import org.eclipse.ui.wizards.datatransfer.ImportOperation; import org.eclipse.ui.wizards.datatransfer.ZipFileStructureProvider; import org.osgi.framework.BundleException; import org.osgi.framework.Constants; public class NewLibraryPluginCreationOperation extends NewProjectCreationOperation { private LibraryPluginFieldData fData; public NewLibraryPluginCreationOperation(LibraryPluginFieldData data, IProjectProvider provider, IPluginContentWizard contentWizard) { super(data, provider, contentWizard); fData = data; } private void addJar(File jarFile, IProject project, IProgressMonitor monitor) throws CoreException { String jarName = jarFile.getName(); IFile file = project.getFile(jarName); monitor.subTask(NLS.bind(MDEUIMessages.NewProjectCreationOperation_copyingJar, jarName)); InputStream in = null; try { in = new FileInputStream(jarFile); file.create(in, true, monitor); } catch (FileNotFoundException fnfe) { } finally { if (in != null) { try { in.close(); } catch (IOException ioe) { } } } } private void adjustExportRoot(IProject project, IBundle bundle) throws CoreException { IResource[] resources = project.members(false); for (int j = 0; j < resources.length; j++) { if (resources[j] instanceof IFile) { if (".project".equals(resources[j].getName()) //$NON-NLS-1$ || ".classpath".equals(resources[j] //$NON-NLS-1$ .getName()) || ICoreConstants.PLUGIN_FILENAME_DESCRIPTOR.equals(resources[j].getName()) || ICoreConstants.BUILD_FILENAME_DESCRIPTOR.equals(resources[j].getName())) { continue; } // resource at the root, export root return; } } removeExportRoot(bundle); } protected void adjustManifests(IProgressMonitor monitor, IProject project, IMonitorBase base) throws CoreException { super.adjustManifests(monitor, project, base); int units = fData.doFindDependencies() ? 4 : 2; units += fData.isUpdateReferences() ? 1 : 0; monitor.beginTask(new String(), units); IBundle bundle = (base instanceof BundlePluginBase) ? ((BundlePluginBase) base).getBundle() : null; if (bundle != null) { adjustExportRoot(project, bundle); monitor.worked(1); addExportedPackages(project, bundle); monitor.worked(1); if (fData.doFindDependencies()) { addDependencies(project, base.getModel(), new SubProgressMonitor(monitor, 2)); } if (fData.isUpdateReferences()) { updateReferences(monitor, project); monitor.worked(1); } } monitor.done(); } protected void updateReferences(IProgressMonitor monitor, IProject project) throws JavaModelException { IJavaProject currentProject = JavaCore.create(project); IMonitorModelBase[] pluginstoUpdate = fData.getPluginsToUpdate(); for (int i = 0; i < pluginstoUpdate.length; ++i) { IProject proj = pluginstoUpdate[i].getUnderlyingResource().getProject(); if (currentProject.getProject().equals(proj)) continue; IJavaProject javaProject = JavaCore.create(proj); IClasspathEntry[] cp = javaProject.getRawClasspath(); IClasspathEntry[] updated = getUpdatedClasspath(cp, currentProject); if (updated != null) { javaProject.setRawClasspath(updated, monitor); } try { updateRequiredPlugins(javaProject, monitor, pluginstoUpdate[i]); } catch (CoreException e) { MDEPlugin.log(e); } } } private static void updateRequiredPlugins(IJavaProject javaProject, IProgressMonitor monitor, IMonitorModelBase model) throws CoreException { IClasspathEntry[] entries = javaProject.getRawClasspath(); List classpath = new ArrayList(); List requiredProjects = new ArrayList(); for (int i = 0; i < entries.length; i++) { if (isPluginProjectEntry(entries[i])) { requiredProjects.add(entries[i]); } else { classpath.add(entries[i]); } } if (requiredProjects.size() <= 0) return; IFile file = PDEProject.getManifest(javaProject.getProject()); try { // TODO format manifest Manifest manifest = new Manifest(file.getContents()); String value = manifest.getMainAttributes().getValue(Constants.REQUIRE_BUNDLE); StringBuffer sb = value != null ? new StringBuffer(value) : new StringBuffer(); if (sb.length() > 0) sb.append(","); //$NON-NLS-1$ for (int i = 0; i < requiredProjects.size(); i++) { IClasspathEntry entry = (IClasspathEntry) requiredProjects.get(i); if (i > 0) sb.append(","); //$NON-NLS-1$ sb.append(entry.getPath().segment(0)); if (entry.isExported()) sb.append(";visibility:=reexport"); // TODO is there a //$NON-NLS-1$ // constant? } manifest.getMainAttributes().putValue(Constants.REQUIRE_BUNDLE, sb.toString()); ByteArrayOutputStream content = new ByteArrayOutputStream(); manifest.write(content); file.setContents(new ByteArrayInputStream(content.toByteArray()), true, false, monitor); // now update .classpath javaProject.setRawClasspath( (IClasspathEntry[]) classpath.toArray(new IClasspathEntry[classpath.size()]), monitor); // ClasspathComputer.setClasspath(javaProject.getProject(), model); } catch (IOException e) { } catch (CoreException e) { } } private static boolean isPluginProjectEntry(IClasspathEntry entry) { if (IClasspathEntry.CPE_PROJECT != entry.getEntryKind()) return false; IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); IProject other = workspaceRoot.getProject(entry.getPath().segment(0)); if (!MDE.hasPluginNature(other)) return false; if (PDEProject.getFragmentXml(other).exists()) return false; try { InputStream is = PDEProject.getManifest(other).getContents(); try { Manifest mf = new Manifest(is); if (mf.getMainAttributes().getValue(Constants.FRAGMENT_HOST) != null) return false; } finally { is.close(); } } catch (IOException e) { // assume "not a fragment" } catch (CoreException e) { // assume "not a fragment" } return true; } /** * @return updated classpath or null if there were no changes */ private IClasspathEntry[] getUpdatedClasspath(IClasspathEntry[] cp, IJavaProject currentProject) { boolean exposed = false; int refIndex = -1; List result = new ArrayList(); Set manifests = new HashSet(); for (int i = 0; i < fData.getLibraryPaths().length; ++i) { try { manifests.add(new JarFile(fData.getLibraryPaths()[i]).getManifest()); } catch (IOException e) { MDEPlugin.log(e); } } IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); for (int i = 0; i < cp.length; ++i) { IClasspathEntry cpe = cp[i]; switch (cpe.getEntryKind()) { case IClasspathEntry.CPE_LIBRARY: String path = null; IPath location = root.getFile(cpe.getPath()).getLocation(); if (location != null) { path = location.toString(); } //try maybe path is absolute if (path == null) { path = cpe.getPath().toString(); } try { JarFile jarFile = new JarFile(path); if (manifests.contains(jarFile.getManifest())) { if (refIndex < 0) { // allocate slot refIndex = result.size(); result.add(null); } exposed |= cpe.isExported(); } else { result.add(cpe); } } catch (IOException e) { MDEPlugin.log(e); } break; default: result.add(cpe); break; } } if (refIndex >= 0) { result.set(refIndex, JavaCore.newProjectEntry(currentProject.getPath(), exposed)); return (IClasspathEntry[]) result.toArray(new IClasspathEntry[result.size()]); } return null; } protected void createContents(IProgressMonitor monitor, IProject project) throws CoreException, JavaModelException, InvocationTargetException, InterruptedException { // copy jars String[] paths = fData.getLibraryPaths(); for (int i = paths.length - 1; i >= 0; i--) { File jarFile = new File(paths[i]); if (fData.isUnzipLibraries()) { importJar(jarFile, project, monitor); } else { addJar(jarFile, project, monitor); } monitor.worked(1); } // delete manifest.mf imported from libraries IFile importedManifest = PDEProject.getManifest(project); if (importedManifest.exists()) { importedManifest.delete(true, false, monitor); if (!fData.hasBundleStructure()) { IFolder meta_inf = project.getFolder("META-INF"); //$NON-NLS-1$ if (meta_inf.members().length == 0) { meta_inf.delete(true, false, monitor); } } } } protected void fillBinIncludes(IProject project, IBuildEntry binEntry) throws CoreException { if (fData.hasBundleStructure()) binEntry.addToken(ICoreConstants.MANIFEST_FOLDER_NAME); else binEntry.addToken(ICoreConstants.PLUGIN_FILENAME_DESCRIPTOR); if (fData.isUnzipLibraries()) { IResource[] resources = project.members(false); for (int j = 0; j < resources.length; j++) { String resourceName = resources[j].getName(); if (resources[j] instanceof IFolder) { if (!".settings".equals(resourceName) && !binEntry.contains(resourceName + "/")) //$NON-NLS-1$ //$NON-NLS-2$ binEntry.addToken(resourceName + "/"); //$NON-NLS-1$ } else { if (".project".equals(resourceName) //$NON-NLS-1$ || ".classpath".equals(resourceName) //$NON-NLS-1$ || ICoreConstants.BUILD_FILENAME_DESCRIPTOR.equals(resourceName)) { continue; } if (!binEntry.contains(resourceName)) binEntry.addToken(resourceName); } } } else { String[] libraryPaths = fData.getLibraryPaths(); for (int j = 0; j < libraryPaths.length; j++) { File jarFile = new File(libraryPaths[j]); String name = jarFile.getName(); if (!binEntry.contains(name)) binEntry.addToken(name); } } } protected IClasspathEntry[] getInternalClassPathEntries(IJavaProject project, IFieldData data) { String[] libraryPaths; if (fData.isUnzipLibraries()) { libraryPaths = new String[] { "" }; //$NON-NLS-1$ } else { libraryPaths = fData.getLibraryPaths(); } IClasspathEntry[] entries = new IClasspathEntry[libraryPaths.length]; for (int j = 0; j < libraryPaths.length; j++) { File jarFile = new File(libraryPaths[j]); String jarName = jarFile.getName(); IPath path = project.getProject().getFullPath().append(jarName); entries[j] = JavaCore.newLibraryEntry(path, null, null, true); } return entries; } protected int getNumberOfWorkUnits() { int numUnits = super.getNumberOfWorkUnits(); numUnits += fData.getLibraryPaths().length; return numUnits; } private void importJar(File jar, IResource destination, IProgressMonitor monitor) throws CoreException, InvocationTargetException, InterruptedException { ZipFile input = null; try { try { input = new ZipFile(jar); ZipFileStructureProvider provider = new ZipFileStructureProvider(input); ImportOperation op = new ImportOperation(destination.getFullPath(), provider.getRoot(), provider, new IOverwriteQuery() { public String queryOverwrite(String pathString) { return IOverwriteQuery.ALL; } }); op.run(monitor); } finally { if (input != null) input.close(); } } catch (IOException e) { throw new CoreException(new Status(IStatus.ERROR, IMDEUIConstants.PLUGIN_ID, IStatus.OK, NLS.bind(MDEUIMessages.NewProjectCreationOperation_errorImportingJar, jar), e)); } } private void removeExportRoot(IBundle bundle) { String value = bundle.getHeader(Constants.BUNDLE_CLASSPATH); if (value == null) value = "."; //$NON-NLS-1$ try { ManifestElement[] elems = ManifestElement.parseHeader(Constants.BUNDLE_CLASSPATH, value); StringBuffer buff = new StringBuffer(value.length()); for (int i = 0; i < elems.length; i++) { if (!elems[i].getValue().equals(".")) //$NON-NLS-1$ buff.append(elems[i].getValue()); } bundle.setHeader(Constants.BUNDLE_CLASSPATH, buff.toString()); } catch (BundleException e) { } } protected void setPluginLibraries(WorkspaceMonitorModelBase model) throws CoreException { IMonitorBase pluginBase = model.getMonitorBase(); if (fData.isUnzipLibraries()) { IMonitorLibrary library = model.getMonitorFactory().createLibrary(); library.setName("."); //$NON-NLS-1$ library.setExported(true); pluginBase.add(library); } else { String[] paths = fData.getLibraryPaths(); for (int i = 0; i < paths.length; i++) { File jarFile = new File(paths[i]); IMonitorLibrary library = model.getMonitorFactory().createLibrary(); library.setName(jarFile.getName()); library.setExported(true); pluginBase.add(library); } } } protected void createSourceOutputBuildEntries(WorkspaceBuildModel model, IBuildModelFactory factory) throws CoreException { if (fData.isUnzipLibraries()) { // SOURCE.<LIBRARY_NAME> IBuildEntry entry = factory.createEntry(IBuildEntry.JAR_PREFIX + "."); //$NON-NLS-1$ entry.addToken("."); //$NON-NLS-1$ model.getBuild().add(entry); // OUTPUT.<LIBRARY_NAME> entry = factory.createEntry(IBuildEntry.OUTPUT_PREFIX + "."); //$NON-NLS-1$ entry.addToken("."); //$NON-NLS-1$ model.getBuild().add(entry); } } private void addExportedPackages(IProject project, IBundle bundle) { String value = bundle.getHeader(Constants.BUNDLE_CLASSPATH); if (value == null) value = "."; //$NON-NLS-1$ try { ManifestElement[] elems = ManifestElement.parseHeader(Constants.BUNDLE_CLASSPATH, value); HashMap map = new HashMap(); for (int i = 0; i < elems.length; i++) { ArrayList filter = new ArrayList(); filter.add("*"); //$NON-NLS-1$ map.put(elems[i].getValue(), filter); } Set packages = MonitorConverter.getDefault().getExports(project, map); String pkgValue = getCommaValuesFromPackagesSet(packages, fData.getVersion()); bundle.setHeader(Constants.EXPORT_PACKAGE, pkgValue); } catch (BundleException e) { } } private void addDependencies(IProject project, ISharedMonitorModel model, IProgressMonitor monitor) { if (!(model instanceof IBundlePluginModelBase)) { monitor.done(); return; } final boolean unzip = fData.isUnzipLibraries(); try { new AddNewBinaryDependenciesOperation(project, (IBundlePluginModelBase) model) { // Need to override this function to include every bundle in the // target platform as a possible dependency protected String[] findSecondaryBundles(IBundle bundle, Set ignorePkgs) { IMonitorModelBase[] bases = MonitorRegistry.getActiveModels(); String[] ids = new String[bases.length]; for (int i = 0; i < bases.length; i++) { BundleDescription desc = bases[i].getBundleDescription(); if (desc == null) ids[i] = bases[i].getMonitorBase().getId(); else ids[i] = desc.getSymbolicName(); } return ids; } // Need to override this function because when jar is unzipped, // build.properties does not contain entry for '.'. // Therefore, the super.addProjectPackages will not find the // project packages(it includes only things in bin.includes) protected void addProjectPackages(IBundle bundle, Set ignorePkgs) { if (!unzip) super.addProjectPackages(bundle, ignorePkgs); Stack stack = new Stack(); stack.push(fProject); try { while (!stack.isEmpty()) { IContainer folder = (IContainer) stack.pop(); IResource[] children = folder.members(); for (int i = 0; i < children.length; i++) { if (children[i] instanceof IContainer) stack.push(children[i]); else if ("class".equals(((IFile) children[i]).getFileExtension())) { //$NON-NLS-1$ String path = folder.getProjectRelativePath().toString(); ignorePkgs.add(path.replace('/', '.')); } } } } catch (CoreException e) { } } }.run(monitor); } catch (InvocationTargetException e) { } catch (InterruptedException e) { } } }