001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.pde.internal.ui.wizards.plugin;
011:
012: import java.io.File;
013: import java.io.FileInputStream;
014: import java.io.FileNotFoundException;
015: import java.io.IOException;
016: import java.io.InputStream;
017: import java.lang.reflect.InvocationTargetException;
018: import java.util.ArrayList;
019: import java.util.HashMap;
020: import java.util.Set;
021: import java.util.Stack;
022: import java.util.zip.ZipFile;
023:
024: import org.eclipse.core.resources.IContainer;
025: import org.eclipse.core.resources.IFile;
026: import org.eclipse.core.resources.IFolder;
027: import org.eclipse.core.resources.IProject;
028: import org.eclipse.core.resources.IResource;
029: import org.eclipse.core.runtime.CoreException;
030: import org.eclipse.core.runtime.IPath;
031: import org.eclipse.core.runtime.IProgressMonitor;
032: import org.eclipse.core.runtime.IStatus;
033: import org.eclipse.core.runtime.Status;
034: import org.eclipse.core.runtime.SubProgressMonitor;
035: import org.eclipse.jdt.core.IClasspathEntry;
036: import org.eclipse.jdt.core.JavaCore;
037: import org.eclipse.jdt.core.JavaModelException;
038: import org.eclipse.osgi.service.resolver.BundleDescription;
039: import org.eclipse.osgi.util.ManifestElement;
040: import org.eclipse.osgi.util.NLS;
041: import org.eclipse.pde.core.build.IBuildEntry;
042: import org.eclipse.pde.core.build.IBuildModelFactory;
043: import org.eclipse.pde.core.plugin.IPluginBase;
044: import org.eclipse.pde.core.plugin.IPluginLibrary;
045: import org.eclipse.pde.core.plugin.IPluginModelBase;
046: import org.eclipse.pde.core.plugin.ISharedPluginModel;
047: import org.eclipse.pde.core.plugin.PluginRegistry;
048: import org.eclipse.pde.internal.core.build.WorkspaceBuildModel;
049: import org.eclipse.pde.internal.core.bundle.BundlePluginBase;
050: import org.eclipse.pde.internal.core.converter.PluginConverter;
051: import org.eclipse.pde.internal.core.ibundle.IBundle;
052: import org.eclipse.pde.internal.core.ibundle.IBundlePluginModelBase;
053: import org.eclipse.pde.internal.core.plugin.WorkspacePluginModelBase;
054: import org.eclipse.pde.internal.ui.IPDEUIConstants;
055: import org.eclipse.pde.internal.ui.PDEUIMessages;
056: import org.eclipse.pde.internal.ui.search.dependencies.AddNewBinaryDependenciesOperation;
057: import org.eclipse.pde.internal.ui.wizards.IProjectProvider;
058: import org.eclipse.pde.ui.IFieldData;
059: import org.eclipse.pde.ui.IPluginContentWizard;
060: import org.eclipse.ui.dialogs.IOverwriteQuery;
061: import org.eclipse.ui.wizards.datatransfer.ImportOperation;
062: import org.eclipse.ui.wizards.datatransfer.ZipFileStructureProvider;
063: import org.osgi.framework.BundleException;
064: import org.osgi.framework.Constants;
065:
066: public class NewLibraryPluginCreationOperation extends
067: NewProjectCreationOperation {
068:
069: private LibraryPluginFieldData fData;
070:
071: public NewLibraryPluginCreationOperation(
072: LibraryPluginFieldData data, IProjectProvider provider,
073: IPluginContentWizard contentWizard) {
074: super (data, provider, contentWizard);
075: fData = data;
076: }
077:
078: private void addJar(File jarFile, IProject project,
079: IProgressMonitor monitor) throws CoreException {
080: String jarName = jarFile.getName();
081: IFile file = project.getFile(jarName);
082: monitor.subTask(NLS.bind(
083: PDEUIMessages.NewProjectCreationOperation_copyingJar,
084: jarName));
085: InputStream in = null;
086: try {
087: in = new FileInputStream(jarFile);
088: file.create(in, true, monitor);
089: } catch (FileNotFoundException fnfe) {
090: } finally {
091: if (in != null) {
092: try {
093: in.close();
094: } catch (IOException ioe) {
095: }
096: }
097: }
098: }
099:
100: private void adjustExportRoot(IProject project, IBundle bundle)
101: throws CoreException {
102: IResource[] resources = project.members(false);
103: for (int j = 0; j < resources.length; j++) {
104: if (resources[j] instanceof IFile) {
105: if (".project".equals(resources[j].getName()) //$NON-NLS-1$
106: || ".classpath".equals(resources[j] //$NON-NLS-1$
107: .getName())
108: || "plugin.xml".equals(resources[j] //$NON-NLS-1$
109: .getName())
110: || "build.properties".equals(resources[j] //$NON-NLS-1$
111: .getName())) {
112: continue;
113: }
114: // resource at the root, export root
115: return;
116: }
117: }
118: removeExportRoot(bundle);
119: }
120:
121: protected void adjustManifests(IProgressMonitor monitor,
122: IProject project, IPluginBase base) throws CoreException {
123: super .adjustManifests(monitor, project, base);
124: monitor.beginTask(new String(), fData.doFindDependencies() ? 4
125: : 2);
126: IBundle bundle = (base instanceof BundlePluginBase) ? ((BundlePluginBase) base)
127: .getBundle()
128: : null;
129: if (bundle != null) {
130: adjustExportRoot(project, bundle);
131: monitor.worked(1);
132: addExportedPackages(project, bundle);
133: monitor.worked(1);
134: if (fData.doFindDependencies())
135: addDependencies(project, base.getModel(),
136: new SubProgressMonitor(monitor, 2));
137: }
138: monitor.done();
139: }
140:
141: protected void createContents(IProgressMonitor monitor,
142: IProject project) throws CoreException, JavaModelException,
143: InvocationTargetException, InterruptedException {
144: // copy jars
145: String[] paths = fData.getLibraryPaths();
146: for (int i = paths.length - 1; i >= 0; i--) {
147: File jarFile = new File(paths[i]);
148: if (fData.isUnzipLibraries()) {
149: importJar(jarFile, project, monitor);
150: } else {
151: addJar(jarFile, project, monitor);
152: }
153: monitor.worked(1);
154: }
155:
156: // delete manifest.mf imported from libraries
157: IFile importedManifest = project
158: .getFile("META-INF/MANIFEST.MF"); //$NON-NLS-1$
159: if (importedManifest.exists()) {
160: importedManifest.delete(true, false, monitor);
161: if (!fData.hasBundleStructure()) {
162: IFolder meta_inf = project.getFolder("META-INF"); //$NON-NLS-1$
163: if (meta_inf.members().length == 0) {
164: meta_inf.delete(true, false, monitor);
165: }
166: }
167: }
168: }
169:
170: protected void fillBinIncludes(IProject project,
171: IBuildEntry binEntry) throws CoreException {
172: if (fData.hasBundleStructure())
173: binEntry.addToken("META-INF/"); //$NON-NLS-1$
174: else
175: binEntry.addToken("plugin.xml"); //$NON-NLS-1$
176:
177: if (fData.isUnzipLibraries()) {
178: IResource[] resources = project.members(false);
179: for (int j = 0; j < resources.length; j++) {
180: if (resources[j] instanceof IFolder) {
181: if (!binEntry
182: .contains(resources[j].getName() + "/")) //$NON-NLS-1$
183: binEntry.addToken(resources[j].getName() + "/"); //$NON-NLS-1$
184: } else {
185: if (".project".equals(resources[j].getName()) //$NON-NLS-1$
186: || ".classpath".equals(resources[j] //$NON-NLS-1$
187: .getName())
188: || "build.properties".equals(resources[j] //$NON-NLS-1$
189: .getName())) {
190: continue;
191: }
192: if (!binEntry.contains(resources[j].getName()))
193: binEntry.addToken(resources[j].getName());
194: }
195: }
196: } else {
197: String[] libraryPaths = fData.getLibraryPaths();
198: for (int j = 0; j < libraryPaths.length; j++) {
199: File jarFile = new File(libraryPaths[j]);
200: String name = jarFile.getName();
201: if (!binEntry.contains(name))
202: binEntry.addToken(name);
203: }
204: }
205: }
206:
207: protected IClasspathEntry[] getInternalClassPathEntries(
208: IProject project, IFieldData data) {
209: String[] libraryPaths;
210: if (fData.isUnzipLibraries()) {
211: libraryPaths = new String[] { "" }; //$NON-NLS-1$
212: } else {
213: libraryPaths = fData.getLibraryPaths();
214: }
215: IClasspathEntry[] entries = new IClasspathEntry[libraryPaths.length];
216: for (int j = 0; j < libraryPaths.length; j++) {
217: File jarFile = new File(libraryPaths[j]);
218: String jarName = jarFile.getName();
219: IPath path = project.getFullPath().append(jarName);
220: entries[j] = JavaCore.newLibraryEntry(path, null, null,
221: true);
222: }
223: return entries;
224: }
225:
226: protected int getNumberOfWorkUnits() {
227: int numUnits = super .getNumberOfWorkUnits();
228: numUnits += fData.getLibraryPaths().length;
229: return numUnits;
230: }
231:
232: private void importJar(File jar, IResource destination,
233: IProgressMonitor monitor) throws CoreException,
234: InvocationTargetException, InterruptedException {
235: ZipFile input = null;
236: try {
237: try {
238: input = new ZipFile(jar);
239: ZipFileStructureProvider provider = new ZipFileStructureProvider(
240: input);
241: ImportOperation op = new ImportOperation(destination
242: .getFullPath(), provider.getRoot(), provider,
243: new IOverwriteQuery() {
244: public String queryOverwrite(
245: String pathString) {
246: return IOverwriteQuery.ALL;
247: }
248: });
249: op.run(monitor);
250: } finally {
251: if (input != null)
252: input.close();
253: }
254: } catch (IOException e) {
255: throw new CoreException(
256: new Status(
257: IStatus.ERROR,
258: IPDEUIConstants.PLUGIN_ID,
259: IStatus.OK,
260: NLS
261: .bind(
262: PDEUIMessages.NewProjectCreationOperation_errorImportingJar,
263: jar), e));
264: }
265: }
266:
267: private void removeExportRoot(IBundle bundle) {
268: String value = bundle.getHeader(Constants.BUNDLE_CLASSPATH);
269: if (value == null)
270: value = "."; //$NON-NLS-1$
271: try {
272: ManifestElement[] elems = ManifestElement.parseHeader(
273: Constants.BUNDLE_CLASSPATH, value);
274: StringBuffer buff = new StringBuffer(value.length());
275: for (int i = 0; i < elems.length; i++) {
276: if (!elems[i].getValue().equals(".")) //$NON-NLS-1$
277: buff.append(elems[i].getValue());
278: }
279: bundle.setHeader(Constants.BUNDLE_CLASSPATH, buff
280: .toString());
281: } catch (BundleException e) {
282: }
283: }
284:
285: protected void setPluginLibraries(WorkspacePluginModelBase model)
286: throws CoreException {
287: IPluginBase pluginBase = model.getPluginBase();
288: if (fData.isUnzipLibraries()) {
289: IPluginLibrary library = model.getPluginFactory()
290: .createLibrary();
291: library.setName("."); //$NON-NLS-1$
292: library.setExported(true);
293: pluginBase.add(library);
294: } else {
295: String[] paths = fData.getLibraryPaths();
296: for (int i = 0; i < paths.length; i++) {
297: File jarFile = new File(paths[i]);
298: IPluginLibrary library = model.getPluginFactory()
299: .createLibrary();
300: library.setName(jarFile.getName());
301: library.setExported(true);
302: pluginBase.add(library);
303: }
304: }
305: }
306:
307: protected void createSourceOutputBuildEntries(
308: WorkspaceBuildModel model, IBuildModelFactory factory)
309: throws CoreException {
310: if (fData.isUnzipLibraries()) {
311: // SOURCE.<LIBRARY_NAME>
312: IBuildEntry entry = factory
313: .createEntry(IBuildEntry.JAR_PREFIX + "."); //$NON-NLS-1$
314: entry.addToken("."); //$NON-NLS-1$
315: model.getBuild().add(entry);
316:
317: // OUTPUT.<LIBRARY_NAME>
318: entry = factory
319: .createEntry(IBuildEntry.OUTPUT_PREFIX + "."); //$NON-NLS-1$
320: entry.addToken("."); //$NON-NLS-1$
321: model.getBuild().add(entry);
322: }
323: }
324:
325: private void addExportedPackages(IProject project, IBundle bundle) {
326: String value = bundle.getHeader(Constants.BUNDLE_CLASSPATH);
327: if (value == null)
328: value = "."; //$NON-NLS-1$
329: try {
330: ManifestElement[] elems = ManifestElement.parseHeader(
331: Constants.BUNDLE_CLASSPATH, value);
332: HashMap map = new HashMap();
333: for (int i = 0; i < elems.length; i++) {
334: ArrayList filter = new ArrayList();
335: filter.add("*"); //$NON-NLS-1$
336: map.put(elems[i].getValue(), filter);
337: }
338: Set packages = PluginConverter.getDefault().getExports(
339: project, map);
340: String pkgValue = getCommaValueFromSet(packages);
341: bundle.setHeader(Constants.EXPORT_PACKAGE, pkgValue);
342: } catch (BundleException e) {
343: }
344: }
345:
346: private void addDependencies(IProject project,
347: ISharedPluginModel model, IProgressMonitor monitor) {
348: if (!(model instanceof IBundlePluginModelBase)) {
349: monitor.done();
350: return;
351: }
352: final boolean unzip = fData.isUnzipLibraries();
353: try {
354: new AddNewBinaryDependenciesOperation(project,
355: (IBundlePluginModelBase) model) {
356: // Need to override this function to include every bundle in the target platform as a possible dependency
357: protected String[] findSecondaryBundles(IBundle bundle,
358: Set ignorePkgs) {
359: IPluginModelBase[] bases = PluginRegistry
360: .getActiveModels();
361: String[] ids = new String[bases.length];
362: for (int i = 0; i < bases.length; i++) {
363: BundleDescription desc = bases[i]
364: .getBundleDescription();
365: if (desc == null)
366: ids[i] = bases[i].getPluginBase().getId();
367: else
368: ids[i] = desc.getSymbolicName();
369: }
370: return ids;
371: }
372:
373: // Need to override this function because when jar is unzipped, build.properties does not contain entry for '.'.
374: // Therefore, the super.addProjectPackages will not find the project packages(it includes only things in bin.includes)
375: protected void addProjectPackages(IBundle bundle,
376: Set ignorePkgs) {
377: if (!unzip)
378: super .addProjectPackages(bundle, ignorePkgs);
379: Stack stack = new Stack();
380: stack.push(fProject);
381: try {
382: while (!stack.isEmpty()) {
383: IContainer folder = (IContainer) stack
384: .pop();
385: IResource[] children = folder.members();
386: for (int i = 0; i < children.length; i++) {
387: if (children[i] instanceof IContainer)
388: stack.push(children[i]);
389: else if ("class".equals(((IFile) children[i]).getFileExtension())) { //$NON-NLS-1$
390: String path = folder
391: .getProjectRelativePath()
392: .toString();
393: ignorePkgs.add(path.replace('/',
394: '.'));
395: }
396: }
397: }
398: } catch (CoreException e) {
399: }
400:
401: }
402: }.run(monitor);
403: } catch (InvocationTargetException e) {
404: } catch (InterruptedException e) {
405: }
406: }
407:
408: }
|