EMMA Coverage Report (generated Thu Nov 26 15:54:18 CST 2009)
[all classes][org.eclipse.pde.api.tools.internal.util]

COVERAGE SUMMARY FOR SOURCE FILE [Util.java]

nameclass, %method, %block, %line, %
Util.java83%  (5/6)73%  (71/97)53%  (1993/3741)55%  (551.9/1011)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class Util$40%   (0/1)0%   (0/2)0%   (0/15)0%   (0/3)
Util$4 (): void 0%   (0/1)0%   (0/3)0%   (0/2)
accept (File, String): boolean 0%   (0/1)0%   (0/12)0%   (0/1)
     
class Util$1100% (1/1)50%  (1/2)7%   (3/45)22%  (2/9)
compare (Object, Object): int 0%   (0/1)0%   (0/42)0%   (0/7)
Util$1 (): void 100% (1/1)100% (3/3)100% (2/2)
     
class Util$2100% (1/1)50%  (1/2)16%  (3/19)40%  (2/5)
compare (Object, Object): int 0%   (0/1)0%   (0/16)0%   (0/3)
Util$2 (): void 100% (1/1)100% (3/3)100% (2/2)
     
class Util$BuildJob100% (1/1)57%  (4/7)46%  (97/212)43%  (21.7/50)
Util$BuildJob (String, IProject []): void 0%   (0/1)0%   (0/6)0%   (0/2)
contains (IProject): boolean 0%   (0/1)0%   (0/26)0%   (0/5)
isCoveredBy (Util$BuildJob): boolean 0%   (0/1)0%   (0/32)0%   (0/8)
cancelBuild (Object): void 100% (1/1)61%  (20/33)59%  (4.7/8)
run (IProgressMonitor): IStatus 100% (1/1)61%  (60/98)55%  (12/22)
Util$BuildJob (String, IProject [], int): void 100% (1/1)100% (10/10)100% (4/4)
belongsTo (Object): boolean 100% (1/1)100% (7/7)100% (1/1)
     
class Util100% (1/1)77%  (63/82)55%  (1871/3431)56%  (525.4/945)
Util (): void 0%   (0/1)0%   (0/3)0%   (0/1)
abort (String, Throwable): void 0%   (0/1)0%   (0/13)0%   (0/2)
addJarEntries (String, String [], ArrayList): void 0%   (0/1)0%   (0/35)0%   (0/6)
collectAllFiles (File, ArrayList, FileFilter): void 0%   (0/1)0%   (0/29)0%   (0/7)
copy (File, File): boolean 0%   (0/1)0%   (0/118)0%   (0/30)
equalsOrNull (Object, Object): boolean 0%   (0/1)0%   (0/12)0%   (0/3)
flushDirectoryContent (File): void 0%   (0/1)0%   (0/22)0%   (0/5)
getAllFiles (File, FileFilter): File [] 0%   (0/1)0%   (0/23)0%   (0/7)
getApiProjects (): IProject [] 0%   (0/1)0%   (0/53)0%   (0/14)
getBuildJob (IProject []): Job 0%   (0/1)0%   (0/18)0%   (0/5)
getDeltaElementTypeValue (String): int 0%   (0/1)0%   (0/33)0%   (0/8)
getParentChildFile (File): File 0%   (0/1)0%   (0/62)0%   (0/13)
guntar (String, String): void 0%   (0/1)0%   (0/99)0%   (0/24)
isApiProblemMarker (IMarker): boolean 0%   (0/1)0%   (0/9)0%   (0/1)
isConstructor (String): boolean 0%   (0/1)0%   (0/5)0%   (0/1)
isFileDeleted (File): boolean 0%   (0/1)0%   (0/10)0%   (0/1)
touchCorrespondingResource (IProject, IResource, String): void 0%   (0/1)0%   (0/48)0%   (0/18)
unzip (String, String): void 0%   (0/1)0%   (0/125)0%   (0/31)
waitUntilFileDeleted (File): boolean 0%   (0/1)0%   (0/90)0%   (0/27)
getApiElementType (int): String 100% (1/1)22%  (4/18)22%  (2/9)
delete (File): boolean 100% (1/1)24%  (5/21)25%  (2/8)
parseDocument (String): Element 100% (1/1)30%  (31/103)34%  (7.2/21)
getJavaClassLibs (): String [] 100% (1/1)31%  (64/207)35%  (16/46)
getDeltaPrefererenceKey (int, int, int): String 100% (1/1)50%  (57/114)48%  (15/31)
getDeltaArgumentString (IDelta): String 100% (1/1)52%  (14/27)50%  (4/8)
getMethod (IType, String): IMember 100% (1/1)53%  (122/230)51%  (32.6/64)
isApiProject (IProject): boolean 100% (1/1)57%  (4/7)33%  (1/3)
getFileContentAsString (File): String 100% (1/1)57%  (27/47)50%  (6.5/13)
getInputStreamFromString (String): InputStream 100% (1/1)58%  (7/12)25%  (1/4)
getEEProfile (String): Properties 100% (1/1)59%  (43/73)45%  (6.4/14)
getInputStreamAsCharArray (InputStream, int, String): char [] 100% (1/1)59%  (35/59)60%  (9/15)
getSeverity (int): String 100% (1/1)60%  (6/10)60%  (3/5)
isApiToolsComponent (IApiComponent): boolean 100% (1/1)61%  (43/71)55%  (8.2/15)
initializeRegexExcludeList (String, IApiBaseline): Set 100% (1/1)65%  (88/135)58%  (18.6/32)
getResource (IProject, IType): IResource 100% (1/1)67%  (39/58)62%  (15/24)
saveFile (File, String): void 100% (1/1)69%  (22/32)59%  (5.9/10)
toNativePath (String): String 100% (1/1)69%  (18/26)80%  (4/5)
getInputStreamAsByteArray (InputStream, int): byte [] 100% (1/1)71%  (63/89)75%  (18/24)
getDocument (ICompilationUnit): IDocument 100% (1/1)71%  (35/49)70%  (7.8/11)
updateMonitor (IProgressMonitor, int): void 100% (1/1)71%  (10/14)83%  (5/6)
newDocument (): Document 100% (1/1)76%  (13/17)71%  (5/7)
serializeDocument (Document): String 100% (1/1)78%  (39/50)67%  (10/15)
getEEDescriptionFile (): File 100% (1/1)79%  (49/62)75%  (13.5/18)
createEEFile (IVMInstall, String): File 100% (1/1)81%  (29/36)72%  (7.9/11)
<static initializer> 100% (1/1)83%  (30/36)98%  (9.8/10)
getDeltaElementType (int): String 100% (1/1)83%  (20/24)83%  (10/12)
collectRegexIds (String, Set, IApiComponent []): void 100% (1/1)84%  (43/51)73%  (11/15)
isDifferentVersion (String, String): boolean 100% (1/1)85%  (40/47)73%  (11/15)
getClassFile (IApiComponent [], String): IApiTypeRoot 100% (1/1)87%  (27/31)77%  (6.9/9)
getComponentVersionsId (IApiComponent): String 100% (1/1)89%  (39/44)86%  (12/14)
getDeltaComponentVersionsId (IApiComponent): String 100% (1/1)90%  (43/48)87%  (13/15)
getIMember (IDelta, IJavaProject): IMember 100% (1/1)95%  (87/92)94%  (28.2/30)
getReexportedComponents (IApiComponent): IApiComponent [] 100% (1/1)95%  (62/65)90%  (18/20)
getDetail (IDelta): String 100% (1/1)96%  (94/98)97%  (29/30)
getDeltaFlagsName (int): String 100% (1/1)99%  (134/136)99%  (67/68)
appendProperty (StringBuffer, String, String): void 100% (1/1)100% (17/17)100% (5/5)
collectAllDeltas (IDelta): List 100% (1/1)100% (12/12)100% (3/3)
convertAsSet (String []): Set 100% (1/1)100% (27/27)100% (5/5)
generateEEContents (IVMInstall, String): String 100% (1/1)100% (57/57)100% (12/12)
getBuildJob (IProject [], int): Job 100% (1/1)100% (19/19)100% (5/5)
getDeltaElementType (IDelta): String 100% (1/1)100% (4/4)100% (1/1)
getDeltaKindName (IDelta): String 100% (1/1)100% (4/4)100% (1/1)
getDeltaKindName (int): String 100% (1/1)100% (10/10)100% (5/5)
getDescriptorName (IApiType): String 100% (1/1)100% (17/17)100% (5/5)
getFragmentNumber (String): int 100% (1/1)100% (46/46)100% (14/14)
getJavaClassLibsAsString (): String 100% (1/1)100% (31/31)100% (7/7)
getManifestFile (IProject): IResource 100% (1/1)100% (4/4)100% (1/1)
getType (String): IReferenceTypeDescriptor 100% (1/1)100% (30/30)100% (4/4)
getTypeNameFromMarker (IMarker): String 100% (1/1)100% (5/5)100% (1/1)
isAPI (int, IApiType): boolean 100% (1/1)100% (16/16)100% (2/2)
isApiProject (IJavaProject): boolean 100% (1/1)100% (4/4)100% (1/1)
isArchive (String): boolean 100% (1/1)100% (15/15)100% (2/2)
isBinaryProject (IProject): boolean 100% (1/1)100% (3/3)100% (1/1)
isClass (int): boolean 100% (1/1)100% (8/8)100% (1/1)
isClassFile (String): boolean 100% (1/1)100% (5/5)100% (1/1)
isDefault (int): boolean 100% (1/1)100% (8/8)100% (1/1)
isJavaFileName (String): boolean 100% (1/1)100% (5/5)100% (1/1)
isJavaLangObject (String): boolean 100% (1/1)100% (10/10)100% (1/1)
isJavaLangRuntimeException (String): boolean 100% (1/1)100% (10/10)100% (1/1)
isManifest (IPath): boolean 100% (1/1)100% (4/4)100% (1/1)
isVisible (int): boolean 100% (1/1)100% (10/10)100% (1/1)
updateMonitor (IProgressMonitor): void 100% (1/1)100% (4/4)100% (2/2)
     
class Util$3100% (1/1)100% (2/2)100% (19/19)100% (6/6)
Util$3 (List): void 100% (1/1)100% (6/6)100% (2/2)
endVisit (IDelta): void 100% (1/1)100% (13/13)100% (4/4)

1/*******************************************************************************
2 * Copyright (c) 2007, 2009 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 * 
8 * Contributors:
9 *     IBM Corporation - initial API and implementation
10 *******************************************************************************/
11package org.eclipse.pde.api.tools.internal.util;
12 
13import java.io.BufferedInputStream;
14import java.io.BufferedOutputStream;
15import java.io.BufferedWriter;
16import java.io.ByteArrayInputStream;
17import java.io.ByteArrayOutputStream;
18import java.io.File;
19import java.io.FileFilter;
20import java.io.FileInputStream;
21import java.io.FileNotFoundException;
22import java.io.FileOutputStream;
23import java.io.FileWriter;
24import java.io.FilenameFilter;
25import java.io.IOException;
26import java.io.InputStream;
27import java.io.LineNumberReader;
28import java.io.PrintWriter;
29import java.io.StringReader;
30import java.io.UnsupportedEncodingException;
31import java.lang.reflect.Field;
32import java.nio.ByteBuffer;
33import java.nio.charset.Charset;
34import java.nio.charset.CharsetDecoder;
35import java.nio.charset.CodingErrorAction;
36import java.nio.charset.IllegalCharsetNameException;
37import java.nio.charset.UnsupportedCharsetException;
38import java.util.ArrayList;
39import java.util.Arrays;
40import java.util.Comparator;
41import java.util.Enumeration;
42import java.util.HashSet;
43import java.util.Iterator;
44import java.util.List;
45import java.util.Properties;
46import java.util.Set;
47import java.util.StringTokenizer;
48import java.util.jar.JarFile;
49import java.util.regex.Pattern;
50import java.util.regex.PatternSyntaxException;
51import java.util.zip.ZipEntry;
52import java.util.zip.ZipException;
53import java.util.zip.ZipFile;
54import java.util.zip.ZipInputStream;
55 
56import javax.xml.parsers.DocumentBuilder;
57import javax.xml.parsers.DocumentBuilderFactory;
58import javax.xml.parsers.FactoryConfigurationError;
59import javax.xml.parsers.ParserConfigurationException;
60import javax.xml.transform.OutputKeys;
61import javax.xml.transform.Transformer;
62import javax.xml.transform.TransformerException;
63import javax.xml.transform.TransformerFactory;
64import javax.xml.transform.dom.DOMSource;
65import javax.xml.transform.stream.StreamResult;
66 
67import org.eclipse.core.filebuffers.FileBuffers;
68import org.eclipse.core.filebuffers.ITextFileBufferManager;
69import org.eclipse.core.filebuffers.LocationKind;
70import org.eclipse.core.resources.IFile;
71import org.eclipse.core.resources.IMarker;
72import org.eclipse.core.resources.IProject;
73import org.eclipse.core.resources.IResource;
74import org.eclipse.core.resources.IncrementalProjectBuilder;
75import org.eclipse.core.resources.ResourcesPlugin;
76import org.eclipse.core.runtime.Assert;
77import org.eclipse.core.runtime.CoreException;
78import org.eclipse.core.runtime.IPath;
79import org.eclipse.core.runtime.IProgressMonitor;
80import org.eclipse.core.runtime.IStatus;
81import org.eclipse.core.runtime.NullProgressMonitor;
82import org.eclipse.core.runtime.OperationCanceledException;
83import org.eclipse.core.runtime.Path;
84import org.eclipse.core.runtime.Status;
85import org.eclipse.core.runtime.SubMonitor;
86import org.eclipse.core.runtime.jobs.Job;
87import org.eclipse.jdt.core.Flags;
88import org.eclipse.jdt.core.ICompilationUnit;
89import org.eclipse.jdt.core.IField;
90import org.eclipse.jdt.core.IJavaProject;
91import org.eclipse.jdt.core.IMember;
92import org.eclipse.jdt.core.IMethod;
93import org.eclipse.jdt.core.IType;
94import org.eclipse.jdt.core.JavaCore;
95import org.eclipse.jdt.core.JavaModelException;
96import org.eclipse.jdt.core.Signature;
97import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
98import org.eclipse.jdt.launching.IVMInstall;
99import org.eclipse.jdt.launching.JavaRuntime;
100import org.eclipse.jdt.launching.LibraryLocation;
101import org.eclipse.jdt.launching.environments.ExecutionEnvironmentDescription;
102import org.eclipse.jface.text.IDocument;
103import org.eclipse.osgi.util.NLS;
104import org.eclipse.pde.api.tools.internal.ApiFilterStore;
105import org.eclipse.pde.api.tools.internal.IApiCoreConstants;
106import org.eclipse.pde.api.tools.internal.builder.BuildState;
107import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
108import org.eclipse.pde.api.tools.internal.provisional.Factory;
109import org.eclipse.pde.api.tools.internal.provisional.IApiMarkerConstants;
110import org.eclipse.pde.api.tools.internal.provisional.IRequiredComponentDescription;
111import org.eclipse.pde.api.tools.internal.provisional.VisibilityModifiers;
112import org.eclipse.pde.api.tools.internal.provisional.comparator.DeltaVisitor;
113import org.eclipse.pde.api.tools.internal.provisional.comparator.IDelta;
114import org.eclipse.pde.api.tools.internal.provisional.descriptors.IReferenceTypeDescriptor;
115import org.eclipse.pde.api.tools.internal.provisional.model.IApiBaseline;
116import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent;
117import org.eclipse.pde.api.tools.internal.provisional.model.IApiElement;
118import org.eclipse.pde.api.tools.internal.provisional.model.IApiType;
119import org.eclipse.pde.api.tools.internal.provisional.model.IApiTypeRoot;
120import org.eclipse.pde.api.tools.internal.search.SkippedComponent;
121import org.objectweb.asm.Opcodes;
122import org.osgi.framework.Version;
123import org.w3c.dom.Document;
124import org.w3c.dom.Element;
125import org.xml.sax.SAXException;
126import org.xml.sax.helpers.DefaultHandler;
127 
128/**
129 * A Utility class to use for API tools
130 * 
131 * @since 1.0.0
132 */
133public final class Util {
134 
135        /**
136         * Class that runs a build in the workspace or the given project
137         */
138        private static final class BuildJob extends Job {
139                private final IProject[] fProjects;
140                private int fBuildType;
141 
142                /**
143                 * Constructor
144                 * @param name
145                 * @param project
146                 */
147                BuildJob(String name, IProject[] projects) {
148                        this(name, projects, IncrementalProjectBuilder.FULL_BUILD);
149                }
150                BuildJob(String name, IProject[] projects, int buildType) {
151                        super(name);
152                        fProjects = projects;
153                        this.fBuildType = buildType;
154                }
155                public boolean belongsTo(Object family) {
156                        return ResourcesPlugin.FAMILY_MANUAL_BUILD == family;
157                }
158                
159                /**
160                 * Returns if this build job is covered by another build job
161                 * @param other
162                 * @return true if covered by another build job, false otherwise
163                 */
164                public boolean isCoveredBy(BuildJob other) {
165                        if (other.fProjects == null) {
166                                return true;
167                        }
168                        if (this.fProjects != null) {
169                                for (int i = 0, max = this.fProjects.length; i < max; i++) {
170                                        if (!other.contains(this.fProjects[i])) {
171                                                return false;
172                                        }
173                                }
174                                return true;
175                        }
176                        return false;
177                }
178                
179                public boolean contains(IProject project) {
180                        if (project == null) return false;
181                        for (int i = 0, max = this.fProjects.length; i < max; i++) {
182                                if (project.equals(this.fProjects[i])) {
183                                        return true;
184                                }
185                        }
186                        return false;
187                }
188                /* (non-Javadoc)
189                 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
190                 */
191                protected IStatus run(IProgressMonitor monitor) {
192                        synchronized (getClass()) {
193                                if (monitor.isCanceled()) {
194                                        return Status.CANCEL_STATUS;
195                                }
196                                //cancelBuild(ResourcesPlugin.FAMILY_AUTO_BUILD);
197                                cancelBuild(ResourcesPlugin.FAMILY_MANUAL_BUILD);
198                        }
199                        try {
200                                if (fProjects != null) {
201                                        SubMonitor localmonitor = SubMonitor.convert(monitor, UtilMessages.Util_0, fProjects.length);
202                                        for (int i = 0, max = fProjects.length; i < max; i++) {
203                                                // clear last build state for project to force a full build using our builder
204                                                // This makes it possible to have only an incremental build from the java builder
205                                                IProject currentProject = fProjects[i];
206                                                if (this.fBuildType == IncrementalProjectBuilder.FULL_BUILD) {
207                                                        BuildState.setLastBuiltState(currentProject, null);
208                                                }
209                                                localmonitor.subTask(NLS.bind(UtilMessages.Util_5, currentProject.getName())); 
210                                                if (ResourcesPlugin.getWorkspace().isAutoBuilding()) {
211                                                        currentProject.touch(null);
212                                                } else {
213                                                        currentProject.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, localmonitor.newChild(1));
214                                                }
215                                        }
216                                }
217                        } catch (CoreException e) {
218                                return e.getStatus();
219                        } catch (OperationCanceledException e) {
220                                return Status.CANCEL_STATUS;
221                        }
222                        finally {
223                                monitor.done();
224                        }
225                        return Status.OK_STATUS;
226                }
227                
228                private void cancelBuild(Object jobfamily) {
229                        Job[] buildJobs = Job.getJobManager().find(jobfamily);
230                        for (int i= 0; i < buildJobs.length; i++) {
231                                Job curr = buildJobs[i];
232                                if (curr != this && curr instanceof BuildJob) {
233                                        BuildJob job = (BuildJob) curr;
234                                        if (job.isCoveredBy(this)) {
235                                                curr.cancel(); // cancel all other build jobs of our kind
236                                        }
237                                }
238                        }
239                }
240        }
241        
242        public static boolean DEBUG;
243 
244        public static final String EMPTY_STRING = "";//$NON-NLS-1$
245        public static final String DEFAULT_PACKAGE_NAME = EMPTY_STRING;
246        public static final String MANIFEST_NAME = "MANIFEST.MF"; //$NON-NLS-1$
247        
248        public static final String DOT_CLASS_SUFFIX = ".class"; //$NON-NLS-1$
249        public static final String DOT_JAVA_SUFFIX = ".java"; //$NON-NLS-1$
250 
251        /**
252         * Constant representing the default size to read from an input stream
253         */
254        private static final int DEFAULT_READING_SIZE = 8192;
255        
256        private static final String JAVA_LANG_OBJECT = "java.lang.Object"; //$NON-NLS-1$
257        private static final String JAVA_LANG_RUNTIMEEXCEPTION = "java.lang.RuntimeException"; //$NON-NLS-1$
258        public static final String LINE_DELIMITER = System.getProperty("line.separator"); //$NON-NLS-1$
259        
260        public static final String UNKNOWN_ELEMENT_KIND = "UNKNOWN_ELEMENT_KIND"; //$NON-NLS-1$
261 
262        public static final String UNKNOWN_FLAGS = "UNKNOWN_FLAGS"; //$NON-NLS-1$
263        public static final String UNKNOWN_KIND = "UNKNOWN_KIND"; //$NON-NLS-1$
264        public static final String UNKNOWN_VISIBILITY = "UNKNOWN_VISIBILITY"; //$NON-NLS-1$
265        public static final String ISO_8859_1 = "ISO-8859-1"; //$NON-NLS-1$
266        public static final String REGULAR_EXPRESSION_START = "R:"; //$NON-NLS-1$
267 
268        // Trace for delete operation
269        /*
270         * Maximum time wasted repeating delete operations while running JDT/Core tests.
271         */
272        private static int DELETE_MAX_TIME = 0;
273        /**
274         * Trace deletion operations while running JDT/Core tests.
275         */
276        private static boolean DELETE_DEBUG = false;
277        /**
278         * Maximum of time in ms to wait in deletion operation while running JDT/Core tests.
279         * Default is 10 seconds. This number cannot exceed 1 minute (i.e. 60000).
280         * <br>
281         * To avoid too many loops while waiting, the ten first ones are done waiting
282         * 10ms before repeating, the ten loops after are done waiting 100ms and
283         * the other loops are done waiting 1s...
284         */
285        private static int DELETE_MAX_WAIT = 10000;
286 
287        public static final IPath MANIFEST_PROJECT_RELATIVE_PATH = new Path(JarFile.MANIFEST_NAME);
288 
289        public static final String ORG_ECLIPSE_SWT = "org.eclipse.swt"; //$NON-NLS-1$
290 
291        static {
292                String property = System.getProperty("DEBUG"); //$NON-NLS-1$
293                DEBUG = property != null && property.equalsIgnoreCase("TRUE"); //$NON-NLS-1$
294        }
295 
296        /**
297         * Throws an exception with the given message and underlying exception.
298         * 
299         * @param message error message
300         * @param exception underlying exception, or <code>null</code>
301         * @throws CoreException
302         */
303        private static void abort(String message, Throwable exception) throws CoreException {
304                IStatus status = new Status(IStatus.ERROR, ApiPlugin.PLUGIN_ID, message, exception);
305                throw new CoreException(status);
306        }
307 
308        /**
309         * Appends a property to the given string buffer with the given key and value
310         * in the format "key=value\n".
311         * 
312         * @param buffer buffer to append to
313         * @param key key
314         * @param value value
315         */
316        private static void appendProperty(StringBuffer buffer, String key, String value) {
317                buffer.append(key);
318                buffer.append('=');
319                buffer.append(value);
320                buffer.append('\n');
321        }
322 
323        /**
324         * Collects all of the deltas from the given parent delta
325         * @param delta
326         * @return
327         */
328        public static List collectAllDeltas(IDelta delta) {
329                final List list = new ArrayList();
330                delta.accept(new DeltaVisitor() {
331                        public void endVisit(IDelta localDelta) {
332                                if (localDelta.getChildren().length == 0) {
333                                        list.add(localDelta);
334                                }
335                                super.endVisit(localDelta);
336                        }
337                });
338                return list;
339        }
340        
341        /**
342         * Collects files into the collector array list
343         * 
344         * @param root
345         *            the root to collect the files from
346         * @param collector
347         *            the collector to place matches into
348         * @param fileFilter
349         *            the filter for files or <code>null</code> to accept all
350         *            files
351         */
352        private static void collectAllFiles(File root, ArrayList collector, FileFilter fileFilter) {
353                File[] files = root.listFiles(fileFilter);
354                for (int i = 0; i < files.length; i++) {
355                        final File currentFile = files[i];
356                        if (currentFile.isDirectory()) {
357                                collectAllFiles(currentFile, collector, fileFilter);
358                        } else {
359                                collector.add(currentFile);
360                        }
361                }
362        }
363 
364        /**
365         * Returns all of the API projects in the workspace
366         * @return all of the API projects in the workspace or <code>null</code> if there are none.
367         */
368        public static IProject[] getApiProjects() {
369                IProject[] allProjects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
370                ArrayList temp = new ArrayList();
371                IProject project = null;
372                for (int i = 0, max = allProjects.length; i < max; i++) {
373                        project = allProjects[i];
374                        if (project.isAccessible()) {
375                                try {
376                                        if (project.hasNature(org.eclipse.pde.api.tools.internal.provisional.ApiPlugin.NATURE_ID)) {
377                                                temp.add(project);
378                                        }
379                                } 
380                                catch (CoreException e) {}
381                        }
382                }
383                IProject[] projects = null;
384                if (temp.size() != 0) {
385                        projects = new IProject[temp.size()];
386                        temp.toArray(projects);
387                }
388                return projects;
389        }
390        
391        /**
392         * Copies the given file to the new file
393         * @param file
394         * @param newFile
395         * @return if the copy succeeded
396         */
397        public static boolean copy(File file, File newFile) {
398                byte[] bytes = null;
399                BufferedInputStream inputStream = null;
400                try {
401                        inputStream = new BufferedInputStream(new FileInputStream(file));
402                        bytes = Util.getInputStreamAsByteArray(inputStream, -1);
403                } catch (FileNotFoundException e) {
404                        ApiPlugin.log(e);
405                } catch (IOException e) {
406                        ApiPlugin.log(e);
407                } finally {
408                        if (inputStream != null) {
409                                try {
410                                        inputStream.close();
411                                } catch (IOException e) {
412                                        ApiPlugin.log(e);
413                                }
414                        }
415                }
416                if (bytes != null) {
417                        BufferedOutputStream outputStream = null;
418                        try {
419                                outputStream = new BufferedOutputStream(new FileOutputStream(newFile));
420                                outputStream.write(bytes);
421                                outputStream.flush();
422                        } catch (FileNotFoundException e) {
423                                ApiPlugin.log(e);
424                        } catch (IOException e) {
425                                ApiPlugin.log(e);
426                        } finally {
427                                if (outputStream != null) {
428                                        try {
429                                                outputStream.close();
430                                        } catch(IOException e) {
431                                                // ignore
432                                        }
433                                }
434                        }
435                        return true;
436                }
437                return false;
438        }
439        
440        /**
441         * Creates an EE file for the given JRE and specified EE id
442         * @param jre
443         * @param eeid
444         * @return
445         * @throws IOException
446         */
447        public static File createEEFile(IVMInstall jre, String eeid) throws IOException {
448                String string = Util.generateEEContents(jre, eeid);
449                File eeFile = File.createTempFile("eed", ".ee"); //$NON-NLS-1$ //$NON-NLS-2$
450                eeFile.deleteOnExit();
451                FileOutputStream outputStream = null;
452                try {
453                        outputStream = new FileOutputStream(eeFile);
454                        outputStream.write(string.getBytes(IApiCoreConstants.UTF_8));
455                } finally {
456                        if (outputStream != null) {
457                                outputStream.close();
458                        }
459                }
460                return eeFile;
461        }        
462 
463        /**
464         * Returns whether the objects are equal, accounting for either one being <code>null</code>.
465         * 
466         * @param o1
467         * @param o2
468         * @return whether the objects are equal, or both are <code>null</code>
469         */
470        public static boolean equalsOrNull(Object o1, Object o2) {
471                if (o1 == null) {
472                        return o2 == null;
473                }
474                return o1.equals(o2);
475        }
476 
477        /**
478         * Returns an execution environment description for the given VM.
479         *  
480         * @param vm JRE to create an definition for
481         * @return an execution environment description for the given VM
482         * @throws IOException if unable to generate description
483         */
484        public static String generateEEContents(IVMInstall vm, String eeId) throws IOException {
485                StringBuffer buffer = new StringBuffer();
486                appendProperty(buffer, ExecutionEnvironmentDescription.JAVA_HOME, vm.getInstallLocation().getCanonicalPath());
487                StringBuffer paths = new StringBuffer();
488                LibraryLocation[] libraryLocations = JavaRuntime.getLibraryLocations(vm);
489                for (int i = 0; i < libraryLocations.length; i++) {
490                        LibraryLocation lib = libraryLocations[i];
491                        paths.append(lib.getSystemLibraryPath().toOSString());
492                        if (i < (libraryLocations.length - 1)) {
493                                paths.append(File.pathSeparatorChar);
494                        }
495                }
496                appendProperty(buffer, ExecutionEnvironmentDescription.BOOT_CLASS_PATH, paths.toString());
497                appendProperty(buffer, ExecutionEnvironmentDescription.CLASS_LIB_LEVEL, eeId);
498                return  buffer.toString();
499        }
500        
501        /**
502         * Returns an array of all of the files from the given root that are
503         * accepted by the given file filter. If the file filter is null all files
504         * within the given root are returned.
505         * 
506         * @param root
507         * @param fileFilter
508         * @return the list of files from within the given root
509         */
510        public static File[] getAllFiles(File root, FileFilter fileFilter) {
511                ArrayList files = new ArrayList();
512                if (root.isDirectory()) {
513                        collectAllFiles(root, files, fileFilter);
514                        File[] result = new File[files.size()];
515                        files.toArray(result);
516                        return result;
517                }
518                return null;
519        }
520 
521        /**
522         * Returns a build job that will perform a full build on the given projects.
523         * 
524         * If <code>projects</code> are null, then an AssertionFailedException is thrown
525         * @param projects the projects to build
526         * @return the build job
527         * @throws AssertionFailedException if the given projects are null
528         */
529        public static Job getBuildJob(final IProject[] projects) {
530                Assert.isNotNull(projects);
531                Job buildJob = new BuildJob(UtilMessages.Util_4, projects);
532                buildJob.setRule(ResourcesPlugin.getWorkspace().getRuleFactory().buildRule());
533                buildJob.setUser(true);
534                return buildJob;
535        }
536        
537        /**
538         * Returns a build job that will return the build that corresponds to the given
539         * build kind on the given projects.
540         * 
541         * If <code>projects</code> are null, then an AssertionFailedException is thrown
542         * @param projects the projects to build
543         * @param buildKind the given build kind
544         * @return the build job
545         * @throws AssertionFailedException if the given projects are null
546         */
547        public static Job getBuildJob(final IProject[] projects, int buildKind) {
548                Assert.isNotNull(projects);
549                Job buildJob = new BuildJob(UtilMessages.Util_4, projects, buildKind);
550                buildJob.setRule(ResourcesPlugin.getWorkspace().getRuleFactory().buildRule());
551                buildJob.setUser(true);
552                return buildJob;
553        }
554 
555        /**
556         * Returns a result of searching the given components for  class file with the
557         * given type name.
558         *  
559         * @param components API components to search or <code>null</code> if none
560         * @param typeName type to search for
561         * @return class file or <code>null</code> if none found
562         */
563        public static IApiTypeRoot getClassFile(IApiComponent[] components, String typeName) {
564                if (components == null) {
565                        return null;
566                }
567                for (int i = 0, max = components.length; i < max; i++) {
568                        IApiComponent apiComponent = components[i];
569                        if (apiComponent != null) {
570                                try {
571                                        IApiTypeRoot classFile = apiComponent.findTypeRoot(typeName);
572                                        if (classFile != null) return classFile;
573                                } catch (CoreException e) {
574                                        // ignore
575                                }
576                        }
577                }
578                return null;
579        }
580        
581        /**
582         * Return a string that represents the element type of the given delta.
583         * Returns {@link #UNKNOWN_ELEMENT_KIND} if the element type cannot be determined.
584         * 
585         * @param delta the given delta
586         * @return a string that represents the element type of the given delta.
587         */
588        public static String getDeltaElementType(IDelta delta) {
589                return getDeltaElementType(delta.getElementType());
590        }
591 
592        /**
593         * Returns a text representation of a marker severity level
594         * @param severity
595         * @return text of a marker severity level
596         */
597        public static String getSeverity(int severity) {
598                switch(severity) {
599                        case IMarker.SEVERITY_ERROR: {
600                                return "ERROR"; //$NON-NLS-1$
601                        }
602                        case IMarker.SEVERITY_INFO: {
603                                return "INFO"; //$NON-NLS-1$
604                        }
605                        case IMarker.SEVERITY_WARNING: {
606                                return "WARNING"; //$NON-NLS-1$
607                        }
608                        default: {
609                                return "UNKNOWN_SEVERITY"; //$NON-NLS-1$
610                        }
611                }
612        }
613        /**
614         * Return an int value that represents the given element type
615         * Returns -1 if the element type cannot be determined.
616         * 
617         * @param elementType the given element type
618         * @return an int that represents the given element type constant.
619         */
620        public static int getDeltaElementTypeValue(String elementType) {
621                Class IDeltaClass = IDelta.class;
622                try {
623                        Field field = IDeltaClass.getField(elementType);
624                        return field.getInt(null);
625                } catch (SecurityException e) {
626                        // ignore
627                } catch (IllegalArgumentException e) {
628                        // ignore
629                } catch (NoSuchFieldException e) {
630                        // ignore
631                } catch (IllegalAccessException e) {
632                        // ignore
633                }
634                return -1;
635        }
636        /**
637         * Return a string that represents the given element type
638         * Returns {@link #UNKNOWN_ELEMENT_KIND} if the element type cannot be determined.
639         * 
640         * @param elementType the given element type
641         * @return a string that represents the given element type.
642         */
643        public static String getDeltaElementType(int elementType) {
644                switch(elementType) {
645                        case IDelta.ANNOTATION_ELEMENT_TYPE :
646                                return "ANNOTATION_ELEMENT_TYPE"; //$NON-NLS-1$
647                        case IDelta.INTERFACE_ELEMENT_TYPE :
648                                return "INTERFACE_ELEMENT_TYPE"; //$NON-NLS-1$
649                        case IDelta.ENUM_ELEMENT_TYPE :
650                                return "ENUM_ELEMENT_TYPE"; //$NON-NLS-1$
651                        case IDelta.API_COMPONENT_ELEMENT_TYPE :
652                                return "API_COMPONENT_ELEMENT_TYPE"; //$NON-NLS-1$
653                        case IDelta.API_PROFILE_ELEMENT_TYPE :
654                                return "API_PROFILE_ELEMENT_TYPE"; //$NON-NLS-1$
655                        case IDelta.CONSTRUCTOR_ELEMENT_TYPE :
656                                return "CONSTRUCTOR_ELEMENT_TYPE"; //$NON-NLS-1$
657                        case IDelta.METHOD_ELEMENT_TYPE :
658                                return "METHOD_ELEMENT_TYPE"; //$NON-NLS-1$
659                        case IDelta.FIELD_ELEMENT_TYPE :
660                                return "FIELD_ELEMENT_TYPE"; //$NON-NLS-1$
661                        case IDelta.CLASS_ELEMENT_TYPE :
662                                return "CLASS_ELEMENT_TYPE"; //$NON-NLS-1$
663                        case IDelta.TYPE_PARAMETER_ELEMENT_TYPE :
664                                return "TYPE_PARAMETER_ELEMENT_TYPE"; //$NON-NLS-1$
665                }
666                return UNKNOWN_ELEMENT_KIND;
667        }
668        
669        /**
670         * Return a string that represents the given flags
671         * Returns {@link #UNKNOWN_FLAGS} if the flags cannot be determined.
672         * 
673         * @param flags the given delta's flags
674         * @return a string that represents the given flags.
675         */
676        public static String getDeltaFlagsName(int flags) {
677                switch(flags) {
678                        case IDelta.ABSTRACT_TO_NON_ABSTRACT : return "ABSTRACT_TO_NON_ABSTRACT"; //$NON-NLS-1$
679                        case IDelta.ANNOTATION_DEFAULT_VALUE : return "ANNOTATION_DEFAULT_VALUE"; //$NON-NLS-1$
680                        case IDelta.API_COMPONENT : return "API_COMPONENT"; //$NON-NLS-1$
681                        case IDelta.ARRAY_TO_VARARGS : return "ARRAY_TO_VARARGS"; //$NON-NLS-1$
682                        case IDelta.CHECKED_EXCEPTION : return "CHECKED_EXCEPTION"; //$NON-NLS-1$
683                        case IDelta.CLASS_BOUND : return "CLASS_BOUND"; //$NON-NLS-1$
684                        case IDelta.CLINIT : return "CLINIT"; //$NON-NLS-1$
685                        case IDelta.CONSTRUCTOR : return "CONSTRUCTOR"; //$NON-NLS-1$
686                        case IDelta.CONTRACTED_SUPERINTERFACES_SET : return "CONTRACTED_SUPERINTERFACES_SET"; //$NON-NLS-1$
687                        case IDelta.DECREASE_ACCESS : return "DECREASE_ACCESS"; //$NON-NLS-1$
688                        case IDelta.ENUM_CONSTANT : return "ENUM_CONSTANT"; //$NON-NLS-1$
689                        case IDelta.EXECUTION_ENVIRONMENT : return "EXECUTION_ENVIRONMENT"; //$NON-NLS-1$
690                        case IDelta.EXPANDED_SUPERINTERFACES_SET : return "EXPANDED_SUPERINTERFACES_SET"; //$NON-NLS-1$
691                        case IDelta.FIELD : return "FIELD"; //$NON-NLS-1$
692                        case IDelta.FIELD_MOVED_UP : return "FIELD_MOVED_UP"; //$NON-NLS-1$
693                        case IDelta.FINAL_TO_NON_FINAL : return "FINAL_TO_NON_FINAL"; //$NON-NLS-1$
694                        case IDelta.FINAL_TO_NON_FINAL_NON_STATIC : return "FINAL_TO_NON_FINAL_NON_STATIC"; //$NON-NLS-1$
695                        case IDelta.FINAL_TO_NON_FINAL_STATIC_CONSTANT : return "FINAL_TO_NON_FINAL_STATIC_CONSTANT"; //$NON-NLS-1$
696                        case IDelta.FINAL_TO_NON_FINAL_STATIC_NON_CONSTANT : return "FINAL_TO_NON_FINAL_STATIC_NON_CONSTANT"; //$NON-NLS-1$
697                        case IDelta.INCREASE_ACCESS : return "INCREASE_ACCESS"; //$NON-NLS-1$
698                        case IDelta.INTERFACE_BOUND : return "INTERFACE_BOUND"; //$NON-NLS-1$
699                        case IDelta.METHOD : return "METHOD"; //$NON-NLS-1$
700                        case IDelta.METHOD_MOVED_UP : return "METHOD_MOVED_UP"; //$NON-NLS-1$
701                        case IDelta.METHOD_WITH_DEFAULT_VALUE : return "METHOD_WITH_DEFAULT_VALUE"; //$NON-NLS-1$
702                        case IDelta.METHOD_WITHOUT_DEFAULT_VALUE : return "METHOD_WITHOUT_DEFAULT_VALUE"; //$NON-NLS-1$
703                        case IDelta.NATIVE_TO_NON_NATIVE : return "NATIVE_TO_NON_NATIVE"; //$NON-NLS-1$
704                        case IDelta.NON_ABSTRACT_TO_ABSTRACT : return "NON_ABSTRACT_TO_ABSTRACT"; //$NON-NLS-1$
705                        case IDelta.NON_FINAL_TO_FINAL : return "NON_FINAL_TO_FINAL"; //$NON-NLS-1$
706                        case IDelta.NON_NATIVE_TO_NATIVE : return "NON_NATIVE_TO_NATIVE"; //$NON-NLS-1$
707                        case IDelta.NON_STATIC_TO_STATIC : return "NON_STATIC_TO_STATIC"; //$NON-NLS-1$
708                        case IDelta.NON_SYNCHRONIZED_TO_SYNCHRONIZED : return "NON_SYNCHRONIZED_TO_SYNCHRONIZED"; //$NON-NLS-1$
709                        case IDelta.NON_TRANSIENT_TO_TRANSIENT : return "NON_TRANSIENT_TO_TRANSIENT"; //$NON-NLS-1$
710                        case IDelta.OVERRIDEN_METHOD : return "OVERRIDEN_METHOD"; //$NON-NLS-1$
711                        case IDelta.STATIC_TO_NON_STATIC : return "STATIC_TO_NON_STATIC"; //$NON-NLS-1$
712                        case IDelta.SUPERCLASS : return "SUPERCLASS"; //$NON-NLS-1$
713                        case IDelta.SYNCHRONIZED_TO_NON_SYNCHRONIZED : return "SYNCHRONIZED_TO_NON_SYNCHRONIZED"; //$NON-NLS-1$
714                        case IDelta.TYPE_CONVERSION : return "TYPE_CONVERSION"; //$NON-NLS-1$
715                        case IDelta.TRANSIENT_TO_NON_TRANSIENT : return "TRANSIENT_TO_NON_TRANSIENT"; //$NON-NLS-1$
716                        case IDelta.TYPE : return "TYPE"; //$NON-NLS-1$
717                        case IDelta.TYPE_ARGUMENTS : return "TYPE_ARGUMENTS"; //$NON-NLS-1$
718                        case IDelta.TYPE_MEMBER : return "TYPE_MEMBER"; //$NON-NLS-1$
719                        case IDelta.TYPE_PARAMETER : return "TYPE_PARAMETER"; //$NON-NLS-1$
720                        case IDelta.TYPE_PARAMETER_NAME : return "TYPE_PARAMETER_NAME"; //$NON-NLS-1$
721                        case IDelta.TYPE_PARAMETERS : return "TYPE_PARAMETERS"; //$NON-NLS-1$
722                        case IDelta.TYPE_VISIBILITY : return "TYPE_VISIBILITY"; //$NON-NLS-1$
723                        case IDelta.UNCHECKED_EXCEPTION : return "UNCHECKED_EXCEPTION"; //$NON-NLS-1$
724                        case IDelta.VALUE : return "VALUE"; //$NON-NLS-1$
725                        case IDelta.VARARGS_TO_ARRAY : return "VARARGS_TO_ARRAY"; //$NON-NLS-1$
726                        case IDelta.RESTRICTIONS : return "RESTRICTIONS"; //$NON-NLS-1$
727                        case IDelta.API_TYPE : return "API_TYPE"; //$NON-NLS-1$
728                        case IDelta.NON_VOLATILE_TO_VOLATILE : return "NON_VOLATILE_TO_VOLATILE"; //$NON-NLS-1$
729                        case IDelta.VOLATILE_TO_NON_VOLATILE : return "VOLATILE_TO_NON_VOLATILE"; //$NON-NLS-1$
730                        case IDelta.MINOR_VERSION : return "MINOR_VERSION"; //$NON-NLS-1$
731                        case IDelta.MAJOR_VERSION : return "MAJOR_VERSION"; //$NON-NLS-1$
732                        case IDelta.API_FIELD : return "API_FIELD"; //$NON-NLS-1$
733                        case IDelta.API_METHOD : return "API_METHOD"; //$NON-NLS-1$
734                        case IDelta.API_CONSTRUCTOR : return "API_CONSTRUCTOR"; //$NON-NLS-1$
735                        case IDelta.API_ENUM_CONSTANT : return "API_ENUM_CONSTANT"; //$NON-NLS-1$
736                        case IDelta.API_METHOD_WITH_DEFAULT_VALUE : return "API_METHOD_WITH_DEFAULT_VALUE"; //$NON-NLS-1$
737                        case IDelta.API_METHOD_WITHOUT_DEFAULT_VALUE : return "API_METHOD_WITHOUT_DEFAULT_VALUE"; //$NON-NLS-1$
738                        case IDelta.TYPE_ARGUMENT : return "TYPE_ARGUMENT"; //$NON-NLS-1$
739                        case IDelta.SUPER_INTERFACE_WITH_METHODS : return "SUPER_INTERFACE_WITH_METHODS"; //$NON-NLS-1$
740                        case IDelta.REEXPORTED_API_TYPE : return "REEXPORTED_API_TYPE"; //$NON-NLS-1$
741                        case IDelta.REEXPORTED_TYPE : return "REEXPORTED_TYPE"; //$NON-NLS-1$
742                        case IDelta.METHOD_MOVED_DOWN : return "METHOD_MOVED_DOWN"; //$NON-NLS-1$
743                        case IDelta.DEPRECATION : return "DEPRECATION"; //$NON-NLS-1$
744                }
745                return UNKNOWN_FLAGS;
746        }
747 
748        /**
749         * Return a string that represents the kind of the given delta.
750         * Returns {@link #UNKNOWN_KIND} if the kind cannot be determined.
751         * 
752         * @param delta the given delta
753         * @return a string that represents the kind of the given delta.
754         */
755        public static String getDeltaKindName(IDelta delta) {
756                return getDeltaKindName(delta.getKind());
757        }
758 
759        /**
760         * Return a string that represents the given kind.
761         * Returns {@link #UNKNOWN_KIND} if the kind cannot be determined.
762         * 
763         * @param delta the given kind
764         * @return a string that represents the given kind.
765         */
766        public static String getDeltaKindName(int kind) {
767                switch(kind) {
768                        case IDelta.ADDED :
769                                return "ADDED"; //$NON-NLS-1$
770                        case IDelta.CHANGED :
771                                return "CHANGED"; //$NON-NLS-1$
772                        case IDelta.REMOVED :
773                                return "REMOVED"; //$NON-NLS-1$
774                }
775                return UNKNOWN_KIND;
776        }
777 
778        /**
779         * Returns the preference key for the given element type, the given kind and the given flags.
780         * 
781         * @param elementType the given element type (retrieved using {@link IDelta#getElementType()}
782         * @param kind the given kind (retrieved using {@link IDelta#getKind()}
783         * @param flags the given flags (retrieved using {@link IDelta#getFlags()}
784         * @return the preference key for the given element type, the given kind and the given flags.
785         */
786        public static String getDeltaPrefererenceKey(int elementType, int kind, int flags) {
787                StringBuffer buffer = new StringBuffer(Util.getDeltaElementType(elementType));
788                buffer.append('_').append(Util.getDeltaKindName(kind));
789                if (flags != -1) {
790                        buffer.append('_');
791                        switch(flags) {
792                                case IDelta.API_FIELD :
793                                        buffer.append(Util.getDeltaFlagsName(IDelta.FIELD));
794                                        break;
795                                case IDelta.API_ENUM_CONSTANT :
796                                        buffer.append(Util.getDeltaFlagsName(IDelta.ENUM_CONSTANT));
797                                        break;
798                                case IDelta.API_CONSTRUCTOR :
799                                        buffer.append(Util.getDeltaFlagsName(IDelta.CONSTRUCTOR));
800                                        break;
801                                case IDelta.API_METHOD :
802                                        buffer.append(Util.getDeltaFlagsName(IDelta.METHOD));
803                                        break;
804                                case IDelta.API_METHOD_WITH_DEFAULT_VALUE :
805                                        if (kind == IDelta.REMOVED) {
806                                                buffer.append(Util.getDeltaFlagsName(IDelta.METHOD));
807                                        } else {
808                                                buffer.append(Util.getDeltaFlagsName(IDelta.METHOD_WITH_DEFAULT_VALUE));
809                                        }
810                                        break;
811                                case IDelta.API_METHOD_WITHOUT_DEFAULT_VALUE :
812                                        if (kind == IDelta.REMOVED) {
813                                                buffer.append(Util.getDeltaFlagsName(IDelta.METHOD));
814                                        } else {
815                                                buffer.append(Util.getDeltaFlagsName(IDelta.METHOD_WITHOUT_DEFAULT_VALUE));
816                                        }
817                                        break;
818                                case IDelta.METHOD_WITH_DEFAULT_VALUE :
819                                        if (kind == IDelta.REMOVED) {
820                                                buffer.append(Util.getDeltaFlagsName(IDelta.METHOD));
821                                        } else {
822                                                buffer.append(Util.getDeltaFlagsName(IDelta.METHOD_WITH_DEFAULT_VALUE));
823                                        }
824                                        break;
825                                case IDelta.METHOD_WITHOUT_DEFAULT_VALUE :
826                                        if (kind == IDelta.REMOVED) {
827                                                buffer.append(Util.getDeltaFlagsName(IDelta.METHOD));
828                                        } else {
829                                                buffer.append(Util.getDeltaFlagsName(IDelta.METHOD_WITHOUT_DEFAULT_VALUE));
830                                        }
831                                        break;
832                                default:
833                                        buffer.append(Util.getDeltaFlagsName(flags));
834                        }
835                }
836                return String.valueOf(buffer);
837        }
838 
839        /**
840         * Returns the details of the api delta as a string
841         * @param delta
842         * @return the details of the delta as a string
843         */
844        public static String getDetail(IDelta delta) {
845                StringBuffer buffer = new StringBuffer();
846                switch(delta.getElementType()) {
847                        case IDelta.CLASS_ELEMENT_TYPE :
848                                buffer.append("class"); //$NON-NLS-1$
849                                break;
850                        case IDelta.ANNOTATION_ELEMENT_TYPE :
851                                buffer.append("annotation"); //$NON-NLS-1$
852                                break;
853                        case IDelta.INTERFACE_ELEMENT_TYPE :
854                                buffer.append("interface"); //$NON-NLS-1$
855                                break;
856                        case IDelta.API_COMPONENT_ELEMENT_TYPE :
857                                buffer.append("api component"); //$NON-NLS-1$
858                                break;
859                        case IDelta.API_PROFILE_ELEMENT_TYPE :
860                                buffer.append("api profile"); //$NON-NLS-1$
861                                break;
862                        case IDelta.METHOD_ELEMENT_TYPE:
863                                buffer.append("method"); //$NON-NLS-1$
864                                break;
865                        case IDelta.CONSTRUCTOR_ELEMENT_TYPE :
866                                buffer.append("constructor"); //$NON-NLS-1$
867                                break;
868                        case IDelta.ENUM_ELEMENT_TYPE :
869                                buffer.append("enum"); //$NON-NLS-1$
870                                break;
871                        case IDelta.FIELD_ELEMENT_TYPE :
872                                buffer.append("field"); //$NON-NLS-1$
873                                break;
874                }
875                buffer.append(' ');
876                switch(delta.getKind()) {
877                        case IDelta.ADDED :
878                                buffer.append("added"); //$NON-NLS-1$
879                                break;
880                        case IDelta.REMOVED :
881                                buffer.append("removed"); //$NON-NLS-1$
882                                break;
883                        case IDelta.CHANGED :
884                                buffer.append("changed"); //$NON-NLS-1$
885                                break;
886                        default:
887                                buffer.append("unknown kind"); //$NON-NLS-1$
888                        break;
889                }
890                buffer.append(' ').append(getDeltaFlagsName(delta.getFlags())).append(' ').append(delta.getTypeName()).append("#").append(delta.getKey()); //$NON-NLS-1$
891                return String.valueOf(buffer);
892        }
893 
894        /**
895         * Returns the {@link IDocument} for the specified {@link ICompilationUnit}
896         * @param cu
897         * @return the {@link IDocument} for the specified {@link ICompilationUnit}
898         * @throws CoreException
899         */
900        public static IDocument getDocument(ICompilationUnit cu) throws CoreException {
901                if (cu.getOwner() == null) {
902                        IFile file= (IFile) cu.getResource();
903                        if (file.exists()) {
904                                ITextFileBufferManager bufferManager= FileBuffers.getTextFileBufferManager();
905                                IPath path= cu.getPath();
906                                bufferManager.connect(path, LocationKind.IFILE, new NullProgressMonitor());
907                                try {
908                                        return bufferManager.getTextFileBuffer(path, LocationKind.IFILE).getDocument();
909                                } finally {
910                                        bufferManager.disconnect(path, LocationKind.IFILE, null);
911                                }
912                        }
913                }
914                return new org.eclipse.jface.text.Document(cu.getSource());
915        }
916 
917        /**
918         * Returns the OSGi profile properties corresponding to the given execution
919         * environment id, or <code>null</code> if none.
920         * 
921         * @param eeId OSGi profile identifier
922         *
923         * @return the corresponding properties or <code>null</code> if none
924         */
925        public static Properties getEEProfile(String eeId) {
926                String profileName = eeId + ".profile"; //$NON-NLS-1$
927                InputStream stream = Util.class.getResourceAsStream("profiles/" + profileName); //$NON-NLS-1$
928                if (stream != null) {
929                        try {
930                                Properties profile = new Properties();
931                                profile.load(stream);
932                                return profile;
933                        } catch (IOException e) {
934                                ApiPlugin.log(e);
935                        } finally {
936                                try {
937                                        stream.close();
938                                } catch(IOException e) {
939                                        ApiPlugin.log(e);
940                                }
941                        }
942                }
943                return null;
944        }
945        
946        /**
947         * Returns the number of fragments for the given version value, -1 if the format is unknown.
948         * The version is formed like: [optional plugin name] major.minor.micro.qualifier.
949         * 
950         * @param version the given version value
951         * @return the number of fragments for the given version value or -1 if the format is unknown
952         * @throws IllegalArgumentException if version is null
953         */
954        public static final int getFragmentNumber(String version) {
955                if (version == null) throw new IllegalArgumentException("The given version should not be null"); //$NON-NLS-1$
956                int index = version.indexOf(' ');
957                char[] charArray = version.toCharArray();
958                int length = charArray.length;
959                if (index + 1 >= length) {
960                        return -1;
961                }
962                int counter = 1;
963                for (int i = index + 1; i < length; i++) {
964                        switch(charArray[i]) {
965                                case '0' :
966                                case '1' :
967                                case '2' :
968                                case '3' :
969                                case '4' :
970                                case '5' :
971                                case '6' :
972                                case '7' :
973                                case '8' :
974                                case '9' :
975                                        continue;
976                                case '.' :
977                                        counter++;
978                                        break;
979                                default :
980                                        return -1;
981                        }
982                }
983                return counter;
984        }
985 
986        public static IMember getIMember(IDelta delta, IJavaProject javaProject) {
987                String typeName = delta.getTypeName();
988                if (typeName == null) return null;
989                IType type = null;
990                try {
991                        type = javaProject.findType(typeName.replace('$', '.'));
992                } catch (JavaModelException e) {
993                        // ignore
994                }
995                if (type == null) return null;
996                String key = delta.getKey();
997                switch(delta.getElementType()) {
998                        case IDelta.FIELD_ELEMENT_TYPE : {
999                                        IField field = type.getField(key);
1000                                        if (field.exists()) {
1001                                                return field;
1002                                        }
1003                                }
1004                                break;
1005                        case IDelta.CLASS_ELEMENT_TYPE :
1006                        case IDelta.ANNOTATION_ELEMENT_TYPE :
1007                        case IDelta.INTERFACE_ELEMENT_TYPE :
1008                        case IDelta.ENUM_ELEMENT_TYPE :
1009                                // we report the marker on the type
1010                                switch(delta.getKind()) {
1011                                        case IDelta.ADDED :
1012                                                switch(delta.getFlags()) {
1013                                                        case IDelta.FIELD :
1014                                                        case IDelta.ENUM_CONSTANT :
1015                                                                IField field = type.getField(key);
1016                                                                if (field.exists()) {
1017                                                                        return field;
1018                                                                }
1019                                                                break;
1020                                                        case IDelta.METHOD_WITH_DEFAULT_VALUE :
1021                                                        case IDelta.METHOD_WITHOUT_DEFAULT_VALUE :
1022                                                        case IDelta.METHOD :
1023                                                        case IDelta.CONSTRUCTOR :
1024                                                                return getMethod(type, key);
1025                                                        case IDelta.TYPE_MEMBER :
1026                                                                IType type2 = type.getType(key);
1027                                                                if (type2.exists()) {
1028                                                                        return type2;
1029                                                                }
1030                                                }
1031                                                break;
1032                                        case IDelta.REMOVED :
1033                                                switch(delta.getFlags()) {
1034                                                        case IDelta.API_FIELD :
1035                                                        case IDelta.API_ENUM_CONSTANT :
1036                                                                IField field = type.getField(key);
1037                                                                if (field.exists()) {
1038                                                                        return field;
1039                                                                }
1040                                                                break;
1041                                                        case IDelta.API_METHOD_WITH_DEFAULT_VALUE :
1042                                                        case IDelta.API_METHOD_WITHOUT_DEFAULT_VALUE :
1043                                                        case IDelta.API_METHOD :
1044                                                        case IDelta.API_CONSTRUCTOR :
1045                                                                return getMethod(type, key);
1046                                                }
1047                                }
1048                                return type;
1049                        case IDelta.METHOD_ELEMENT_TYPE :
1050                        case IDelta.CONSTRUCTOR_ELEMENT_TYPE : {
1051                                        return getMethod(type, key);
1052                                }
1053                        case IDelta.API_COMPONENT_ELEMENT_TYPE :
1054                                return type;
1055                }
1056                return null;
1057        }
1058 
1059        /**
1060         * Updates a given progress monitor the given amount of work.
1061         * Throws an {@link OperationCanceledException} if the monitor has been canceled.
1062         * 
1063         * @param monitor
1064         * @param work
1065         * @throws OperationCanceledException
1066         */
1067        public static void updateMonitor(IProgressMonitor monitor, int work) throws OperationCanceledException {
1068                if(monitor == null) {
1069                        return;
1070                }
1071                if(monitor.isCanceled()) {
1072                        throw new OperationCanceledException();
1073                }
1074                monitor.worked(work);
1075        }
1076        
1077        /**
1078         * Updates the given monitor 0 work ticks. This method is used to poll for cancellation
1079         * without advancing the work done.
1080         * 
1081         * @param monitor
1082         * @throws OperationCanceledException
1083         */
1084        public static void updateMonitor(IProgressMonitor monitor) throws OperationCanceledException {
1085                updateMonitor(monitor, 0);
1086        }
1087        
1088        private static IMember getMethod(IType type, String key) {
1089                boolean isGeneric = false;
1090                int indexOfTypeVariable = key.indexOf('<');
1091                int index = 0;
1092                if (indexOfTypeVariable == -1) {
1093                        int indexOfParen = key.indexOf('(');
1094                        if (indexOfParen == -1) {
1095                                return null;
1096                        }
1097                        index = indexOfParen;
1098                } else {
1099                        int indexOfParen = key.indexOf('(');
1100                        if (indexOfParen == -1) {
1101                                return null;
1102                        }
1103                        if (indexOfParen < indexOfTypeVariable) {
1104                                index = indexOfParen;
1105                        } else {
1106                                index = indexOfTypeVariable;
1107                                isGeneric = true;
1108                        }
1109                }
1110                String selector = key.substring(0, index);
1111                String descriptor = key.substring(index, key.length());
1112                IMethod method = null;
1113                String signature = descriptor.replace('/', '.');
1114                String[] parameterTypes = null;
1115                if (isGeneric) {
1116                        // remove all type variables first
1117                        signature = signature.substring(signature.indexOf('('));
1118                        parameterTypes = Signature.getParameterTypes(signature);
1119                } else {
1120                        parameterTypes = Signature.getParameterTypes(signature);
1121                }
1122 
1123                try {
1124                        method = type.getMethod(selector, parameterTypes);
1125                } catch (IllegalArgumentException e) {
1126                        ApiPlugin.log(e);
1127                }
1128                if (method == null) {
1129                        return null;
1130                }
1131                if (method.exists()) {
1132                        return method;
1133                } else {
1134                        // if the method is not null and it doesn't exist, it might be the default constructor
1135                        if (selector.equals(type.getElementName()) && parameterTypes.length == 0) {
1136                                return null;
1137                        }
1138                        // try to check by selector
1139                        IMethod[] methods = null;
1140                        try {
1141                                methods = type.getMethods();
1142                        } catch (JavaModelException e) {
1143                                ApiPlugin.log(e);
1144                                // do not default to the enclosing type - see bug 224713
1145                                ApiPlugin.log(
1146                                                new Status(IStatus.ERROR,
1147                                                                ApiPlugin.PLUGIN_ID,
1148                                                                NLS.bind(UtilMessages.Util_6, new String[] { selector, descriptor })));
1149                                return null;
1150                        }
1151                        List list = new ArrayList();
1152                        for (int i = 0, max = methods.length; i < max; i++) {
1153                                IMethod method2 = methods[i];
1154                                if (selector.equals(method2.getElementName())) {
1155                                        list.add(method2);
1156                                }
1157                        }
1158                        switch(list.size()) {
1159                                case 0 :
1160                                        // do not default to the enclosing type - see bug 224713
1161                                        ApiPlugin.log(
1162                                                        new Status(IStatus.ERROR,
1163                                                                        ApiPlugin.PLUGIN_ID,
1164                                                                        NLS.bind(UtilMessages.Util_6, new String[] { selector, descriptor })));
1165                                        return null;
1166                                case 1 :
1167                                        return (IMember) list.get(0);
1168                                default:
1169                                        // need to find a matching parameters
1170                                        for (Iterator iterator = list.iterator(); iterator.hasNext(); ) {
1171                                                IMethod method2 = (IMethod) iterator.next();
1172                                                try {
1173                                                        if (Signatures.matchesSignatures(method2.getSignature(), signature)) {
1174                                                                return method2;
1175                                                        }
1176                                                } catch (JavaModelException e) {
1177                                                        // ignore
1178                                                }
1179                                        }
1180                        }
1181                }
1182                // do not default to the enclosing type - see bug 224713
1183                ApiPlugin.log(
1184                                new Status(IStatus.ERROR,
1185                                                ApiPlugin.PLUGIN_ID,
1186                                                NLS.bind(UtilMessages.Util_6, new String[] { selector, descriptor })));
1187                return null;
1188        }
1189 
1190        /**
1191         * Returns the given input stream as a byte array
1192         * @param stream the stream to get as a byte array
1193         * @param length the length to read from the stream or -1 for unknown
1194         * @return the given input stream as a byte array
1195         * @throws IOException
1196         */
1197        public static byte[] getInputStreamAsByteArray(InputStream stream, int length) throws IOException {
1198                byte[] contents;
1199                if (length == -1) {
1200                        contents = new byte[0];
1201                        int contentsLength = 0;
1202                        int amountRead = -1;
1203                        do {
1204                                // read at least 8K
1205                                int amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE);
1206                                // resize contents if needed
1207                                if (contentsLength + amountRequested > contents.length) {
1208                                        System.arraycopy(contents,
1209                                                        0,
1210                                                        contents = new byte[contentsLength + amountRequested],
1211                                                        0,
1212                                                        contentsLength);
1213                                }
1214                                // read as many bytes as possible
1215                                amountRead = stream.read(contents, contentsLength, amountRequested);
1216                                if (amountRead > 0) {
1217                                        // remember length of contents
1218                                        contentsLength += amountRead;
1219                                }
1220                        } while (amountRead != -1);
1221                        // resize contents if necessary
1222                        if (contentsLength < contents.length) {
1223                                System.arraycopy(contents, 0, contents = new byte[contentsLength], 0, contentsLength);
1224                        }
1225                } else {
1226                        contents = new byte[length];
1227                        int len = 0;
1228                        int readSize = 0;
1229                        while ((readSize != -1) && (len != length)) {
1230                                // See PR 1FMS89U
1231                                // We record first the read size. In this case length is the actual
1232                                // read size.
1233                                len += readSize;
1234                                readSize = stream.read(contents, len, length - len);
1235                        }
1236                }
1237                return contents;
1238        }
1239        
1240        /**
1241         * Returns the given input stream's contents as a character array.
1242         * If a length is specified (i.e. if length != -1), this represents the number of bytes in the stream.
1243         * Note the specified stream is not closed in this method
1244         * @param stream the stream to get convert to the char array 
1245         * @param length the length of the input stream, or -1 if unknown
1246         * @param encoding the encoding to use when reading the stream
1247         * @return the given input stream's contents as a character array.
1248         * @throws IOException if a problem occurred reading the stream.
1249         */
1250        public static char[] getInputStreamAsCharArray(InputStream stream, int length, String encoding) throws IOException {
1251                Charset charset = null;
1252                try {
1253                        charset = Charset.forName(encoding);
1254                } catch (IllegalCharsetNameException e) {
1255                        System.err.println("Illegal charset name : " + encoding); //$NON-NLS-1$
1256                        return null;
1257                } catch(UnsupportedCharsetException e) {
1258                        System.err.println("Unsupported charset : " + encoding); //$NON-NLS-1$
1259                        return null;
1260                }
1261                CharsetDecoder charsetDecoder = charset.newDecoder();
1262                charsetDecoder.onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE);
1263                byte[] contents = getInputStreamAsByteArray(stream, length);
1264                ByteBuffer byteBuffer = ByteBuffer.allocate(contents.length);
1265                byteBuffer.put(contents);
1266                byteBuffer.flip();
1267                return charsetDecoder.decode(byteBuffer).array();
1268        }
1269        
1270        /**
1271         * Tries to find the 'MANIFEST.MF' file with in the given project in the 
1272         * 'META-INF folder'.
1273         * 
1274         * @param currentProject
1275         * @return a handle to the manifest file or <code>null</code> if not found
1276         */
1277        public static IResource getManifestFile(IProject currentProject) {
1278                return currentProject.findMember("META-INF/MANIFEST.MF"); //$NON-NLS-1$
1279        }
1280        
1281        /**
1282         * Returns if the given {@link IMarker} is representing an {@link org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem}
1283         * or not
1284         * @param marker the marker to check
1285         * @return true if the marker is for an {@link org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem} false otherwise
1286         * @throws CoreException
1287         */
1288        public static boolean isApiProblemMarker(IMarker marker) {
1289                return marker.getAttribute(IApiMarkerConstants.API_MARKER_ATTR_ID, -1) > 0;
1290        }
1291        
1292        /**
1293         * Returns a reference type for the given fully qualified type name.
1294         * 
1295         * @param fullyQualifiedName type name
1296         * @return reference type
1297         */
1298        public static IReferenceTypeDescriptor getType(String fullyQualifiedName) {
1299                int index = fullyQualifiedName.lastIndexOf('.');
1300                String pkg = index == -1 ? DEFAULT_PACKAGE_NAME : fullyQualifiedName.substring(0, index);
1301                String type = index == -1 ? fullyQualifiedName : fullyQualifiedName.substring(index + 1);
1302                return Factory.packageDescriptor(pkg).getType(type);
1303        }
1304        /**
1305         * Returns if the given project is API enabled
1306         * @param project
1307         * @return true if the project is API enabled, false otherwise
1308         */
1309        public static boolean isApiProject(IProject project) {
1310                try {
1311                        return project.hasNature(ApiPlugin.NATURE_ID);
1312                } catch (CoreException e) {
1313                        return false;
1314                }
1315        }
1316        
1317        /**
1318         * Returns if the given project is API enabled
1319         * @param project
1320         * @return true if the project is API enabled, false otherwise
1321         */
1322        public static boolean isApiProject(IJavaProject project) {
1323                return isApiProject(project.getProject());
1324        }
1325        
1326        /**
1327         * Returns if the given {@link IApiComponent} is a valid {@link IApiComponent}
1328         * @param apiComponent
1329         * @return true if the given {@link IApiComponent} is valid, false otherwise
1330         */
1331        public static boolean isApiToolsComponent(IApiComponent apiComponent) {
1332                File file = new File(apiComponent.getLocation());
1333                if (file.exists()) {
1334                        if (file.isDirectory()) {
1335                                // directory binary bundle
1336                                File apiDescription = new File(file, IApiCoreConstants.API_DESCRIPTION_XML_NAME);
1337                                return apiDescription.exists();
1338                        }
1339                        ZipFile zipFile = null;
1340                        try {
1341                                zipFile = new ZipFile(file);
1342                                return zipFile.getEntry(IApiCoreConstants.API_DESCRIPTION_XML_NAME) != null;
1343                        } catch (ZipException e) {
1344                                // ignore
1345                        } catch (IOException e) {
1346                                // ignore
1347                        } finally {
1348                                try {
1349                                        if (zipFile != null) zipFile.close();
1350                                } catch (IOException e) {
1351                                        // ignore
1352                                }
1353                        }
1354                }
1355                return false;
1356        }
1357        
1358        /**
1359         * Returns if the specified file name is an archive name. A name is
1360         * considered to be an archive name if it ends with either '.zip' or '.jar'
1361         * 
1362         * @param fileName
1363         * @return true if the file name is an archive name false otherwise
1364         */
1365        public static boolean isArchive(String fileName) {
1366                String normalizedFileName = fileName.toLowerCase();
1367                return normalizedFileName.endsWith(".zip") || normalizedFileName.endsWith(".jar"); //$NON-NLS-1$ //$NON-NLS-2$
1368        }
1369        
1370        /**
1371         * Returns if the flags are for a class
1372         * @param accessFlags
1373         * @return
1374         */
1375        public static boolean isClass(int accessFlags) {
1376                return (accessFlags & (Opcodes.ACC_ENUM | Opcodes.ACC_ANNOTATION | Opcodes.ACC_INTERFACE)) == 0;
1377        }
1378        
1379        /**
1380         * Returns if the specified file name is for a class file. A name is
1381         * considered to be a class file if it ends in '.class'
1382         * 
1383         * @param fileName
1384         * @return true if the name is for a class file false otherwise
1385         */
1386        public static boolean isClassFile(String fileName) {
1387                return fileName.toLowerCase().endsWith(DOT_CLASS_SUFFIX); 
1388        }
1389 
1390        public static boolean isDefault(int accessFlags) {
1391                // none of the private, protected or public bit is set
1392                return (accessFlags & (Opcodes.ACC_PRIVATE
1393                |        Opcodes.ACC_PROTECTED
1394                |        Opcodes.ACC_PUBLIC)) == 0;
1395        }
1396 
1397        public static final boolean isDifferentVersion(String versionToBeChecked, String referenceVersion) {
1398                SinceTagVersion sinceTagVersion1 = null;
1399                SinceTagVersion sinceTagVersion2 = null;
1400                try {
1401                        sinceTagVersion1 = new SinceTagVersion(versionToBeChecked);
1402                        sinceTagVersion2 = new SinceTagVersion(referenceVersion);
1403                } catch (IllegalArgumentException e) {
1404                        // We cannot compare the two versions as their format is unknown
1405                        // TODO (olivier) should we report these as malformed tags?
1406                        return false;
1407                }
1408                Version version1 = sinceTagVersion1.getVersion();
1409                Version version2 = sinceTagVersion2.getVersion();
1410                if (version1.getMajor() != version2.getMajor()) {
1411                        return true;
1412                }
1413                if (version1.getMinor() != version2.getMinor()) {
1414                        return true;
1415                }
1416                if (version1.getMicro() != version2.getMicro()) {
1417                        return true;
1418                }
1419                return false;
1420        }
1421 
1422        /**
1423         * Returns if the specified file name is for a java source file. A name is
1424         * considered to be a java source file if it ends in '.java'
1425         * 
1426         * @param fileName
1427         * @return true if the name is for a java source file, false otherwise
1428         */
1429        public static boolean isJavaFileName(String fileName) {
1430                return fileName.toLowerCase().endsWith(DOT_JAVA_SUFFIX);
1431        }
1432 
1433        /**
1434         * Returns if the given name is {@link java.lang.Object}
1435         * @param name
1436         * @return true if the name is java.lang.Object, false otherwise
1437         */
1438        public static boolean isJavaLangObject(String name) {
1439                return name != null && name.equals(JAVA_LANG_OBJECT);
1440        }
1441        
1442        /**
1443         * Return if the name is {@link java.lang.RuntimeException}
1444         * @param name
1445         * @return true if the name is java.lang.RuntimeException, false otherwise
1446         */
1447        public static boolean isJavaLangRuntimeException(String name) {
1448                return name != null && name.equals(JAVA_LANG_RUNTIMEEXCEPTION);
1449        }
1450        public static boolean isVisible(int modifiers) {
1451                return Flags.isProtected(modifiers) || Flags.isPublic(modifiers);
1452        }
1453        public static boolean isBinaryProject(IProject project) {
1454                return org.eclipse.pde.internal.core.WorkspaceModelManager.isBinaryProject(project);
1455        }
1456        /**
1457         * Returns a new XML document.
1458         * 
1459         * @return document
1460         * @throws CoreException if unable to create a new document
1461         */
1462        public static Document newDocument() throws CoreException {
1463                DocumentBuilderFactory dfactory= DocumentBuilderFactory.newInstance();
1464                DocumentBuilder docBuilder = null;
1465                try {
1466                        docBuilder = dfactory.newDocumentBuilder();
1467                } catch (ParserConfigurationException e) {
1468                        abort("Unable to create new XML document.", e); //$NON-NLS-1$
1469                }
1470                Document doc= docBuilder.newDocument();
1471                return doc;
1472        }
1473        
1474        /**
1475         * Parses the given string representing an XML document, returning its
1476         * root element.
1477         * 
1478         * @param document XML document as a string
1479         * @return the document's root element
1480         * @throws CoreException if unable to parse the document
1481         */
1482        public static Element parseDocument(String document) throws CoreException {
1483                Element root = null;
1484                InputStream stream = null;
1485                try{
1486                        DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
1487                        parser.setErrorHandler(new DefaultHandler());
1488                        stream = new ByteArrayInputStream(document.getBytes());
1489                        root = parser.parse(stream).getDocumentElement();
1490                } catch (ParserConfigurationException e) {
1491                        abort("Unable to parse XML document.", e);  //$NON-NLS-1$
1492                } catch (FactoryConfigurationError e) {
1493                        abort("Unable to parse XML document.", e);  //$NON-NLS-1$
1494                } catch (SAXException e) {
1495                        abort("Unable to parse XML document.", e);  //$NON-NLS-1$
1496                } catch (IOException e) {
1497                        abort("Unable to parse XML document.", e);  //$NON-NLS-1$
1498                } finally { 
1499                        try{
1500                                if (stream != null) {
1501                                        stream.close();
1502                                }
1503                        } catch(IOException e) {
1504                                abort("Unable to parse XML document.", e);  //$NON-NLS-1$
1505                        }
1506                }
1507                return root;
1508        }
1509        
1510        /**
1511         * Save the given contents into the given file. The file parent folder must exist.
1512         * 
1513         * @param file the given file target
1514         * @param contents the given contents
1515         * @throws IOException if an IOException occurs while saving the file
1516         */
1517        public static void saveFile(File file, String contents) throws IOException {
1518                BufferedWriter writer = null;
1519                try {
1520                        writer = new BufferedWriter(new FileWriter(file));
1521                        writer.write(contents);
1522                        writer.flush();
1523                } finally {
1524                        if (writer != null) {
1525                                try {
1526                                        writer.close();
1527                                } catch(IOException e) {
1528                                        // ignore
1529                                }
1530                        }
1531                }
1532        }
1533 
1534        /**
1535         * Returns the contents of the given file as a string, or <code>null</code>
1536         * @param file the file to get the contents for
1537         * @return the contents of the file as a {@link String} or <code>null</code>
1538         */
1539        public static String getFileContentAsString(File file) {
1540                String contents = null;
1541                FileInputStream stream = null;
1542                try {
1543                        stream = new FileInputStream(file);
1544                        char[] array = getInputStreamAsCharArray(stream, -1, IApiCoreConstants.UTF_8);
1545                        contents = new String(array);
1546                }
1547                catch(IOException ioe) {
1548                        ApiPlugin.log(ioe);
1549                } finally {
1550                        if (stream != null) {
1551                                try {
1552                                        stream.close();
1553                                } catch (IOException e) {
1554                                        // ignore
1555                                }
1556                        }
1557                }
1558                return contents;
1559        }
1560        
1561        /**
1562         * Returns the given string as an {@link InputStream}. It is up to the caller to close
1563         * the new stream.
1564         * @param string the string to convert
1565         * @return the {@link InputStream} for the given string
1566         */
1567        public static InputStream getInputStreamFromString(String string) {
1568                try {
1569                        return new ByteArrayInputStream(string.getBytes(IApiCoreConstants.UTF_8));
1570                }
1571                catch(UnsupportedEncodingException uee) {
1572                        ApiPlugin.log(uee);
1573                }
1574                return null;
1575        }
1576        
1577        /**
1578         * Serializes the given XML document into a UTF-8 string.
1579         * 
1580         * @param document XML document to serialize
1581         * @return a string representing the given document
1582         * @throws CoreException if unable to serialize the document
1583         */
1584        public static String serializeDocument(Document document) throws CoreException {
1585                try {
1586                        ByteArrayOutputStream s = new ByteArrayOutputStream();
1587                        TransformerFactory factory = TransformerFactory.newInstance();
1588                        Transformer transformer = factory.newTransformer();
1589                        transformer.setOutputProperty(OutputKeys.METHOD, "xml");  //$NON-NLS-1$
1590                        transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
1591                        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount","4"); //$NON-NLS-1$ //$NON-NLS-2$
1592                        DOMSource source = new DOMSource(document);
1593                        StreamResult outputTarget = new StreamResult(s);
1594                        transformer.transform(source, outputTarget);
1595                        return s.toString(IApiCoreConstants.UTF_8);        
1596                } catch (TransformerException e) {
1597                        abort("Unable to serialize XML document.", e);   //$NON-NLS-1$
1598                } catch (IOException e) {
1599                        abort("Unable to serialize XML document.",e);  //$NON-NLS-1$
1600                }
1601                return null;
1602        }
1603        /**
1604         * Unzip the contents of the given zip in the given directory (create it if it doesn't exist)
1605         */
1606        public static void unzip(String zipPath, String destDirPath) throws IOException {
1607                InputStream zipIn = new FileInputStream(zipPath);
1608                byte[] buf = new byte[8192];
1609                File destDir = new File(destDirPath);
1610                ZipInputStream zis = new ZipInputStream(new BufferedInputStream(zipIn));
1611                BufferedOutputStream outputStream = null;
1612                try {
1613                        ZipEntry zEntry;
1614                        while ((zEntry = zis.getNextEntry()) != null) {
1615                                // if it is empty directory, create it
1616                                if (zEntry.isDirectory()) {
1617                                        new File(destDir, zEntry.getName()).mkdirs();
1618                                        continue;
1619                                }
1620                                // if it is a file, extract it
1621                                String filePath = zEntry.getName();
1622                                int lastSeparator = filePath.lastIndexOf("/"); //$NON-NLS-1$
1623                                String fileDir = ""; //$NON-NLS-1$
1624                                if (lastSeparator >= 0) {
1625                                        fileDir = filePath.substring(0, lastSeparator);
1626                                }
1627                                //create directory for a file
1628                                new File(destDir, fileDir).mkdirs();
1629                                //write file
1630                                File outFile = new File(destDir, filePath);
1631                                outputStream = new BufferedOutputStream(new FileOutputStream(outFile));
1632                                int n = 0;
1633                                while ((n = zis.read(buf)) >= 0) {
1634                                        outputStream.write(buf, 0, n);
1635                                }
1636                                outputStream.close();
1637                        }
1638                } catch (IOException ioe) {
1639                        if (outputStream != null) {
1640                                try {
1641                                        outputStream.close();
1642                                } catch (IOException ioe2) {
1643                                }
1644                        }
1645                } finally {
1646                        try {
1647                                zipIn.close();
1648                                zis.close();
1649                        } catch (IOException ioe) {
1650                        }
1651                }
1652        }
1653        /**
1654         * Unzip the contents of the given zip in the given directory (create it if it doesn't exist)
1655         */
1656        public static void guntar(String zipPath, String destDirPath) throws TarException, IOException {
1657                TarFile tarFile = new TarFile(zipPath);
1658                Enumeration entries = tarFile.entries();
1659                byte[] buf = new byte[8192];
1660                for (;entries.hasMoreElements(); ) {
1661                        TarEntry zEntry;
1662                        while ((zEntry = (TarEntry) entries.nextElement()) != null) {
1663                                // if it is empty directory, create it
1664                                if (zEntry.getFileType() == TarEntry.DIRECTORY) {
1665                                        new File(destDirPath, zEntry.getName()).mkdirs();
1666                                        continue;
1667                                }
1668                                // if it is a file, extract it
1669                                String filePath = zEntry.getName();
1670                                int lastSeparator = filePath.lastIndexOf("/"); //$NON-NLS-1$
1671                                String fileDir = ""; //$NON-NLS-1$
1672                                if (lastSeparator >= 0) {
1673                                        fileDir = filePath.substring(0, lastSeparator);
1674                                }
1675                                //create directory for a file
1676                                new File(destDirPath, fileDir).mkdirs();
1677                                //write file
1678                                File outFile = new File(destDirPath, filePath);
1679                                BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outFile));
1680                                int n = 0;
1681                                InputStream inputStream = tarFile.getInputStream(zEntry);
1682                                BufferedInputStream stream = new BufferedInputStream(inputStream);
1683                                while ((n = stream.read(buf)) >= 0) {
1684                                        outputStream.write(buf, 0, n);
1685                                }
1686                                outputStream.close();
1687                                stream.close();
1688                        }
1689                }
1690        }
1691        /**
1692         * Gets the .ee file supplied to run tests based on system
1693         * property.
1694         * 
1695         * @return
1696         */
1697        public static File getEEDescriptionFile() {
1698                // generate a fake 1.6 ee file
1699                File fakeEEFile = null;
1700                PrintWriter writer = null;
1701                try {
1702                        fakeEEFile = File.createTempFile("eefile", ".ee"); //$NON-NLS-1$ //$NON-NLS-2$
1703                        fakeEEFile.deleteOnExit();
1704                        writer = new PrintWriter(new BufferedWriter(new FileWriter(fakeEEFile)));
1705                        writer.print("-Djava.home="); //$NON-NLS-1$
1706                        writer.println(System.getProperty("java.home")); //$NON-NLS-1$
1707                        writer.print("-Dee.bootclasspath="); //$NON-NLS-1$
1708                        writer.println(getJavaClassLibsAsString());
1709                        writer.println("-Dee.language.level=1.6"); //$NON-NLS-1$
1710                        writer.println("-Dee.class.library.level=JavaSE-1.6"); //$NON-NLS-1$
1711                        writer.flush();
1712                } catch (IOException e) {
1713                        // ignore
1714                } finally {
1715                        if (writer != null) {
1716                                writer.close();
1717                        }
1718                }
1719                return fakeEEFile;
1720        }
1721 
1722        /**
1723         * @return a string representation of all of the libraries from the bootpath 
1724         * of the current default system VM.
1725         */
1726        public static String getJavaClassLibsAsString() {
1727                String[] libs = Util.getJavaClassLibs();
1728                StringBuffer buffer = new StringBuffer();
1729                for (int i = 0, max = libs.length; i < max; i++) {
1730                        if (i > 0) {
1731                                buffer.append(File.pathSeparatorChar);
1732                        }
1733                        buffer.append(libs[i]);
1734                }
1735                return String.valueOf(buffer);
1736        }
1737        
1738        /**
1739         * @return an array of the library names from the bootpath of the current default system VM 
1740         */
1741        public static String[] getJavaClassLibs() {
1742                // check bootclasspath properties for Sun, JRockit and Harmony VMs
1743                String bootclasspathProperty = System.getProperty("sun.boot.class.path"); //$NON-NLS-1$
1744                if ((bootclasspathProperty == null) || (bootclasspathProperty.length() == 0)) {
1745                        // IBM J9 VMs
1746                        bootclasspathProperty = System.getProperty("vm.boot.class.path"); //$NON-NLS-1$
1747                        if ((bootclasspathProperty == null) || (bootclasspathProperty.length() == 0)) {
1748                                // Harmony using IBM VME
1749                                bootclasspathProperty = System.getProperty("org.apache.harmony.boot.class.path"); //$NON-NLS-1$
1750                        }
1751                }
1752                String[] jars = null;
1753                if ((bootclasspathProperty != null) && (bootclasspathProperty.length() != 0)) {
1754                        StringTokenizer tokenizer = new StringTokenizer(bootclasspathProperty, File.pathSeparator);
1755                        final int size = tokenizer.countTokens();
1756                        jars = new String[size];
1757                        int i = 0;
1758                        while (tokenizer.hasMoreTokens()) {
1759                                final String fileName = toNativePath(tokenizer.nextToken());
1760                                if (new File(fileName).exists()) {
1761                                        jars[i] = fileName;
1762                                        i++;
1763                                }
1764                        }
1765                        if (size != i) {
1766                                // resize
1767                                System.arraycopy(jars, 0, (jars = new String[i]), 0, i);
1768                        }
1769                } else {
1770                        String jreDir = System.getProperty("java.home"); //$NON-NLS-1$
1771                        final String osName = System.getProperty("os.name"); //$NON-NLS-1$
1772                        if (jreDir == null) {
1773                                return new String[] {};
1774                        }
1775                        if (osName.startsWith("Mac")) { //$NON-NLS-1$
1776                                return new String[] {
1777                                                toNativePath(jreDir + "/../Classes/classes.jar") //$NON-NLS-1$
1778                                };
1779                        }
1780                        final String vmName = System.getProperty("java.vm.name"); //$NON-NLS-1$
1781                        if ("J9".equals(vmName)) { //$NON-NLS-1$
1782                                return new String[] {
1783                                                toNativePath(jreDir + "/lib/jclMax/classes.zip") //$NON-NLS-1$
1784                                };
1785                        }
1786                        String[] jarsNames = null;
1787                        ArrayList paths = new ArrayList();
1788                        if ("DRLVM".equals(vmName)) { //$NON-NLS-1$
1789                                FilenameFilter jarFilter = new FilenameFilter() {
1790                                        public boolean accept(File dir, String name) {
1791                                                return name.endsWith(".jar") & !name.endsWith("-src.jar");  //$NON-NLS-1$//$NON-NLS-2$
1792                                        }
1793                                };
1794                                jarsNames = new File(jreDir + "/lib/boot/").list(jarFilter); //$NON-NLS-1$
1795                                addJarEntries(jreDir + "/lib/boot/", jarsNames, paths); //$NON-NLS-1$
1796                        } else {
1797                                jarsNames = new String[] {
1798                                                "/lib/vm.jar", //$NON-NLS-1$
1799                                                "/lib/rt.jar", //$NON-NLS-1$
1800                                                "/lib/core.jar", //$NON-NLS-1$
1801                                                "/lib/security.jar", //$NON-NLS-1$
1802                                                "/lib/xml.jar", //$NON-NLS-1$
1803                                                "/lib/graphics.jar" //$NON-NLS-1$
1804                                };
1805                                addJarEntries(jreDir, jarsNames, paths);
1806                        }
1807                        jars = new String[paths.size()];
1808                        paths.toArray(jars);
1809                }
1810                return jars;
1811        }
1812        /**
1813         * Makes the given path a path using native path separators as returned by File.getPath()
1814         * and trimming any extra slash.
1815         */
1816        public static String toNativePath(String path) {
1817                String nativePath = path.replace('\\', File.separatorChar).replace('/', File.separatorChar);
1818                return
1819                nativePath.endsWith("/") || nativePath.endsWith("\\") ? //$NON-NLS-1$ //$NON-NLS-2$
1820                                nativePath.substring(0, nativePath.length() - 1) :
1821                                        nativePath;
1822        }
1823 
1824        private static void addJarEntries(String jreDir, String[] jarNames, ArrayList paths) {
1825                for (int i = 0, max = jarNames.length; i < max; i++) {
1826                        final String currentName = jreDir + jarNames[i];
1827                        File f = new File(currentName);
1828                        if (f.exists()) {
1829                                paths.add(toNativePath(currentName));
1830                        }
1831                }
1832        }
1833        /**
1834         * Delete a file or directory and insure that the file is no longer present
1835         * on file system. In case of directory, delete all the hierarchy underneath.
1836         *
1837         * @param file The file or directory to delete
1838         * @return true iff the file was really delete, false otherwise
1839         */
1840        public static boolean delete(File file) {
1841                if (!file.exists()) {
1842                        return true;
1843                }
1844                // flush all directory content
1845                if (file.isDirectory()) {
1846                        flushDirectoryContent(file);
1847                }
1848                // remove file
1849                file.delete();
1850                if (isFileDeleted(file)) {
1851                        return true;
1852                }
1853                return waitUntilFileDeleted(file);
1854        }
1855        public static void flushDirectoryContent(File dir) {
1856                File[] files = dir.listFiles();
1857                if (files == null) return;
1858                for (int i = 0, max = files.length; i < max; i++) {
1859                        delete(files[i]);
1860                }
1861        }
1862        /**
1863         * Wait until the file is _really_ deleted on file system.
1864         *
1865         * @param file Deleted file
1866         * @return true if the file was finally deleted, false otherwise
1867         */
1868        private static boolean waitUntilFileDeleted(File file) {
1869                int count = 0;
1870                int delay = 10; // ms
1871                int maxRetry = DELETE_MAX_WAIT / delay;
1872                int time = 0;
1873                while (count < maxRetry) {
1874                        try {
1875                                count++;
1876                                Thread.sleep(delay);
1877                                time += delay;
1878                                if (time > DELETE_MAX_TIME) DELETE_MAX_TIME = time;
1879                                if (DELETE_DEBUG) System.out.print('.');
1880                                if (file.exists()) {
1881                                        if (file.delete()) {
1882                                                // SUCCESS
1883                                                return true;
1884                                        }
1885                                }
1886                                if (isFileDeleted(file)) {
1887                                        // SUCCESS
1888                                        return true;
1889                                }
1890                                // Increment waiting delay exponentially
1891                                if (count >= 10 && delay <= 100) {
1892                                        count = 1;
1893                                        delay *= 10;
1894                                        maxRetry = DELETE_MAX_WAIT / delay;
1895                                        if ((DELETE_MAX_WAIT%delay) != 0) {
1896                                                maxRetry++;
1897                                        }
1898                                }
1899                        }
1900                        catch (InterruptedException ie) {
1901                                break; // end loop
1902                        }
1903                }
1904                System.err.println();
1905                System.err.println("        !!! ERROR: "+file+" was never deleted even after having waited "+DELETE_MAX_TIME+"ms!!!"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1906                System.err.println();
1907                return false;
1908        }
1909        /**
1910         * Returns whether a file is really deleted or not.
1911         * Does not only rely on {@link File#exists()} method but also
1912         * look if it's not in its parent children {@link #getParentChildFile(File)}.
1913         *
1914         * @param file The file to test if deleted
1915         * @return true if the file does not exist and was not found in its parent children.
1916         */
1917        public static boolean isFileDeleted(File file) {
1918                return !file.exists() && getParentChildFile(file) == null;
1919        }
1920        /**
1921         * Returns the parent's child file matching the given file or null if not found.
1922         *
1923         * @param file The searched file in parent
1924         * @return The parent's child matching the given file or null if not found.
1925         */
1926        private static File getParentChildFile(File file) {
1927                File parent = file.getParentFile();
1928                if (parent == null || !parent.exists()) return null;
1929                File[] files = parent.listFiles();
1930                int length = files==null ? 0 : files.length;
1931                if (length > 0) {
1932                        for (int i=0; i<length; i++) {
1933                                if (files[i] == file) {
1934                                        return files[i];
1935                                } else if (files[i].equals(file)) {
1936                                        return files[i];
1937                                } else if (files[i].getPath().equals(file.getPath())) {
1938                                        return files[i];
1939                                }
1940                        }
1941                }
1942                return null;
1943        }
1944 
1945        /**
1946         * Turns the given array of strings into a {@link HashSet}
1947         * @param values
1948         * @return a new {@link HashSet} of the string array
1949         */
1950        public static Set convertAsSet(String[] values) {
1951                Set set = new HashSet();
1952                if (values != null && values.length != 0) {
1953                        for (int i = 0, max = values.length; i < max; i++) {
1954                                set.add(values[i]);
1955                        }
1956                }
1957                return set;
1958        }
1959 
1960        /**
1961         * Returns an identifier for the given API component including its version identifier
1962         * (component id + '(' + major + . + minor + . + micro + ')' )
1963         *  
1964         * @param component API component
1965         * @return API component + version identifier
1966         */
1967        public static String getDeltaComponentVersionsId(IApiComponent component) {
1968                StringBuffer buffer = new StringBuffer(component.getId());
1969                String version = component.getVersion();
1970                // remove the qualifier part
1971                if (version != null) {
1972                        buffer.append('(');
1973                        try {
1974                                Version version2 = new Version(version);
1975                                buffer
1976                                        .append(version2.getMajor())
1977                                        .append('.')
1978                                        .append(version2.getMinor())
1979                                        .append('.')
1980                                        .append(version2.getMicro());
1981                        } catch (IllegalArgumentException e) {
1982                                // the version string doesn't follow the Eclipse pattern
1983                                // we keep the version as is
1984                                buffer.append(version);
1985                        }
1986                        buffer.append(')');
1987                }
1988                return String.valueOf(buffer);
1989        }
1990        /**
1991         * Returns an identifier for the given API component including its version identifier
1992         * (component id + _ + major + _ + minor + _ + micro)
1993         *  
1994         * @param component API component
1995         * @return API component + version identifier
1996         */
1997        public static String getComponentVersionsId(IApiComponent component) {
1998                StringBuffer buffer = new StringBuffer(component.getId());
1999                String version = component.getVersion();
2000                // remove the qualifier part
2001                if (version != null) {
2002                        buffer.append('_');
2003                        try {
2004                                Version version2 = new Version(version);
2005                                buffer
2006                                        .append(version2.getMajor())
2007                                        .append('.')
2008                                        .append(version2.getMinor())
2009                                        .append('.')
2010                                        .append(version2.getMicro());
2011                        } catch (IllegalArgumentException e) {
2012                                // the version string doesn't follow the Eclipse pattern
2013                                // we keep the version as is
2014                                buffer.append(version);
2015                        }
2016                }
2017                return String.valueOf(buffer);
2018        }
2019        public static String getDescriptorName(IApiType descriptor) {
2020                String typeName = descriptor.getName();
2021                int index = typeName.lastIndexOf('$');
2022                if (index != -1) {
2023                        return typeName.replace('$', '.');
2024                }
2025                return typeName;
2026        }
2027 
2028        public static String getDeltaArgumentString(IDelta delta) {
2029                String[] arguments = delta.getArguments();
2030                switch(delta.getFlags()) {
2031                        case IDelta.TYPE_MEMBER :
2032                        case IDelta.TYPE :
2033                                return arguments[0];
2034                        case IDelta.METHOD :
2035                        case IDelta.CONSTRUCTOR :
2036                        case IDelta.ENUM_CONSTANT :
2037                        case IDelta.METHOD_WITH_DEFAULT_VALUE :
2038                        case IDelta.METHOD_WITHOUT_DEFAULT_VALUE :
2039                        case IDelta.FIELD :
2040                                return arguments[1];
2041                        case IDelta.INCREASE_ACCESS :
2042                                switch(delta.getElementType()) {
2043                                        case IDelta.FIELD_ELEMENT_TYPE :
2044                                        case IDelta.METHOD_ELEMENT_TYPE :
2045                                        case IDelta.CONSTRUCTOR_ELEMENT_TYPE :
2046                                                return arguments[1];
2047                                        default:
2048                                                return arguments[0];
2049                                }
2050                }
2051                return EMPTY_STRING;
2052        }
2053        
2054        /**
2055         * Returns the string representation of the {@link IApiElement} type
2056         * @param type
2057         * @return the string of the {@link IApiElement} type
2058         */
2059        public static String getApiElementType(int type) {
2060                switch(type) {
2061                        case IApiElement.API_TYPE_CONTAINER :
2062                                return "API_TYPE_CONTAINER"; //$NON-NLS-1$
2063                        case IApiElement.API_TYPE_ROOT :
2064                                return "API_TYPE_ROOT"; //$NON-NLS-1$
2065                        case IApiElement.BASELINE :
2066                                return "BASELINE"; //$NON-NLS-1$
2067                        case IApiElement.COMPONENT :
2068                                return "COMPONENT"; //$NON-NLS-1$
2069                        case IApiElement.FIELD :
2070                                return "FIELD"; //$NON-NLS-1$
2071                        case IApiElement.METHOD :
2072                                return "METHOD"; //$NON-NLS-1$
2073                        case IApiElement.TYPE :
2074                                return "TYPE"; //$NON-NLS-1$
2075                        default:
2076                                return "UNKNOWN"; //$NON-NLS-1$
2077                }
2078        }
2079 
2080        public static boolean isConstructor(String referenceMemberName) {
2081                return Arrays.equals(ConstantPool.Init, referenceMemberName.toCharArray());
2082        }
2083        
2084        public static boolean isManifest(IPath path) {
2085                return MANIFEST_PROJECT_RELATIVE_PATH.equals(path);
2086        }
2087        public static void touchCorrespondingResource(IProject project, IResource resource, String typeName) {
2088                if (typeName != null && typeName != ApiFilterStore.GLOBAL) {
2089                        if (Util.isManifest(resource.getProjectRelativePath())) {
2090                                try {
2091                                        IJavaProject javaProject = JavaCore.create(project);
2092                                        IType findType = javaProject.findType(typeName);
2093                                        if (findType != null) {
2094                                                ICompilationUnit compilationUnit = findType.getCompilationUnit();
2095                                                if (compilationUnit != null) {
2096                                                        IResource cuResource = compilationUnit.getResource();
2097                                                        if (cuResource != null) {
2098                                                                cuResource.touch(null);
2099                                                        }
2100                                                }
2101                                        }
2102                                } catch (JavaModelException e) {
2103                                        ApiPlugin.log(e);
2104                                } catch (CoreException e) {
2105                                        ApiPlugin.log(e);
2106                                }
2107                        } else {
2108                                try {
2109                                        resource.touch(null);
2110                                } catch (CoreException e) {
2111                                        ApiPlugin.log(e);
2112                                }
2113                        }
2114                }
2115        }
2116        public static String getTypeNameFromMarker(IMarker marker) {
2117                return marker.getAttribute(IApiMarkerConstants.MARKER_ATTR_PROBLEM_TYPE_NAME, null);
2118        }
2119        
2120        public static IApiComponent[] getReexportedComponents(IApiComponent component) {
2121                try {
2122                        IRequiredComponentDescription[] requiredComponents = component.getRequiredComponents();
2123                        int length = requiredComponents.length;
2124                        if (length != 0) {
2125                                List reexportedComponents = null;
2126                                IApiBaseline baseline = component.getBaseline();
2127                                for (int i = 0; i < length; i++) {
2128                                        IRequiredComponentDescription description = requiredComponents[i];
2129                                        if (description.isExported()) {
2130                                                String id = description.getId();
2131                                                IApiComponent reexportedComponent = baseline.getApiComponent(id);
2132                                                if (reexportedComponent != null) {
2133                                                        if (reexportedComponents == null) {
2134                                                                reexportedComponents = new ArrayList();
2135                                                        }
2136                                                        reexportedComponents.add(reexportedComponent);
2137                                                }
2138                                        }
2139                                }
2140                                if (reexportedComponents == null || reexportedComponents.size() == 0) {
2141                                        return null;
2142                                }
2143                                return (IApiComponent[]) reexportedComponents.toArray(new IApiComponent[reexportedComponents.size()]);
2144                        }
2145                } catch (CoreException e) {
2146                        ApiPlugin.log(e);
2147                }
2148                return null;
2149        }
2150 
2151        /**
2152         * Returns the {@link IResource} to create markers on when building. If the {@link IType} is <code>null</code>
2153         * or the type cannot be located (does not exist) than the MANIFEST.MF will be returned.
2154         * @param project the project to look in for the {@link IResource}
2155         * @param type the type we are looking for the resource for, or <code>null</code>
2156         * @return the {@link IResource} associated with the given {@link IType} or the MANIFEST.MF file
2157         */
2158        public static IResource getResource(IProject project, IType type) {
2159                IResource resource = null;
2160                try {
2161                        if (type == null) {
2162                                IResource manifestFile = Util.getManifestFile(project);
2163                                if (manifestFile == null) {
2164                                        // Cannot retrieve the manifest.mf file
2165                                        return null;
2166                                }
2167                                resource = manifestFile;
2168                        } else {
2169                                ICompilationUnit unit = type.getCompilationUnit();
2170                                if (unit != null) {
2171                                        resource = unit.getCorrespondingResource();
2172                                        if (resource == null) {
2173                                                return null;
2174                                        }
2175                                        if (project.findMember(resource.getProjectRelativePath()) == null) {
2176                                                resource = null;
2177                                                IResource manifestFile = Util.getManifestFile(project);
2178                                                if (manifestFile == null) {
2179                                                        // Cannot retrieve the manifest.mf file
2180                                                        return null;
2181                                                }
2182                                                resource = manifestFile;
2183                                        }
2184                                } else {
2185                                        IResource manifestFile = Util.getManifestFile(project);
2186                                        if (manifestFile == null) {
2187                                                // Cannot retrieve the manifest.mf file
2188                                                return null;
2189                                        }
2190                                        resource = manifestFile;
2191                                }
2192                        }
2193                } catch (JavaModelException e) {
2194                        ApiPlugin.log(e);
2195                }
2196                return resource;
2197        }
2198 
2199        /**
2200         * Default comparator that orders {@link IApiComponent} by their ID 
2201         */
2202        public static final Comparator componentsorter = new Comparator(){
2203                public int compare(Object o1, Object o2) {
2204                        if(o1 instanceof IApiComponent && o2 instanceof IApiComponent) {
2205                                return ((IApiComponent)o1).getId().compareTo(((IApiComponent)o2).getId());
2206                        }
2207                        if(o1 instanceof SkippedComponent && o2 instanceof SkippedComponent) {
2208                                return ((SkippedComponent)o1).getComponentId().compareTo(((SkippedComponent)o2).getComponentId());
2209                        }
2210                        if(o1 instanceof String && o2 instanceof String) {
2211                                return ((String)o1).compareTo((String)o2);
2212                        }
2213                        return -1;
2214                }
2215        };
2216 
2217        /**
2218         * Initializes the exclude set with regex support. The API baseline is used to determine which
2219         * bundles should be added to the list when processing regex expressions.
2220         * 
2221         * @param location
2222         * @param baseline
2223         * @return the list of bundles to be excluded
2224         */
2225        public static Set initializeRegexExcludeList(String location, IApiBaseline baseline) {
2226                HashSet list = new HashSet();
2227                if (location != null) {
2228                        File file = new File(location);
2229                        if (file.exists()) {
2230                                InputStream stream = null;
2231                                char[] contents = null;
2232                                try {
2233                                        stream = new BufferedInputStream(new FileInputStream(file));
2234                                        contents = getInputStreamAsCharArray(stream, -1, ISO_8859_1);
2235                                } 
2236                                catch (FileNotFoundException e) {} 
2237                                catch (IOException e) {} 
2238                                finally {
2239                                        if (stream != null) {
2240                                                try {
2241                                                        stream.close();
2242                                                } catch (IOException e) {}
2243                                        }
2244                                }
2245                                if (contents != null) {
2246                                        LineNumberReader reader = new LineNumberReader(new StringReader(new String(contents)));
2247                                        String line = null;
2248                                        try {
2249                                                while ((line = reader.readLine()) != null) {
2250                                                        if (line.startsWith("#") || line.length() == 0) { //$NON-NLS-1$
2251                                                                continue; 
2252                                                        }
2253                                                        if(line.startsWith(REGULAR_EXPRESSION_START)) {
2254                                                                if(baseline != null) {
2255                                                                        Util.collectRegexIds(line, list, baseline.getApiComponents());
2256                                                                }
2257                                                        }
2258                                                        else {
2259                                                                list.add(line);
2260                                                        }
2261                                                }
2262                                        } 
2263                                        catch (IOException e) {} 
2264                                        catch (Exception e) {} 
2265                                        finally {
2266                                                try {
2267                                                        reader.close();
2268                                                } catch (IOException e) {}
2269                                        }
2270                                }
2271                        }
2272                }
2273                return list;
2274        }
2275 
2276        /**
2277         * Collects the set of component ids that match a given regex in the exclude file
2278         * @param line
2279         * @param list
2280         * @param components
2281         */
2282        public static void collectRegexIds(String line, Set list, IApiComponent[] components) throws Exception {
2283                if (line.startsWith(REGULAR_EXPRESSION_START)) {
2284                        String componentname = line;
2285                        // regular expression
2286                        componentname = componentname.substring(2);
2287                        Pattern pattern = null;
2288                        try {
2289                                pattern = Pattern.compile(componentname);
2290                                String componentid = null;
2291                                for (int j = 0, max2 = components.length; j < max2; j++) {
2292                                        componentid = components[j].getId();
2293                                        if (pattern.matcher(componentid).matches()) {
2294                                                list.add(componentid);
2295                                        }
2296                                }
2297                        } catch (PatternSyntaxException e) {
2298                                throw new Exception(NLS.bind(
2299                                                UtilMessages.comparison_invalidRegularExpression,
2300                                                componentname));
2301                        }
2302                }
2303        }
2304 
2305        /**
2306         * Default comparator that orders {@link File}s by their name
2307         */
2308        public static final Comparator filesorter = new Comparator(){
2309                public int compare(Object o1, Object o2) {
2310                        if(o1 instanceof File && o2 instanceof File) {
2311                                return ((File)o1).getName().compareTo(((File)o2).getName());
2312                        }
2313                        return 0;
2314                }
2315        };
2316 
2317        /**
2318         * Returns true if the given {@link IApiType} is API or not, where API is defined
2319         * as having API visibility in an API description and having either the public of protected 
2320         * Java flag set
2321         * 
2322         * @param visibility
2323         * @param typeDescriptor
2324         * @return true if the given type is API, false otherwise
2325         */
2326        public static boolean isAPI(int visibility, IApiType typeDescriptor) {
2327                int access = typeDescriptor.getModifiers();
2328                return VisibilityModifiers.isAPI(visibility) && (Flags.isPublic(access) || Flags.isProtected(access));
2329        }
2330}

[all classes][org.eclipse.pde.api.tools.internal.util]
EMMA 2.0.5312 EclEmma Fix 1 (C) Vladimir Roubtsov