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

COVERAGE SUMMARY FOR SOURCE FILE [BuildState.java]

nameclass, %method, %block, %line, %
BuildState.java100% (1/1)100% (20/20)78%  (667/853)80%  (169.2/211)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class BuildState100% (1/1)100% (20/20)78%  (667/853)80%  (169.2/211)
readState (IProject): BuildState 100% (1/1)27%  (28/105)31%  (5.3/17)
saveBuiltState (IProject, BuildState): void 100% (1/1)31%  (32/102)33%  (9.2/28)
getLastBuiltState (IProject): BuildState 100% (1/1)75%  (6/8)67%  (2/3)
setLastBuiltState (IProject, BuildState): void 100% (1/1)78%  (18/23)75%  (6/8)
read (DataInputStream): BuildState 100% (1/1)81%  (84/104)79%  (20.7/26)
getSerializationFile (IProject): File 100% (1/1)86%  (12/14)75%  (3/4)
readDelta (DataInputStream): IDelta 100% (1/1)89%  (85/95)91%  (21/23)
<static initializer> 100% (1/1)100% (7/7)100% (3/3)
BuildState (): void 100% (1/1)100% (13/13)100% (4/4)
addApiToolingDependentProject (String): void 100% (1/1)100% (15/15)100% (4/4)
addBreakingChange (IDelta): void 100% (1/1)100% (31/31)100% (8/8)
addCompatibleChange (IDelta): void 100% (1/1)100% (31/31)100% (8/8)
cleanup (String): void 100% (1/1)100% (14/14)100% (4/4)
getApiToolingDependentProjects (): Set 100% (1/1)100% (8/8)100% (1/1)
getBreakingChanges (): IDelta [] 100% (1/1)100% (37/37)100% (7/7)
getCompatibleChanges (): IDelta [] 100% (1/1)100% (37/37)100% (7/7)
getReexportedComponents (): String [] 100% (1/1)100% (8/8)100% (3/3)
setReexportedComponents (IApiComponent []): void 100% (1/1)100% (30/30)100% (9/9)
write (BuildState, DataOutputStream): void 100% (1/1)100% (97/97)100% (25/25)
writeDelta (IDelta, DataOutputStream): void 100% (1/1)100% (74/74)100% (19/19)

1/*******************************************************************************
2 * Copyright (c) 2008, 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.builder;
12 
13import java.io.BufferedInputStream;
14import java.io.BufferedOutputStream;
15import java.io.DataInputStream;
16import java.io.DataOutputStream;
17import java.io.File;
18import java.io.FileInputStream;
19import java.io.FileOutputStream;
20import java.io.IOException;
21import java.util.ArrayList;
22import java.util.Collection;
23import java.util.Collections;
24import java.util.HashMap;
25import java.util.HashSet;
26import java.util.Iterator;
27import java.util.Map;
28import java.util.Set;
29 
30import org.eclipse.core.resources.IProject;
31import org.eclipse.core.runtime.CoreException;
32import org.eclipse.core.runtime.IPath;
33import org.eclipse.core.runtime.IStatus;
34import org.eclipse.core.runtime.Platform;
35import org.eclipse.core.runtime.Status;
36import org.eclipse.jdt.core.JavaCore;
37import org.eclipse.osgi.util.NLS;
38import org.eclipse.pde.api.tools.internal.comparator.Delta;
39import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
40import org.eclipse.pde.api.tools.internal.provisional.comparator.IDelta;
41import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent;
42import org.eclipse.pde.api.tools.internal.util.Util;
43 
44/**
45 * The API tools build state
46 * 
47 * @since 1.0.1
48 */
49public class BuildState {
50        private static final IDelta[] EMPTY_DELTAS = new IDelta[0];
51        private static final String[] NO_REEXPORTED_COMPONENTS = new String[0];
52        private static final int VERSION = 0x10;
53        
54        private Map compatibleChanges;
55        private Map breakingChanges;
56        private String[] reexportedComponents;
57        private Set apiToolingDependentProjects;
58        
59        /**
60         * Constructor
61         */
62        BuildState() {
63                this.compatibleChanges = new HashMap();
64                this.breakingChanges = new HashMap();
65        }
66        
67        /**
68         * Reads the build state from an input stream
69         * @param in
70         * @return the {@link BuildState} from the given input stream
71         * @throws IOException
72         */
73         public static BuildState read(DataInputStream in) throws IOException {
74                String pluginID= in.readUTF();
75                if (!pluginID.equals(ApiPlugin.PLUGIN_ID)) {
76                        throw new IOException(BuilderMessages.build_wrongFileFormat);
77                }
78                String kind= in.readUTF();
79                if (!kind.equals("STATE")) {//$NON-NLS-1$
80                        throw new IOException(BuilderMessages.build_wrongFileFormat);
81                }
82                if (in.readInt() != VERSION) {
83                        // this is an old build state - a full build is required
84                        return null;
85                }
86                if (in.readBoolean()) {
87                        // continue to read
88                        BuildState state = new BuildState();
89                        int numberOfCompatibleDeltas = in.readInt();
90                        // read all compatible deltas
91                        for (int i = 0; i < numberOfCompatibleDeltas; i++) {
92                                state.addCompatibleChange(readDelta(in));
93                        }
94                        int numberOfBreakingDeltas = in.readInt();
95                        // read all breaking deltas
96                        for (int i = 0; i < numberOfBreakingDeltas; i++) {
97                                state.addBreakingChange(readDelta(in));
98                        }
99                        int numberOfReexportedComponents = in.readInt();
100                        // read all reexported component names
101                        String[] components = new String[numberOfReexportedComponents];
102                        for (int i = 0; i < numberOfReexportedComponents; i++) {
103                                components[i] = in.readUTF();
104                        }
105                        state.reexportedComponents = components;
106                        int numberOfApiToolingDependents = in.readInt();
107                        for (int i = 0; i < numberOfApiToolingDependents; i++) {
108                                state.addApiToolingDependentProject(in.readUTF());
109                        }
110                        return state;
111                }
112                return null;
113        }
114         
115        /**
116         * Writes the given {@link BuildState} to the given output stream
117         * @param state
118         * @param out
119         * @throws IOException
120         */
121        public static void write(BuildState state, DataOutputStream out) throws IOException {
122                out.writeUTF(ApiPlugin.PLUGIN_ID);
123                out.writeUTF("STATE"); //$NON-NLS-1$
124                out.writeInt(VERSION);
125                out.writeBoolean(true);
126                IDelta[] compatibleChangesDeltas = state.getCompatibleChanges();
127                int length = compatibleChangesDeltas.length;
128                out.writeInt(length);
129                for (int i = 0; i < length; i++) {
130                        writeDelta(compatibleChangesDeltas[i], out);
131                }
132                IDelta[] breakingChangesDeltas = state.getBreakingChanges();
133                length = breakingChangesDeltas.length;
134                out.writeInt(length);
135                for (int i = 0; i < length; i++) {
136                        writeDelta(breakingChangesDeltas[i], out);
137                }
138                String[] reexportedComponents = state.getReexportedComponents();
139                length = reexportedComponents.length;
140                out.writeInt(length);
141                for (int i = 0; i < length; i++) {
142                        out.writeUTF(reexportedComponents[i]);
143                }
144                Set apiToolingDependentsProjects = state.getApiToolingDependentProjects();
145                length = apiToolingDependentsProjects.size();
146                out.writeInt(length);
147                for (Iterator iterator = apiToolingDependentsProjects.iterator(); iterator.hasNext(); ) {
148                        out.writeUTF((String) iterator.next());
149                }
150        }
151        
152        /**
153         * Read the {@link IDelta} from the build state (input stream)
154         * @param in the input stream to read the {@link IDelta} from
155         * @return a reconstructed {@link IDelta} from the build state
156         * @throws IOException
157         */
158        private static IDelta readDelta(DataInputStream in) throws IOException {
159                // decode the delta from the build state
160                boolean hasComponentID = in.readBoolean();
161                String componentID = null;
162                if (hasComponentID) in.readUTF(); // delta.getComponentID()
163                int elementType = in.readInt(); // delta.getElementType()
164                int kind = in.readInt(); // delta.getKind()
165                int flags = in.readInt(); // delta.getFlags()
166                int restrictions = in.readInt(); // delta.getRestrictions()
167                int modifiers = in.readInt(); // delta.getModifiers()
168                String typeName = in.readUTF(); // delta.getTypeName()
169                String key = in.readUTF(); // delta.getKey()
170                int length = in.readInt(); // arguments.length;
171                String[] datas = null;
172                if (length != 0) {
173                        ArrayList arguments = new ArrayList();
174                        for (int i = 0; i < length; i++) {
175                                arguments.add(in.readUTF());
176                        }
177                        datas = new String[length];
178                        arguments.toArray(datas);
179                } else {
180                        datas = new String[1];
181                        datas[0] = typeName.replace('$', '.');
182                }
183                int oldModifiers = modifiers & Delta.MODIFIERS_MASK;
184                int newModifiers = modifiers >>> Delta.NEW_MODIFIERS_OFFSET;
185                return new Delta(componentID, elementType, kind, flags, restrictions, oldModifiers, newModifiers, typeName, key, datas);
186        }
187        
188        /**
189         * Writes a given {@link IDelta} to the build state (the output stream)
190         * @param delta the delta to write
191         * @param out the stream to write to
192         * @throws IOException
193         */
194        private static void writeDelta(IDelta delta, DataOutputStream out) throws IOException {
195                // encode a delta into the build state
196                // int elementType, int kind, int flags, int restrictions, int modifiers, String typeName, String key, Object data
197                String apiComponentID = delta.getComponentVersionId();
198                boolean hasComponentID = apiComponentID != null;
199                out.writeBoolean(hasComponentID);
200                if (hasComponentID) {
201                        out.writeUTF(apiComponentID);
202                }
203                out.writeInt(delta.getElementType());
204                out.writeInt(delta.getKind());
205                out.writeInt(delta.getFlags());
206                out.writeInt(delta.getRestrictions());
207                int modifiers = (delta.getNewModifiers() << Delta.NEW_MODIFIERS_OFFSET) | delta.getOldModifiers();
208                out.writeInt(modifiers);
209                out.writeUTF(delta.getTypeName());
210                out.writeUTF(delta.getKey());
211                String[] arguments = delta.getArguments();
212                int length = arguments.length;
213                out.writeInt(length);
214                for (int i = 0; i < length; i++) {
215                        out.writeUTF(arguments[i]);
216                }
217        }
218 
219        /**
220         * Adds an {@link IDelta} for a compatible compatibility change to the current state
221         * 
222         * @param delta the {@link IDelta} to add to the state
223         */
224        public void addCompatibleChange(IDelta delta) {
225                String typeName = delta.getTypeName();
226                Set object = (Set) this.compatibleChanges.get(typeName);
227                if (object == null) {
228                        Set changes = new HashSet();
229                        changes.add(delta);
230                        this.compatibleChanges.put(typeName, changes);
231                } else {
232                        object.add(delta);
233                }
234        }
235 
236        /**
237         * Add an {@link IDelta} for an incompatible compatibility change to the current state
238         * 
239         * @param delta the {@link IDelta} to add to the state
240         */
241        public void addBreakingChange(IDelta delta) {
242                String typeName = delta.getTypeName();
243                Set object = (Set) this.breakingChanges.get(typeName);
244                if (object == null) {
245                        Set changes = new HashSet();
246                        changes.add(delta);
247                        this.breakingChanges.put(typeName, changes);
248                } else {
249                        object.add(delta);
250                }
251        }
252        
253        /**
254         * @return the complete list of recorded breaking changes with duplicates removed, or 
255         * an empty array, never <code>null</code>
256         */
257        public IDelta[] getBreakingChanges() {
258                if (this.breakingChanges == null || this.breakingChanges.size() == 0) {
259                        return EMPTY_DELTAS;
260                }
261                HashSet collector = new HashSet();
262                Collection values = this.breakingChanges.values();
263                for (Iterator iterator = values.iterator(); iterator.hasNext(); ) {
264                        collector.addAll((HashSet) iterator.next());
265                }
266                return (IDelta[]) collector.toArray(new IDelta[collector.size()]);
267        }
268 
269        /**
270         * @return the complete list of recorded compatible changes with duplicates removed,
271         * or an empty array, never <code>null</code>
272         */
273        public IDelta[] getCompatibleChanges() {
274                if (this.compatibleChanges == null || this.compatibleChanges.size() == 0) {
275                        return EMPTY_DELTAS;
276                }
277                HashSet collector = new HashSet();
278                Collection values = this.compatibleChanges.values();
279                for (Iterator iterator = values.iterator(); iterator.hasNext(); ) {
280                        collector.addAll((HashSet) iterator.next());
281                }
282                return (IDelta[]) collector.toArray(new IDelta[collector.size()]);
283        }
284 
285        /**
286         * @return the complete list of re-exported {@link IApiComponent}s
287         */
288        public String[] getReexportedComponents() {
289                if (this.reexportedComponents == null) {
290                        return NO_REEXPORTED_COMPONENTS;
291                }
292                return this.reexportedComponents;
293        }
294        
295        /**
296         * Remove all entries for the given type name.
297         *
298         * @param typeName the given type name
299         */
300        public void cleanup(String typeName) {
301                this.breakingChanges.remove(typeName);
302                this.compatibleChanges.remove(typeName);
303                this.reexportedComponents = null;
304        }
305 
306        /**
307         * Sets the current list if re-exported {@link IApiComponent}s for this build state
308         * @param components
309         */
310        public void setReexportedComponents(IApiComponent[] components) {
311                if (components == null) {
312                        return;
313                }
314                if (this.reexportedComponents == null) {
315                        final int length = components.length;
316                        String[] result = new String[length];
317                        for (int i = 0; i < length; i++) {
318                                result[i] = components[i].getId();
319                        }
320                        this.reexportedComponents = result;
321                }
322        }
323 
324        /**
325         * Adds a dependent project to the listing of dependent projects
326         * @param projectName
327         */
328        public void addApiToolingDependentProject(String projectName) {
329                if (this.apiToolingDependentProjects == null) {
330                        this.apiToolingDependentProjects = new HashSet(3);
331                }
332                this.apiToolingDependentProjects.add(projectName);
333        }
334        
335        /**
336         * @return the complete listing of dependent projects
337         */
338        public Set getApiToolingDependentProjects() {
339                return this.apiToolingDependentProjects == null ? Collections.EMPTY_SET : this.apiToolingDependentProjects;
340        }
341        /**
342         * Return the last built state for the given project, or null if none
343         */
344        public static BuildState getLastBuiltState(IProject project) throws CoreException {
345                if (!Util.isApiProject(project)) {
346                        // should never be requested on non-Java projects
347                        return null;
348                }
349                return readState(project);
350        }
351        
352        /**
353         * Reads the build state for the relevant project.
354         * @return the current {@link BuildState} for the given project or <code>null</code> if there is not one
355         */
356        static BuildState readState(IProject project) throws CoreException {
357                File file = getSerializationFile(project);
358                if (file != null && file.exists()) {
359                        try {
360                                DataInputStream in= new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
361                                try {
362                                        return read(in);
363                                } finally {
364                                        if (ApiAnalysisBuilder.DEBUG) {
365                                                System.out.println("Saved state thinks last build failed for " + project.getName()); //$NON-NLS-1$
366                                        }
367                                        in.close();
368                                }
369                        } catch (Exception e) {
370                                e.printStackTrace();
371                                throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, Platform.PLUGIN_ERROR, "Error reading last build state for project "+ project.getName(), e)); //$NON-NLS-1$
372                        }
373                } else if (ApiAnalysisBuilder.DEBUG) {
374                        if (file == null) {
375                                System.out.println("Project does not exist: " + project); //$NON-NLS-1$
376                        } else {
377                                System.out.println("Build state file " + file.getPath() + " does not exist"); //$NON-NLS-1$ //$NON-NLS-2$
378                        }
379                }
380                return null;
381        }
382        
383        /**
384         * Sets the last built state for the given project, or null to reset it.
385         * 
386         * @param project the project to set a state for
387         * @param state the {@link BuildState} to set as the last state
388         */
389        public static void setLastBuiltState(IProject project, BuildState state) throws CoreException {
390                if (Util.isApiProject(project)) {
391                        // should never be requested on non-Java projects
392                        if (state != null) {
393                                saveBuiltState(project, state);
394                        } else {
395                                try {
396                                        File file = getSerializationFile(project);
397                                        if (file != null && file.exists()) {
398                                                file.delete();
399                                        }
400                                } catch(SecurityException se) {
401                                        // could not delete file: cannot do much more
402                                }
403                        }
404                }
405        }
406        
407        /**
408         * Returns the {@link File} to use for saving and restoring the last built state for the given project.
409         * 
410         * @param project gets the saved state file for the given project
411         * @return the {@link File} to use for saving and restoring the last built state for the given project.
412         */
413        static File getSerializationFile(IProject project) {
414                if (!project.exists()) {
415                        return null;
416                }
417                IPath workingLocation = project.getWorkingLocation(ApiPlugin.PLUGIN_ID);
418                return workingLocation.append("state.dat").toFile(); //$NON-NLS-1$
419        }
420        
421        /**
422         * Saves the current build state
423         * @param project
424         * @param state
425         * @throws CoreException
426         */
427        static void saveBuiltState(IProject project, BuildState state) throws CoreException {
428                if (ApiAnalysisBuilder.DEBUG) {
429                        System.out.println("Saving build state for project: "+project.getName()); //$NON-NLS-1$
430                }
431                File file = BuildState.getSerializationFile(project);
432                if (file == null) return;
433                long t = 0;
434                if (ApiAnalysisBuilder.DEBUG) {
435                        t = System.currentTimeMillis();
436                }
437                try {
438                        DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
439                        try {
440                                write(state, out);
441                        } finally {
442                                out.close();
443                        }
444                } catch (RuntimeException e) {
445                        try {
446                                file.delete();
447                        } catch(SecurityException se) {
448                                // could not delete file: cannot do much more
449                        }
450                        throw new CoreException(
451                                new Status(IStatus.ERROR, ApiPlugin.PLUGIN_ID, Platform.PLUGIN_ERROR,
452                                        NLS.bind(BuilderMessages.build_cannotSaveState, project.getName()), e)); 
453                } catch (IOException e) {
454                        try {
455                                file.delete();
456                        } catch(SecurityException se) {
457                                // could not delete file: cannot do much more
458                        }
459                        throw new CoreException(
460                                new Status(IStatus.ERROR, ApiPlugin.PLUGIN_ID, Platform.PLUGIN_ERROR,
461                                        NLS.bind(BuilderMessages.build_cannotSaveState, project.getName()), e)); 
462                }
463                if (ApiAnalysisBuilder.DEBUG) {
464                        t = System.currentTimeMillis() - t;
465                        System.out.println(NLS.bind(BuilderMessages.build_saveStateComplete, String.valueOf(t))); 
466                }
467        }
468}

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