Source Code Cross Referenced for JavaModelManager.java in  » IDE-Eclipse » jdt » org » eclipse » jdt » internal » core » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Eclipse » jdt » org.eclipse.jdt.internal.core 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*******************************************************************************
0002:         * Copyright (c) 2000, 2007 IBM Corporation and others.
0003:         * All rights reserved. This program and the accompanying materials
0004:         * are made available under the terms of the Eclipse Public License v1.0
0005:         * which accompanies this distribution, and is available at
0006:         * http://www.eclipse.org/legal/epl-v10.html
0007:         *
0008:         * Contributors:
0009:         *     IBM Corporation - initial API and implementation
0010:         *     Theodora Yeung (tyeung@bea.com) - ensure that JarPackageFragmentRoot make it into cache
0011:         *                                                           before its contents
0012:         *                                                           (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=102422) 
0013:         *******************************************************************************/package org.eclipse.jdt.internal.core;
0014:
0015:        import java.io.*;
0016:        import java.net.URI;
0017:        import java.text.MessageFormat;
0018:        import java.util.*;
0019:        import java.util.Map.Entry;
0020:        import java.util.zip.ZipFile;
0021:
0022:        import javax.xml.parsers.DocumentBuilder;
0023:        import javax.xml.parsers.DocumentBuilderFactory;
0024:        import javax.xml.parsers.ParserConfigurationException;
0025:
0026:        import org.eclipse.core.resources.*;
0027:        import org.eclipse.core.runtime.*;
0028:        import org.eclipse.core.runtime.content.IContentTypeManager.ContentTypeChangeEvent;
0029:        import org.eclipse.core.runtime.content.IContentTypeManager.IContentTypeChangeListener;
0030:        import org.eclipse.core.runtime.jobs.Job;
0031:        import org.eclipse.core.runtime.preferences.DefaultScope;
0032:        import org.eclipse.core.runtime.preferences.IEclipsePreferences;
0033:        import org.eclipse.core.runtime.preferences.IPreferencesService;
0034:        import org.eclipse.core.runtime.preferences.IScopeContext;
0035:        import org.eclipse.core.runtime.preferences.InstanceScope;
0036:        import org.eclipse.jdt.core.*;
0037:        import org.eclipse.jdt.core.compiler.CharOperation;
0038:        import org.eclipse.jdt.core.compiler.CompilationParticipant;
0039:        import org.eclipse.jdt.core.compiler.IProblem;
0040:        import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
0041:        import org.eclipse.jdt.internal.codeassist.CompletionEngine;
0042:        import org.eclipse.jdt.internal.codeassist.SelectionEngine;
0043:        import org.eclipse.jdt.internal.compiler.AbstractAnnotationProcessorManager;
0044:        import org.eclipse.jdt.internal.compiler.Compiler;
0045:        import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
0046:        import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
0047:        import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
0048:        import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt;
0049:        import org.eclipse.jdt.internal.core.JavaProjectElementInfo.ProjectCache;
0050:        import org.eclipse.jdt.internal.core.builder.JavaBuilder;
0051:        import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
0052:        import org.eclipse.jdt.internal.core.search.AbstractSearchScope;
0053:        import org.eclipse.jdt.internal.core.search.BasicSearchEngine;
0054:        import org.eclipse.jdt.internal.core.search.IRestrictedAccessTypeRequestor;
0055:        import org.eclipse.jdt.internal.core.search.JavaWorkspaceScope;
0056:        import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
0057:        import org.eclipse.jdt.internal.core.search.processing.JobManager;
0058:        import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject;
0059:        import org.eclipse.jdt.internal.core.util.LRUCache;
0060:        import org.eclipse.jdt.internal.core.util.Messages;
0061:        import org.eclipse.jdt.internal.core.util.Util;
0062:        import org.eclipse.jdt.internal.core.util.WeakHashSet;
0063:        import org.eclipse.jdt.internal.core.util.WeakHashSetOfCharArray;
0064:        import org.osgi.service.prefs.BackingStoreException;
0065:        import org.w3c.dom.Element;
0066:        import org.w3c.dom.Node;
0067:        import org.w3c.dom.NodeList;
0068:        import org.xml.sax.InputSource;
0069:        import org.xml.sax.SAXException;
0070:
0071:        /**
0072:         * The <code>JavaModelManager</code> manages instances of <code>IJavaModel</code>.
0073:         * <code>IElementChangedListener</code>s register with the <code>JavaModelManager</code>,
0074:         * and receive <code>ElementChangedEvent</code>s for all <code>IJavaModel</code>s.
0075:         * <p>
0076:         * The single instance of <code>JavaModelManager</code> is available from
0077:         * the static method <code>JavaModelManager.getJavaModelManager()</code>.
0078:         */
0079:        public class JavaModelManager implements  ISaveParticipant,
0080:                IContentTypeChangeListener {
0081:
0082:            /**
0083:             * Unique handle onto the JavaModel
0084:             */
0085:            final JavaModel javaModel = new JavaModel();
0086:
0087:            /**
0088:             * Classpath variables pool
0089:             */
0090:            public HashMap variables = new HashMap(5);
0091:            public HashSet variablesWithInitializer = new HashSet(5);
0092:            public HashMap deprecatedVariables = new HashMap(5);
0093:            public HashSet readOnlyVariables = new HashSet(5);
0094:            public HashMap previousSessionVariables = new HashMap(5);
0095:            private ThreadLocal variableInitializationInProgress = new ThreadLocal();
0096:
0097:            /**
0098:             * Classpath containers pool
0099:             */
0100:            public HashMap containers = new HashMap(5);
0101:            public HashMap previousSessionContainers = new HashMap(5);
0102:            private ThreadLocal containerInitializationInProgress = new ThreadLocal();
0103:            public boolean batchContainerInitializations = false;
0104:            public ThreadLocal batchContainerInitializationsProgress = new ThreadLocal();
0105:            public HashMap containerInitializersCache = new HashMap(5);
0106:
0107:            /*
0108:             * A HashSet that contains the IJavaProject whose classpath is being resolved.
0109:             */
0110:            private ThreadLocal classpathsBeingResolved = new ThreadLocal();
0111:
0112:            /*
0113:             * The unique workspace scope
0114:             */
0115:            public JavaWorkspaceScope workspaceScope;
0116:
0117:            /*
0118:             * Pools of symbols used in the Java model.
0119:             * Used as a replacement for String#intern() that could prevent garbage collection of strings on some VMs.
0120:             */
0121:            private WeakHashSet stringSymbols = new WeakHashSet(5);
0122:            private WeakHashSetOfCharArray charArraySymbols = new WeakHashSetOfCharArray(
0123:                    5);
0124:
0125:            /*
0126:             * Extension used to construct Java 6 annotation processor managers
0127:             */
0128:            private IConfigurationElement annotationProcessorManagerFactory = null;
0129:
0130:            /* 
0131:             * Map from a package fragment root's path to a source attachment property (source path + ATTACHMENT_PROPERTY_DELIMITER + source root path)
0132:             */
0133:            public Map rootPathToAttachments = new HashMap();
0134:
0135:            public final static String CP_VARIABLE_PREFERENCES_PREFIX = JavaCore.PLUGIN_ID
0136:                    + ".classpathVariable."; //$NON-NLS-1$
0137:            public final static String CP_CONTAINER_PREFERENCES_PREFIX = JavaCore.PLUGIN_ID
0138:                    + ".classpathContainer."; //$NON-NLS-1$
0139:            public final static String CP_USERLIBRARY_PREFERENCES_PREFIX = JavaCore.PLUGIN_ID
0140:                    + ".userLibrary."; //$NON-NLS-1$
0141:            public final static String CP_ENTRY_IGNORE = "##<cp entry ignore>##"; //$NON-NLS-1$
0142:            public final static IPath CP_ENTRY_IGNORE_PATH = new Path(
0143:                    CP_ENTRY_IGNORE);
0144:            public final static String TRUE = "true"; //$NON-NLS-1$
0145:
0146:            private final static int VARIABLES_AND_CONTAINERS_FILE_VERSION = 2;
0147:
0148:            /**
0149:             * Name of the extension point for contributing classpath variable initializers
0150:             */
0151:            public static final String CPVARIABLE_INITIALIZER_EXTPOINT_ID = "classpathVariableInitializer"; //$NON-NLS-1$
0152:
0153:            /**
0154:             * Name of the extension point for contributing classpath container initializers
0155:             */
0156:            public static final String CPCONTAINER_INITIALIZER_EXTPOINT_ID = "classpathContainerInitializer"; //$NON-NLS-1$
0157:
0158:            /**
0159:             * Name of the extension point for contributing a source code formatter
0160:             */
0161:            public static final String FORMATTER_EXTPOINT_ID = "codeFormatter"; //$NON-NLS-1$
0162:
0163:            /**
0164:             * Name of the extension point for contributing a compilation participant
0165:             */
0166:            public static final String COMPILATION_PARTICIPANT_EXTPOINT_ID = "compilationParticipant"; //$NON-NLS-1$
0167:
0168:            /**
0169:             * Name of the extension point for contributing the Java 6 annotation processor manager
0170:             */
0171:            public static final String ANNOTATION_PROCESSOR_MANAGER_EXTPOINT_ID = "annotationProcessorManager"; //$NON-NLS-1$
0172:
0173:            /**
0174:             * Special value used for recognizing ongoing initialization and breaking initialization cycles
0175:             */
0176:            public final static IPath VARIABLE_INITIALIZATION_IN_PROGRESS = new Path(
0177:                    "Variable Initialization In Progress"); //$NON-NLS-1$
0178:            public final static IClasspathContainer CONTAINER_INITIALIZATION_IN_PROGRESS = new IClasspathContainer() {
0179:                public IClasspathEntry[] getClasspathEntries() {
0180:                    return null;
0181:                }
0182:
0183:                public String getDescription() {
0184:                    return "Container Initialization In Progress";} //$NON-NLS-1$
0185:
0186:                public int getKind() {
0187:                    return 0;
0188:                }
0189:
0190:                public IPath getPath() {
0191:                    return null;
0192:                }
0193:
0194:                public String toString() {
0195:                    return getDescription();
0196:                }
0197:            };
0198:
0199:            private static final String BUFFER_MANAGER_DEBUG = JavaCore.PLUGIN_ID
0200:                    + "/debug/buffermanager"; //$NON-NLS-1$
0201:            private static final String INDEX_MANAGER_DEBUG = JavaCore.PLUGIN_ID
0202:                    + "/debug/indexmanager"; //$NON-NLS-1$
0203:            private static final String COMPILER_DEBUG = JavaCore.PLUGIN_ID
0204:                    + "/debug/compiler"; //$NON-NLS-1$
0205:            private static final String JAVAMODEL_DEBUG = JavaCore.PLUGIN_ID
0206:                    + "/debug/javamodel"; //$NON-NLS-1$
0207:            private static final String JAVAMODELCACHE_DEBUG = JavaCore.PLUGIN_ID
0208:                    + "/debug/javamodel/cache"; //$NON-NLS-1$
0209:            private static final String CP_RESOLVE_DEBUG = JavaCore.PLUGIN_ID
0210:                    + "/debug/cpresolution"; //$NON-NLS-1$
0211:            private static final String CP_RESOLVE_ADVANCED_DEBUG = JavaCore.PLUGIN_ID
0212:                    + "/debug/cpresolution/advanced"; //$NON-NLS-1$
0213:            private static final String ZIP_ACCESS_DEBUG = JavaCore.PLUGIN_ID
0214:                    + "/debug/zipaccess"; //$NON-NLS-1$
0215:            private static final String DELTA_DEBUG = JavaCore.PLUGIN_ID
0216:                    + "/debug/javadelta"; //$NON-NLS-1$
0217:            private static final String DELTA_DEBUG_VERBOSE = JavaCore.PLUGIN_ID
0218:                    + "/debug/javadelta/verbose"; //$NON-NLS-1$
0219:            private static final String HIERARCHY_DEBUG = JavaCore.PLUGIN_ID
0220:                    + "/debug/hierarchy"; //$NON-NLS-1$
0221:            private static final String POST_ACTION_DEBUG = JavaCore.PLUGIN_ID
0222:                    + "/debug/postaction"; //$NON-NLS-1$
0223:            private static final String BUILDER_DEBUG = JavaCore.PLUGIN_ID
0224:                    + "/debug/builder"; //$NON-NLS-1$
0225:            private static final String COMPLETION_DEBUG = JavaCore.PLUGIN_ID
0226:                    + "/debug/completion"; //$NON-NLS-1$
0227:            private static final String RESOLUTION_DEBUG = JavaCore.PLUGIN_ID
0228:                    + "/debug/resolution"; //$NON-NLS-1$
0229:            private static final String SELECTION_DEBUG = JavaCore.PLUGIN_ID
0230:                    + "/debug/selection"; //$NON-NLS-1$
0231:            private static final String SEARCH_DEBUG = JavaCore.PLUGIN_ID
0232:                    + "/debug/search"; //$NON-NLS-1$
0233:            private static final String SOURCE_MAPPER_DEBUG_VERBOSE = JavaCore.PLUGIN_ID
0234:                    + "/debug/sourcemapper"; //$NON-NLS-1$
0235:
0236:            public static final String COMPLETION_PERF = JavaCore.PLUGIN_ID
0237:                    + "/perf/completion"; //$NON-NLS-1$
0238:            public static final String SELECTION_PERF = JavaCore.PLUGIN_ID
0239:                    + "/perf/selection"; //$NON-NLS-1$
0240:            public static final String DELTA_LISTENER_PERF = JavaCore.PLUGIN_ID
0241:                    + "/perf/javadeltalistener"; //$NON-NLS-1$
0242:            public static final String VARIABLE_INITIALIZER_PERF = JavaCore.PLUGIN_ID
0243:                    + "/perf/variableinitializer"; //$NON-NLS-1$
0244:            public static final String CONTAINER_INITIALIZER_PERF = JavaCore.PLUGIN_ID
0245:                    + "/perf/containerinitializer"; //$NON-NLS-1$
0246:            public static final String RECONCILE_PERF = JavaCore.PLUGIN_ID
0247:                    + "/perf/reconcile"; //$NON-NLS-1$
0248:
0249:            private final static String INDEXED_SECONDARY_TYPES = "#@*_indexing secondary cache_*@#"; //$NON-NLS-1$
0250:
0251:            public static boolean PERF_VARIABLE_INITIALIZER = false;
0252:            public static boolean PERF_CONTAINER_INITIALIZER = false;
0253:
0254:            public final static ICompilationUnit[] NO_WORKING_COPY = new ICompilationUnit[0];
0255:
0256:            // Preferences
0257:            HashSet optionNames = new HashSet(20);
0258:            Hashtable optionsCache;
0259:
0260:            public final IEclipsePreferences[] preferencesLookup = new IEclipsePreferences[2];
0261:            static final int PREF_INSTANCE = 0;
0262:            static final int PREF_DEFAULT = 1;
0263:
0264:            static final Object[][] NO_PARTICIPANTS = new Object[0][];
0265:
0266:            public static class CompilationParticipants {
0267:
0268:                private final static int MAX_SOURCE_LEVEL = 7; // 1.1 to 1.7
0269:
0270:                /*
0271:                 * The registered compilation participants (a table from int (source level) to Object[])
0272:                 * The Object array contains first IConfigurationElements when not resolved yet, then
0273:                 * it contains CompilationParticipants.
0274:                 */
0275:                private Object[][] registeredParticipants = null;
0276:                private HashSet managedMarkerTypes;
0277:
0278:                public CompilationParticipant[] getCompilationParticipants(
0279:                        IJavaProject project) {
0280:                    final Object[][] participantsPerSource = getRegisteredParticipants();
0281:                    if (participantsPerSource == NO_PARTICIPANTS)
0282:                        return null;
0283:                    String sourceLevel = project.getOption(
0284:                            JavaCore.COMPILER_SOURCE, true/*inherit options*/);
0285:                    final int sourceLevelIndex = indexForSourceLevel(sourceLevel);
0286:                    final Object[] participants = participantsPerSource[sourceLevelIndex];
0287:                    int length = participants.length;
0288:                    CompilationParticipant[] result = new CompilationParticipant[length];
0289:                    int index = 0;
0290:                    for (int i = 0; i < length; i++) {
0291:                        if (participants[i] instanceof  IConfigurationElement) {
0292:                            final IConfigurationElement configElement = (IConfigurationElement) participants[i];
0293:                            final int participantIndex = i;
0294:                            SafeRunner.run(new ISafeRunnable() {
0295:                                public void handleException(Throwable exception) {
0296:                                    Util
0297:                                            .log(exception,
0298:                                                    "Exception occurred while creating compilation participant"); //$NON-NLS-1$
0299:                                }
0300:
0301:                                public void run() throws Exception {
0302:                                    Object executableExtension = configElement
0303:                                            .createExecutableExtension("class"); //$NON-NLS-1$ 
0304:                                    for (int j = sourceLevelIndex; j < MAX_SOURCE_LEVEL; j++)
0305:                                        participantsPerSource[j][participantIndex] = executableExtension;
0306:                                }
0307:                            });
0308:                        }
0309:                        CompilationParticipant participant = (CompilationParticipant) participants[i];
0310:                        if (participant != null
0311:                                && participant.isActive(project))
0312:                            result[index++] = participant;
0313:                    }
0314:                    if (index == 0)
0315:                        return null;
0316:                    if (index < length)
0317:                        System.arraycopy(result, 0,
0318:                                result = new CompilationParticipant[index], 0,
0319:                                index);
0320:                    return result;
0321:                }
0322:
0323:                public HashSet managedMarkerTypes() {
0324:                    if (this .managedMarkerTypes == null) {
0325:                        // force extension points to be read
0326:                        getRegisteredParticipants();
0327:                    }
0328:                    return this .managedMarkerTypes;
0329:                }
0330:
0331:                private synchronized Object[][] getRegisteredParticipants() {
0332:                    if (this .registeredParticipants != null) {
0333:                        return this .registeredParticipants;
0334:                    }
0335:                    this .managedMarkerTypes = new HashSet();
0336:                    IExtensionPoint extension = Platform.getExtensionRegistry()
0337:                            .getExtensionPoint(JavaCore.PLUGIN_ID,
0338:                                    COMPILATION_PARTICIPANT_EXTPOINT_ID);
0339:                    if (extension == null)
0340:                        return this .registeredParticipants = NO_PARTICIPANTS;
0341:                    final ArrayList modifyingEnv = new ArrayList();
0342:                    final ArrayList creatingProblems = new ArrayList();
0343:                    final ArrayList others = new ArrayList();
0344:                    IExtension[] extensions = extension.getExtensions();
0345:                    // for all extensions of this point...
0346:                    for (int i = 0; i < extensions.length; i++) {
0347:                        IConfigurationElement[] configElements = extensions[i]
0348:                                .getConfigurationElements();
0349:                        // for all config elements named "compilationParticipant"
0350:                        for (int j = 0; j < configElements.length; j++) {
0351:                            final IConfigurationElement configElement = configElements[j];
0352:                            String elementName = configElement.getName();
0353:                            if (!("compilationParticipant".equals(elementName))) { //$NON-NLS-1$
0354:                                continue;
0355:                            }
0356:                            // add config element in the group it belongs to
0357:                            if (TRUE.equals(configElement
0358:                                    .getAttribute("modifiesEnvironment"))) //$NON-NLS-1$
0359:                                modifyingEnv.add(configElement);
0360:                            else if (TRUE.equals(configElement
0361:                                    .getAttribute("createsProblems"))) //$NON-NLS-1$
0362:                                creatingProblems.add(configElement);
0363:                            else
0364:                                others.add(configElement);
0365:                            // add managed marker types
0366:                            IConfigurationElement[] managedMarkers = configElement
0367:                                    .getChildren("managedMarker"); //$NON-NLS-1$
0368:                            for (int k = 0, length = managedMarkers.length; k < length; k++) {
0369:                                IConfigurationElement element = managedMarkers[k];
0370:                                String markerType = element
0371:                                        .getAttribute("markerType"); //$NON-NLS-1$
0372:                                if (markerType != null)
0373:                                    this .managedMarkerTypes.add(markerType);
0374:                            }
0375:                        }
0376:                    }
0377:                    int size = modifyingEnv.size() + creatingProblems.size()
0378:                            + others.size();
0379:                    if (size == 0)
0380:                        return this .registeredParticipants = NO_PARTICIPANTS;
0381:
0382:                    // sort config elements in each group
0383:                    IConfigurationElement[] configElements = new IConfigurationElement[size];
0384:                    int index = 0;
0385:                    index = sortParticipants(modifyingEnv, configElements,
0386:                            index);
0387:                    index = sortParticipants(creatingProblems, configElements,
0388:                            index);
0389:                    index = sortParticipants(others, configElements, index);
0390:
0391:                    // create result table
0392:                    Object[][] result = new Object[MAX_SOURCE_LEVEL][];
0393:                    int length = configElements.length;
0394:                    for (int i = 0; i < MAX_SOURCE_LEVEL; i++) {
0395:                        result[i] = new Object[length];
0396:                    }
0397:                    for (int i = 0; i < length; i++) {
0398:                        String sourceLevel = configElements[i]
0399:                                .getAttribute("requiredSourceLevel"); //$NON-NLS-1$
0400:                        int sourceLevelIndex = indexForSourceLevel(sourceLevel);
0401:                        for (int j = sourceLevelIndex; j < MAX_SOURCE_LEVEL; j++) {
0402:                            result[j][i] = configElements[i];
0403:                        }
0404:                    }
0405:                    return this .registeredParticipants = result;
0406:                }
0407:
0408:                /*
0409:                 * 1.1 -> 0
0410:                 * 1.2 -> 1
0411:                 * ...
0412:                 * 1.6 -> 5
0413:                 * 1.7 -> 6
0414:                 * null -> 0
0415:                 */
0416:                private int indexForSourceLevel(String sourceLevel) {
0417:                    if (sourceLevel == null)
0418:                        return 0;
0419:                    int majVersion = (int) (CompilerOptions
0420:                            .versionToJdkLevel(sourceLevel) >>> 16);
0421:                    switch (majVersion) {
0422:                    case ClassFileConstants.MAJOR_VERSION_1_2:
0423:                        return 1;
0424:                    case ClassFileConstants.MAJOR_VERSION_1_3:
0425:                        return 2;
0426:                    case ClassFileConstants.MAJOR_VERSION_1_4:
0427:                        return 3;
0428:                    case ClassFileConstants.MAJOR_VERSION_1_5:
0429:                        return 4;
0430:                    case ClassFileConstants.MAJOR_VERSION_1_6:
0431:                        return 5;
0432:                    case ClassFileConstants.MAJOR_VERSION_1_7:
0433:                        return 6;
0434:                    default:
0435:                        // all other cases including ClassFileConstants.MAJOR_VERSION_1_1
0436:                        return 0;
0437:                    }
0438:                }
0439:
0440:                private int sortParticipants(ArrayList group,
0441:                        IConfigurationElement[] configElements, int index) {
0442:                    int size = group.size();
0443:                    if (size == 0)
0444:                        return index;
0445:                    Object[] elements = group.toArray();
0446:                    Util.sort(elements, new Util.Comparer() {
0447:                        public int compare(Object a, Object b) {
0448:                            if (a == b)
0449:                                return 0;
0450:                            String id = ((IConfigurationElement) a)
0451:                                    .getAttribute("id"); //$NON-NLS-1$
0452:                            if (id == null)
0453:                                return -1;
0454:                            IConfigurationElement[] requiredElements = ((IConfigurationElement) b)
0455:                                    .getChildren("requires"); //$NON-NLS-1$
0456:                            for (int i = 0, length = requiredElements.length; i < length; i++) {
0457:                                IConfigurationElement required = requiredElements[i];
0458:                                if (id.equals(required.getAttribute("id"))) //$NON-NLS-1$
0459:                                    return 1;
0460:                            }
0461:                            return -1;
0462:                        }
0463:                    });
0464:                    for (int i = 0; i < size; i++)
0465:                        configElements[index + i] = (IConfigurationElement) elements[i];
0466:                    return index + size;
0467:                }
0468:            }
0469:
0470:            public final CompilationParticipants compilationParticipants = new CompilationParticipants();
0471:
0472:            /**
0473:             * Returns whether the given full path (for a package) conflicts with the output location
0474:             * of the given project.
0475:             */
0476:            public static boolean conflictsWithOutputLocation(IPath folderPath,
0477:                    JavaProject project) {
0478:                try {
0479:                    IPath outputLocation = project.getOutputLocation();
0480:                    if (outputLocation == null) {
0481:                        // in doubt, there is a conflict
0482:                        return true;
0483:                    }
0484:                    if (outputLocation.isPrefixOf(folderPath)) {
0485:                        // only allow nesting in project's output if there is a corresponding source folder
0486:                        // or if the project's output is not used (in other words, if all source folders have their custom output)
0487:                        IClasspathEntry[] classpath = project
0488:                                .getResolvedClasspath();
0489:                        boolean isOutputUsed = false;
0490:                        for (int i = 0, length = classpath.length; i < length; i++) {
0491:                            IClasspathEntry entry = classpath[i];
0492:                            if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
0493:                                if (entry.getPath().equals(outputLocation)) {
0494:                                    return false;
0495:                                }
0496:                                if (entry.getOutputLocation() == null) {
0497:                                    isOutputUsed = true;
0498:                                }
0499:                            }
0500:                        }
0501:                        return isOutputUsed;
0502:                    }
0503:                    return false;
0504:                } catch (JavaModelException e) {
0505:                    // in doubt, there is a conflict
0506:                    return true;
0507:                }
0508:            }
0509:
0510:            public synchronized IClasspathContainer containerGet(
0511:                    IJavaProject project, IPath containerPath) {
0512:                // check initialization in progress first
0513:                if (containerIsInitializationInProgress(project, containerPath)) {
0514:                    return CONTAINER_INITIALIZATION_IN_PROGRESS;
0515:                }
0516:
0517:                Map projectContainers = (Map) this .containers.get(project);
0518:                if (projectContainers == null) {
0519:                    return null;
0520:                }
0521:                IClasspathContainer container = (IClasspathContainer) projectContainers
0522:                        .get(containerPath);
0523:                return container;
0524:            }
0525:
0526:            public synchronized IClasspathContainer containerGetDefaultToPreviousSession(
0527:                    IJavaProject project, IPath containerPath) {
0528:                Map projectContainers = (Map) this .containers.get(project);
0529:                if (projectContainers == null)
0530:                    return getPreviousSessionContainer(containerPath, project);
0531:                IClasspathContainer container = (IClasspathContainer) projectContainers
0532:                        .get(containerPath);
0533:                if (container == null)
0534:                    return getPreviousSessionContainer(containerPath, project);
0535:                return container;
0536:            }
0537:
0538:            private synchronized Map containerClone(IJavaProject project) {
0539:                Map originalProjectContainers = (Map) this .containers
0540:                        .get(project);
0541:                if (originalProjectContainers == null)
0542:                    return null;
0543:                Map projectContainers = new HashMap(originalProjectContainers
0544:                        .size());
0545:                projectContainers.putAll(originalProjectContainers);
0546:                return projectContainers;
0547:            }
0548:
0549:            private boolean containerIsInitializationInProgress(
0550:                    IJavaProject project, IPath containerPath) {
0551:                Map initializations = (Map) this .containerInitializationInProgress
0552:                        .get();
0553:                if (initializations == null)
0554:                    return false;
0555:                HashSet projectInitializations = (HashSet) initializations
0556:                        .get(project);
0557:                if (projectInitializations == null)
0558:                    return false;
0559:                return projectInitializations.contains(containerPath);
0560:            }
0561:
0562:            private void containerAddInitializationInProgress(
0563:                    IJavaProject project, IPath containerPath) {
0564:                Map initializations = (Map) this .containerInitializationInProgress
0565:                        .get();
0566:                if (initializations == null)
0567:                    this .containerInitializationInProgress
0568:                            .set(initializations = new HashMap());
0569:                HashSet projectInitializations = (HashSet) initializations
0570:                        .get(project);
0571:                if (projectInitializations == null)
0572:                    initializations.put(project,
0573:                            projectInitializations = new HashSet());
0574:                projectInitializations.add(containerPath);
0575:            }
0576:
0577:            public synchronized void containerPut(IJavaProject project,
0578:                    IPath containerPath, IClasspathContainer container) {
0579:
0580:                // set/unset the initialization in progress
0581:                if (container == CONTAINER_INITIALIZATION_IN_PROGRESS) {
0582:                    containerAddInitializationInProgress(project, containerPath);
0583:
0584:                    // do not write out intermediate initialization value
0585:                    return;
0586:                } else {
0587:                    containerRemoveInitializationInProgress(project,
0588:                            containerPath);
0589:
0590:                    Map projectContainers = (Map) this .containers.get(project);
0591:                    if (projectContainers == null) {
0592:                        projectContainers = new HashMap(1);
0593:                        this .containers.put(project, projectContainers);
0594:                    }
0595:
0596:                    if (container == null) {
0597:                        projectContainers.remove(containerPath);
0598:                    } else {
0599:                        projectContainers.put(containerPath, container);
0600:                    }
0601:                    // discard obsoleted information about previous session
0602:                    Map previousContainers = (Map) this .previousSessionContainers
0603:                            .get(project);
0604:                    if (previousContainers != null) {
0605:                        previousContainers.remove(containerPath);
0606:                    }
0607:                }
0608:                // container values are persisted in preferences during save operations, see #saving(ISaveContext)
0609:            }
0610:
0611:            /*
0612:             * The given project is being removed. Remove all containers for this project from the cache.
0613:             */
0614:            public synchronized void containerRemove(IJavaProject project) {
0615:                Map initializations = (Map) this .containerInitializationInProgress
0616:                        .get();
0617:                if (initializations != null) {
0618:                    initializations.remove(project);
0619:                }
0620:                this .containers.remove(project);
0621:            }
0622:
0623:            public boolean containerPutIfInitializingWithSameEntries(
0624:                    IPath containerPath, IJavaProject[] projects,
0625:                    IClasspathContainer[] respectiveContainers) {
0626:                int projectLength = projects.length;
0627:                if (projectLength != 1)
0628:                    return false;
0629:                final IClasspathContainer container = respectiveContainers[0];
0630:                IJavaProject project = projects[0];
0631:                // optimize only if initializing, otherwise we are in a regular setContainer(...) call
0632:                if (!containerIsInitializationInProgress(project, containerPath))
0633:                    return false;
0634:                IClasspathContainer previousContainer = containerGetDefaultToPreviousSession(
0635:                        project, containerPath);
0636:                if (container == null) {
0637:                    if (previousContainer == null) {
0638:                        containerPut(project, containerPath, null);
0639:                        return true;
0640:                    }
0641:                    return false;
0642:                }
0643:                final IClasspathEntry[] newEntries = container
0644:                        .getClasspathEntries();
0645:                if (previousContainer == null)
0646:                    if (newEntries.length == 0) {
0647:                        containerPut(project, containerPath, container);
0648:                        return true;
0649:                    } else {
0650:                        if (CP_RESOLVE_VERBOSE)
0651:                            verbose_missbehaving_container(containerPath,
0652:                                    projects, respectiveContainers, container,
0653:                                    newEntries, null/*no old entries*/);
0654:                        return false;
0655:                    }
0656:                final IClasspathEntry[] oldEntries = previousContainer
0657:                        .getClasspathEntries();
0658:                if (oldEntries.length != newEntries.length) {
0659:                    if (CP_RESOLVE_VERBOSE)
0660:                        verbose_missbehaving_container(containerPath, projects,
0661:                                respectiveContainers, container, newEntries,
0662:                                oldEntries);
0663:                    return false;
0664:                }
0665:                for (int i = 0, length = newEntries.length; i < length; i++) {
0666:                    if (newEntries[i] == null) {
0667:                        if (CP_RESOLVE_VERBOSE)
0668:                            verbose_missbehaving_container(project,
0669:                                    containerPath, newEntries);
0670:                        return false;
0671:                    }
0672:                    if (!newEntries[i].equals(oldEntries[i])) {
0673:                        if (CP_RESOLVE_VERBOSE)
0674:                            verbose_missbehaving_container(containerPath,
0675:                                    projects, respectiveContainers, container,
0676:                                    newEntries, oldEntries);
0677:                        return false;
0678:                    }
0679:                }
0680:                containerPut(project, containerPath, container);
0681:                return true;
0682:            }
0683:
0684:            private void verbose_missbehaving_container(IPath containerPath,
0685:                    IJavaProject[] projects,
0686:                    IClasspathContainer[] respectiveContainers,
0687:                    final IClasspathContainer container,
0688:                    final IClasspathEntry[] newEntries,
0689:                    final IClasspathEntry[] oldEntries) {
0690:                Util
0691:                        .verbose("CPContainer SET  - missbehaving container\n" + //$NON-NLS-1$
0692:                                "	container path: "
0693:                                + containerPath
0694:                                + '\n'
0695:                                + //$NON-NLS-1$
0696:                                "	projects: {"
0697:                                + //$NON-NLS-1$
0698:                                org.eclipse.jdt.internal.compiler.util.Util
0699:                                        .toString(
0700:                                                projects,
0701:                                                new org.eclipse.jdt.internal.compiler.util.Util.Displayable() {
0702:                                                    public String displayString(
0703:                                                            Object o) {
0704:                                                        return ((IJavaProject) o)
0705:                                                                .getElementName();
0706:                                                    }
0707:                                                })
0708:                                + "}\n	values on previous session: {\n" + //$NON-NLS-1$
0709:                                org.eclipse.jdt.internal.compiler.util.Util
0710:                                        .toString(
0711:                                                respectiveContainers,
0712:                                                new org.eclipse.jdt.internal.compiler.util.Util.Displayable() {
0713:                                                    public String displayString(
0714:                                                            Object o) {
0715:                                                        StringBuffer buffer = new StringBuffer(
0716:                                                                "		"); //$NON-NLS-1$
0717:                                                        if (o == null) {
0718:                                                            buffer
0719:                                                                    .append("<null>"); //$NON-NLS-1$
0720:                                                            return buffer
0721:                                                                    .toString();
0722:                                                        }
0723:                                                        buffer
0724:                                                                .append(container
0725:                                                                        .getDescription());
0726:                                                        buffer.append(" {\n"); //$NON-NLS-1$
0727:                                                        if (oldEntries == null) {
0728:                                                            buffer
0729:                                                                    .append(" 			"); //$NON-NLS-1$
0730:                                                            buffer
0731:                                                                    .append("<null>\n"); //$NON-NLS-1$
0732:                                                        } else {
0733:                                                            for (int j = 0; j < oldEntries.length; j++) {
0734:                                                                buffer
0735:                                                                        .append(" 			"); //$NON-NLS-1$
0736:                                                                buffer
0737:                                                                        .append(oldEntries[j]);
0738:                                                                buffer
0739:                                                                        .append('\n');
0740:                                                            }
0741:                                                        }
0742:                                                        buffer.append(" 		}"); //$NON-NLS-1$
0743:                                                        return buffer
0744:                                                                .toString();
0745:                                                    }
0746:                                                })
0747:                                + "}\n	new values: {\n" + //$NON-NLS-1$
0748:                                org.eclipse.jdt.internal.compiler.util.Util
0749:                                        .toString(
0750:                                                respectiveContainers,
0751:                                                new org.eclipse.jdt.internal.compiler.util.Util.Displayable() {
0752:                                                    public String displayString(
0753:                                                            Object o) {
0754:                                                        StringBuffer buffer = new StringBuffer(
0755:                                                                "		"); //$NON-NLS-1$
0756:                                                        if (o == null) {
0757:                                                            buffer
0758:                                                                    .append("<null>"); //$NON-NLS-1$
0759:                                                            return buffer
0760:                                                                    .toString();
0761:                                                        }
0762:                                                        buffer
0763:                                                                .append(container
0764:                                                                        .getDescription());
0765:                                                        buffer.append(" {\n"); //$NON-NLS-1$
0766:                                                        for (int j = 0; j < newEntries.length; j++) {
0767:                                                            buffer
0768:                                                                    .append(" 			"); //$NON-NLS-1$
0769:                                                            buffer
0770:                                                                    .append(newEntries[j]);
0771:                                                            buffer.append('\n');
0772:                                                        }
0773:                                                        buffer.append(" 		}"); //$NON-NLS-1$
0774:                                                        return buffer
0775:                                                                .toString();
0776:                                                    }
0777:                                                }) + "\n	}"); //$NON-NLS-1$
0778:            }
0779:
0780:            void verbose_missbehaving_container(IJavaProject project,
0781:                    IPath containerPath, IClasspathEntry[] classpathEntries) {
0782:                Util
0783:                        .verbose("CPContainer GET - missbehaving container (returning null classpath entry)\n" + //$NON-NLS-1$
0784:                                "	project: "
0785:                                + project.getElementName()
0786:                                + '\n'
0787:                                + //$NON-NLS-1$
0788:                                "	container path: "
0789:                                + containerPath
0790:                                + '\n'
0791:                                + //$NON-NLS-1$
0792:                                "	classpath entries: {\n"
0793:                                + //$NON-NLS-1$
0794:                                org.eclipse.jdt.internal.compiler.util.Util
0795:                                        .toString(
0796:                                                classpathEntries,
0797:                                                new org.eclipse.jdt.internal.compiler.util.Util.Displayable() {
0798:                                                    public String displayString(
0799:                                                            Object o) {
0800:                                                        StringBuffer buffer = new StringBuffer(
0801:                                                                "		"); //$NON-NLS-1$
0802:                                                        if (o == null) {
0803:                                                            buffer
0804:                                                                    .append("<null>"); //$NON-NLS-1$
0805:                                                            return buffer
0806:                                                                    .toString();
0807:                                                        }
0808:                                                        buffer.append(o);
0809:                                                        return buffer
0810:                                                                .toString();
0811:                                                    }
0812:                                                }) + "\n	}" //$NON-NLS-1$
0813:                        );
0814:            }
0815:
0816:            private void containerRemoveInitializationInProgress(
0817:                    IJavaProject project, IPath containerPath) {
0818:                Map initializations = (Map) this .containerInitializationInProgress
0819:                        .get();
0820:                if (initializations == null)
0821:                    return;
0822:                HashSet projectInitializations = (HashSet) initializations
0823:                        .get(project);
0824:                if (projectInitializations == null)
0825:                    return;
0826:                projectInitializations.remove(containerPath);
0827:                if (projectInitializations.size() == 0)
0828:                    initializations.remove(project);
0829:                if (initializations.size() == 0)
0830:                    this .containerInitializationInProgress.set(null);
0831:            }
0832:
0833:            private synchronized void containersReset(String[] containerIDs) {
0834:                for (int i = 0; i < containerIDs.length; i++) {
0835:                    String containerID = containerIDs[i];
0836:                    Iterator projectIterator = this .containers.values()
0837:                            .iterator();
0838:                    while (projectIterator.hasNext()) {
0839:                        Map projectContainers = (Map) projectIterator.next();
0840:                        if (projectContainers != null) {
0841:                            Iterator containerIterator = projectContainers
0842:                                    .keySet().iterator();
0843:                            while (containerIterator.hasNext()) {
0844:                                IPath containerPath = (IPath) containerIterator
0845:                                        .next();
0846:                                if (containerPath.segment(0)
0847:                                        .equals(containerID)) { // registered container
0848:                                    projectContainers.put(containerPath, null); // reset container value, but leave entry in Map
0849:                                }
0850:                            }
0851:                        }
0852:                    }
0853:                }
0854:            }
0855:
0856:            /**
0857:             * Returns the Java element corresponding to the given resource, or
0858:             * <code>null</code> if unable to associate the given resource
0859:             * with a Java element.
0860:             * <p>
0861:             * The resource must be one of:<ul>
0862:             *	<li>a project - the element returned is the corresponding <code>IJavaProject</code></li>
0863:             *	<li>a <code>.java</code> file - the element returned is the corresponding <code>ICompilationUnit</code></li>
0864:             *	<li>a <code>.class</code> file - the element returned is the corresponding <code>IClassFile</code></li>
0865:             *	<li>a <code>.jar</code> file - the element returned is the corresponding <code>IPackageFragmentRoot</code></li>
0866:             *  <li>a folder - the element returned is the corresponding <code>IPackageFragmentRoot</code>
0867:             *			or <code>IPackageFragment</code></li>
0868:             *  <li>the workspace root resource - the element returned is the <code>IJavaModel</code></li>
0869:             *	</ul>
0870:             * <p>
0871:             * Creating a Java element has the side effect of creating and opening all of the
0872:             * element's parents if they are not yet open.
0873:             */
0874:            public static IJavaElement create(IResource resource,
0875:                    IJavaProject project) {
0876:                if (resource == null) {
0877:                    return null;
0878:                }
0879:                int type = resource.getType();
0880:                switch (type) {
0881:                case IResource.PROJECT:
0882:                    return JavaCore.create((IProject) resource);
0883:                case IResource.FILE:
0884:                    return create((IFile) resource, project);
0885:                case IResource.FOLDER:
0886:                    return create((IFolder) resource, project);
0887:                case IResource.ROOT:
0888:                    return JavaCore.create((IWorkspaceRoot) resource);
0889:                default:
0890:                    return null;
0891:                }
0892:            }
0893:
0894:            /**
0895:             * Returns the Java element corresponding to the given file, its project being the given
0896:             * project.
0897:             * Returns <code>null</code> if unable to associate the given file
0898:             * with a Java element.
0899:             *
0900:             * <p>The file must be one of:<ul>
0901:             *	<li>a <code>.java</code> file - the element returned is the corresponding <code>ICompilationUnit</code></li>
0902:             *	<li>a <code>.class</code> file - the element returned is the corresponding <code>IClassFile</code></li>
0903:             *	<li>a <code>.jar</code> file - the element returned is the corresponding <code>IPackageFragmentRoot</code></li>
0904:             *	</ul>
0905:             * <p>
0906:             * Creating a Java element has the side effect of creating and opening all of the
0907:             * element's parents if they are not yet open.
0908:             */
0909:            public static IJavaElement create(IFile file, IJavaProject project) {
0910:                if (file == null) {
0911:                    return null;
0912:                }
0913:                if (project == null) {
0914:                    project = JavaCore.create(file.getProject());
0915:                }
0916:
0917:                if (file.getFileExtension() != null) {
0918:                    String name = file.getName();
0919:                    if (org.eclipse.jdt.internal.core.util.Util
0920:                            .isJavaLikeFileName(name))
0921:                        return createCompilationUnitFrom(file, project);
0922:                    if (org.eclipse.jdt.internal.compiler.util.Util
0923:                            .isClassFileName(name))
0924:                        return createClassFileFrom(file, project);
0925:                    if (org.eclipse.jdt.internal.compiler.util.Util
0926:                            .isArchiveFileName(name))
0927:                        return createJarPackageFragmentRootFrom(file, project);
0928:                }
0929:                return null;
0930:            }
0931:
0932:            /**
0933:             * Returns the package fragment or package fragment root corresponding to the given folder,
0934:             * its parent or great parent being the given project. 
0935:             * or <code>null</code> if unable to associate the given folder with a Java element.
0936:             * <p>
0937:             * Note that a package fragment root is returned rather than a default package.
0938:             * <p>
0939:             * Creating a Java element has the side effect of creating and opening all of the
0940:             * element's parents if they are not yet open.
0941:             */
0942:            public static IJavaElement create(IFolder folder,
0943:                    IJavaProject project) {
0944:                if (folder == null) {
0945:                    return null;
0946:                }
0947:                IJavaElement element;
0948:                if (project == null) {
0949:                    project = JavaCore.create(folder.getProject());
0950:                    element = determineIfOnClasspath(folder, project);
0951:                    if (element == null) {
0952:                        // walk all projects and find one that have the given folder on its classpath
0953:                        IJavaProject[] projects;
0954:                        try {
0955:                            projects = JavaModelManager.getJavaModelManager()
0956:                                    .getJavaModel().getJavaProjects();
0957:                        } catch (JavaModelException e) {
0958:                            return null;
0959:                        }
0960:                        for (int i = 0, length = projects.length; i < length; i++) {
0961:                            project = projects[i];
0962:                            element = determineIfOnClasspath(folder, project);
0963:                            if (element != null)
0964:                                break;
0965:                        }
0966:                    }
0967:                } else {
0968:                    element = determineIfOnClasspath(folder, project);
0969:                }
0970:                return element;
0971:            }
0972:
0973:            /**
0974:             * Creates and returns a class file element for the given <code>.class</code> file,
0975:             * its project being the given project. Returns <code>null</code> if unable
0976:             * to recognize the class file.
0977:             */
0978:            public static IClassFile createClassFileFrom(IFile file,
0979:                    IJavaProject project) {
0980:                if (file == null) {
0981:                    return null;
0982:                }
0983:                if (project == null) {
0984:                    project = JavaCore.create(file.getProject());
0985:                }
0986:                IPackageFragment pkg = (IPackageFragment) determineIfOnClasspath(
0987:                        file, project);
0988:                if (pkg == null) {
0989:                    // fix for 1FVS7WE
0990:                    // not on classpath - make the root its folder, and a default package
0991:                    PackageFragmentRoot root = (PackageFragmentRoot) project
0992:                            .getPackageFragmentRoot(file.getParent());
0993:                    pkg = root.getPackageFragment(CharOperation.NO_STRINGS);
0994:                }
0995:                return pkg.getClassFile(file.getName());
0996:            }
0997:
0998:            /**
0999:             * Creates and returns a compilation unit element for the given <code>.java</code> 
1000:             * file, its project being the given project. Returns <code>null</code> if unable
1001:             * to recognize the compilation unit.
1002:             */
1003:            public static ICompilationUnit createCompilationUnitFrom(
1004:                    IFile file, IJavaProject project) {
1005:
1006:                if (file == null)
1007:                    return null;
1008:
1009:                if (project == null) {
1010:                    project = JavaCore.create(file.getProject());
1011:                }
1012:                IPackageFragment pkg = (IPackageFragment) determineIfOnClasspath(
1013:                        file, project);
1014:                if (pkg == null) {
1015:                    // not on classpath - make the root its folder, and a default package
1016:                    IPackageFragmentRoot root = project
1017:                            .getPackageFragmentRoot(file.getParent());
1018:                    pkg = root
1019:                            .getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
1020:
1021:                    if (VERBOSE) {
1022:                        System.out
1023:                                .println("WARNING : creating unit element outside classpath (" + Thread.currentThread() + "): " + file.getFullPath()); //$NON-NLS-1$//$NON-NLS-2$
1024:                    }
1025:                }
1026:                return pkg.getCompilationUnit(file.getName());
1027:            }
1028:
1029:            /**
1030:             * Creates and returns a handle for the given JAR file, its project being the given project.
1031:             * The Java model associated with the JAR's project may be
1032:             * created as a side effect. 
1033:             * Returns <code>null</code> if unable to create a JAR package fragment root.
1034:             * (for example, if the JAR file represents a non-Java resource)
1035:             */
1036:            public static IPackageFragmentRoot createJarPackageFragmentRootFrom(
1037:                    IFile file, IJavaProject project) {
1038:                if (file == null) {
1039:                    return null;
1040:                }
1041:                if (project == null) {
1042:                    project = JavaCore.create(file.getProject());
1043:                }
1044:
1045:                // Create a jar package fragment root only if on the classpath
1046:                IPath resourcePath = file.getFullPath();
1047:                try {
1048:                    IClasspathEntry entry = ((JavaProject) project)
1049:                            .getClasspathEntryFor(resourcePath);
1050:                    if (entry != null) {
1051:                        return project.getPackageFragmentRoot(file);
1052:                    }
1053:                } catch (JavaModelException e) {
1054:                    // project doesn't exist: return null
1055:                }
1056:                return null;
1057:            }
1058:
1059:            /**
1060:             * Returns the package fragment root represented by the resource, or
1061:             * the package fragment the given resource is located in, or <code>null</code>
1062:             * if the given resource is not on the classpath of the given project.
1063:             */
1064:            public static IJavaElement determineIfOnClasspath(
1065:                    IResource resource, IJavaProject project) {
1066:
1067:                IPath resourcePath = resource.getFullPath();
1068:                try {
1069:                    JavaProjectElementInfo projectInfo = (JavaProjectElementInfo) getJavaModelManager()
1070:                            .getInfo(project);
1071:                    ProjectCache projectCache = projectInfo == null ? null
1072:                            : projectInfo.projectCache;
1073:                    HashtableOfArrayToObject allPkgFragmentsCache = projectCache == null ? null
1074:                            : projectCache.allPkgFragmentsCache;
1075:                    IClasspathEntry[] entries = org.eclipse.jdt.internal.core.util.Util
1076:                            .isJavaLikeFileName(resourcePath.lastSegment()) ? project
1077:                            .getRawClasspath() // JAVA file can only live inside SRC folder (on the raw path)
1078:                            : ((JavaProject) project).getResolvedClasspath();
1079:
1080:                    int length = entries.length;
1081:                    if (length > 0) {
1082:                        String sourceLevel = project.getOption(
1083:                                JavaCore.COMPILER_SOURCE, true);
1084:                        String complianceLevel = project.getOption(
1085:                                JavaCore.COMPILER_COMPLIANCE, true);
1086:                        for (int i = 0; i < length; i++) {
1087:                            IClasspathEntry entry = entries[i];
1088:                            if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT)
1089:                                continue;
1090:                            IPath rootPath = entry.getPath();
1091:                            if (rootPath.equals(resourcePath)) {
1092:                                return project.getPackageFragmentRoot(resource);
1093:                            } else if (rootPath.isPrefixOf(resourcePath)) {
1094:                                // allow creation of package fragment if it contains a .java file that is included
1095:                                if (!Util.isExcluded(resource,
1096:                                        ((ClasspathEntry) entry)
1097:                                                .fullInclusionPatternChars(),
1098:                                        ((ClasspathEntry) entry)
1099:                                                .fullExclusionPatternChars())) {
1100:                                    // given we have a resource child of the root, it cannot be a JAR pkg root
1101:                                    PackageFragmentRoot root = (PackageFragmentRoot) ((JavaProject) project)
1102:                                            .getFolderPackageFragmentRoot(rootPath);
1103:                                    if (root == null)
1104:                                        return null;
1105:                                    IPath pkgPath = resourcePath
1106:                                            .removeFirstSegments(rootPath
1107:                                                    .segmentCount());
1108:
1109:                                    if (resource.getType() == IResource.FILE) {
1110:                                        // if the resource is a file, then remove the last segment which
1111:                                        // is the file name in the package
1112:                                        pkgPath = pkgPath.removeLastSegments(1);
1113:                                    }
1114:                                    String[] pkgName = pkgPath.segments();
1115:
1116:                                    // if package name is in the cache, then it has already been validated
1117:                                    // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=133141)
1118:                                    if (allPkgFragmentsCache != null
1119:                                            && allPkgFragmentsCache
1120:                                                    .containsKey(pkgName))
1121:                                        return root.getPackageFragment(pkgName);
1122:
1123:                                    if (pkgName.length != 0
1124:                                            && JavaConventions
1125:                                                    .validatePackageName(
1126:                                                            Util
1127:                                                                    .packageName(
1128:                                                                            pkgPath,
1129:                                                                            sourceLevel,
1130:                                                                            complianceLevel),
1131:                                                            sourceLevel,
1132:                                                            complianceLevel)
1133:                                                    .getSeverity() == IStatus.ERROR) {
1134:                                        return null;
1135:                                    }
1136:                                    return root.getPackageFragment(pkgName);
1137:                                }
1138:                            }
1139:                        }
1140:                    }
1141:                } catch (JavaModelException npe) {
1142:                    return null;
1143:                }
1144:                return null;
1145:            }
1146:
1147:            /**
1148:             * The singleton manager
1149:             */
1150:            private static JavaModelManager MANAGER = new JavaModelManager();
1151:
1152:            /**
1153:             * Infos cache.
1154:             */
1155:            private JavaModelCache cache;
1156:
1157:            /*
1158:             * Temporary cache of newly opened elements
1159:             */
1160:            private ThreadLocal temporaryCache = new ThreadLocal();
1161:
1162:            /**
1163:             * Set of elements which are out of sync with their buffers.
1164:             */
1165:            protected HashSet elementsOutOfSynchWithBuffers = new HashSet(11);
1166:
1167:            /**
1168:             * Holds the state used for delta processing.
1169:             */
1170:            public DeltaProcessingState deltaState = new DeltaProcessingState();
1171:
1172:            public IndexManager indexManager = null;
1173:
1174:            /**
1175:             * Table from IProject to PerProjectInfo.
1176:             * NOTE: this object itself is used as a lock to synchronize creation/removal of per project infos
1177:             */
1178:            protected Map perProjectInfos = new HashMap(5);
1179:
1180:            /**
1181:             * Table from WorkingCopyOwner to a table of ICompilationUnit (working copy handle) to PerWorkingCopyInfo.
1182:             * NOTE: this object itself is used as a lock to synchronize creation/removal of per working copy infos
1183:             */
1184:            protected Map perWorkingCopyInfos = new HashMap(5);
1185:
1186:            /**
1187:             * A weak set of the known search scopes.
1188:             */
1189:            protected WeakHashMap searchScopes = new WeakHashMap();
1190:
1191:            public static class PerProjectInfo {
1192:                private static final int JAVADOC_CACHE_INITIAL_SIZE = 10;
1193:
1194:                public IProject project;
1195:                public Object savedState;
1196:                public boolean triedRead;
1197:                public IClasspathEntry[] rawClasspath;
1198:                public IJavaModelStatus rawClasspathStatus;
1199:                public IClasspathEntry[] resolvedClasspath;
1200:                public IJavaModelStatus unresolvedEntryStatus;
1201:                public Map rootPathToRawEntries; // reverse map from a package fragment root's path to the raw entry
1202:                public Map rootPathToResolvedEntries; // map from a package fragment root's path to the resolved entry
1203:                public IPath outputLocation;
1204:
1205:                public IEclipsePreferences preferences;
1206:                public Hashtable options;
1207:                public Hashtable secondaryTypes;
1208:                public LRUCache javadocCache;
1209:
1210:                public PerProjectInfo(IProject project) {
1211:
1212:                    this .triedRead = false;
1213:                    this .savedState = null;
1214:                    this .project = project;
1215:                    this .javadocCache = new LRUCache(JAVADOC_CACHE_INITIAL_SIZE);
1216:                }
1217:
1218:                public void rememberExternalLibTimestamps() {
1219:                    IClasspathEntry[] classpath = this .resolvedClasspath;
1220:                    if (classpath == null)
1221:                        return;
1222:                    IWorkspaceRoot wRoot = ResourcesPlugin.getWorkspace()
1223:                            .getRoot();
1224:                    Map externalTimeStamps = JavaModelManager
1225:                            .getJavaModelManager().deltaState
1226:                            .getExternalLibTimeStamps();
1227:                    for (int i = 0, length = classpath.length; i < length; i++) {
1228:                        IClasspathEntry entry = classpath[i];
1229:                        if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
1230:                            IPath path = entry.getPath();
1231:                            if (externalTimeStamps.get(path) == null) {
1232:                                Object target = JavaModel.getTarget(wRoot,
1233:                                        path, true);
1234:                                if (target instanceof  java.io.File) {
1235:                                    long timestamp = DeltaProcessor
1236:                                            .getTimeStamp((java.io.File) target);
1237:                                    externalTimeStamps.put(path, new Long(
1238:                                            timestamp));
1239:                                }
1240:                            }
1241:                        }
1242:                    }
1243:                }
1244:
1245:                public synchronized void resetResolvedClasspath() {
1246:                    // null out resolved information
1247:                    setClasspath(this .rawClasspath, this .outputLocation,
1248:                            this .rawClasspathStatus, null, null, null, null);
1249:                }
1250:
1251:                public synchronized void setClasspath(
1252:                        IClasspathEntry[] newRawClasspath,
1253:                        IPath newOutputLocation,
1254:                        IJavaModelStatus newRawClasspathStatus,
1255:                        IClasspathEntry[] newResolvedClasspath,
1256:                        Map newRootPathToRawEntries,
1257:                        Map newRootPathToResolvedEntries,
1258:                        IJavaModelStatus newUnresolvedEntryStatus) {
1259:                    // remember old info
1260:                    JavaModelManager manager = JavaModelManager
1261:                            .getJavaModelManager();
1262:                    DeltaProcessor deltaProcessor = manager.deltaState
1263:                            .getDeltaProcessor();
1264:                    deltaProcessor.addClasspathChange(this .project,
1265:                            this .rawClasspath, this .outputLocation,
1266:                            this .resolvedClasspath);
1267:
1268:                    this .rawClasspath = newRawClasspath;
1269:                    this .outputLocation = newOutputLocation;
1270:                    this .rawClasspathStatus = newRawClasspathStatus;
1271:                    this .resolvedClasspath = newResolvedClasspath;
1272:                    this .rootPathToRawEntries = newRootPathToRawEntries;
1273:                    this .rootPathToResolvedEntries = newRootPathToResolvedEntries;
1274:                    this .unresolvedEntryStatus = newUnresolvedEntryStatus;
1275:                    this .javadocCache = new LRUCache(JAVADOC_CACHE_INITIAL_SIZE);
1276:                }
1277:
1278:                /*
1279:                 * Reads the raw classpath and output location from disk, and remember them.
1280:                 * Return the raw classpath, or JavaProject#INVALID_CLASSPATH if unable to read it.
1281:                 */
1282:                public synchronized IClasspathEntry[] readAndCacheClasspath(
1283:                        JavaProject javaProject) {
1284:                    // read file entries and update status
1285:                    IClasspathEntry[] classpath;
1286:                    IJavaModelStatus status;
1287:                    try {
1288:                        classpath = javaProject
1289:                                .readFileEntriesWithException(null/*not interested in unknown elements*/);
1290:                        status = JavaModelStatus.VERIFIED_OK;
1291:                    } catch (CoreException e) {
1292:                        classpath = JavaProject.INVALID_CLASSPATH;
1293:                        status = new JavaModelStatus(
1294:                                IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
1295:                                Messages
1296:                                        .bind(
1297:                                                Messages.classpath_cannotReadClasspathFile,
1298:                                                javaProject.getElementName()));
1299:                    } catch (IOException e) {
1300:                        classpath = JavaProject.INVALID_CLASSPATH;
1301:                        if (Messages.file_badFormat.equals(e.getMessage()))
1302:                            status = new JavaModelStatus(
1303:                                    IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
1304:                                    Messages.bind(
1305:                                            Messages.classpath_xmlFormatError,
1306:                                            javaProject.getElementName(),
1307:                                            Messages.file_badFormat));
1308:                        else
1309:                            status = new JavaModelStatus(
1310:                                    IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
1311:                                    Messages
1312:                                            .bind(
1313:                                                    Messages.classpath_cannotReadClasspathFile,
1314:                                                    javaProject
1315:                                                            .getElementName()));
1316:                    } catch (AssertionFailedException e) {
1317:                        classpath = JavaProject.INVALID_CLASSPATH;
1318:                        status = new JavaModelStatus(
1319:                                IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
1320:                                Messages
1321:                                        .bind(
1322:                                                Messages.classpath_illegalEntryInClasspathFile,
1323:                                                new String[] {
1324:                                                        javaProject
1325:                                                                .getElementName(),
1326:                                                        e.getMessage() }));
1327:                    }
1328:
1329:                    // extract out the output location
1330:                    IPath output = null;
1331:                    if (classpath.length > 0) {
1332:                        IClasspathEntry entry = classpath[classpath.length - 1];
1333:                        if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
1334:                            output = entry.getPath();
1335:                            IClasspathEntry[] copy = new IClasspathEntry[classpath.length - 1];
1336:                            System
1337:                                    .arraycopy(classpath, 0, copy, 0,
1338:                                            copy.length);
1339:                            classpath = copy;
1340:                        }
1341:                    }
1342:
1343:                    // store new raw classpath, new output and new status, and null out resolved info
1344:                    setClasspath(classpath, output, status, null, null, null,
1345:                            null);
1346:
1347:                    return classpath;
1348:                }
1349:
1350:                public String toString() {
1351:                    StringBuffer buffer = new StringBuffer();
1352:                    buffer.append("Info for "); //$NON-NLS-1$
1353:                    buffer.append(this .project.getFullPath());
1354:                    buffer.append("\nRaw classpath:\n"); //$NON-NLS-1$
1355:                    if (this .rawClasspath == null) {
1356:                        buffer.append("  <null>\n"); //$NON-NLS-1$
1357:                    } else {
1358:                        for (int i = 0, length = this .rawClasspath.length; i < length; i++) {
1359:                            buffer.append("  "); //$NON-NLS-1$
1360:                            buffer.append(this .rawClasspath[i]);
1361:                            buffer.append('\n');
1362:                        }
1363:                    }
1364:                    buffer.append("Resolved classpath:\n"); //$NON-NLS-1$
1365:                    IClasspathEntry[] resolvedCP = this .resolvedClasspath;
1366:                    if (resolvedCP == null) {
1367:                        buffer.append("  <null>\n"); //$NON-NLS-1$
1368:                    } else {
1369:                        for (int i = 0, length = resolvedCP.length; i < length; i++) {
1370:                            buffer.append("  "); //$NON-NLS-1$
1371:                            buffer.append(resolvedCP[i]);
1372:                            buffer.append('\n');
1373:                        }
1374:                    }
1375:                    buffer.append("Output location:\n  "); //$NON-NLS-1$
1376:                    if (this .outputLocation == null) {
1377:                        buffer.append("<null>"); //$NON-NLS-1$
1378:                    } else {
1379:                        buffer.append(this .outputLocation);
1380:                    }
1381:                    return buffer.toString();
1382:                }
1383:            }
1384:
1385:            public static class PerWorkingCopyInfo implements  IProblemRequestor {
1386:                int useCount = 0;
1387:                IProblemRequestor problemRequestor;
1388:                CompilationUnit workingCopy;
1389:
1390:                public PerWorkingCopyInfo(CompilationUnit workingCopy,
1391:                        IProblemRequestor problemRequestor) {
1392:                    this .workingCopy = workingCopy;
1393:                    this .problemRequestor = problemRequestor;
1394:                }
1395:
1396:                public void acceptProblem(IProblem problem) {
1397:                    IProblemRequestor requestor = getProblemRequestor();
1398:                    if (requestor == null)
1399:                        return;
1400:                    requestor.acceptProblem(problem);
1401:                }
1402:
1403:                public void beginReporting() {
1404:                    IProblemRequestor requestor = getProblemRequestor();
1405:                    if (requestor == null)
1406:                        return;
1407:                    requestor.beginReporting();
1408:                }
1409:
1410:                public void endReporting() {
1411:                    IProblemRequestor requestor = getProblemRequestor();
1412:                    if (requestor == null)
1413:                        return;
1414:                    requestor.endReporting();
1415:                }
1416:
1417:                public IProblemRequestor getProblemRequestor() {
1418:                    if (this .problemRequestor == null
1419:                            && this .workingCopy.owner != null) {
1420:                        return this .workingCopy.owner
1421:                                .getProblemRequestor(this .workingCopy);
1422:                    }
1423:                    return this .problemRequestor;
1424:                }
1425:
1426:                public ICompilationUnit getWorkingCopy() {
1427:                    return this .workingCopy;
1428:                }
1429:
1430:                public boolean isActive() {
1431:                    IProblemRequestor requestor = getProblemRequestor();
1432:                    return requestor != null && requestor.isActive();
1433:                }
1434:
1435:                public String toString() {
1436:                    StringBuffer buffer = new StringBuffer();
1437:                    buffer.append("Info for "); //$NON-NLS-1$
1438:                    buffer.append(((JavaElement) this .workingCopy)
1439:                            .toStringWithAncestors());
1440:                    buffer.append("\nUse count = "); //$NON-NLS-1$
1441:                    buffer.append(this .useCount);
1442:                    buffer.append("\nProblem requestor:\n  "); //$NON-NLS-1$
1443:                    buffer.append(this .problemRequestor);
1444:                    if (this .problemRequestor == null) {
1445:                        IProblemRequestor requestor = getProblemRequestor();
1446:                        buffer.append("\nOwner problem requestor:\n  "); //$NON-NLS-1$
1447:                        buffer.append(requestor);
1448:                    }
1449:                    return buffer.toString();
1450:                }
1451:            }
1452:
1453:            public static boolean VERBOSE = false;
1454:            public static boolean CP_RESOLVE_VERBOSE = false;
1455:            public static boolean CP_RESOLVE_VERBOSE_ADVANCED = false;
1456:            public static boolean ZIP_ACCESS_VERBOSE = false;
1457:
1458:            /**
1459:             * A cache of opened zip files per thread.
1460:             * (for a given thread, the object value is a HashMap from IPath to java.io.ZipFile)
1461:             */
1462:            private ThreadLocal zipFiles = new ThreadLocal();
1463:
1464:            private UserLibraryManager userLibraryManager;
1465:
1466:            /**
1467:             * Update the classpath variable cache
1468:             */
1469:            public static class EclipsePreferencesListener implements 
1470:                    IEclipsePreferences.IPreferenceChangeListener {
1471:                /**
1472:                 * @see org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener#preferenceChange(org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent)
1473:                 */
1474:                public void preferenceChange(
1475:                        IEclipsePreferences.PreferenceChangeEvent event) {
1476:                    String propertyName = event.getKey();
1477:                    if (propertyName.startsWith(CP_VARIABLE_PREFERENCES_PREFIX)) {
1478:                        String varName = propertyName
1479:                                .substring(CP_VARIABLE_PREFERENCES_PREFIX
1480:                                        .length());
1481:                        JavaModelManager manager = getJavaModelManager();
1482:                        if (manager.variablesWithInitializer.contains(varName)) {
1483:                            // revert preference value as we will not apply it to JavaCore classpath variable
1484:                            String oldValue = (String) event.getOldValue();
1485:                            if (oldValue == null) {
1486:                                // unexpected old value => remove variable from set
1487:                                manager.variablesWithInitializer
1488:                                        .remove(varName);
1489:                            } else {
1490:                                manager.getInstancePreferences().put(varName,
1491:                                        oldValue);
1492:                            }
1493:                        } else {
1494:                            String newValue = (String) event.getNewValue();
1495:                            IPath newPath;
1496:                            if (newValue != null
1497:                                    && !(newValue = newValue.trim())
1498:                                            .equals(CP_ENTRY_IGNORE)) {
1499:                                newPath = new Path(newValue);
1500:                            } else {
1501:                                newPath = null;
1502:                            }
1503:                            try {
1504:                                SetVariablesOperation operation = new SetVariablesOperation(
1505:                                        new String[] { varName },
1506:                                        new IPath[] { newPath }, false/*don't update preferences*/);
1507:                                operation
1508:                                        .runOperation(null/*no progress available*/);
1509:                            } catch (JavaModelException e) {
1510:                                Util
1511:                                        .log(
1512:                                                e,
1513:                                                "Could not set classpath variable " + varName + " to " + newPath); //$NON-NLS-1$ //$NON-NLS-2$
1514:                            }
1515:                        }
1516:                    } else if (propertyName
1517:                            .startsWith(CP_CONTAINER_PREFERENCES_PREFIX)) {
1518:                        recreatePersistedContainer(propertyName, (String) event
1519:                                .getNewValue(), false);
1520:                    } else if (propertyName
1521:                            .equals(JavaCore.CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER)
1522:                            || propertyName
1523:                                    .equals(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER)
1524:                            || propertyName
1525:                                    .equals(JavaCore.CORE_JAVA_BUILD_DUPLICATE_RESOURCE)
1526:                            || propertyName
1527:                                    .equals(JavaCore.CORE_JAVA_BUILD_RECREATE_MODIFIED_CLASS_FILES_IN_OUTPUT_FOLDER)
1528:                            || propertyName
1529:                                    .equals(JavaCore.CORE_JAVA_BUILD_INVALID_CLASSPATH)
1530:                            || propertyName
1531:                                    .equals(JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS)
1532:                            || propertyName
1533:                                    .equals(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS)
1534:                            || propertyName
1535:                                    .equals(JavaCore.CORE_INCOMPLETE_CLASSPATH)
1536:                            || propertyName
1537:                                    .equals(JavaCore.CORE_CIRCULAR_CLASSPATH)
1538:                            || propertyName
1539:                                    .equals(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL)) {
1540:                        JavaModelManager manager = JavaModelManager
1541:                                .getJavaModelManager();
1542:                        IJavaModel model = manager.getJavaModel();
1543:                        IJavaProject[] projects;
1544:                        try {
1545:                            projects = model.getJavaProjects();
1546:                            for (int i = 0, pl = projects.length; i < pl; i++) {
1547:                                JavaProject javaProject = (JavaProject) projects[i];
1548:                                manager.deltaState
1549:                                        .addClasspathValidation(javaProject);
1550:                                try {
1551:                                    // need to touch the project to force validation by DeltaProcessor
1552:                                    javaProject.getProject().touch(null);
1553:                                } catch (CoreException e) {
1554:                                    // skip
1555:                                }
1556:                            }
1557:                        } catch (JavaModelException e) {
1558:                            // skip
1559:                        }
1560:                    } else if (propertyName
1561:                            .startsWith(CP_USERLIBRARY_PREFERENCES_PREFIX)) {
1562:                        String libName = propertyName
1563:                                .substring(CP_USERLIBRARY_PREFERENCES_PREFIX
1564:                                        .length());
1565:                        UserLibraryManager manager = JavaModelManager
1566:                                .getUserLibraryManager();
1567:                        manager.updateUserLibrary(libName, (String) event
1568:                                .getNewValue());
1569:                    }
1570:                }
1571:            }
1572:
1573:            /**
1574:             * Listener on eclipse preferences changes.
1575:             */
1576:            EclipsePreferencesListener instancePreferencesListener = new EclipsePreferencesListener();
1577:            /**
1578:             * Listener on eclipse preferences default/instance node changes.
1579:             */
1580:            IEclipsePreferences.INodeChangeListener instanceNodeListener = new IEclipsePreferences.INodeChangeListener() {
1581:                public void added(IEclipsePreferences.NodeChangeEvent event) {
1582:                    // do nothing
1583:                }
1584:
1585:                public void removed(IEclipsePreferences.NodeChangeEvent event) {
1586:                    if (event.getChild() == preferencesLookup[PREF_INSTANCE]) {
1587:                        preferencesLookup[PREF_INSTANCE] = ((IScopeContext) new InstanceScope())
1588:                                .getNode(JavaCore.PLUGIN_ID);
1589:                        preferencesLookup[PREF_INSTANCE]
1590:                                .addPreferenceChangeListener(new EclipsePreferencesListener());
1591:                    }
1592:                }
1593:            };
1594:            IEclipsePreferences.INodeChangeListener defaultNodeListener = new IEclipsePreferences.INodeChangeListener() {
1595:                public void added(IEclipsePreferences.NodeChangeEvent event) {
1596:                    // do nothing
1597:                }
1598:
1599:                public void removed(IEclipsePreferences.NodeChangeEvent event) {
1600:                    if (event.getChild() == preferencesLookup[PREF_DEFAULT]) {
1601:                        preferencesLookup[PREF_DEFAULT] = ((IScopeContext) new DefaultScope())
1602:                                .getNode(JavaCore.PLUGIN_ID);
1603:                    }
1604:                }
1605:            };
1606:            /**
1607:             * Listener on properties changes.
1608:             */
1609:            Preferences.IPropertyChangeListener propertyListener = new Preferences.IPropertyChangeListener() {
1610:                public void propertyChange(Preferences.PropertyChangeEvent event) {
1611:                    JavaModelManager.this .optionsCache = null;
1612:                }
1613:            };
1614:
1615:            /**
1616:             * Constructs a new JavaModelManager
1617:             */
1618:            private JavaModelManager() {
1619:                // singleton: prevent others from creating a new instance
1620:                if (Platform.isRunning())
1621:                    this .indexManager = new IndexManager();
1622:            }
1623:
1624:            /**
1625:             * @deprecated
1626:             */
1627:            private void addDeprecatedOptions(Hashtable options) {
1628:                options
1629:                        .put(JavaCore.COMPILER_PB_INVALID_IMPORT,
1630:                                JavaCore.ERROR);
1631:                options.put(JavaCore.COMPILER_PB_UNREACHABLE_CODE,
1632:                        JavaCore.ERROR);
1633:            }
1634:
1635:            /**
1636:             * Starts caching ZipFiles.
1637:             * Ignores if there are already clients.
1638:             */
1639:            public void cacheZipFiles() {
1640:                if (this .zipFiles.get() != null)
1641:                    return;
1642:                this .zipFiles.set(new HashMap());
1643:            }
1644:
1645:            public void closeZipFile(ZipFile zipFile) {
1646:                if (zipFile == null)
1647:                    return;
1648:                if (this .zipFiles.get() != null) {
1649:                    return; // zip file will be closed by call to flushZipFiles
1650:                }
1651:                try {
1652:                    if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
1653:                        System.out
1654:                                .println("(" + Thread.currentThread() + ") [JavaModelManager.closeZipFile(ZipFile)] Closing ZipFile on " + zipFile.getName()); //$NON-NLS-1$	//$NON-NLS-2$
1655:                    }
1656:                    zipFile.close();
1657:                } catch (IOException e) {
1658:                    // problem occured closing zip file: cannot do much more
1659:                }
1660:            }
1661:
1662:            /**
1663:             * Configure the plugin with respect to option settings defined in ".options" file
1664:             */
1665:            public void configurePluginDebugOptions() {
1666:                if (JavaCore.getPlugin().isDebugging()) {
1667:                    String option = Platform
1668:                            .getDebugOption(BUFFER_MANAGER_DEBUG);
1669:                    if (option != null)
1670:                        BufferManager.VERBOSE = option.equalsIgnoreCase(TRUE);
1671:
1672:                    option = Platform.getDebugOption(BUILDER_DEBUG);
1673:                    if (option != null)
1674:                        JavaBuilder.DEBUG = option.equalsIgnoreCase(TRUE);
1675:
1676:                    option = Platform.getDebugOption(COMPILER_DEBUG);
1677:                    if (option != null)
1678:                        Compiler.DEBUG = option.equalsIgnoreCase(TRUE);
1679:
1680:                    option = Platform.getDebugOption(COMPLETION_DEBUG);
1681:                    if (option != null)
1682:                        CompletionEngine.DEBUG = option.equalsIgnoreCase(TRUE);
1683:
1684:                    option = Platform.getDebugOption(CP_RESOLVE_DEBUG);
1685:                    if (option != null)
1686:                        JavaModelManager.CP_RESOLVE_VERBOSE = option
1687:                                .equalsIgnoreCase(TRUE);
1688:
1689:                    option = Platform.getDebugOption(CP_RESOLVE_ADVANCED_DEBUG);
1690:                    if (option != null)
1691:                        JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED = option
1692:                                .equalsIgnoreCase(TRUE);
1693:
1694:                    option = Platform.getDebugOption(DELTA_DEBUG);
1695:                    if (option != null)
1696:                        DeltaProcessor.DEBUG = option.equalsIgnoreCase(TRUE);
1697:
1698:                    option = Platform.getDebugOption(DELTA_DEBUG_VERBOSE);
1699:                    if (option != null)
1700:                        DeltaProcessor.VERBOSE = option.equalsIgnoreCase(TRUE);
1701:
1702:                    option = Platform.getDebugOption(HIERARCHY_DEBUG);
1703:                    if (option != null)
1704:                        TypeHierarchy.DEBUG = option.equalsIgnoreCase(TRUE);
1705:
1706:                    option = Platform.getDebugOption(INDEX_MANAGER_DEBUG);
1707:                    if (option != null)
1708:                        JobManager.VERBOSE = option.equalsIgnoreCase(TRUE);
1709:
1710:                    option = Platform.getDebugOption(JAVAMODEL_DEBUG);
1711:                    if (option != null)
1712:                        JavaModelManager.VERBOSE = option
1713:                                .equalsIgnoreCase(TRUE);
1714:
1715:                    option = Platform.getDebugOption(JAVAMODELCACHE_DEBUG);
1716:                    if (option != null)
1717:                        JavaModelCache.VERBOSE = option.equalsIgnoreCase(TRUE);
1718:
1719:                    option = Platform.getDebugOption(POST_ACTION_DEBUG);
1720:                    if (option != null)
1721:                        JavaModelOperation.POST_ACTION_VERBOSE = option
1722:                                .equalsIgnoreCase(TRUE);
1723:
1724:                    option = Platform.getDebugOption(RESOLUTION_DEBUG);
1725:                    if (option != null)
1726:                        NameLookup.VERBOSE = option.equalsIgnoreCase(TRUE);
1727:
1728:                    option = Platform.getDebugOption(SEARCH_DEBUG);
1729:                    if (option != null)
1730:                        BasicSearchEngine.VERBOSE = option
1731:                                .equalsIgnoreCase(TRUE);
1732:
1733:                    option = Platform.getDebugOption(SELECTION_DEBUG);
1734:                    if (option != null)
1735:                        SelectionEngine.DEBUG = option.equalsIgnoreCase(TRUE);
1736:
1737:                    option = Platform.getDebugOption(ZIP_ACCESS_DEBUG);
1738:                    if (option != null)
1739:                        JavaModelManager.ZIP_ACCESS_VERBOSE = option
1740:                                .equalsIgnoreCase(TRUE);
1741:
1742:                    option = Platform
1743:                            .getDebugOption(SOURCE_MAPPER_DEBUG_VERBOSE);
1744:                    if (option != null)
1745:                        SourceMapper.VERBOSE = option.equalsIgnoreCase(TRUE);
1746:                }
1747:
1748:                // configure performance options
1749:                if (PerformanceStats.ENABLED) {
1750:                    CompletionEngine.PERF = PerformanceStats
1751:                            .isEnabled(COMPLETION_PERF);
1752:                    SelectionEngine.PERF = PerformanceStats
1753:                            .isEnabled(SELECTION_PERF);
1754:                    DeltaProcessor.PERF = PerformanceStats
1755:                            .isEnabled(DELTA_LISTENER_PERF);
1756:                    JavaModelManager.PERF_VARIABLE_INITIALIZER = PerformanceStats
1757:                            .isEnabled(VARIABLE_INITIALIZER_PERF);
1758:                    JavaModelManager.PERF_CONTAINER_INITIALIZER = PerformanceStats
1759:                            .isEnabled(CONTAINER_INITIALIZER_PERF);
1760:                    ReconcileWorkingCopyOperation.PERF = PerformanceStats
1761:                            .isEnabled(RECONCILE_PERF);
1762:                }
1763:            }
1764:
1765:            /*
1766:             * Return a new Java 6 annotation processor manager.  The manager will need to
1767:             * be configured before it can be used.  Returns null if a manager cannot be
1768:             * created, ie if the current VM does not support Java 6 annotation processing.
1769:             */
1770:            public AbstractAnnotationProcessorManager createAnnotationProcessorManager() {
1771:                synchronized (this ) {
1772:                    if (this .annotationProcessorManagerFactory == null) {
1773:                        IExtensionPoint extension = Platform
1774:                                .getExtensionRegistry()
1775:                                .getExtensionPoint(JavaCore.PLUGIN_ID,
1776:                                        ANNOTATION_PROCESSOR_MANAGER_EXTPOINT_ID);
1777:                        if (extension == null)
1778:                            return null;
1779:                        IExtension[] extensions = extension.getExtensions();
1780:                        for (int i = 0; i < extensions.length; i++) {
1781:                            if (i > 0) {
1782:                                Util
1783:                                        .log(
1784:                                                null,
1785:                                                "An annotation processor manager is already registered: ignoring " + extensions[i].getUniqueIdentifier()); //$NON-NLS-1$
1786:                                break;
1787:                            }
1788:                            IConfigurationElement[] configElements = extensions[i]
1789:                                    .getConfigurationElements();
1790:                            for (int j = 0; j < configElements.length; j++) {
1791:                                final IConfigurationElement configElement = configElements[j];
1792:                                if ("annotationProcessorManager".equals(configElement.getName())) { //$NON-NLS-1$
1793:                                    this .annotationProcessorManagerFactory = configElement;
1794:                                    break;
1795:                                }
1796:                            }
1797:                        }
1798:                    }
1799:                }
1800:
1801:                if (this .annotationProcessorManagerFactory == null) {
1802:                    return null;
1803:                }
1804:                final AbstractAnnotationProcessorManager[] apm = new AbstractAnnotationProcessorManager[1];
1805:                apm[0] = null;
1806:                final IConfigurationElement factory = this .annotationProcessorManagerFactory;
1807:                SafeRunner.run(new ISafeRunnable() {
1808:                    public void handleException(Throwable exception) {
1809:                        Util
1810:                                .log(exception,
1811:                                        "Exception occurred while loading annotation processor manager"); //$NON-NLS-1$
1812:                    }
1813:
1814:                    public void run() throws Exception {
1815:                        Object executableExtension = factory
1816:                                .createExecutableExtension("class"); //$NON-NLS-1$ 
1817:                        if (executableExtension instanceof  AbstractAnnotationProcessorManager) {
1818:                            apm[0] = (AbstractAnnotationProcessorManager) executableExtension;
1819:                        }
1820:                    }
1821:                });
1822:                return apm[0];
1823:            }
1824:
1825:            /*
1826:             * Discards the per working copy info for the given working copy (making it a compilation unit)
1827:             * if its use count was 1. Otherwise, just decrement the use count.
1828:             * If the working copy is primary, computes the delta between its state and the original compilation unit
1829:             * and register it.
1830:             * Close the working copy, its buffer and remove it from the shared working copy table.
1831:             * Ignore if no per-working copy info existed.
1832:             * NOTE: it must NOT be synchronized as it may interact with the element info cache (if useCount is decremented to 0), see bug 50667.
1833:             * Returns the new use count (or -1 if it didn't exist).
1834:             */
1835:            public int discardPerWorkingCopyInfo(CompilationUnit workingCopy)
1836:                    throws JavaModelException {
1837:
1838:                // create the delta builder (this remembers the current content of the working copy)
1839:                // outside the perWorkingCopyInfos lock (see bug 50667)
1840:                JavaElementDeltaBuilder deltaBuilder = null;
1841:                if (workingCopy.isPrimary() && workingCopy.hasUnsavedChanges()) {
1842:                    deltaBuilder = new JavaElementDeltaBuilder(workingCopy);
1843:                }
1844:                PerWorkingCopyInfo info = null;
1845:                synchronized (this .perWorkingCopyInfos) {
1846:                    WorkingCopyOwner owner = workingCopy.owner;
1847:                    Map workingCopyToInfos = (Map) this .perWorkingCopyInfos
1848:                            .get(owner);
1849:                    if (workingCopyToInfos == null)
1850:                        return -1;
1851:
1852:                    info = (PerWorkingCopyInfo) workingCopyToInfos
1853:                            .get(workingCopy);
1854:                    if (info == null)
1855:                        return -1;
1856:
1857:                    if (--info.useCount == 0) {
1858:                        // remove per working copy info
1859:                        workingCopyToInfos.remove(workingCopy);
1860:                        if (workingCopyToInfos.isEmpty()) {
1861:                            this .perWorkingCopyInfos.remove(owner);
1862:                        }
1863:                    }
1864:                }
1865:                if (info.useCount == 0) { // info cannot be null here (check was done above)
1866:                    // remove infos + close buffer (since no longer working copy)
1867:                    // outside the perWorkingCopyInfos lock (see bug 50667)
1868:                    removeInfoAndChildren(workingCopy);
1869:                    workingCopy.closeBuffer();
1870:
1871:                    // compute the delta if needed and register it if there are changes
1872:                    if (deltaBuilder != null) {
1873:                        deltaBuilder.buildDeltas();
1874:                        if (deltaBuilder.delta != null) {
1875:                            getDeltaProcessor().registerJavaModelDelta(
1876:                                    deltaBuilder.delta);
1877:                        }
1878:                    }
1879:                }
1880:                return info.useCount;
1881:            }
1882:
1883:            /**
1884:             * @see ISaveParticipant
1885:             */
1886:            public void doneSaving(ISaveContext context) {
1887:                // nothing to do for jdt.core
1888:            }
1889:
1890:            /**
1891:             * Flushes ZipFiles cache if there are no more clients.
1892:             */
1893:            public void flushZipFiles() {
1894:                Thread currentThread = Thread.currentThread();
1895:                HashMap map = (HashMap) this .zipFiles.get();
1896:                if (map == null)
1897:                    return;
1898:                this .zipFiles.set(null);
1899:                Iterator iterator = map.values().iterator();
1900:                while (iterator.hasNext()) {
1901:                    try {
1902:                        ZipFile zipFile = (ZipFile) iterator.next();
1903:                        if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
1904:                            System.out
1905:                                    .println("(" + currentThread + ") [JavaModelManager.flushZipFiles()] Closing ZipFile on " + zipFile.getName()); //$NON-NLS-1$//$NON-NLS-2$
1906:                        }
1907:                        zipFile.close();
1908:                    } catch (IOException e) {
1909:                        // problem occured closing zip file: cannot do much more
1910:                    }
1911:                }
1912:            }
1913:
1914:            private synchronized boolean batchContainerInitializations() {
1915:                if (this .batchContainerInitializations) {
1916:                    this .batchContainerInitializations = false;
1917:                    return true;
1918:                }
1919:                return false;
1920:            }
1921:
1922:            public IClasspathContainer getClasspathContainer(
1923:                    final IPath containerPath, final IJavaProject project)
1924:                    throws JavaModelException {
1925:
1926:                IClasspathContainer container = containerGet(project,
1927:                        containerPath);
1928:
1929:                if (container == null) {
1930:                    if (batchContainerInitializations()) {
1931:                        // avoid deep recursion while initializaing container on workspace restart
1932:                        // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=60437)
1933:                        container = initializeAllContainers(project,
1934:                                containerPath);
1935:                    } else {
1936:                        container = initializeContainer(project, containerPath);
1937:                    }
1938:                }
1939:                return container;
1940:            }
1941:
1942:            public DeltaProcessor getDeltaProcessor() {
1943:                return this .deltaState.getDeltaProcessor();
1944:            }
1945:
1946:            public static DeltaProcessingState getDeltaState() {
1947:                return MANAGER.deltaState;
1948:            }
1949:
1950:            /** 
1951:             * Returns the set of elements which are out of synch with their buffers.
1952:             */
1953:            protected HashSet getElementsOutOfSynchWithBuffers() {
1954:                return this .elementsOutOfSynchWithBuffers;
1955:            }
1956:
1957:            public static IndexManager getIndexManager() {
1958:                return MANAGER.indexManager;
1959:            }
1960:
1961:            /**
1962:             *  Returns the info for the element.
1963:             */
1964:            public synchronized Object getInfo(IJavaElement element) {
1965:                HashMap tempCache = (HashMap) this .temporaryCache.get();
1966:                if (tempCache != null) {
1967:                    Object result = tempCache.get(element);
1968:                    if (result != null) {
1969:                        return result;
1970:                    }
1971:                }
1972:                return this .cache.getInfo(element);
1973:            }
1974:
1975:            /**
1976:             * Get workspace eclipse preference for JavaCore plug-in.
1977:             */
1978:            public IEclipsePreferences getInstancePreferences() {
1979:                return preferencesLookup[PREF_INSTANCE];
1980:            }
1981:
1982:            // If modified, also modify the method getDefaultOptionsNoInitialization()
1983:            public Hashtable getDefaultOptions() {
1984:
1985:                Hashtable defaultOptions = new Hashtable(10);
1986:
1987:                // see JavaCorePreferenceInitializer#initializeDefaultPluginPreferences() for changing default settings
1988:                // If modified, also modify the method getDefaultOptionsNoInitialization()
1989:                IEclipsePreferences defaultPreferences = getDefaultPreferences();
1990:
1991:                // initialize preferences to their default
1992:                Iterator iterator = this .optionNames.iterator();
1993:                while (iterator.hasNext()) {
1994:                    String propertyName = (String) iterator.next();
1995:                    String value = defaultPreferences.get(propertyName, null);
1996:                    if (value != null)
1997:                        defaultOptions.put(propertyName, value);
1998:                }
1999:                // get encoding through resource plugin
2000:                defaultOptions.put(JavaCore.CORE_ENCODING, JavaCore
2001:                        .getEncoding());
2002:                // backward compatibility
2003:                addDeprecatedOptions(defaultOptions);
2004:
2005:                return defaultOptions;
2006:            }
2007:
2008:            /**
2009:             * Get default eclipse preference for JavaCore plugin.
2010:             */
2011:            public IEclipsePreferences getDefaultPreferences() {
2012:                return preferencesLookup[PREF_DEFAULT];
2013:            }
2014:
2015:            /**
2016:             * Returns the handle to the active Java Model.
2017:             */
2018:            public final JavaModel getJavaModel() {
2019:                return this .javaModel;
2020:            }
2021:
2022:            /**
2023:             * Returns the singleton JavaModelManager
2024:             */
2025:            public final static JavaModelManager getJavaModelManager() {
2026:                return MANAGER;
2027:            }
2028:
2029:            /**
2030:             * Returns the last built state for the given project, or null if there is none.
2031:             * Deserializes the state if necessary.
2032:             *
2033:             * For use by image builder and evaluation support only
2034:             */
2035:            public Object getLastBuiltState(IProject project,
2036:                    IProgressMonitor monitor) {
2037:                if (!JavaProject.hasJavaNature(project)) {
2038:                    if (JavaBuilder.DEBUG)
2039:                        System.out.println(project + " is not a Java project"); //$NON-NLS-1$
2040:                    return null; // should never be requested on non-Java projects
2041:                }
2042:                PerProjectInfo info = getPerProjectInfo(project, true/*create if missing*/);
2043:                if (!info.triedRead) {
2044:                    info.triedRead = true;
2045:                    try {
2046:                        if (monitor != null)
2047:                            monitor.subTask(Messages.bind(
2048:                                    Messages.build_readStateProgress, project
2049:                                            .getName()));
2050:                        info.savedState = readState(project);
2051:                    } catch (CoreException e) {
2052:                        e.printStackTrace();
2053:                    }
2054:                }
2055:                return info.savedState;
2056:            }
2057:
2058:            public String getOption(String optionName) {
2059:
2060:                if (JavaCore.CORE_ENCODING.equals(optionName)) {
2061:                    return JavaCore.getEncoding();
2062:                }
2063:                // backward compatibility
2064:                if (isDeprecatedOption(optionName)) {
2065:                    return JavaCore.ERROR;
2066:                }
2067:                String propertyName = optionName;
2068:                if (this .optionNames.contains(propertyName)) {
2069:                    IPreferencesService service = Platform
2070:                            .getPreferencesService();
2071:                    String value = service.get(optionName, null,
2072:                            this .preferencesLookup);
2073:                    return value == null ? null : value.trim();
2074:                }
2075:                return null;
2076:            }
2077:
2078:            public Hashtable getOptions() {
2079:
2080:                // return cached options if already computed
2081:                if (this .optionsCache != null)
2082:                    return new Hashtable(this .optionsCache);
2083:
2084:                if (!Platform.isRunning()) {
2085:                    return this .optionsCache = getDefaultOptionsNoInitialization();
2086:                }
2087:                // init
2088:                Hashtable options = new Hashtable(10);
2089:                IPreferencesService service = Platform.getPreferencesService();
2090:
2091:                // set options using preferences service lookup
2092:                Iterator iterator = optionNames.iterator();
2093:                while (iterator.hasNext()) {
2094:                    String propertyName = (String) iterator.next();
2095:                    String propertyValue = service.get(propertyName, null,
2096:                            this .preferencesLookup);
2097:                    if (propertyValue != null) {
2098:                        options.put(propertyName, propertyValue);
2099:                    }
2100:                }
2101:
2102:                // get encoding through resource plugin
2103:                options.put(JavaCore.CORE_ENCODING, JavaCore.getEncoding());
2104:
2105:                // backward compatibility
2106:                addDeprecatedOptions(options);
2107:
2108:                // store built map in cache
2109:                this .optionsCache = new Hashtable(options);
2110:
2111:                // return built map
2112:                return options;
2113:            }
2114:
2115:            // Do not modify without modifying getDefaultOptions()
2116:            private Hashtable getDefaultOptionsNoInitialization() {
2117:                Map defaultOptionsMap = new CompilerOptions().getMap(); // compiler defaults
2118:
2119:                // Override some compiler defaults
2120:                defaultOptionsMap.put(JavaCore.COMPILER_LOCAL_VARIABLE_ATTR,
2121:                        JavaCore.GENERATE);
2122:                defaultOptionsMap.put(JavaCore.COMPILER_CODEGEN_UNUSED_LOCAL,
2123:                        JavaCore.PRESERVE);
2124:                defaultOptionsMap.put(JavaCore.COMPILER_TASK_TAGS,
2125:                        JavaCore.DEFAULT_TASK_TAGS);
2126:                defaultOptionsMap.put(JavaCore.COMPILER_TASK_PRIORITIES,
2127:                        JavaCore.DEFAULT_TASK_PRIORITIES);
2128:                defaultOptionsMap.put(JavaCore.COMPILER_TASK_CASE_SENSITIVE,
2129:                        JavaCore.ENABLED);
2130:                defaultOptionsMap.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT,
2131:                        JavaCore.ENABLED);
2132:                defaultOptionsMap.put(JavaCore.COMPILER_PB_FORBIDDEN_REFERENCE,
2133:                        JavaCore.ERROR);
2134:
2135:                // Builder settings
2136:                defaultOptionsMap.put(
2137:                        JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, ""); //$NON-NLS-1$
2138:                defaultOptionsMap.put(
2139:                        JavaCore.CORE_JAVA_BUILD_INVALID_CLASSPATH,
2140:                        JavaCore.ABORT);
2141:                defaultOptionsMap.put(
2142:                        JavaCore.CORE_JAVA_BUILD_DUPLICATE_RESOURCE,
2143:                        JavaCore.WARNING);
2144:                defaultOptionsMap.put(
2145:                        JavaCore.CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER,
2146:                        JavaCore.CLEAN);
2147:
2148:                // JavaCore settings
2149:                defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_ORDER,
2150:                        JavaCore.IGNORE);
2151:                defaultOptionsMap.put(JavaCore.CORE_INCOMPLETE_CLASSPATH,
2152:                        JavaCore.ERROR);
2153:                defaultOptionsMap.put(JavaCore.CORE_CIRCULAR_CLASSPATH,
2154:                        JavaCore.ERROR);
2155:                defaultOptionsMap.put(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL,
2156:                        JavaCore.IGNORE);
2157:                defaultOptionsMap.put(
2158:                        JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS,
2159:                        JavaCore.ENABLED);
2160:                defaultOptionsMap
2161:                        .put(
2162:                                JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS,
2163:                                JavaCore.ENABLED);
2164:
2165:                // Formatter settings
2166:                defaultOptionsMap.putAll(DefaultCodeFormatterConstants
2167:                        .getEclipseDefaultSettings());
2168:
2169:                // CodeAssist settings
2170:                defaultOptionsMap.put(JavaCore.CODEASSIST_VISIBILITY_CHECK,
2171:                        JavaCore.DISABLED);
2172:                defaultOptionsMap.put(JavaCore.CODEASSIST_DEPRECATION_CHECK,
2173:                        JavaCore.DISABLED);
2174:                defaultOptionsMap.put(
2175:                        JavaCore.CODEASSIST_IMPLICIT_QUALIFICATION,
2176:                        JavaCore.DISABLED);
2177:                defaultOptionsMap.put(JavaCore.CODEASSIST_FIELD_PREFIXES, ""); //$NON-NLS-1$
2178:                defaultOptionsMap.put(
2179:                        JavaCore.CODEASSIST_STATIC_FIELD_PREFIXES, ""); //$NON-NLS-1$
2180:                defaultOptionsMap.put(JavaCore.CODEASSIST_LOCAL_PREFIXES, ""); //$NON-NLS-1$
2181:                defaultOptionsMap
2182:                        .put(JavaCore.CODEASSIST_ARGUMENT_PREFIXES, ""); //$NON-NLS-1$
2183:                defaultOptionsMap.put(JavaCore.CODEASSIST_FIELD_SUFFIXES, ""); //$NON-NLS-1$
2184:                defaultOptionsMap.put(
2185:                        JavaCore.CODEASSIST_STATIC_FIELD_SUFFIXES, ""); //$NON-NLS-1$
2186:                defaultOptionsMap.put(JavaCore.CODEASSIST_LOCAL_SUFFIXES, ""); //$NON-NLS-1$
2187:                defaultOptionsMap
2188:                        .put(JavaCore.CODEASSIST_ARGUMENT_SUFFIXES, ""); //$NON-NLS-1$
2189:                defaultOptionsMap.put(
2190:                        JavaCore.CODEASSIST_FORBIDDEN_REFERENCE_CHECK,
2191:                        JavaCore.ENABLED);
2192:                defaultOptionsMap.put(
2193:                        JavaCore.CODEASSIST_DISCOURAGED_REFERENCE_CHECK,
2194:                        JavaCore.DISABLED);
2195:                defaultOptionsMap.put(JavaCore.CODEASSIST_CAMEL_CASE_MATCH,
2196:                        JavaCore.ENABLED);
2197:                defaultOptionsMap.put(
2198:                        JavaCore.CODEASSIST_SUGGEST_STATIC_IMPORTS,
2199:                        JavaCore.ENABLED);
2200:
2201:                // Time out for parameter names
2202:                defaultOptionsMap
2203:                        .put(
2204:                                JavaCore.TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC,
2205:                                "50"); //$NON-NLS-1$
2206:
2207:                return new Hashtable(defaultOptionsMap);
2208:            }
2209:
2210:            /*
2211:             * Returns the per-project info for the given project. If specified, create the info if the info doesn't exist.
2212:             */
2213:            public PerProjectInfo getPerProjectInfo(IProject project,
2214:                    boolean create) {
2215:                synchronized (this .perProjectInfos) { // use the perProjectInfo collection as its own lock
2216:                    PerProjectInfo info = (PerProjectInfo) this .perProjectInfos
2217:                            .get(project);
2218:                    if (info == null && create) {
2219:                        info = new PerProjectInfo(project);
2220:                        this .perProjectInfos.put(project, info);
2221:                    }
2222:                    return info;
2223:                }
2224:            }
2225:
2226:            /*
2227:             * Returns  the per-project info for the given project.
2228:             * If the info doesn't exist, check for the project existence and create the info.
2229:             * @throws JavaModelException if the project doesn't exist.
2230:             */
2231:            public PerProjectInfo getPerProjectInfoCheckExistence(
2232:                    IProject project) throws JavaModelException {
2233:                JavaModelManager.PerProjectInfo info = getPerProjectInfo(
2234:                        project, false /* don't create info */);
2235:                if (info == null) {
2236:                    if (!JavaProject.hasJavaNature(project)) {
2237:                        throw ((JavaProject) JavaCore.create(project))
2238:                                .newNotPresentException();
2239:                    }
2240:                    info = getPerProjectInfo(project, true /* create info */);
2241:                }
2242:                return info;
2243:            }
2244:
2245:            /*
2246:             * Returns the per-working copy info for the given working copy at the given path.
2247:             * If it doesn't exist and if create, add a new per-working copy info with the given problem requestor.
2248:             * If recordUsage, increment the per-working copy info's use count.
2249:             * Returns null if it doesn't exist and not create.
2250:             */
2251:            public PerWorkingCopyInfo getPerWorkingCopyInfo(
2252:                    CompilationUnit workingCopy, boolean create,
2253:                    boolean recordUsage, IProblemRequestor problemRequestor) {
2254:                synchronized (this .perWorkingCopyInfos) { // use the perWorkingCopyInfo collection as its own lock
2255:                    WorkingCopyOwner owner = workingCopy.owner;
2256:                    Map workingCopyToInfos = (Map) this .perWorkingCopyInfos
2257:                            .get(owner);
2258:                    if (workingCopyToInfos == null && create) {
2259:                        workingCopyToInfos = new HashMap();
2260:                        this .perWorkingCopyInfos.put(owner, workingCopyToInfos);
2261:                    }
2262:
2263:                    PerWorkingCopyInfo info = workingCopyToInfos == null ? null
2264:                            : (PerWorkingCopyInfo) workingCopyToInfos
2265:                                    .get(workingCopy);
2266:                    if (info == null && create) {
2267:                        info = new PerWorkingCopyInfo(workingCopy,
2268:                                problemRequestor);
2269:                        workingCopyToInfos.put(workingCopy, info);
2270:                    }
2271:                    if (info != null && recordUsage)
2272:                        info.useCount++;
2273:                    return info;
2274:                }
2275:            }
2276:
2277:            /**
2278:             * Returns a persisted container from previous session if any. Note that it is not the original container from previous
2279:             * session (i.e. it did not get serialized) but rather a summary of its entries recreated for CP initialization purpose.
2280:             * As such it should not be stored into container caches.
2281:             */
2282:            public IClasspathContainer getPreviousSessionContainer(
2283:                    IPath containerPath, IJavaProject project) {
2284:                Map previousContainerValues = (Map) this .previousSessionContainers
2285:                        .get(project);
2286:                if (previousContainerValues != null) {
2287:                    IClasspathContainer previousContainer = (IClasspathContainer) previousContainerValues
2288:                            .get(containerPath);
2289:                    if (previousContainer != null) {
2290:                        if (JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED)
2291:                            verbose_reentering_project_container_access(
2292:                                    containerPath, project, previousContainer);
2293:                        return previousContainer;
2294:                    }
2295:                }
2296:                return null; // break cycle if none found
2297:            }
2298:
2299:            private void verbose_reentering_project_container_access(
2300:                    IPath containerPath, IJavaProject project,
2301:                    IClasspathContainer previousContainer) {
2302:                StringBuffer buffer = new StringBuffer();
2303:                buffer
2304:                        .append("CPContainer INIT - reentering access to project container during its initialization, will see previous value\n"); //$NON-NLS-1$ 
2305:                buffer.append("	project: " + project.getElementName() + '\n'); //$NON-NLS-1$
2306:                buffer.append("	container path: " + containerPath + '\n'); //$NON-NLS-1$
2307:                buffer.append("	previous value: "); //$NON-NLS-1$
2308:                buffer.append(previousContainer.getDescription());
2309:                buffer.append(" {\n"); //$NON-NLS-1$
2310:                IClasspathEntry[] entries = previousContainer
2311:                        .getClasspathEntries();
2312:                if (entries != null) {
2313:                    for (int j = 0; j < entries.length; j++) {
2314:                        buffer.append(" 		"); //$NON-NLS-1$
2315:                        buffer.append(entries[j]);
2316:                        buffer.append('\n');
2317:                    }
2318:                }
2319:                buffer.append(" 	}"); //$NON-NLS-1$
2320:                Util.verbose(buffer.toString());
2321:                new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
2322:            }
2323:
2324:            /**
2325:             * Returns a persisted container from previous session if any
2326:             */
2327:            public IPath getPreviousSessionVariable(String variableName) {
2328:                IPath previousPath = (IPath) this .previousSessionVariables
2329:                        .get(variableName);
2330:                if (previousPath != null) {
2331:                    if (CP_RESOLVE_VERBOSE_ADVANCED)
2332:                        verbose_reentering_variable_access(variableName,
2333:                                previousPath);
2334:                    return previousPath;
2335:                }
2336:                return null; // break cycle
2337:            }
2338:
2339:            private void verbose_reentering_variable_access(
2340:                    String variableName, IPath previousPath) {
2341:                Util
2342:                        .verbose("CPVariable INIT - reentering access to variable during its initialization, will see previous value\n" + //$NON-NLS-1$
2343:                                "	variable: " + variableName + '\n' + //$NON-NLS-1$
2344:                                "	previous value: " + previousPath); //$NON-NLS-1$
2345:                new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
2346:            }
2347:
2348:            /**
2349:             * Returns the temporary cache for newly opened elements for the current thread.
2350:             * Creates it if not already created.
2351:             */
2352:            public HashMap getTemporaryCache() {
2353:                HashMap result = (HashMap) this .temporaryCache.get();
2354:                if (result == null) {
2355:                    result = new HashMap();
2356:                    this .temporaryCache.set(result);
2357:                }
2358:                return result;
2359:            }
2360:
2361:            private File getVariableAndContainersFile() {
2362:                return JavaCore.getPlugin().getStateLocation().append(
2363:                        "variablesAndContainers.dat").toFile(); //$NON-NLS-1$
2364:            }
2365:
2366:            /**
2367:             * Returns the name of the variables for which an CP variable initializer is registered through an extension point
2368:             */
2369:            public static String[] getRegisteredVariableNames() {
2370:
2371:                Plugin jdtCorePlugin = JavaCore.getPlugin();
2372:                if (jdtCorePlugin == null)
2373:                    return null;
2374:
2375:                ArrayList variableList = new ArrayList(5);
2376:                IExtensionPoint extension = Platform
2377:                        .getExtensionRegistry()
2378:                        .getExtensionPoint(
2379:                                JavaCore.PLUGIN_ID,
2380:                                JavaModelManager.CPVARIABLE_INITIALIZER_EXTPOINT_ID);
2381:                if (extension != null) {
2382:                    IExtension[] extensions = extension.getExtensions();
2383:                    for (int i = 0; i < extensions.length; i++) {
2384:                        IConfigurationElement[] configElements = extensions[i]
2385:                                .getConfigurationElements();
2386:                        for (int j = 0; j < configElements.length; j++) {
2387:                            String varAttribute = configElements[j]
2388:                                    .getAttribute("variable"); //$NON-NLS-1$
2389:                            if (varAttribute != null)
2390:                                variableList.add(varAttribute);
2391:                        }
2392:                    }
2393:                }
2394:                String[] variableNames = new String[variableList.size()];
2395:                variableList.toArray(variableNames);
2396:                return variableNames;
2397:            }
2398:
2399:            /**
2400:             * Returns the name of the container IDs for which an CP container initializer is registered through an extension point
2401:             */
2402:            public static String[] getRegisteredContainerIDs() {
2403:
2404:                Plugin jdtCorePlugin = JavaCore.getPlugin();
2405:                if (jdtCorePlugin == null)
2406:                    return null;
2407:
2408:                ArrayList containerIDList = new ArrayList(5);
2409:                IExtensionPoint extension = Platform
2410:                        .getExtensionRegistry()
2411:                        .getExtensionPoint(
2412:                                JavaCore.PLUGIN_ID,
2413:                                JavaModelManager.CPCONTAINER_INITIALIZER_EXTPOINT_ID);
2414:                if (extension != null) {
2415:                    IExtension[] extensions = extension.getExtensions();
2416:                    for (int i = 0; i < extensions.length; i++) {
2417:                        IConfigurationElement[] configElements = extensions[i]
2418:                                .getConfigurationElements();
2419:                        for (int j = 0; j < configElements.length; j++) {
2420:                            String idAttribute = configElements[j]
2421:                                    .getAttribute("id"); //$NON-NLS-1$
2422:                            if (idAttribute != null)
2423:                                containerIDList.add(idAttribute);
2424:                        }
2425:                    }
2426:                }
2427:                String[] containerIDs = new String[containerIDList.size()];
2428:                containerIDList.toArray(containerIDs);
2429:                return containerIDs;
2430:            }
2431:
2432:            /**
2433:             * Returns the File to use for saving and restoring the last built state for the given project.
2434:             */
2435:            private File getSerializationFile(IProject project) {
2436:                if (!project.exists())
2437:                    return null;
2438:                IPath workingLocation = project
2439:                        .getWorkingLocation(JavaCore.PLUGIN_ID);
2440:                return workingLocation.append("state.dat").toFile(); //$NON-NLS-1$
2441:            }
2442:
2443:            public static UserLibraryManager getUserLibraryManager() {
2444:                if (MANAGER.userLibraryManager == null) {
2445:                    UserLibraryManager libraryManager = new UserLibraryManager();
2446:                    synchronized (MANAGER) {
2447:                        if (MANAGER.userLibraryManager == null) { // ensure another library manager was not set while creating the instance above
2448:                            MANAGER.userLibraryManager = libraryManager;
2449:                        }
2450:                    }
2451:                }
2452:                return MANAGER.userLibraryManager;
2453:            }
2454:
2455:            /*
2456:             * Returns all the working copies which have the given owner.
2457:             * Adds the working copies of the primary owner if specified.
2458:             * Returns null if it has none.
2459:             */
2460:            public ICompilationUnit[] getWorkingCopies(WorkingCopyOwner owner,
2461:                    boolean addPrimary) {
2462:                synchronized (this .perWorkingCopyInfos) {
2463:                    ICompilationUnit[] primaryWCs = addPrimary
2464:                            && owner != DefaultWorkingCopyOwner.PRIMARY ? getWorkingCopies(
2465:                            DefaultWorkingCopyOwner.PRIMARY, false)
2466:                            : null;
2467:                    Map workingCopyToInfos = (Map) this .perWorkingCopyInfos
2468:                            .get(owner);
2469:                    if (workingCopyToInfos == null)
2470:                        return primaryWCs;
2471:                    int primaryLength = primaryWCs == null ? 0
2472:                            : primaryWCs.length;
2473:                    int size = workingCopyToInfos.size(); // note size is > 0 otherwise pathToPerWorkingCopyInfos would be null
2474:                    ICompilationUnit[] result = new ICompilationUnit[primaryLength
2475:                            + size];
2476:                    int index = 0;
2477:                    if (primaryWCs != null) {
2478:                        for (int i = 0; i < primaryLength; i++) {
2479:                            ICompilationUnit primaryWorkingCopy = primaryWCs[i];
2480:                            ICompilationUnit workingCopy = new CompilationUnit(
2481:                                    (PackageFragment) primaryWorkingCopy
2482:                                            .getParent(), primaryWorkingCopy
2483:                                            .getElementName(), owner);
2484:                            if (!workingCopyToInfos.containsKey(workingCopy))
2485:                                result[index++] = primaryWorkingCopy;
2486:                        }
2487:                        if (index != primaryLength)
2488:                            System
2489:                                    .arraycopy(result, 0,
2490:                                            result = new ICompilationUnit[index
2491:                                                    + size], 0, index);
2492:                    }
2493:                    Iterator iterator = workingCopyToInfos.values().iterator();
2494:                    while (iterator.hasNext()) {
2495:                        result[index++] = ((JavaModelManager.PerWorkingCopyInfo) iterator
2496:                                .next()).getWorkingCopy();
2497:                    }
2498:                    return result;
2499:                }
2500:            }
2501:
2502:            public JavaWorkspaceScope getWorkspaceScope() {
2503:                if (this .workspaceScope == null) {
2504:                    this .workspaceScope = new JavaWorkspaceScope();
2505:                }
2506:                return this .workspaceScope;
2507:            }
2508:
2509:            /**
2510:             * Returns the open ZipFile at the given path. If the ZipFile
2511:             * does not yet exist, it is created, opened, and added to the cache
2512:             * of open ZipFiles. 
2513:             * 
2514:             * The path must be a file system path if representing an external 
2515:             * zip/jar, or it must be an absolute workspace relative path if 
2516:             * representing a zip/jar inside the workspace.
2517:             *
2518:             * @exception CoreException If unable to create/open the ZipFile
2519:             */
2520:            public ZipFile getZipFile(IPath path) throws CoreException {
2521:
2522:                HashMap map;
2523:                ZipFile zipFile;
2524:                if ((map = (HashMap) this .zipFiles.get()) != null
2525:                        && (zipFile = (ZipFile) map.get(path)) != null) {
2526:
2527:                    return zipFile;
2528:                }
2529:                File localFile = null;
2530:                IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
2531:                IResource file = root.findMember(path);
2532:                if (file != null) {
2533:                    // internal resource
2534:                    URI location;
2535:                    if (file.getType() != IResource.FILE
2536:                            || (location = file.getLocationURI()) == null) {
2537:                        throw new CoreException(new Status(IStatus.ERROR,
2538:                                JavaCore.PLUGIN_ID, -1, Messages
2539:                                        .bind(Messages.file_notFound, path
2540:                                                .toString()), null));
2541:                    }
2542:                    localFile = Util
2543:                            .toLocalFile(location, null/*no progress availaible*/);
2544:                    if (localFile == null)
2545:                        throw new CoreException(new Status(IStatus.ERROR,
2546:                                JavaCore.PLUGIN_ID, -1, Messages
2547:                                        .bind(Messages.file_notFound, path
2548:                                                .toString()), null));
2549:                } else {
2550:                    // external resource -> it is ok to use toFile()
2551:                    localFile = path.toFile();
2552:                }
2553:
2554:                try {
2555:                    if (ZIP_ACCESS_VERBOSE) {
2556:                        System.out
2557:                                .println("(" + Thread.currentThread() + ") [JavaModelManager.getZipFile(IPath)] Creating ZipFile on " + localFile); //$NON-NLS-1$ //$NON-NLS-2$
2558:                    }
2559:                    zipFile = new ZipFile(localFile);
2560:                    if (map != null) {
2561:                        map.put(path, zipFile);
2562:                    }
2563:                    return zipFile;
2564:                } catch (IOException e) {
2565:                    throw new CoreException(new Status(IStatus.ERROR,
2566:                            JavaCore.PLUGIN_ID, -1,
2567:                            Messages.status_IOException, e));
2568:                }
2569:            }
2570:
2571:            /*
2572:             * Returns whether there is a temporary cache for the current thread.
2573:             */
2574:            public boolean hasTemporaryCache() {
2575:                return this .temporaryCache.get() != null;
2576:            }
2577:
2578:            /*
2579:             * Initialize all container at the same time as the given container.
2580:             * Return the container for the given path and project.
2581:             */
2582:            private IClasspathContainer initializeAllContainers(
2583:                    IJavaProject javaProjectToInit, IPath containerToInit)
2584:                    throws JavaModelException {
2585:                if (CP_RESOLVE_VERBOSE_ADVANCED)
2586:                    verbose_batching_containers_initialization(
2587:                            javaProjectToInit, containerToInit);
2588:
2589:                // collect all container paths
2590:                final HashMap allContainerPaths = new HashMap();
2591:                IProject[] projects = ResourcesPlugin.getWorkspace().getRoot()
2592:                        .getProjects();
2593:                for (int i = 0, length = projects.length; i < length; i++) {
2594:                    IProject project = projects[i];
2595:                    if (!JavaProject.hasJavaNature(project))
2596:                        continue;
2597:                    IJavaProject javaProject = new JavaProject(project,
2598:                            getJavaModel());
2599:                    HashSet paths = (HashSet) allContainerPaths
2600:                            .get(javaProject);
2601:                    IClasspathEntry[] rawClasspath = javaProject
2602:                            .getRawClasspath();
2603:                    for (int j = 0, length2 = rawClasspath.length; j < length2; j++) {
2604:                        IClasspathEntry entry = rawClasspath[j];
2605:                        IPath path = entry.getPath();
2606:                        if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER
2607:                                && containerGet(javaProject, path) == null) {
2608:                            if (paths == null) {
2609:                                paths = new HashSet();
2610:                                allContainerPaths.put(javaProject, paths);
2611:                            }
2612:                            paths.add(path);
2613:                            // mark container as being initialized
2614:                            containerAddInitializationInProgress(javaProject,
2615:                                    path);
2616:                        }
2617:                    }
2618:                    /* TODO (frederic) put back when JDT/UI dummy project will be thrown away...
2619:                     * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=97524
2620:                     *
2621:                    if (javaProject.equals(javaProjectToInit)) {
2622:                    	if (paths == null) {
2623:                    		paths = new HashSet();
2624:                    		allContainerPaths.put(javaProject, paths);
2625:                    	}
2626:                    	paths.add(containerToInit);
2627:                    }
2628:                     */
2629:                }
2630:                // TODO (frederic) remove following block when JDT/UI dummy project will be thrown away...
2631:                HashSet containerPaths = (HashSet) allContainerPaths
2632:                        .get(javaProjectToInit);
2633:                if (containerPaths == null) {
2634:                    containerPaths = new HashSet();
2635:                    allContainerPaths.put(javaProjectToInit, containerPaths);
2636:                }
2637:                containerPaths.add(containerToInit);
2638:                // mark container as being initialized
2639:                containerAddInitializationInProgress(javaProjectToInit,
2640:                        containerToInit);
2641:                // end block
2642:
2643:                // initialize all containers
2644:                boolean ok = false;
2645:                try {
2646:                    // if possible run inside an IWokspaceRunnable with AVOID_UPATE to avoid unwanted builds
2647:                    // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=118507)
2648:                    IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
2649:                        public void run(IProgressMonitor monitor)
2650:                                throws CoreException {
2651:                            try {
2652:                                Set entrySet = allContainerPaths.entrySet();
2653:                                int length = entrySet.size();
2654:                                if (monitor != null)
2655:                                    monitor.beginTask("", length); //$NON-NLS-1$
2656:                                Map.Entry[] entries = new Map.Entry[length]; // clone as the following will have a side effect
2657:                                entrySet.toArray(entries);
2658:                                for (int i = 0; i < length; i++) {
2659:                                    Map.Entry entry = entries[i];
2660:                                    IJavaProject javaProject = (IJavaProject) entry
2661:                                            .getKey();
2662:                                    HashSet pathSet = (HashSet) entry
2663:                                            .getValue();
2664:                                    if (pathSet == null)
2665:                                        continue;
2666:                                    int length2 = pathSet.size();
2667:                                    IPath[] paths = new IPath[length2];
2668:                                    pathSet.toArray(paths); // clone as the following will have a side effect
2669:                                    for (int j = 0; j < length2; j++) {
2670:                                        IPath path = paths[j];
2671:                                        initializeContainer(javaProject, path);
2672:                                    }
2673:                                    if (monitor != null)
2674:                                        monitor.worked(1);
2675:                                }
2676:                            } finally {
2677:                                if (monitor != null)
2678:                                    monitor.done();
2679:                            }
2680:                        }
2681:                    };
2682:                    IProgressMonitor monitor = (IProgressMonitor) this .batchContainerInitializationsProgress
2683:                            .get();
2684:                    IWorkspace workspace = ResourcesPlugin.getWorkspace();
2685:                    if (workspace.isTreeLocked())
2686:                        runnable.run(monitor);
2687:                    else
2688:                        workspace.run(runnable, null/*don't take any lock*/,
2689:                                IWorkspace.AVOID_UPDATE, monitor);
2690:                    ok = true;
2691:                } catch (CoreException e) {
2692:                    // ignore
2693:                    Util.log(e, "Exception while initializing all containers"); //$NON-NLS-1$
2694:                } finally {
2695:                    if (!ok) {
2696:                        // if we're being traversed by an exception, ensure that that containers are 
2697:                        // no longer marked as initialization in progress
2698:                        // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=66437)
2699:                        this .containerInitializationInProgress.set(null);
2700:                    }
2701:                }
2702:
2703:                return containerGet(javaProjectToInit, containerToInit);
2704:            }
2705:
2706:            private void verbose_batching_containers_initialization(
2707:                    IJavaProject javaProjectToInit, IPath containerToInit) {
2708:                Util
2709:                        .verbose("CPContainer INIT - batching containers initialization\n" + //$NON-NLS-1$
2710:                                "	project to init: "
2711:                                + javaProjectToInit.getElementName() + '\n' + //$NON-NLS-1$
2712:                                "	container path to init: " + containerToInit); //$NON-NLS-1$
2713:            }
2714:
2715:            IClasspathContainer initializeContainer(IJavaProject project,
2716:                    IPath containerPath) throws JavaModelException {
2717:
2718:                IProgressMonitor monitor = (IProgressMonitor) this .batchContainerInitializationsProgress
2719:                        .get();
2720:                if (monitor != null && monitor.isCanceled())
2721:                    throw new OperationCanceledException();
2722:
2723:                IClasspathContainer container = null;
2724:                final ClasspathContainerInitializer initializer = JavaCore
2725:                        .getClasspathContainerInitializer(containerPath
2726:                                .segment(0));
2727:                if (initializer != null) {
2728:                    if (CP_RESOLVE_VERBOSE)
2729:                        verbose_triggering_container_initialization(project,
2730:                                containerPath, initializer);
2731:                    if (CP_RESOLVE_VERBOSE_ADVANCED)
2732:                        verbose_triggering_container_initialization_invocation_trace();
2733:                    PerformanceStats stats = null;
2734:                    if (JavaModelManager.PERF_CONTAINER_INITIALIZER) {
2735:                        stats = PerformanceStats.getStats(
2736:                                JavaModelManager.CONTAINER_INITIALIZER_PERF,
2737:                                this );
2738:                        stats.startRun(containerPath
2739:                                + " of " + project.getPath()); //$NON-NLS-1$
2740:                    }
2741:                    containerPut(project, containerPath,
2742:                            CONTAINER_INITIALIZATION_IN_PROGRESS); // avoid initialization cycles
2743:                    boolean ok = false;
2744:                    try {
2745:                        if (monitor != null)
2746:                            monitor.subTask(Messages.bind(
2747:                                    Messages.javamodel_configuring, initializer
2748:                                            .getDescription(containerPath,
2749:                                                    project)));
2750:
2751:                        // let OperationCanceledException go through
2752:                        // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=59363)
2753:                        initializer.initialize(containerPath, project);
2754:
2755:                        if (monitor != null)
2756:                            monitor.subTask(""); //$NON-NLS-1$
2757:
2758:                        // retrieve value (if initialization was successful)
2759:                        container = containerGet(project, containerPath);
2760:                        if (container == CONTAINER_INITIALIZATION_IN_PROGRESS) {
2761:                            // initializer failed to do its job: redirect to the failure container
2762:                            container = initializer.getFailureContainer(
2763:                                    containerPath, project);
2764:                            if (container == null) {
2765:                                if (CP_RESOLVE_VERBOSE)
2766:                                    verbose_container_null_failure_container(
2767:                                            project, containerPath, initializer);
2768:                                return null; // break cycle
2769:                            }
2770:                            if (CP_RESOLVE_VERBOSE)
2771:                                verbose_container_using_failure_container(
2772:                                        project, containerPath, initializer);
2773:                            containerPut(project, containerPath, container);
2774:                        }
2775:                        ok = true;
2776:                    } catch (CoreException e) {
2777:                        if (e instanceof  JavaModelException) {
2778:                            throw (JavaModelException) e;
2779:                        } else {
2780:                            throw new JavaModelException(e);
2781:                        }
2782:                    } catch (RuntimeException e) {
2783:                        if (JavaModelManager.CP_RESOLVE_VERBOSE)
2784:                            e.printStackTrace();
2785:                        throw e;
2786:                    } catch (Error e) {
2787:                        if (JavaModelManager.CP_RESOLVE_VERBOSE)
2788:                            e.printStackTrace();
2789:                        throw e;
2790:                    } finally {
2791:                        if (JavaModelManager.PERF_CONTAINER_INITIALIZER) {
2792:                            stats.endRun();
2793:                        }
2794:                        if (!ok) {
2795:                            // just remove initialization in progress and keep previous session container so as to avoid a full build
2796:                            // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=92588
2797:                            containerRemoveInitializationInProgress(project,
2798:                                    containerPath);
2799:                            if (CP_RESOLVE_VERBOSE)
2800:                                verbose_container_initialization_failed(
2801:                                        project, containerPath, container,
2802:                                        initializer);
2803:                        }
2804:                    }
2805:                    if (CP_RESOLVE_VERBOSE_ADVANCED)
2806:                        verbose_container_value_after_initialization(project,
2807:                                containerPath, container);
2808:                } else {
2809:                    // create a dummy initializer and get the default failure container
2810:                    container = (new ClasspathContainerInitializer() {
2811:                        public void initialize(IPath path,
2812:                                IJavaProject javaProject) throws CoreException {
2813:                            // not used
2814:                        }
2815:                    }).getFailureContainer(containerPath, project);
2816:                    if (CP_RESOLVE_VERBOSE_ADVANCED)
2817:                        verbose_no_container_initializer_found(project,
2818:                                containerPath);
2819:                }
2820:                return container;
2821:            }
2822:
2823:            private void verbose_no_container_initializer_found(
2824:                    IJavaProject project, IPath containerPath) {
2825:                Util.verbose("CPContainer INIT - no initializer found\n" + //$NON-NLS-1$
2826:                        "	project: " + project.getElementName() + '\n' + //$NON-NLS-1$
2827:                        "	container path: " + containerPath); //$NON-NLS-1$
2828:            }
2829:
2830:            private void verbose_container_value_after_initialization(
2831:                    IJavaProject project, IPath containerPath,
2832:                    IClasspathContainer container) {
2833:                StringBuffer buffer = new StringBuffer();
2834:                buffer.append("CPContainer INIT - after resolution\n"); //$NON-NLS-1$
2835:                buffer.append("	project: " + project.getElementName() + '\n'); //$NON-NLS-1$
2836:                buffer.append("	container path: " + containerPath + '\n'); //$NON-NLS-1$
2837:                if (container != null) {
2838:                    buffer
2839:                            .append("	container: " + container.getDescription() + " {\n"); //$NON-NLS-2$//$NON-NLS-1$
2840:                    IClasspathEntry[] entries = container.getClasspathEntries();
2841:                    if (entries != null) {
2842:                        for (int i = 0; i < entries.length; i++) {
2843:                            buffer.append("		" + entries[i] + '\n'); //$NON-NLS-1$
2844:                        }
2845:                    }
2846:                    buffer.append("	}");//$NON-NLS-1$
2847:                } else {
2848:                    buffer.append("	container: {unbound}");//$NON-NLS-1$
2849:                }
2850:                Util.verbose(buffer.toString());
2851:            }
2852:
2853:            private void verbose_container_initialization_failed(
2854:                    IJavaProject project, IPath containerPath,
2855:                    IClasspathContainer container,
2856:                    ClasspathContainerInitializer initializer) {
2857:                if (container == CONTAINER_INITIALIZATION_IN_PROGRESS) {
2858:                    Util
2859:                            .verbose("CPContainer INIT - FAILED (initializer did not initialize container)\n" + //$NON-NLS-1$
2860:                                    "	project: "
2861:                                    + project.getElementName()
2862:                                    + '\n' + //$NON-NLS-1$
2863:                                    "	container path: " + containerPath + '\n' + //$NON-NLS-1$
2864:                                    "	initializer: " + initializer); //$NON-NLS-1$
2865:
2866:                } else {
2867:                    Util
2868:                            .verbose("CPContainer INIT - FAILED (see exception above)\n" + //$NON-NLS-1$
2869:                                    "	project: "
2870:                                    + project.getElementName()
2871:                                    + '\n' + //$NON-NLS-1$
2872:                                    "	container path: " + containerPath + '\n' + //$NON-NLS-1$
2873:                                    "	initializer: " + initializer); //$NON-NLS-1$
2874:                }
2875:            }
2876:
2877:            private void verbose_container_null_failure_container(
2878:                    IJavaProject project, IPath containerPath,
2879:                    ClasspathContainerInitializer initializer) {
2880:                Util
2881:                        .verbose("CPContainer INIT - FAILED (and failure container is null)\n" + //$NON-NLS-1$
2882:                                "	project: " + project.getElementName() + '\n' + //$NON-NLS-1$
2883:                                "	container path: " + containerPath + '\n' + //$NON-NLS-1$
2884:                                "	initializer: " + initializer); //$NON-NLS-1$
2885:            }
2886:
2887:            private void verbose_container_using_failure_container(
2888:                    IJavaProject project, IPath containerPath,
2889:                    ClasspathContainerInitializer initializer) {
2890:                Util
2891:                        .verbose("CPContainer INIT - FAILED (using failure container)\n" + //$NON-NLS-1$
2892:                                "	project: " + project.getElementName() + '\n' + //$NON-NLS-1$
2893:                                "	container path: " + containerPath + '\n' + //$NON-NLS-1$
2894:                                "	initializer: " + initializer); //$NON-NLS-1$
2895:            }
2896:
2897:            private void verbose_triggering_container_initialization(
2898:                    IJavaProject project, IPath containerPath,
2899:                    ClasspathContainerInitializer initializer) {
2900:                Util.verbose("CPContainer INIT - triggering initialization\n" + //$NON-NLS-1$
2901:                        "	project: " + project.getElementName() + '\n' + //$NON-NLS-1$
2902:                        "	container path: " + containerPath + '\n' + //$NON-NLS-1$
2903:                        "	initializer: " + initializer); //$NON-NLS-1$
2904:            }
2905:
2906:            private void verbose_triggering_container_initialization_invocation_trace() {
2907:                Util.verbose("CPContainer INIT - triggering initialization\n" + //$NON-NLS-1$
2908:                        "	invocation trace:"); //$NON-NLS-1$
2909:                new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
2910:            }
2911:
2912:            /**
2913:             * Initialize preferences lookups for JavaCore plug-in.
2914:             */
2915:            public void initializePreferences() {
2916:
2917:                // Create lookups
2918:                preferencesLookup[PREF_INSTANCE] = ((IScopeContext) new InstanceScope())
2919:                        .getNode(JavaCore.PLUGIN_ID);
2920:                preferencesLookup[PREF_DEFAULT] = ((IScopeContext) new DefaultScope())
2921:                        .getNode(JavaCore.PLUGIN_ID);
2922:
2923:                // Listen to instance preferences node removal from parent in order to refresh stored one
2924:                this .instanceNodeListener = new IEclipsePreferences.INodeChangeListener() {
2925:                    public void added(IEclipsePreferences.NodeChangeEvent event) {
2926:                        // do nothing
2927:                    }
2928:
2929:                    public void removed(
2930:                            IEclipsePreferences.NodeChangeEvent event) {
2931:                        if (event.getChild() == preferencesLookup[PREF_INSTANCE]) {
2932:                            preferencesLookup[PREF_INSTANCE] = ((IScopeContext) new InstanceScope())
2933:                                    .getNode(JavaCore.PLUGIN_ID);
2934:                            preferencesLookup[PREF_INSTANCE]
2935:                                    .addPreferenceChangeListener(new EclipsePreferencesListener());
2936:                        }
2937:                    }
2938:                };
2939:                ((IEclipsePreferences) preferencesLookup[PREF_INSTANCE]
2940:                        .parent())
2941:                        .addNodeChangeListener(this .instanceNodeListener);
2942:                preferencesLookup[PREF_INSTANCE]
2943:                        .addPreferenceChangeListener(this .instancePreferencesListener = new EclipsePreferencesListener());
2944:
2945:                // Listen to default preferences node removal from parent in order to refresh stored one
2946:                this .defaultNodeListener = new IEclipsePreferences.INodeChangeListener() {
2947:                    public void added(IEclipsePreferences.NodeChangeEvent event) {
2948:                        // do nothing
2949:                    }
2950:
2951:                    public void removed(
2952:                            IEclipsePreferences.NodeChangeEvent event) {
2953:                        if (event.getChild() == preferencesLookup[PREF_DEFAULT]) {
2954:                            preferencesLookup[PREF_DEFAULT] = ((IScopeContext) new DefaultScope())
2955:                                    .getNode(JavaCore.PLUGIN_ID);
2956:                        }
2957:                    }
2958:                };
2959:                ((IEclipsePreferences) preferencesLookup[PREF_DEFAULT].parent())
2960:                        .addNodeChangeListener(this .defaultNodeListener);
2961:            }
2962:
2963:            public synchronized char[] intern(char[] array) {
2964:                return this .charArraySymbols.add(array);
2965:            }
2966:
2967:            public synchronized String intern(String s) {
2968:                // make sure to copy the string (so that it doesn't hold on the underlying char[] that might be much bigger than necessary)
2969:                return (String) this .stringSymbols.add(new String(s));
2970:
2971:                // Note1: String#intern() cannot be used as on some VMs this prevents the string from being garbage collected
2972:                // Note 2: Instead of using a WeakHashset, one could use a WeakHashMap with the following implementation
2973:                // 			   This would costs more per entry (one Entry object and one WeakReference more))
2974:
2975:                /*
2976:                WeakReference reference = (WeakReference) this.symbols.get(s);
2977:                String existing;
2978:                if (reference != null && (existing = (String) reference.get()) != null)
2979:                	return existing;
2980:                this.symbols.put(s, new WeakReference(s));
2981:                return s;
2982:                 */
2983:            }
2984:
2985:            private HashSet getClasspathBeingResolved() {
2986:                HashSet result = (HashSet) this .classpathsBeingResolved.get();
2987:                if (result == null) {
2988:                    result = new HashSet();
2989:                    this .classpathsBeingResolved.set(result);
2990:                }
2991:                return result;
2992:            }
2993:
2994:            public boolean isClasspathBeingResolved(IJavaProject project) {
2995:                return getClasspathBeingResolved().contains(project);
2996:            }
2997:
2998:            /**
2999:             * @deprecated
3000:             */
3001:            private boolean isDeprecatedOption(String optionName) {
3002:                return JavaCore.COMPILER_PB_INVALID_IMPORT.equals(optionName)
3003:                        || JavaCore.COMPILER_PB_UNREACHABLE_CODE
3004:                                .equals(optionName);
3005:            }
3006:
3007:            public void setClasspathBeingResolved(IJavaProject project,
3008:                    boolean classpathIsResolved) {
3009:                if (classpathIsResolved) {
3010:                    getClasspathBeingResolved().add(project);
3011:                } else {
3012:                    getClasspathBeingResolved().remove(project);
3013:                }
3014:            }
3015:
3016:            public void loadVariablesAndContainers() throws CoreException {
3017:                // backward compatibility, consider persistent property	
3018:                QualifiedName qName = new QualifiedName(JavaCore.PLUGIN_ID,
3019:                        "variables"); //$NON-NLS-1$
3020:                String xmlString = ResourcesPlugin.getWorkspace().getRoot()
3021:                        .getPersistentProperty(qName);
3022:
3023:                try {
3024:                    if (xmlString != null) {
3025:                        StringReader reader = new StringReader(xmlString);
3026:                        Element cpElement;
3027:                        try {
3028:                            DocumentBuilder parser = DocumentBuilderFactory
3029:                                    .newInstance().newDocumentBuilder();
3030:                            cpElement = parser.parse(new InputSource(reader))
3031:                                    .getDocumentElement();
3032:                        } catch (SAXException e) {
3033:                            return;
3034:                        } catch (ParserConfigurationException e) {
3035:                            return;
3036:                        } finally {
3037:                            reader.close();
3038:                        }
3039:                        if (cpElement == null)
3040:                            return;
3041:                        if (!cpElement.getNodeName().equalsIgnoreCase(
3042:                                "variables")) { //$NON-NLS-1$
3043:                            return;
3044:                        }
3045:
3046:                        NodeList list = cpElement.getChildNodes();
3047:                        int length = list.getLength();
3048:                        for (int i = 0; i < length; ++i) {
3049:                            Node node = list.item(i);
3050:                            short type = node.getNodeType();
3051:                            if (type == Node.ELEMENT_NODE) {
3052:                                Element element = (Element) node;
3053:                                if (element.getNodeName().equalsIgnoreCase(
3054:                                        "variable")) { //$NON-NLS-1$
3055:                                    variablePut(element.getAttribute("name"), //$NON-NLS-1$
3056:                                            new Path(element
3057:                                                    .getAttribute("path"))); //$NON-NLS-1$
3058:                                }
3059:                            }
3060:                        }
3061:                    }
3062:                } catch (IOException e) {
3063:                    // problem loading xml file: nothing we can do
3064:                } finally {
3065:                    if (xmlString != null) {
3066:                        ResourcesPlugin.getWorkspace().getRoot()
3067:                                .setPersistentProperty(qName, null); // flush old one
3068:                    }
3069:                }
3070:
3071:                // backward compatibility, load variables and containers from preferences into cache
3072:                loadVariablesAndContainers(getDefaultPreferences());
3073:                loadVariablesAndContainers(getInstancePreferences());
3074:
3075:                // load variables and containers from saved file into cache
3076:                File file = getVariableAndContainersFile();
3077:                DataInputStream in = null;
3078:                try {
3079:                    in = new DataInputStream(new BufferedInputStream(
3080:                            new FileInputStream(file)));
3081:                    switch (in.readInt()) {
3082:                    case 2:
3083:                        new VariablesAndContainersLoadHelper(in).load();
3084:                        break;
3085:                    case 1: // backward compatibility, load old format
3086:                        // variables
3087:                        int size = in.readInt();
3088:                        while (size-- > 0) {
3089:                            String varName = in.readUTF();
3090:                            String pathString = in.readUTF();
3091:                            if (CP_ENTRY_IGNORE.equals(pathString))
3092:                                continue;
3093:                            IPath varPath = Path.fromPortableString(pathString);
3094:                            this .variables.put(varName, varPath);
3095:                            this .previousSessionVariables.put(varName, varPath);
3096:                        }
3097:
3098:                        // containers
3099:                        IJavaModel model = getJavaModel();
3100:                        int projectSize = in.readInt();
3101:                        while (projectSize-- > 0) {
3102:                            String projectName = in.readUTF();
3103:                            IJavaProject project = model
3104:                                    .getJavaProject(projectName);
3105:                            int containerSize = in.readInt();
3106:                            while (containerSize-- > 0) {
3107:                                IPath containerPath = Path
3108:                                        .fromPortableString(in.readUTF());
3109:                                int length = in.readInt();
3110:                                byte[] containerString = new byte[length];
3111:                                in.readFully(containerString);
3112:                                recreatePersistedContainer(project,
3113:                                        containerPath, new String(
3114:                                                containerString), true/*add to container values*/);
3115:                            }
3116:                        }
3117:                        break;
3118:                    }
3119:                } catch (IOException e) {
3120:                    if (file.exists())
3121:                        Util.log(e,
3122:                                "Unable to read variable and containers file"); //$NON-NLS-1$
3123:                } catch (RuntimeException e) {
3124:                    if (file.exists())
3125:                        Util
3126:                                .log(e,
3127:                                        "Unable to read variable and containers file (file is corrupt)"); //$NON-NLS-1$
3128:                } finally {
3129:                    if (in != null) {
3130:                        try {
3131:                            in.close();
3132:                        } catch (IOException e) {
3133:                            // nothing we can do: ignore
3134:                        }
3135:                    }
3136:                }
3137:
3138:                // override persisted values for variables which have a registered initializer
3139:                String[] registeredVariables = getRegisteredVariableNames();
3140:                for (int i = 0; i < registeredVariables.length; i++) {
3141:                    String varName = registeredVariables[i];
3142:                    this .variables.put(varName, null); // reset variable, but leave its entry in the Map, so it will be part of variable names.
3143:                }
3144:                // override persisted values for containers which have a registered initializer
3145:                containersReset(getRegisteredContainerIDs());
3146:            }
3147:
3148:            private void loadVariablesAndContainers(
3149:                    IEclipsePreferences preferences) {
3150:                try {
3151:                    // only get variable from preferences not set to their default
3152:                    String[] propertyNames = preferences.keys();
3153:                    int variablePrefixLength = CP_VARIABLE_PREFERENCES_PREFIX
3154:                            .length();
3155:                    for (int i = 0; i < propertyNames.length; i++) {
3156:                        String propertyName = propertyNames[i];
3157:                        if (propertyName
3158:                                .startsWith(CP_VARIABLE_PREFERENCES_PREFIX)) {
3159:                            String varName = propertyName
3160:                                    .substring(variablePrefixLength);
3161:                            String propertyValue = preferences.get(
3162:                                    propertyName, null);
3163:                            if (propertyValue != null) {
3164:                                String pathString = propertyValue.trim();
3165:
3166:                                if (CP_ENTRY_IGNORE.equals(pathString)) {
3167:                                    // cleanup old preferences
3168:                                    preferences.remove(propertyName);
3169:                                    continue;
3170:                                }
3171:
3172:                                // add variable to table
3173:                                IPath varPath = new Path(pathString);
3174:                                this .variables.put(varName, varPath);
3175:                                this .previousSessionVariables.put(varName,
3176:                                        varPath);
3177:                            }
3178:                        } else if (propertyName
3179:                                .startsWith(CP_CONTAINER_PREFERENCES_PREFIX)) {
3180:                            String propertyValue = preferences.get(
3181:                                    propertyName, null);
3182:                            if (propertyValue != null) {
3183:                                // cleanup old preferences
3184:                                preferences.remove(propertyName);
3185:
3186:                                // recreate container
3187:                                recreatePersistedContainer(propertyName,
3188:                                        propertyValue, true/*add to container values*/);
3189:                            }
3190:                        }
3191:                    }
3192:                } catch (BackingStoreException e1) {
3193:                    // TODO (frederic) see if it's necessary to report this failure...
3194:                }
3195:            }
3196:
3197:            private static final class PersistedClasspathContainer implements 
3198:                    IClasspathContainer {
3199:
3200:                private final IPath containerPath;
3201:
3202:                private final IClasspathEntry[] entries;
3203:
3204:                private final IJavaProject project;
3205:
3206:                PersistedClasspathContainer(IJavaProject project,
3207:                        IPath containerPath, IClasspathEntry[] entries) {
3208:                    super ();
3209:                    this .containerPath = containerPath;
3210:                    this .entries = entries;
3211:                    this .project = project;
3212:                }
3213:
3214:                public IClasspathEntry[] getClasspathEntries() {
3215:                    return entries;
3216:                }
3217:
3218:                public String getDescription() {
3219:                    return "Persisted container [" + containerPath //$NON-NLS-1$
3220:                            + " for project [" + project.getElementName() //$NON-NLS-1$
3221:                            + "]]"; //$NON-NLS-1$  
3222:                }
3223:
3224:                public int getKind() {
3225:                    return 0;
3226:                }
3227:
3228:                public IPath getPath() {
3229:                    return containerPath;
3230:                }
3231:
3232:                public String toString() {
3233:                    return getDescription();
3234:                }
3235:            }
3236:
3237:            private final class VariablesAndContainersLoadHelper {
3238:
3239:                private static final int ARRAY_INCREMENT = 200;
3240:
3241:                private IClasspathEntry[] allClasspathEntries;
3242:                private int allClasspathEntryCount;
3243:
3244:                private final Map allPaths; // String -> IPath
3245:
3246:                private String[] allStrings;
3247:                private int allStringsCount;
3248:
3249:                private final DataInputStream in;
3250:
3251:                VariablesAndContainersLoadHelper(DataInputStream in) {
3252:                    super ();
3253:                    this .allClasspathEntries = null;
3254:                    this .allClasspathEntryCount = 0;
3255:                    this .allPaths = new HashMap();
3256:                    this .allStrings = null;
3257:                    this .allStringsCount = 0;
3258:                    this .in = in;
3259:                }
3260:
3261:                void load() throws IOException {
3262:                    loadProjects(JavaModelManager.this .getJavaModel());
3263:                    loadVariables();
3264:                }
3265:
3266:                private IAccessRule loadAccessRule() throws IOException {
3267:                    int problemId = loadInt();
3268:                    IPath pattern = loadPath();
3269:                    return new ClasspathAccessRule(pattern.toString()
3270:                            .toCharArray(), problemId);
3271:                }
3272:
3273:                private IAccessRule[] loadAccessRules() throws IOException {
3274:                    int count = loadInt();
3275:
3276:                    if (count == 0)
3277:                        return ClasspathEntry.NO_ACCESS_RULES;
3278:
3279:                    IAccessRule[] rules = new IAccessRule[count];
3280:
3281:                    for (int i = 0; i < count; ++i)
3282:                        rules[i] = loadAccessRule();
3283:
3284:                    return rules;
3285:                }
3286:
3287:                private IClasspathAttribute loadAttribute() throws IOException {
3288:                    String name = loadString();
3289:                    String value = loadString();
3290:
3291:                    return new ClasspathAttribute(name, value);
3292:                }
3293:
3294:                private IClasspathAttribute[] loadAttributes()
3295:                        throws IOException {
3296:                    int count = loadInt();
3297:
3298:                    if (count == 0)
3299:                        return ClasspathEntry.NO_EXTRA_ATTRIBUTES;
3300:
3301:                    IClasspathAttribute[] attributes = new IClasspathAttribute[count];
3302:
3303:                    for (int i = 0; i < count; ++i)
3304:                        attributes[i] = loadAttribute();
3305:
3306:                    return attributes;
3307:                }
3308:
3309:                private boolean loadBoolean() throws IOException {
3310:                    return this .in.readBoolean();
3311:                }
3312:
3313:                private IClasspathEntry[] loadClasspathEntries()
3314:                        throws IOException {
3315:                    int count = loadInt();
3316:                    IClasspathEntry[] entries = new IClasspathEntry[count];
3317:
3318:                    for (int i = 0; i < count; ++i)
3319:                        entries[i] = loadClasspathEntry();
3320:
3321:                    return entries;
3322:                }
3323:
3324:                private IClasspathEntry loadClasspathEntry() throws IOException {
3325:                    int id = loadInt();
3326:
3327:                    if (id < 0 || id > this .allClasspathEntryCount)
3328:                        throw new IOException("Unexpected classpathentry id"); //$NON-NLS-1$
3329:
3330:                    if (id < this .allClasspathEntryCount)
3331:                        return this .allClasspathEntries[id];
3332:
3333:                    int contentKind = loadInt();
3334:                    int entryKind = loadInt();
3335:                    IPath path = loadPath();
3336:                    IPath[] inclusionPatterns = loadPaths();
3337:                    IPath[] exclusionPatterns = loadPaths();
3338:                    IPath sourceAttachmentPath = loadPath();
3339:                    IPath sourceAttachmentRootPath = loadPath();
3340:                    IPath specificOutputLocation = loadPath();
3341:                    boolean isExported = loadBoolean();
3342:                    IAccessRule[] accessRules = loadAccessRules();
3343:                    boolean combineAccessRules = loadBoolean();
3344:                    IClasspathAttribute[] extraAttributes = loadAttributes();
3345:
3346:                    IClasspathEntry entry = new ClasspathEntry(contentKind,
3347:                            entryKind, path, inclusionPatterns,
3348:                            exclusionPatterns, sourceAttachmentPath,
3349:                            sourceAttachmentRootPath, specificOutputLocation,
3350:                            isExported, accessRules, combineAccessRules,
3351:                            extraAttributes);
3352:
3353:                    IClasspathEntry[] array = this .allClasspathEntries;
3354:
3355:                    if (array == null || id == array.length) {
3356:                        array = new IClasspathEntry[id + ARRAY_INCREMENT];
3357:
3358:                        if (id != 0)
3359:                            System.arraycopy(this .allClasspathEntries, 0,
3360:                                    array, 0, id);
3361:
3362:                        this .allClasspathEntries = array;
3363:                    }
3364:
3365:                    array[id] = entry;
3366:                    this .allClasspathEntryCount = id + 1;
3367:
3368:                    return entry;
3369:                }
3370:
3371:                private void loadContainers(IJavaProject project)
3372:                        throws IOException {
3373:                    boolean projectIsAccessible = project.getProject()
3374:                            .isAccessible();
3375:                    int count = loadInt();
3376:                    for (int i = 0; i < count; ++i) {
3377:                        IPath path = loadPath();
3378:                        IClasspathEntry[] entries = loadClasspathEntries();
3379:
3380:                        if (!projectIsAccessible)
3381:                            // avoid leaking deleted project's persisted container,
3382:                            // but still read the container as it is is part of the file format
3383:                            continue;
3384:
3385:                        IClasspathContainer container = new PersistedClasspathContainer(
3386:                                project, path, entries);
3387:
3388:                        JavaModelManager.this .containerPut(project, path,
3389:                                container);
3390:
3391:                        Map oldContainers = (Map) JavaModelManager.this .previousSessionContainers
3392:                                .get(project);
3393:
3394:                        if (oldContainers == null) {
3395:                            oldContainers = new HashMap();
3396:                            JavaModelManager.this .previousSessionContainers
3397:                                    .put(project, oldContainers);
3398:                        }
3399:
3400:                        oldContainers.put(path, container);
3401:                    }
3402:                }
3403:
3404:                private int loadInt() throws IOException {
3405:                    return this .in.readInt();
3406:                }
3407:
3408:                private IPath loadPath() throws IOException {
3409:                    if (loadBoolean())
3410:                        return null;
3411:
3412:                    String portableString = loadString();
3413:                    IPath path = (IPath) this .allPaths.get(portableString);
3414:
3415:                    if (path == null) {
3416:                        path = Path.fromPortableString(portableString);
3417:                        this .allPaths.put(portableString, path);
3418:                    }
3419:
3420:                    return path;
3421:                }
3422:
3423:                private IPath[] loadPaths() throws IOException {
3424:                    int count = loadInt();
3425:                    IPath[] pathArray = new IPath[count];
3426:
3427:                    for (int i = 0; i < count; ++i)
3428:                        pathArray[i] = loadPath();
3429:
3430:                    return pathArray;
3431:                }
3432:
3433:                private void loadProjects(IJavaModel model) throws IOException {
3434:                    int count = loadInt();
3435:
3436:                    for (int i = 0; i < count; ++i) {
3437:                        String projectName = loadString();
3438:
3439:                        loadContainers(model.getJavaProject(projectName));
3440:                    }
3441:                }
3442:
3443:                private String loadString() throws IOException {
3444:                    int id = loadInt();
3445:
3446:                    if (id < 0 || id > this .allStringsCount)
3447:                        throw new IOException("Unexpected string id"); //$NON-NLS-1$
3448:
3449:                    if (id < this .allStringsCount)
3450:                        return this .allStrings[id];
3451:
3452:                    String string = this .in.readUTF();
3453:                    String[] array = this .allStrings;
3454:
3455:                    if (array == null || id == array.length) {
3456:                        array = new String[id + ARRAY_INCREMENT];
3457:
3458:                        if (id != 0)
3459:                            System.arraycopy(this .allStrings, 0, array, 0, id);
3460:
3461:                        this .allStrings = array;
3462:                    }
3463:
3464:                    array[id] = string;
3465:                    this .allStringsCount = id + 1;
3466:
3467:                    return string;
3468:                }
3469:
3470:                private void loadVariables() throws IOException {
3471:                    int size = loadInt();
3472:                    Map loadedVars = new HashMap(size);
3473:
3474:                    for (int i = 0; i < size; ++i) {
3475:                        String varName = loadString();
3476:                        IPath varPath = loadPath();
3477:
3478:                        if (varPath != null)
3479:                            loadedVars.put(varName, varPath);
3480:                    }
3481:
3482:                    JavaModelManager.this .previousSessionVariables
3483:                            .putAll(loadedVars);
3484:                    JavaModelManager.this .variables.putAll(loadedVars);
3485:                }
3486:            }
3487:
3488:            /**
3489:             *  Returns the info for this element without
3490:             *  disturbing the cache ordering.
3491:             */
3492:            protected synchronized Object peekAtInfo(IJavaElement element) {
3493:                HashMap tempCache = (HashMap) this .temporaryCache.get();
3494:                if (tempCache != null) {
3495:                    Object result = tempCache.get(element);
3496:                    if (result != null) {
3497:                        return result;
3498:                    }
3499:                }
3500:                return this .cache.peekAtInfo(element);
3501:            }
3502:
3503:            /**
3504:             * @see ISaveParticipant
3505:             */
3506:            public void prepareToSave(ISaveContext context) /*throws CoreException*/{
3507:                // nothing to do
3508:            }
3509:
3510:            /*
3511:             * Puts the infos in the given map (keys are IJavaElements and values are JavaElementInfos)
3512:             * in the Java model cache in an atomic way.
3513:             * First checks that the info for the opened element (or one of its ancestors) has not been 
3514:             * added to the cache. If it is the case, another thread has opened the element (or one of
3515:             * its ancestors). So returns without updating the cache.
3516:             */
3517:            protected synchronized void putInfos(IJavaElement openedElement,
3518:                    Map newElements) {
3519:                // remove children
3520:                Object existingInfo = this .cache.peekAtInfo(openedElement);
3521:                if (openedElement instanceof  IParent
3522:                        && existingInfo instanceof  JavaElementInfo) {
3523:                    IJavaElement[] children = ((JavaElementInfo) existingInfo)
3524:                            .getChildren();
3525:                    for (int i = 0, size = children.length; i < size; ++i) {
3526:                        JavaElement child = (JavaElement) children[i];
3527:                        try {
3528:                            child.close();
3529:                        } catch (JavaModelException e) {
3530:                            // ignore
3531:                        }
3532:                    }
3533:                }
3534:
3535:                // Need to put any JarPackageFragmentRoot in first.
3536:                // This is due to the way the LRU cache flushes entries.
3537:                // When a JarPackageFragment is flused from the LRU cache, the entire
3538:                // jar is flushed by removing the JarPackageFragmentRoot and all of its
3539:                // children (see ElementCache.close()). If we flush the JarPackageFragment 
3540:                // when its JarPackageFragmentRoot is not in the cache and the root is about to be 
3541:                // added (during the 'while' loop), we will end up in an inconsist state. 
3542:                // Subsequent resolution against package in the jar would fail as a result.
3543:                // https://bugs.eclipse.org/bugs/show_bug.cgi?id=102422
3544:                // (theodora)
3545:                for (Iterator it = newElements.entrySet().iterator(); it
3546:                        .hasNext();) {
3547:                    Map.Entry entry = (Map.Entry) it.next();
3548:                    IJavaElement element = (IJavaElement) entry.getKey();
3549:                    if (element instanceof  JarPackageFragmentRoot) {
3550:                        Object info = entry.getValue();
3551:                        it.remove();
3552:                        this .cache.putInfo(element, info);
3553:                    }
3554:                }
3555:
3556:                Iterator iterator = newElements.entrySet().iterator();
3557:                while (iterator.hasNext()) {
3558:                    Map.Entry entry = (Map.Entry) iterator.next();
3559:                    this .cache.putInfo((IJavaElement) entry.getKey(), entry
3560:                            .getValue());
3561:                }
3562:            }
3563:
3564:            /*
3565:             * Remember the info for the jar binary type
3566:             */
3567:            protected synchronized void putJarTypeInfo(IJavaElement type,
3568:                    Object info) {
3569:                this .cache.jarTypeCache.put(type, info);
3570:            }
3571:
3572:            /**
3573:             * Reads the build state for the relevant project.
3574:             */
3575:            protected Object readState(IProject project) throws CoreException {
3576:                File file = getSerializationFile(project);
3577:                if (file != null && file.exists()) {
3578:                    try {
3579:                        DataInputStream in = new DataInputStream(
3580:                                new BufferedInputStream(new FileInputStream(
3581:                                        file)));
3582:                        try {
3583:                            String pluginID = in.readUTF();
3584:                            if (!pluginID.equals(JavaCore.PLUGIN_ID))
3585:                                throw new IOException(
3586:                                        Messages.build_wrongFileFormat);
3587:                            String kind = in.readUTF();
3588:                            if (!kind.equals("STATE")) //$NON-NLS-1$
3589:                                throw new IOException(
3590:                                        Messages.build_wrongFileFormat);
3591:                            if (in.readBoolean())
3592:                                return JavaBuilder.readState(project, in);
3593:                            if (JavaBuilder.DEBUG)
3594:                                System.out
3595:                                        .println("Saved state thinks last build failed for " + project.getName()); //$NON-NLS-1$
3596:                        } finally {
3597:                            in.close();
3598:                        }
3599:                    } catch (Exception e) {
3600:                        e.printStackTrace();
3601:                        throw new CoreException(
3602:                                new Status(
3603:                                        IStatus.ERROR,
3604:                                        JavaCore.PLUGIN_ID,
3605:                                        Platform.PLUGIN_ERROR,
3606:                                        "Error reading last build state for project " + project.getName(), e)); //$NON-NLS-1$
3607:                    }
3608:                } else if (JavaBuilder.DEBUG) {
3609:                    if (file == null)
3610:                        System.out
3611:                                .println("Project does not exist: " + project); //$NON-NLS-1$
3612:                    else
3613:                        System.out
3614:                                .println("Build state file " + file.getPath() + " does not exist"); //$NON-NLS-1$ //$NON-NLS-2$
3615:                }
3616:                return null;
3617:            }
3618:
3619:            public static void recreatePersistedContainer(String propertyName,
3620:                    String containerString, boolean addToContainerValues) {
3621:                int containerPrefixLength = CP_CONTAINER_PREFERENCES_PREFIX
3622:                        .length();
3623:                int index = propertyName.indexOf('|', containerPrefixLength);
3624:                if (containerString != null)
3625:                    containerString = containerString.trim();
3626:                if (index > 0) {
3627:                    String projectName = propertyName.substring(
3628:                            containerPrefixLength, index).trim();
3629:                    IJavaProject project = getJavaModelManager().getJavaModel()
3630:                            .getJavaProject(projectName);
3631:                    IPath containerPath = new Path(propertyName.substring(
3632:                            index + 1).trim());
3633:                    recreatePersistedContainer(project, containerPath,
3634:                            containerString, addToContainerValues);
3635:                }
3636:            }
3637:
3638:            private static void recreatePersistedContainer(
3639:                    final IJavaProject project, final IPath containerPath,
3640:                    String containerString, boolean addToContainerValues) {
3641:                if (!project.getProject().isAccessible())
3642:                    return; // avoid leaking deleted project's persisted container	
3643:                if (containerString == null) {
3644:                    getJavaModelManager().containerPut(project, containerPath,
3645:                            null);
3646:                } else {
3647:                    IClasspathEntry[] entries;
3648:                    try {
3649:                        entries = ((JavaProject) project)
3650:                                .decodeClasspath(containerString, null/*not interested in unknown elements*/);
3651:                    } catch (IOException e) {
3652:                        Util
3653:                                .log(
3654:                                        e,
3655:                                        "Could not recreate persisted container: \n" + containerString); //$NON-NLS-1$
3656:                        entries = JavaProject.INVALID_CLASSPATH;
3657:                    }
3658:                    if (entries != JavaProject.INVALID_CLASSPATH) {
3659:                        final IClasspathEntry[] containerEntries = entries;
3660:                        IClasspathContainer container = new IClasspathContainer() {
3661:                            public IClasspathEntry[] getClasspathEntries() {
3662:                                return containerEntries;
3663:                            }
3664:
3665:                            public String getDescription() {
3666:                                return "Persisted container [" + containerPath + " for project [" + project.getElementName() + "]"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
3667:                            }
3668:
3669:                            public int getKind() {
3670:                                return 0;
3671:                            }
3672:
3673:                            public IPath getPath() {
3674:                                return containerPath;
3675:                            }
3676:
3677:                            public String toString() {
3678:                                return getDescription();
3679:                            }
3680:
3681:                        };
3682:                        if (addToContainerValues) {
3683:                            getJavaModelManager().containerPut(project,
3684:                                    containerPath, container);
3685:                        }
3686:                        Map projectContainers = (Map) getJavaModelManager().previousSessionContainers
3687:                                .get(project);
3688:                        if (projectContainers == null) {
3689:                            projectContainers = new HashMap(1);
3690:                            getJavaModelManager().previousSessionContainers
3691:                                    .put(project, projectContainers);
3692:                        }
3693:                        projectContainers.put(containerPath, container);
3694:                    }
3695:                }
3696:            }
3697:
3698:            /**
3699:             * Remembers the given scope in a weak set
3700:             * (so no need to remove it: it will be removed by the garbage collector)
3701:             */
3702:            public void rememberScope(AbstractSearchScope scope) {
3703:                // NB: The value has to be null so as to not create a strong reference on the scope
3704:                this .searchScopes.put(scope, null);
3705:            }
3706:
3707:            /*
3708:             * Removes all cached info for the given element (including all children)
3709:             * from the cache.
3710:             * Returns the info for the given element, or null if it was closed.
3711:             */
3712:            public synchronized Object removeInfoAndChildren(JavaElement element)
3713:                    throws JavaModelException {
3714:                Object info = this .cache.peekAtInfo(element);
3715:                if (info != null) {
3716:                    boolean wasVerbose = false;
3717:                    try {
3718:                        if (JavaModelCache.VERBOSE) {
3719:                            String elementType;
3720:                            switch (element.getElementType()) {
3721:                            case IJavaElement.JAVA_PROJECT:
3722:                                elementType = "project"; //$NON-NLS-1$
3723:                                break;
3724:                            case IJavaElement.PACKAGE_FRAGMENT_ROOT:
3725:                                elementType = "root"; //$NON-NLS-1$
3726:                                break;
3727:                            case IJavaElement.PACKAGE_FRAGMENT:
3728:                                elementType = "package"; //$NON-NLS-1$
3729:                                break;
3730:                            case IJavaElement.CLASS_FILE:
3731:                                elementType = "class file"; //$NON-NLS-1$
3732:                                break;
3733:                            case IJavaElement.COMPILATION_UNIT:
3734:                                elementType = "compilation unit"; //$NON-NLS-1$
3735:                                break;
3736:                            default:
3737:                                elementType = "element"; //$NON-NLS-1$
3738:                            }
3739:                            System.out
3740:                                    .println(Thread.currentThread()
3741:                                            + " CLOSING " + elementType + " " + element.toStringWithAncestors()); //$NON-NLS-1$//$NON-NLS-2$
3742:                            wasVerbose = true;
3743:                            JavaModelCache.VERBOSE = false;
3744:                        }
3745:                        element.closing(info);
3746:                        if (element instanceof  IParent
3747:                                && info instanceof  JavaElementInfo) {
3748:                            IJavaElement[] children = ((JavaElementInfo) info)
3749:                                    .getChildren();
3750:                            for (int i = 0, size = children.length; i < size; ++i) {
3751:                                JavaElement child = (JavaElement) children[i];
3752:                                child.close();
3753:                            }
3754:                        }
3755:                        this .cache.removeInfo(element);
3756:                        if (wasVerbose) {
3757:                            System.out.println(this .cache
3758:                                    .toStringFillingRation("-> ")); //$NON-NLS-1$
3759:                        }
3760:                    } finally {
3761:                        JavaModelCache.VERBOSE = wasVerbose;
3762:                    }
3763:                    return info;
3764:                }
3765:                return null;
3766:            }
3767:
3768:            public void removePerProjectInfo(JavaProject javaProject) {
3769:                synchronized (this .perProjectInfos) { // use the perProjectInfo collection as its own lock
3770:                    IProject project = javaProject.getProject();
3771:                    PerProjectInfo info = (PerProjectInfo) this .perProjectInfos
3772:                            .get(project);
3773:                    if (info != null) {
3774:                        this .perProjectInfos.remove(project);
3775:                    }
3776:                }
3777:            }
3778:
3779:            /*
3780:             * Reset project options stored in info cache.
3781:             */
3782:            public void resetProjectOptions(JavaProject javaProject) {
3783:                synchronized (this .perProjectInfos) { // use the perProjectInfo collection as its own lock
3784:                    IProject project = javaProject.getProject();
3785:                    PerProjectInfo info = (PerProjectInfo) this .perProjectInfos
3786:                            .get(project);
3787:                    if (info != null) {
3788:                        info.options = null;
3789:                    }
3790:                }
3791:            }
3792:
3793:            /*
3794:             * Reset project preferences stored in info cache.
3795:             */
3796:            public void resetProjectPreferences(JavaProject javaProject) {
3797:                synchronized (this .perProjectInfos) { // use the perProjectInfo collection as its own lock
3798:                    IProject project = javaProject.getProject();
3799:                    PerProjectInfo info = (PerProjectInfo) this .perProjectInfos
3800:                            .get(project);
3801:                    if (info != null) {
3802:                        info.preferences = null;
3803:                    }
3804:                }
3805:            }
3806:
3807:            public static final void doNotUse() {
3808:                // used by tests to simulate a startup
3809:                MANAGER = new JavaModelManager();
3810:            }
3811:
3812:            /*
3813:             * Resets the cache that holds on binary type in jar files
3814:             */
3815:            protected synchronized void resetJarTypeCache() {
3816:                this .cache.resetJarTypeCache();
3817:            }
3818:
3819:            /*
3820:             * Resets the temporary cache for newly created elements to null.
3821:             */
3822:            public void resetTemporaryCache() {
3823:                this .temporaryCache.set(null);
3824:            }
3825:
3826:            /**
3827:             * @see ISaveParticipant
3828:             */
3829:            public void rollback(ISaveContext context) {
3830:                // nothing to do
3831:            }
3832:
3833:            private void saveState(PerProjectInfo info, ISaveContext context)
3834:                    throws CoreException {
3835:
3836:                // passed this point, save actions are non trivial
3837:                if (context.getKind() == ISaveContext.SNAPSHOT)
3838:                    return;
3839:
3840:                // save built state
3841:                if (info.triedRead)
3842:                    saveBuiltState(info);
3843:            }
3844:
3845:            /**
3846:             * Saves the built state for the project.
3847:             */
3848:            private void saveBuiltState(PerProjectInfo info)
3849:                    throws CoreException {
3850:                if (JavaBuilder.DEBUG)
3851:                    System.out.println(Messages.bind(
3852:                            Messages.build_saveStateProgress, info.project
3853:                                    .getName()));
3854:                File file = getSerializationFile(info.project);
3855:                if (file == null)
3856:                    return;
3857:                long t = System.currentTimeMillis();
3858:                try {
3859:                    DataOutputStream out = new DataOutputStream(
3860:                            new BufferedOutputStream(new FileOutputStream(file)));
3861:                    try {
3862:                        out.writeUTF(JavaCore.PLUGIN_ID);
3863:                        out.writeUTF("STATE"); //$NON-NLS-1$
3864:                        if (info.savedState == null) {
3865:                            out.writeBoolean(false);
3866:                        } else {
3867:                            out.writeBoolean(true);
3868:                            JavaBuilder.writeState(info.savedState, out);
3869:                        }
3870:                    } finally {
3871:                        out.close();
3872:                    }
3873:                } catch (RuntimeException e) {
3874:                    try {
3875:                        file.delete();
3876:                    } catch (SecurityException se) {
3877:                        // could not delete file: cannot do much more
3878:                    }
3879:                    throw new CoreException(new Status(IStatus.ERROR,
3880:                            JavaCore.PLUGIN_ID, Platform.PLUGIN_ERROR, Messages
3881:                                    .bind(Messages.build_cannotSaveState,
3882:                                            info.project.getName()), e));
3883:                } catch (IOException e) {
3884:                    try {
3885:                        file.delete();
3886:                    } catch (SecurityException se) {
3887:                        // could not delete file: cannot do much more
3888:                    }
3889:                    throw new CoreException(new Status(IStatus.ERROR,
3890:                            JavaCore.PLUGIN_ID, Platform.PLUGIN_ERROR, Messages
3891:                                    .bind(Messages.build_cannotSaveState,
3892:                                            info.project.getName()), e));
3893:                }
3894:                if (JavaBuilder.DEBUG) {
3895:                    t = System.currentTimeMillis() - t;
3896:                    System.out.println(Messages
3897:                            .bind(Messages.build_saveStateComplete, String
3898:                                    .valueOf(t)));
3899:                }
3900:            }
3901:
3902:            private void saveVariablesAndContainers(ISaveContext context)
3903:                    throws CoreException {
3904:                File file = getVariableAndContainersFile();
3905:                DataOutputStream out = null;
3906:                try {
3907:                    out = new DataOutputStream(new BufferedOutputStream(
3908:                            new FileOutputStream(file)));
3909:                    out.writeInt(VARIABLES_AND_CONTAINERS_FILE_VERSION);
3910:                    if (VARIABLES_AND_CONTAINERS_FILE_VERSION != 1)
3911:                        new VariablesAndContainersSaveHelper(out).save(context);
3912:                    else {
3913:                        // old code retained for performance comparisons
3914:
3915:                        // variables
3916:                        out.writeInt(this .variables.size());
3917:                        Iterator iterator = this .variables.entrySet()
3918:                                .iterator();
3919:                        while (iterator.hasNext()) {
3920:                            Map.Entry entry = (Map.Entry) iterator.next();
3921:                            String variableName = (String) entry.getKey();
3922:                            out.writeUTF(variableName);
3923:                            IPath path = (IPath) entry.getValue();
3924:                            out.writeUTF(path == null ? CP_ENTRY_IGNORE : path
3925:                                    .toPortableString());
3926:                        }
3927:
3928:                        // containers
3929:                        IJavaProject[] projects = getJavaModel()
3930:                                .getJavaProjects();
3931:                        int length = projects.length;
3932:                        out.writeInt(length);
3933:                        for (int i = 0; i < length; i++) {
3934:                            IJavaProject project = projects[i];
3935:                            // clone while iterating (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=59638)
3936:                            Map projectContainers = containerClone(project);
3937:                            out.writeUTF(project.getElementName());
3938:                            if (projectContainers == null) {
3939:                                out.writeInt(0);
3940:                                continue;
3941:                            }
3942:                            HashMap containersToSave = new HashMap();
3943:                            for (iterator = projectContainers.entrySet()
3944:                                    .iterator(); iterator.hasNext();) {
3945:                                Map.Entry entry = (Map.Entry) iterator.next();
3946:                                IPath containerPath = (IPath) entry.getKey();
3947:                                IClasspathContainer container = (IClasspathContainer) entry
3948:                                        .getValue();
3949:                                String containerString = null;
3950:                                try {
3951:                                    if (container == null) {
3952:                                        // container has not been initialized yet, use previous session value
3953:                                        // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=73969)
3954:                                        container = getPreviousSessionContainer(
3955:                                                containerPath, project);
3956:                                    }
3957:                                    if (container != null) {
3958:                                        IClasspathEntry[] entries = container
3959:                                                .getClasspathEntries();
3960:                                        containerString = ((JavaProject) project)
3961:                                                .encodeClasspath(entries, null,
3962:                                                        false, null/*not interested in unknown elements*/);
3963:                                    }
3964:                                } catch (JavaModelException e) {
3965:                                    // could not encode entry: will not persist
3966:                                    Util
3967:                                            .log(
3968:                                                    e,
3969:                                                    "Could not persist container " + containerPath + " for project " + project.getElementName()); //$NON-NLS-1$ //$NON-NLS-2$
3970:                                }
3971:                                if (containerString != null)
3972:                                    containersToSave.put(containerPath,
3973:                                            containerString);
3974:                            }
3975:                            out.writeInt(containersToSave.size());
3976:                            iterator = containersToSave.entrySet().iterator();
3977:                            while (iterator.hasNext()) {
3978:                                Map.Entry entry = (Map.Entry) iterator.next();
3979:                                IPath containerPath = (IPath) entry.getKey();
3980:                                out.writeUTF(containerPath.toPortableString());
3981:                                String containerString = (String) entry
3982:                                        .getValue();
3983:                                out.writeInt(containerString.length());
3984:                                out.writeBytes(containerString);
3985:                            }
3986:                        }
3987:                    }
3988:                } catch (IOException e) {
3989:                    IStatus status = new Status(IStatus.ERROR,
3990:                            JavaCore.PLUGIN_ID, IStatus.ERROR,
3991:                            "Problems while saving variables and containers", e); //$NON-NLS-1$
3992:                    throw new CoreException(status);
3993:                } finally {
3994:                    if (out != null) {
3995:                        try {
3996:                            out.close();
3997:                        } catch (IOException e) {
3998:                            // nothing we can do: ignore
3999:                        }
4000:                    }
4001:                }
4002:            }
4003:
4004:            private final class VariablesAndContainersSaveHelper {
4005:
4006:                private final HashtableOfObjectToInt classpathEntryIds; // IClasspathEntry -> int
4007:                private final DataOutputStream out;
4008:                private final HashtableOfObjectToInt stringIds; // Strings -> int
4009:
4010:                VariablesAndContainersSaveHelper(DataOutputStream out) {
4011:                    super ();
4012:                    this .classpathEntryIds = new HashtableOfObjectToInt();
4013:                    this .out = out;
4014:                    this .stringIds = new HashtableOfObjectToInt();
4015:                }
4016:
4017:                void save(ISaveContext context) throws IOException,
4018:                        JavaModelException {
4019:                    IProject project = context.getProject();
4020:                    if (project == null) { // save all projects if none specified (snapshot or full save)
4021:                        saveProjects(JavaModelManager.this .getJavaModel()
4022:                                .getJavaProjects());
4023:                    } else {
4024:                        saveProjects(new IJavaProject[] { JavaCore
4025:                                .create(project) });
4026:                    }
4027:
4028:                    switch (context.getKind()) {
4029:                    case ISaveContext.FULL_SAVE:
4030:                        // TODO (eric) - investigate after 3.3 if variables should be saved for a SNAPSHOT
4031:                    case ISaveContext.SNAPSHOT:
4032:                        // remove variables that should not be saved
4033:                        HashMap varsToSave = null;
4034:                        Iterator iterator = JavaModelManager.this .variables
4035:                                .entrySet().iterator();
4036:                        IEclipsePreferences defaultPreferences = getDefaultPreferences();
4037:                        while (iterator.hasNext()) {
4038:                            Map.Entry entry = (Map.Entry) iterator.next();
4039:                            String varName = (String) entry.getKey();
4040:                            if (defaultPreferences.get(
4041:                                    CP_VARIABLE_PREFERENCES_PREFIX + varName,
4042:                                    null) != null // don't save classpath variables from the default preferences as there is no delta if they are removed
4043:                                    || CP_ENTRY_IGNORE_PATH.equals(entry
4044:                                            .getValue())) {
4045:
4046:                                if (varsToSave == null)
4047:                                    varsToSave = new HashMap(
4048:                                            JavaModelManager.this .variables);
4049:                                varsToSave.remove(varName);
4050:                            }
4051:                        }
4052:                        saveVariables(varsToSave != null ? varsToSave
4053:                                : JavaModelManager.this .variables);
4054:                        break;
4055:                    default:
4056:                        // do nothing
4057:                    }
4058:                }
4059:
4060:                private void saveAccessRule(ClasspathAccessRule rule)
4061:                        throws IOException {
4062:                    saveInt(rule.problemId);
4063:                    savePath(rule.getPattern());
4064:                }
4065:
4066:                private void saveAccessRules(IAccessRule[] rules)
4067:                        throws IOException {
4068:                    int count = rules == null ? 0 : rules.length;
4069:
4070:                    saveInt(count);
4071:                    for (int i = 0; i < count; ++i)
4072:                        saveAccessRule((ClasspathAccessRule) rules[i]);
4073:                }
4074:
4075:                private void saveAttribute(IClasspathAttribute attribute)
4076:                        throws IOException {
4077:                    saveString(attribute.getName());
4078:                    saveString(attribute.getValue());
4079:                }
4080:
4081:                private void saveAttributes(IClasspathAttribute[] attributes)
4082:                        throws IOException {
4083:                    int count = attributes == null ? 0 : attributes.length;
4084:
4085:                    saveInt(count);
4086:                    for (int i = 0; i < count; ++i)
4087:                        saveAttribute(attributes[i]);
4088:                }
4089:
4090:                private void saveClasspathEntries(IClasspathEntry[] entries)
4091:                        throws IOException {
4092:                    int count = entries == null ? 0 : entries.length;
4093:
4094:                    saveInt(count);
4095:                    for (int i = 0; i < count; ++i)
4096:                        saveClasspathEntry(entries[i]);
4097:                }
4098:
4099:                private void saveClasspathEntry(IClasspathEntry entry)
4100:                        throws IOException {
4101:                    if (saveNewId(entry, this .classpathEntryIds)) {
4102:                        saveInt(entry.getContentKind());
4103:                        saveInt(entry.getEntryKind());
4104:                        savePath(entry.getPath());
4105:                        savePaths(entry.getInclusionPatterns());
4106:                        savePaths(entry.getExclusionPatterns());
4107:                        savePath(entry.getSourceAttachmentPath());
4108:                        savePath(entry.getSourceAttachmentRootPath());
4109:                        savePath(entry.getOutputLocation());
4110:                        this .out.writeBoolean(entry.isExported());
4111:                        saveAccessRules(entry.getAccessRules());
4112:                        this .out.writeBoolean(entry.combineAccessRules());
4113:                        saveAttributes(entry.getExtraAttributes());
4114:                    }
4115:                }
4116:
4117:                private void saveContainers(IJavaProject project,
4118:                        Map containerMap) throws IOException {
4119:                    saveInt(containerMap.size());
4120:
4121:                    for (Iterator i = containerMap.entrySet().iterator(); i
4122:                            .hasNext();) {
4123:                        Entry entry = (Entry) i.next();
4124:                        IPath path = (IPath) entry.getKey();
4125:                        IClasspathContainer container = (IClasspathContainer) entry
4126:                                .getValue();
4127:                        IClasspathEntry[] cpEntries = null;
4128:
4129:                        if (container == null) {
4130:                            // container has not been initialized yet, use previous
4131:                            // session value
4132:                            // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=73969)
4133:                            container = JavaModelManager.this 
4134:                                    .getPreviousSessionContainer(path, project);
4135:                        }
4136:
4137:                        if (container != null)
4138:                            cpEntries = container.getClasspathEntries();
4139:
4140:                        savePath(path);
4141:                        saveClasspathEntries(cpEntries);
4142:                    }
4143:                }
4144:
4145:                private void saveInt(int value) throws IOException {
4146:                    this .out.writeInt(value);
4147:                }
4148:
4149:                private boolean saveNewId(Object key, HashtableOfObjectToInt map)
4150:                        throws IOException {
4151:                    int id = map.get(key);
4152:
4153:                    if (id == -1) {
4154:                        int newId = map.size();
4155:
4156:                        map.put(key, newId);
4157:
4158:                        saveInt(newId);
4159:
4160:                        return true;
4161:                    } else {
4162:                        saveInt(id);
4163:
4164:                        return false;
4165:                    }
4166:                }
4167:
4168:                private void savePath(IPath path) throws IOException {
4169:                    if (path == null) {
4170:                        this .out.writeBoolean(true);
4171:                    } else {
4172:                        this .out.writeBoolean(false);
4173:                        saveString(path.toPortableString());
4174:                    }
4175:                }
4176:
4177:                private void savePaths(IPath[] paths) throws IOException {
4178:                    int count = paths == null ? 0 : paths.length;
4179:
4180:                    saveInt(count);
4181:                    for (int i = 0; i < count; ++i)
4182:                        savePath(paths[i]);
4183:                }
4184:
4185:                private void saveProjects(IJavaProject[] projects)
4186:                        throws IOException, JavaModelException {
4187:                    int count = projects.length;
4188:
4189:                    saveInt(count);
4190:
4191:                    for (int i = 0; i < count; ++i) {
4192:                        IJavaProject project = projects[i];
4193:
4194:                        saveString(project.getElementName());
4195:
4196:                        Map containerMap = (Map) JavaModelManager.this .containers
4197:                                .get(project);
4198:
4199:                        if (containerMap == null) {
4200:                            containerMap = Collections.EMPTY_MAP;
4201:                        } else {
4202:                            // clone while iterating
4203:                            // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=59638)
4204:                            containerMap = new HashMap(containerMap);
4205:                        }
4206:
4207:                        saveContainers(project, containerMap);
4208:                    }
4209:                }
4210:
4211:                private void saveString(String string) throws IOException {
4212:                    if (saveNewId(string, this .stringIds))
4213:                        this .out.writeUTF(string);
4214:                }
4215:
4216:                private void saveVariables(Map map) throws IOException {
4217:                    saveInt(map.size());
4218:
4219:                    for (Iterator i = map.entrySet().iterator(); i.hasNext();) {
4220:                        Entry entry = (Entry) i.next();
4221:                        String varName = (String) entry.getKey();
4222:                        IPath varPath = (IPath) entry.getValue();
4223:
4224:                        saveString(varName);
4225:                        savePath(varPath);
4226:                    }
4227:                }
4228:            }
4229:
4230:            private void traceVariableAndContainers(String action, long start) {
4231:
4232:                Long delta = new Long(System.currentTimeMillis() - start);
4233:                Long length = new Long(getVariableAndContainersFile().length());
4234:                String pattern = "{0} {1} bytes in variablesAndContainers.dat in {2}ms"; //$NON-NLS-1$
4235:                String message = MessageFormat.format(pattern, new Object[] {
4236:                        action, length, delta });
4237:
4238:                System.out.println(message);
4239:            }
4240:
4241:            /**
4242:             * @see ISaveParticipant
4243:             */
4244:            public void saving(ISaveContext context) throws CoreException {
4245:
4246:                long start = -1;
4247:                if (VERBOSE)
4248:                    start = System.currentTimeMillis();
4249:
4250:                // save variable and container values on snapshot/full save
4251:                saveVariablesAndContainers(context);
4252:
4253:                if (VERBOSE)
4254:                    traceVariableAndContainers("Saved", start); //$NON-NLS-1$
4255:
4256:                if (context.getKind() == ISaveContext.FULL_SAVE) {
4257:                    // will need delta since this save (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=38658)
4258:                    context.needDelta();
4259:
4260:                    // clean up indexes on workspace full save
4261:                    // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=52347)
4262:                    IndexManager manager = this .indexManager;
4263:                    if (manager != null
4264:                    // don't force initialization of workspace scope as we could be shutting down
4265:                            // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=93941)
4266:                            && this .workspaceScope != null) {
4267:                        manager.cleanUpIndexes();
4268:                    }
4269:                }
4270:
4271:                IProject savedProject = context.getProject();
4272:                if (savedProject != null) {
4273:                    if (!JavaProject.hasJavaNature(savedProject))
4274:                        return; // ignore
4275:                    PerProjectInfo info = getPerProjectInfo(savedProject, true /* create info */);
4276:                    saveState(info, context);
4277:                    info.rememberExternalLibTimestamps();
4278:                    return;
4279:                }
4280:
4281:                ArrayList vStats = null; // lazy initialized
4282:                ArrayList values = null;
4283:                synchronized (this .perProjectInfos) {
4284:                    values = new ArrayList(this .perProjectInfos.values());
4285:                }
4286:                Iterator iterator = values.iterator();
4287:                while (iterator.hasNext()) {
4288:                    try {
4289:                        PerProjectInfo info = (PerProjectInfo) iterator.next();
4290:                        saveState(info, context);
4291:                        info.rememberExternalLibTimestamps();
4292:                    } catch (CoreException e) {
4293:                        if (vStats == null)
4294:                            vStats = new ArrayList();
4295:                        vStats.add(e.getStatus());
4296:                    }
4297:                }
4298:                if (vStats != null) {
4299:                    IStatus[] stats = new IStatus[vStats.size()];
4300:                    vStats.toArray(stats);
4301:                    throw new CoreException(new MultiStatus(JavaCore.PLUGIN_ID,
4302:                            IStatus.ERROR, stats,
4303:                            Messages.build_cannotSaveStates, null));
4304:                }
4305:
4306:                // save external libs timestamps
4307:                this .deltaState.saveExternalLibTimeStamps();
4308:            }
4309:
4310:            /**
4311:             * Add a secondary type in temporary indexing cache for a project got from given path.
4312:             * 
4313:             * Current secondary types cache is not modified as we want to wait that indexing
4314:             * was finished before taking new secondary types into account.
4315:             * 
4316:             * Indexing cache is a specific entry in secondary types cache which key is
4317:             * {@link #INDEXED_SECONDARY_TYPES } and value a map with same structure than
4318:             * secondary types cache itself.
4319:             * 
4320:             * @see #secondaryTypes(IJavaProject, boolean, IProgressMonitor)
4321:             */
4322:            public void secondaryTypeAdding(String path, char[] typeName,
4323:                    char[] packageName) {
4324:                if (VERBOSE) {
4325:                    StringBuffer buffer = new StringBuffer(
4326:                            "JavaModelManager.addSecondaryType("); //$NON-NLS-1$
4327:                    buffer.append(path);
4328:                    buffer.append(',');
4329:                    buffer.append('[');
4330:                    buffer.append(new String(packageName));
4331:                    buffer.append('.');
4332:                    buffer.append(new String(typeName));
4333:                    buffer.append(']');
4334:                    buffer.append(')');
4335:                    Util.verbose(buffer.toString());
4336:                }
4337:                IWorkspaceRoot wRoot = ResourcesPlugin.getWorkspace().getRoot();
4338:                IResource resource = wRoot.findMember(path);
4339:                if (resource != null) {
4340:                    if (org.eclipse.jdt.internal.core.util.Util
4341:                            .isJavaLikeFileName(path)
4342:                            && resource.getType() == IResource.FILE) {
4343:                        IProject project = resource.getProject();
4344:                        try {
4345:                            PerProjectInfo projectInfo = getPerProjectInfoCheckExistence(project);
4346:                            // Get or create map to cache secondary types while indexing (can be not synchronized as indexing insure a non-concurrent usage)
4347:                            HashMap indexedSecondaryTypes = null;
4348:                            if (projectInfo.secondaryTypes == null) {
4349:                                projectInfo.secondaryTypes = new Hashtable(3);
4350:                                indexedSecondaryTypes = new HashMap(3);
4351:                                projectInfo.secondaryTypes.put(
4352:                                        INDEXED_SECONDARY_TYPES,
4353:                                        indexedSecondaryTypes);
4354:                            } else {
4355:                                indexedSecondaryTypes = (HashMap) projectInfo.secondaryTypes
4356:                                        .get(INDEXED_SECONDARY_TYPES);
4357:                                if (indexedSecondaryTypes == null) {
4358:                                    indexedSecondaryTypes = new HashMap(3);
4359:                                    projectInfo.secondaryTypes.put(
4360:                                            INDEXED_SECONDARY_TYPES,
4361:                                            indexedSecondaryTypes);
4362:                                }
4363:                            }
4364:                            // Store the secondary type in temporary cache (these are just handles => no problem to create it now...)
4365:                            HashMap allTypes = (HashMap) indexedSecondaryTypes
4366:                                    .get(resource);
4367:                            if (allTypes == null) {
4368:                                allTypes = new HashMap(3);
4369:                                indexedSecondaryTypes.put(resource, allTypes);
4370:                            }
4371:                            ICompilationUnit unit = JavaModelManager
4372:                                    .createCompilationUnitFrom(
4373:                                            (IFile) resource, null);
4374:                            if (unit != null) {
4375:                                String typeString = new String(typeName);
4376:                                IType type = unit.getType(typeString);
4377:                                // String packageString = new String(packageName);
4378:                                // use package fragment name instead of parameter as it may be invalid...
4379:                                // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=186781
4380:                                String packageString = type
4381:                                        .getPackageFragment().getElementName();
4382:                                HashMap packageTypes = (HashMap) allTypes
4383:                                        .get(packageString);
4384:                                if (packageTypes == null) {
4385:                                    packageTypes = new HashMap(3);
4386:                                    allTypes.put(packageString, packageTypes);
4387:                                }
4388:                                packageTypes.put(typeString, type);
4389:                            }
4390:                            if (VERBOSE) {
4391:                                Util.verbose("	- indexing cache:"); //$NON-NLS-1$
4392:                                Iterator entries = indexedSecondaryTypes
4393:                                        .entrySet().iterator();
4394:                                while (entries.hasNext()) {
4395:                                    Map.Entry entry = (Map.Entry) entries
4396:                                            .next();
4397:                                    IFile file = (IFile) entry.getKey();
4398:                                    Util
4399:                                            .verbose("		+ " + file.getFullPath() + ':' + entry.getValue()); //$NON-NLS-1$
4400:                                }
4401:                            }
4402:                        } catch (JavaModelException jme) {
4403:                            // do nothing
4404:                        }
4405:                    }
4406:                }
4407:            }
4408:
4409:            /**
4410:             * Get all secondary types for a project and store result in per project info cache.
4411:             * 
4412:             * This cache is an Hashtable<String, HashMap<String, IType>>:
4413:             * 	- key: package name
4414:             * 	- value:
4415:             * 		+ key: type name
4416:             * 		+ value: java model handle for the secondary type
4417:             * Hashtable was used to protect callers from possible concurrent access.
4418:             * 
4419:             * Note that this map may have a specific entry which key is {@link #INDEXED_SECONDARY_TYPES }
4420:             * and value is a map containing all secondary types created during indexing.
4421:             * When this key is in cache and indexing is finished, returned map is merged
4422:             * with the value of this special key. If indexing is not finished and caller does
4423:             * not wait for the end of indexing, returned map is the current secondary
4424:             * types cache content which may be invalid...
4425:             * 
4426:             * @param project Project we want get secondary types from
4427:             * @return HashMap Table of secondary type names->path for given project
4428:             */
4429:            public Map secondaryTypes(IJavaProject project,
4430:                    boolean waitForIndexes, IProgressMonitor monitor)
4431:                    throws JavaModelException {
4432:                if (VERBOSE) {
4433:                    StringBuffer buffer = new StringBuffer(
4434:                            "JavaModelManager.secondaryTypes("); //$NON-NLS-1$
4435:                    buffer.append(project.getElementName());
4436:                    buffer.append(',');
4437:                    buffer.append(waitForIndexes);
4438:                    buffer.append(')');
4439:                    Util.verbose(buffer.toString());
4440:                }
4441:
4442:                // Return cache if not empty and there's no new secondary types created during indexing
4443:                final PerProjectInfo projectInfo = getPerProjectInfoCheckExistence(project
4444:                        .getProject());
4445:                Map indexingSecondaryCache = projectInfo.secondaryTypes == null ? null
4446:                        : (Map) projectInfo.secondaryTypes
4447:                                .get(INDEXED_SECONDARY_TYPES);
4448:                if (projectInfo.secondaryTypes != null
4449:                        && indexingSecondaryCache == null) {
4450:                    return projectInfo.secondaryTypes;
4451:                }
4452:
4453:                // Perform search request only if secondary types cache is not initialized yet (this will happen only once!)
4454:                if (projectInfo.secondaryTypes == null) {
4455:                    return secondaryTypesSearching(project, waitForIndexes,
4456:                            monitor, projectInfo);
4457:                }
4458:
4459:                // New secondary types have been created while indexing secondary types cache
4460:                // => need to know whether the indexing is finished or not
4461:                boolean indexing = this .indexManager.awaitingJobsCount() > 0;
4462:                if (indexing) {
4463:                    if (!waitForIndexes) {
4464:                        // Indexing is running but caller cannot wait => return current cache
4465:                        return projectInfo.secondaryTypes;
4466:                    }
4467:
4468:                    // Wait for the end of indexing or a cancel
4469:                    while (this .indexManager.awaitingJobsCount() > 0) {
4470:                        if (monitor != null && monitor.isCanceled()) {
4471:                            return projectInfo.secondaryTypes;
4472:                        }
4473:                        try {
4474:                            Thread.sleep(10);
4475:                        } catch (InterruptedException e) {
4476:                            return projectInfo.secondaryTypes;
4477:                        }
4478:                    }
4479:                }
4480:
4481:                // Indexing is finished => merge caches and return result
4482:                return secondaryTypesMerging(projectInfo.secondaryTypes);
4483:            }
4484:
4485:            /*
4486:             * Return secondary types cache merged with new secondary types created while indexing
4487:             * Note that merge result is directly stored in given parameter map.
4488:             */
4489:            private Hashtable secondaryTypesMerging(Hashtable secondaryTypes) {
4490:                if (VERBOSE) {
4491:                    Util.verbose("JavaModelManager.getSecondaryTypesMerged()"); //$NON-NLS-1$
4492:                    Util.verbose("	- current cache to merge:"); //$NON-NLS-1$
4493:                    Iterator entries = secondaryTypes.entrySet().iterator();
4494:                    while (entries.hasNext()) {
4495:                        Map.Entry entry = (Map.Entry) entries.next();
4496:                        String packName = (String) entry.getKey();
4497:                        Util
4498:                                .verbose("		+ " + packName + ':' + entry.getValue()); //$NON-NLS-1$
4499:                    }
4500:                }
4501:
4502:                // Return current cache if there's no indexing cache (double check, this should not happen)
4503:                HashMap indexedSecondaryTypes = (HashMap) secondaryTypes
4504:                        .remove(INDEXED_SECONDARY_TYPES);
4505:                if (indexedSecondaryTypes == null) {
4506:                    return secondaryTypes;
4507:                }
4508:
4509:                // Merge indexing cache in secondary types one
4510:                Iterator entries = indexedSecondaryTypes.entrySet().iterator();
4511:                while (entries.hasNext()) {
4512:                    Map.Entry entry = (Map.Entry) entries.next();
4513:                    IFile file = (IFile) entry.getKey();
4514:
4515:                    // Remove all secondary types of indexed file from cache
4516:                    secondaryTypesRemoving(secondaryTypes, file);
4517:
4518:                    // Add all indexing file secondary types in given secondary types cache
4519:                    HashMap fileSecondaryTypes = (HashMap) entry.getValue();
4520:                    Iterator entries2 = fileSecondaryTypes.entrySet()
4521:                            .iterator();
4522:                    while (entries2.hasNext()) {
4523:                        Map.Entry entry2 = (Map.Entry) entries2.next();
4524:                        String packageName = (String) entry2.getKey();
4525:                        HashMap cachedTypes = (HashMap) secondaryTypes
4526:                                .get(packageName);
4527:                        if (cachedTypes == null) {
4528:                            secondaryTypes.put(packageName, entry2.getValue());
4529:                        } else {
4530:                            HashMap types = (HashMap) entry2.getValue();
4531:                            Iterator entries3 = types.entrySet().iterator();
4532:                            while (entries3.hasNext()) {
4533:                                Map.Entry entry3 = (Map.Entry) entries3.next();
4534:                                String typeName = (String) entry3.getKey();
4535:                                cachedTypes.put(typeName, entry3.getValue());
4536:                            }
4537:                        }
4538:                    }
4539:                }
4540:                if (VERBOSE) {
4541:                    Util.verbose("	- secondary types cache merged:"); //$NON-NLS-1$
4542:                    entries = secondaryTypes.entrySet().iterator();
4543:                    while (entries.hasNext()) {
4544:                        Map.Entry entry = (Map.Entry) entries.next();
4545:                        String packName = (String) entry.getKey();
4546:                        Util
4547:                                .verbose("		+ " + packName + ':' + entry.getValue()); //$NON-NLS-1$
4548:                    }
4549:                }
4550:                return secondaryTypes;
4551:            }
4552:
4553:            /*
4554:             * Perform search request to get all secondary types of a given project.
4555:             * If not waiting for indexes and indexing is running, will return types found in current built indexes...
4556:             */
4557:            private Map secondaryTypesSearching(IJavaProject project,
4558:                    boolean waitForIndexes, IProgressMonitor monitor,
4559:                    final PerProjectInfo projectInfo) throws JavaModelException {
4560:                if (VERBOSE || BasicSearchEngine.VERBOSE) {
4561:                    StringBuffer buffer = new StringBuffer(
4562:                            "JavaModelManager.secondaryTypesSearch("); //$NON-NLS-1$
4563:                    buffer.append(project.getElementName());
4564:                    buffer.append(',');
4565:                    buffer.append(waitForIndexes);
4566:                    buffer.append(')');
4567:                    Util.verbose(buffer.toString());
4568:                }
4569:
4570:                final Hashtable secondaryTypes = new Hashtable(3);
4571:                IRestrictedAccessTypeRequestor nameRequestor = new IRestrictedAccessTypeRequestor() {
4572:                    public void acceptType(int modifiers, char[] packageName,
4573:                            char[] simpleTypeName, char[][] enclosingTypeNames,
4574:                            String path, AccessRestriction access) {
4575:                        String key = packageName == null ? "" : new String(packageName); //$NON-NLS-1$
4576:                        HashMap types = (HashMap) secondaryTypes.get(key);
4577:                        if (types == null)
4578:                            types = new HashMap(3);
4579:                        types.put(new String(simpleTypeName), path);
4580:                        secondaryTypes.put(key, types);
4581:                    }
4582:                };
4583:
4584:                // Build scope using prereq projects but only source folders
4585:                IPackageFragmentRoot[] allRoots = project
4586:                        .getAllPackageFragmentRoots();
4587:                int length = allRoots.length, size = 0;
4588:                IPackageFragmentRoot[] allSourceFolders = new IPackageFragmentRoot[length];
4589:                for (int i = 0; i < length; i++) {
4590:                    if (allRoots[i].getKind() == IPackageFragmentRoot.K_SOURCE) {
4591:                        allSourceFolders[size++] = allRoots[i];
4592:                    }
4593:                }
4594:                if (size < length) {
4595:                    System.arraycopy(allSourceFolders, 0,
4596:                            allSourceFolders = new IPackageFragmentRoot[size],
4597:                            0, size);
4598:                }
4599:
4600:                // Search all secondary types on scope
4601:                new BasicSearchEngine().searchAllSecondaryTypeNames(
4602:                        allSourceFolders, nameRequestor, waitForIndexes,
4603:                        monitor);
4604:
4605:                // Build types from paths
4606:                Iterator packages = secondaryTypes.values().iterator();
4607:                while (packages.hasNext()) {
4608:                    HashMap types = (HashMap) packages.next();
4609:                    Iterator names = types.entrySet().iterator();
4610:                    while (names.hasNext()) {
4611:                        Map.Entry entry = (Map.Entry) names.next();
4612:                        String typeName = (String) entry.getKey();
4613:                        String path = (String) entry.getValue();
4614:                        if (org.eclipse.jdt.internal.core.util.Util
4615:                                .isJavaLikeFileName(path)) {
4616:                            IFile file = ResourcesPlugin.getWorkspace()
4617:                                    .getRoot().getFile(new Path(path));
4618:                            ICompilationUnit unit = JavaModelManager
4619:                                    .createCompilationUnitFrom(file, null);
4620:                            IType type = unit.getType(typeName);
4621:                            types.put(typeName, type); // replace stored path with type itself
4622:                        }
4623:                    }
4624:                }
4625:
4626:                // Store result in per project info cache if still null or there's still an indexing cache (may have been set by another thread...)
4627:                if (projectInfo.secondaryTypes == null
4628:                        || projectInfo.secondaryTypes
4629:                                .get(INDEXED_SECONDARY_TYPES) != null) {
4630:                    projectInfo.secondaryTypes = secondaryTypes;
4631:                    if (VERBOSE || BasicSearchEngine.VERBOSE) {
4632:                        System.out.print(Thread.currentThread()
4633:                                + "	-> secondary paths stored in cache: "); //$NON-NLS-1$
4634:                        System.out.println();
4635:                        Iterator entries = secondaryTypes.entrySet().iterator();
4636:                        while (entries.hasNext()) {
4637:                            Map.Entry entry = (Map.Entry) entries.next();
4638:                            String qualifiedName = (String) entry.getKey();
4639:                            Util
4640:                                    .verbose("		- " + qualifiedName + '-' + entry.getValue()); //$NON-NLS-1$
4641:                        }
4642:                    }
4643:                }
4644:                return projectInfo.secondaryTypes;
4645:            }
4646:
4647:            /**
4648:             * Remove from secondary types cache all types belonging to a given file.
4649:             * Clean secondary types cache built while indexing if requested.
4650:             * 
4651:             * Project's secondary types cache is found using file location.
4652:             * 
4653:             * @param file File to remove
4654:             */
4655:            public void secondaryTypesRemoving(IFile file,
4656:                    boolean cleanIndexCache) {
4657:                if (VERBOSE) {
4658:                    StringBuffer buffer = new StringBuffer(
4659:                            "JavaModelManager.removeFromSecondaryTypesCache("); //$NON-NLS-1$
4660:                    buffer.append(file.getName());
4661:                    buffer.append(')');
4662:                    Util.verbose(buffer.toString());
4663:                }
4664:                if (file != null) {
4665:                    PerProjectInfo projectInfo = getPerProjectInfo(file
4666:                            .getProject(), false);
4667:                    if (projectInfo != null
4668:                            && projectInfo.secondaryTypes != null) {
4669:                        if (VERBOSE) {
4670:                            Util
4671:                                    .verbose("-> remove file from cache of project: " + file.getProject().getName()); //$NON-NLS-1$
4672:                        }
4673:
4674:                        // Clean current cache
4675:                        secondaryTypesRemoving(projectInfo.secondaryTypes, file);
4676:
4677:                        // Clean indexing cache if necessary
4678:                        HashMap indexingCache = (HashMap) projectInfo.secondaryTypes
4679:                                .get(INDEXED_SECONDARY_TYPES);
4680:                        if (!cleanIndexCache) {
4681:                            if (indexingCache == null) {
4682:                                // Need to signify that secondary types indexing will happen before any request happens
4683:                                // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=152841
4684:                                projectInfo.secondaryTypes.put(
4685:                                        INDEXED_SECONDARY_TYPES, new HashMap());
4686:                            }
4687:                            return;
4688:                        }
4689:                        if (indexingCache != null) {
4690:                            Set keys = indexingCache.keySet();
4691:                            int filesSize = keys.size(), filesCount = 0;
4692:                            IFile[] removed = null;
4693:                            Iterator cachedFiles = keys.iterator();
4694:                            while (cachedFiles.hasNext()) {
4695:                                IFile cachedFile = (IFile) cachedFiles.next();
4696:                                if (file.equals(cachedFile)) {
4697:                                    if (removed == null)
4698:                                        removed = new IFile[filesSize];
4699:                                    filesSize--;
4700:                                    removed[filesCount++] = cachedFile;
4701:                                }
4702:                            }
4703:                            if (removed != null) {
4704:                                for (int i = 0; i < filesCount; i++) {
4705:                                    indexingCache.remove(removed[i]);
4706:                                }
4707:                            }
4708:                        }
4709:                    }
4710:                }
4711:            }
4712:
4713:            /*
4714:             * Remove from a given cache map all secondary types belonging to a given file.
4715:             * Note that there can have several secondary types per file...
4716:             */
4717:            private void secondaryTypesRemoving(Hashtable secondaryTypesMap,
4718:                    IFile file) {
4719:                if (VERBOSE) {
4720:                    StringBuffer buffer = new StringBuffer(
4721:                            "JavaModelManager.removeSecondaryTypesFromMap("); //$NON-NLS-1$
4722:                    Iterator entries = secondaryTypesMap.entrySet().iterator();
4723:                    while (entries.hasNext()) {
4724:                        Map.Entry entry = (Map.Entry) entries.next();
4725:                        String qualifiedName = (String) entry.getKey();
4726:                        buffer.append(qualifiedName + ':' + entry.getValue());
4727:                    }
4728:                    buffer.append(',');
4729:                    buffer.append(file.getFullPath());
4730:                    buffer.append(')');
4731:                    Util.verbose(buffer.toString());
4732:                }
4733:                Set packageEntries = secondaryTypesMap.entrySet();
4734:                int packagesSize = packageEntries.size(), removedPackagesCount = 0;
4735:                String[] removedPackages = null;
4736:                Iterator packages = packageEntries.iterator();
4737:                while (packages.hasNext()) {
4738:                    Map.Entry entry = (Map.Entry) packages.next();
4739:                    String packName = (String) entry.getKey();
4740:                    if (packName != INDEXED_SECONDARY_TYPES) { // skip indexing cache entry if present (!= is intentional)
4741:                        HashMap types = (HashMap) entry.getValue();
4742:                        Set nameEntries = types.entrySet();
4743:                        int namesSize = nameEntries.size(), removedNamesCount = 0;
4744:                        String[] removedNames = null;
4745:                        Iterator names = nameEntries.iterator();
4746:                        while (names.hasNext()) {
4747:                            Map.Entry entry2 = (Map.Entry) names.next();
4748:                            String typeName = (String) entry2.getKey();
4749:                            IType type = (IType) entry2.getValue();
4750:                            if (file.equals(type.getResource())) {
4751:                                if (removedNames == null)
4752:                                    removedNames = new String[namesSize];
4753:                                namesSize--;
4754:                                removedNames[removedNamesCount++] = typeName;
4755:                            }
4756:                        }
4757:                        if (removedNames != null) {
4758:                            for (int i = 0; i < removedNamesCount; i++) {
4759:                                types.remove(removedNames[i]);
4760:                            }
4761:                        }
4762:                        if (types.size() == 0) {
4763:                            if (removedPackages == null)
4764:                                removedPackages = new String[packagesSize];
4765:                            packagesSize--;
4766:                            removedPackages[removedPackagesCount++] = packName;
4767:                        }
4768:                    }
4769:                }
4770:                if (removedPackages != null) {
4771:                    for (int i = 0; i < removedPackagesCount; i++) {
4772:                        secondaryTypesMap.remove(removedPackages[i]);
4773:                    }
4774:                }
4775:                if (VERBOSE) {
4776:                    Util.verbose("	- new secondary types map:"); //$NON-NLS-1$
4777:                    Iterator entries = secondaryTypesMap.entrySet().iterator();
4778:                    while (entries.hasNext()) {
4779:                        Map.Entry entry = (Map.Entry) entries.next();
4780:                        String qualifiedName = (String) entry.getKey();
4781:                        Util
4782:                                .verbose("		+ " + qualifiedName + ':' + entry.getValue()); //$NON-NLS-1$
4783:                    }
4784:                }
4785:            }
4786:
4787:            /**
4788:             * Record the order in which to build the java projects (batch build). This order is based
4789:             * on the projects classpath settings.
4790:             */
4791:            protected void setBuildOrder(String[] javaBuildOrder)
4792:                    throws JavaModelException {
4793:
4794:                // optional behaviour
4795:                // possible value of index 0 is Compute
4796:                if (!JavaCore.COMPUTE.equals(JavaCore
4797:                        .getOption(JavaCore.CORE_JAVA_BUILD_ORDER)))
4798:                    return; // cannot be customized at project level
4799:
4800:                if (javaBuildOrder == null || javaBuildOrder.length <= 1)
4801:                    return;
4802:
4803:                IWorkspace workspace = ResourcesPlugin.getWorkspace();
4804:                IWorkspaceDescription description = workspace.getDescription();
4805:                String[] wksBuildOrder = description.getBuildOrder();
4806:
4807:                String[] newOrder;
4808:                if (wksBuildOrder == null) {
4809:                    newOrder = javaBuildOrder;
4810:                } else {
4811:                    // remove projects which are already mentionned in java builder order
4812:                    int javaCount = javaBuildOrder.length;
4813:                    HashMap newSet = new HashMap(javaCount); // create a set for fast check
4814:                    for (int i = 0; i < javaCount; i++) {
4815:                        newSet.put(javaBuildOrder[i], javaBuildOrder[i]);
4816:                    }
4817:                    int removed = 0;
4818:                    int oldCount = wksBuildOrder.length;
4819:                    for (int i = 0; i < oldCount; i++) {
4820:                        if (newSet.containsKey(wksBuildOrder[i])) {
4821:                            wksBuildOrder[i] = null;
4822:                            removed++;
4823:                        }
4824:                    }
4825:                    // add Java ones first
4826:                    newOrder = new String[oldCount - removed + javaCount];
4827:                    System.arraycopy(javaBuildOrder, 0, newOrder, 0, javaCount); // java projects are built first
4828:
4829:                    // copy previous items in their respective order
4830:                    int index = javaCount;
4831:                    for (int i = 0; i < oldCount; i++) {
4832:                        if (wksBuildOrder[i] != null) {
4833:                            newOrder[index++] = wksBuildOrder[i];
4834:                        }
4835:                    }
4836:                }
4837:                // commit the new build order out
4838:                description.setBuildOrder(newOrder);
4839:                try {
4840:                    workspace.setDescription(description);
4841:                } catch (CoreException e) {
4842:                    throw new JavaModelException(e);
4843:                }
4844:            }
4845:
4846:            /**
4847:             * Sets the last built state for the given project, or null to reset it.
4848:             */
4849:            public void setLastBuiltState(IProject project, Object state) {
4850:                if (JavaProject.hasJavaNature(project)) {
4851:                    // should never be requested on non-Java projects
4852:                    PerProjectInfo info = getPerProjectInfo(project, true /*create if missing*/);
4853:                    info.triedRead = true; // no point trying to re-read once using setter
4854:                    info.savedState = state;
4855:                }
4856:                if (state == null) { // delete state file to ensure a full build happens if the workspace crashes
4857:                    try {
4858:                        File file = getSerializationFile(project);
4859:                        if (file != null && file.exists())
4860:                            file.delete();
4861:                    } catch (SecurityException se) {
4862:                        // could not delete file: cannot do much more
4863:                    }
4864:                }
4865:            }
4866:
4867:            public void setOptions(Hashtable newOptions) {
4868:
4869:                try {
4870:                    IEclipsePreferences defaultPreferences = getDefaultPreferences();
4871:                    IEclipsePreferences instancePreferences = getInstancePreferences();
4872:
4873:                    if (newOptions == null) {
4874:                        instancePreferences.clear();
4875:                    } else {
4876:                        Enumeration keys = newOptions.keys();
4877:                        while (keys.hasMoreElements()) {
4878:                            String key = (String) keys.nextElement();
4879:                            if (!this .optionNames.contains(key))
4880:                                continue; // unrecognized option
4881:                            if (key.equals(JavaCore.CORE_ENCODING))
4882:                                continue; // skipped, contributed by resource prefs
4883:                            String value = (String) newOptions.get(key);
4884:                            String defaultValue = defaultPreferences.get(key,
4885:                                    null);
4886:                            if (defaultValue != null
4887:                                    && defaultValue.equals(value)) {
4888:                                instancePreferences.remove(key);
4889:                            } else {
4890:                                instancePreferences.put(key, value);
4891:                            }
4892:                        }
4893:                    }
4894:
4895:                    // persist options
4896:                    instancePreferences.flush();
4897:
4898:                    // update cache
4899:                    this .optionsCache = newOptions == null ? null
4900:                            : new Hashtable(newOptions);
4901:                } catch (BackingStoreException e) {
4902:                    // ignore
4903:                }
4904:            }
4905:
4906:            public void startup() throws CoreException {
4907:                try {
4908:                    configurePluginDebugOptions();
4909:
4910:                    // initialize Java model cache
4911:                    this .cache = new JavaModelCache();
4912:
4913:                    // request state folder creation (workaround 19885)
4914:                    JavaCore.getPlugin().getStateLocation();
4915:
4916:                    // Initialize eclipse preferences
4917:                    initializePreferences();
4918:
4919:                    // Listen to preference changes
4920:                    this .propertyListener = new Preferences.IPropertyChangeListener() {
4921:                        public void propertyChange(
4922:                                Preferences.PropertyChangeEvent event) {
4923:                            JavaModelManager.this .optionsCache = null;
4924:                        }
4925:                    };
4926:                    JavaCore.getPlugin().getPluginPreferences()
4927:                            .addPropertyChangeListener(this .propertyListener);
4928:
4929:                    // Listen to content-type changes
4930:                    Platform.getContentTypeManager()
4931:                            .addContentTypeChangeListener(this );
4932:
4933:                    // retrieve variable values
4934:                    long start = -1;
4935:                    if (VERBOSE)
4936:                        start = System.currentTimeMillis();
4937:                    loadVariablesAndContainers();
4938:                    if (VERBOSE)
4939:                        traceVariableAndContainers("Loaded", start); //$NON-NLS-1$
4940:
4941:                    final IWorkspace workspace = ResourcesPlugin.getWorkspace();
4942:                    workspace.addResourceChangeListener(this .deltaState,
4943:                    /* update spec in JavaCore#addPreProcessingResourceChangedListener(...) if adding more event types */
4944:                    IResourceChangeEvent.PRE_BUILD
4945:                            | IResourceChangeEvent.POST_BUILD
4946:                            | IResourceChangeEvent.POST_CHANGE
4947:                            | IResourceChangeEvent.PRE_DELETE
4948:                            | IResourceChangeEvent.PRE_CLOSE);
4949:
4950:                    startIndexing();
4951:
4952:                    // process deltas since last activated in indexer thread so that indexes are up-to-date.
4953:                    // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=38658
4954:                    Job processSavedState = new Job(Messages.savedState_jobName) {
4955:                        protected IStatus run(IProgressMonitor monitor) {
4956:                            try {
4957:                                // add save participant and process delta atomically
4958:                                // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=59937
4959:                                workspace.run(new IWorkspaceRunnable() {
4960:                                    public void run(IProgressMonitor progress)
4961:                                            throws CoreException {
4962:                                        ISavedState savedState = workspace
4963:                                                .addSaveParticipant(JavaCore
4964:                                                        .getJavaCore(),
4965:                                                        JavaModelManager.this );
4966:                                        if (savedState != null) {
4967:                                            // the event type coming from the saved state is always POST_AUTO_BUILD
4968:                                            // force it to be POST_CHANGE so that the delta processor can handle it
4969:                                            JavaModelManager.this .deltaState
4970:                                                    .getDeltaProcessor().overridenEventType = IResourceChangeEvent.POST_CHANGE;
4971:                                            savedState
4972:                                                    .processResourceChangeEvents(JavaModelManager.this .deltaState);
4973:                                        }
4974:                                    }
4975:                                }, monitor);
4976:                            } catch (CoreException e) {
4977:                                return e.getStatus();
4978:                            }
4979:                            return Status.OK_STATUS;
4980:                        }
4981:                    };
4982:                    processSavedState.setSystem(true);
4983:                    processSavedState.setPriority(Job.SHORT); // process asap
4984:                    processSavedState.schedule();
4985:                } catch (RuntimeException e) {
4986:                    shutdown();
4987:                    throw e;
4988:                }
4989:            }
4990:
4991:            /**
4992:             * Initiate the background indexing process.
4993:             * This should be deferred after the plug-in activation.
4994:             */
4995:            private void startIndexing() {
4996:                if (this .indexManager != null)
4997:                    this .indexManager.reset();
4998:            }
4999:
5000:            public void shutdown() {
5001:                JavaCore javaCore = JavaCore.getJavaCore();
5002:                javaCore.savePluginPreferences();
5003:                IWorkspace workspace = ResourcesPlugin.getWorkspace();
5004:                workspace.removeResourceChangeListener(this .deltaState);
5005:                workspace.removeSaveParticipant(javaCore);
5006:
5007:                // Stop listening to content-type changes
5008:                Platform.getContentTypeManager()
5009:                        .removeContentTypeChangeListener(this );
5010:
5011:                // Stop indexing
5012:                if (this .indexManager != null) {
5013:                    this .indexManager.shutdown();
5014:                }
5015:
5016:                // Stop listening to preferences changes
5017:                JavaCore.getPlugin().getPluginPreferences()
5018:                        .removePropertyChangeListener(this .propertyListener);
5019:                ((IEclipsePreferences) preferencesLookup[PREF_DEFAULT].parent())
5020:                        .removeNodeChangeListener(this .defaultNodeListener);
5021:                preferencesLookup[PREF_DEFAULT] = null;
5022:                ((IEclipsePreferences) preferencesLookup[PREF_INSTANCE]
5023:                        .parent())
5024:                        .removeNodeChangeListener(this .instanceNodeListener);
5025:                preferencesLookup[PREF_INSTANCE]
5026:                        .removePreferenceChangeListener(this .instancePreferencesListener);
5027:                preferencesLookup[PREF_INSTANCE] = null;
5028:
5029:                // wait for the initialization job to finish
5030:                try {
5031:                    Job.getJobManager().join(JavaCore.PLUGIN_ID, null);
5032:                } catch (InterruptedException e) {
5033:                    // ignore
5034:                }
5035:
5036:                // Note: no need to close the Java model as this just removes Java element infos from the Java model cache
5037:            }
5038:
5039:            public synchronized IPath variableGet(String variableName) {
5040:                // check initialization in progress first
5041:                HashSet initializations = variableInitializationInProgress();
5042:                if (initializations.contains(variableName)) {
5043:                    return VARIABLE_INITIALIZATION_IN_PROGRESS;
5044:                }
5045:                return (IPath) this .variables.get(variableName);
5046:            }
5047:
5048:            private synchronized IPath variableGetDefaultToPreviousSession(
5049:                    String variableName) {
5050:                IPath variablePath = (IPath) this .variables.get(variableName);
5051:                if (variablePath == null)
5052:                    return getPreviousSessionVariable(variableName);
5053:                return variablePath;
5054:            }
5055:
5056:            /*
5057:             * Returns the set of variable names that are being initialized in the current thread.
5058:             */
5059:            private HashSet variableInitializationInProgress() {
5060:                HashSet initializations = (HashSet) this .variableInitializationInProgress
5061:                        .get();
5062:                if (initializations == null) {
5063:                    initializations = new HashSet();
5064:                    this .variableInitializationInProgress.set(initializations);
5065:                }
5066:                return initializations;
5067:            }
5068:
5069:            public synchronized String[] variableNames() {
5070:                int length = this .variables.size();
5071:                String[] result = new String[length];
5072:                Iterator vars = this .variables.keySet().iterator();
5073:                int index = 0;
5074:                while (vars.hasNext()) {
5075:                    result[index++] = (String) vars.next();
5076:                }
5077:                return result;
5078:            }
5079:
5080:            public synchronized void variablePut(String variableName,
5081:                    IPath variablePath) {
5082:
5083:                // set/unset the initialization in progress
5084:                HashSet initializations = variableInitializationInProgress();
5085:                if (variablePath == VARIABLE_INITIALIZATION_IN_PROGRESS) {
5086:                    initializations.add(variableName);
5087:
5088:                    // do not write out intermediate initialization value
5089:                    return;
5090:                } else {
5091:                    initializations.remove(variableName);
5092:
5093:                    // update cache - do not only rely on listener refresh		
5094:                    if (variablePath == null) {
5095:                        // if path is null, record that the variable was removed to avoid asking the initializer to initialize it again
5096:                        // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=112609
5097:                        this .variables.put(variableName, CP_ENTRY_IGNORE_PATH);
5098:                        // clean other variables caches
5099:                        this .variablesWithInitializer.remove(variableName);
5100:                        this .deprecatedVariables.remove(variableName);
5101:                    } else {
5102:                        this .variables.put(variableName, variablePath);
5103:                    }
5104:                    // discard obsoleted information about previous session
5105:                    this .previousSessionVariables.remove(variableName);
5106:                }
5107:            }
5108:
5109:            public void variablePreferencesPut(String variableName,
5110:                    IPath variablePath) {
5111:                String variableKey = CP_VARIABLE_PREFERENCES_PREFIX
5112:                        + variableName;
5113:                if (variablePath == null) {
5114:                    getInstancePreferences().remove(variableKey);
5115:                } else {
5116:                    getInstancePreferences().put(variableKey,
5117:                            variablePath.toString());
5118:                }
5119:                try {
5120:                    getInstancePreferences().flush();
5121:                } catch (BackingStoreException e) {
5122:                    // ignore exception
5123:                }
5124:            }
5125:
5126:            /*
5127:             * Optimize startup case where 1 variable is initialized at a time with the same value as on shutdown.
5128:             */
5129:            public boolean variablePutIfInitializingWithSameValue(
5130:                    String[] variableNames, IPath[] variablePaths) {
5131:                if (variableNames.length != 1)
5132:                    return false;
5133:                String variableName = variableNames[0];
5134:                IPath oldPath = variableGetDefaultToPreviousSession(variableName);
5135:                if (oldPath == null)
5136:                    return false;
5137:                IPath newPath = variablePaths[0];
5138:                if (!oldPath.equals(newPath))
5139:                    return false;
5140:                variablePut(variableName, newPath);
5141:                return true;
5142:            }
5143:
5144:            public void contentTypeChanged(ContentTypeChangeEvent event) {
5145:                Util.resetJavaLikeExtensions();
5146:
5147:            }
5148:
5149:            public synchronized String cacheToString(String prefix) {
5150:                return this.cache.toStringFillingRation(prefix);
5151:            }
5152:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.