sandbox/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchUtilities.java
1.1 --- a/sandbox/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchUtilities.java Mon Dec 19 11:37:36 2016 +0100
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,586 +0,0 @@
1.4 -/*
1.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
1.6 - *
1.7 - * Copyright 2009-2011 Oracle and/or its affiliates. All rights reserved.
1.8 - *
1.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
1.10 - * Other names may be trademarks of their respective owners.
1.11 - *
1.12 - * The contents of this file are subject to the terms of either the GNU
1.13 - * General Public License Version 2 only ("GPL") or the Common
1.14 - * Development and Distribution License("CDDL") (collectively, the
1.15 - * "License"). You may not use this file except in compliance with the
1.16 - * License. You can obtain a copy of the License at
1.17 - * http://www.netbeans.org/cddl-gplv2.html
1.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
1.19 - * specific language governing permissions and limitations under the
1.20 - * License. When distributing the software, include this License Header
1.21 - * Notice in each file and include the License file at
1.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
1.23 - * particular file as subject to the "Classpath" exception as provided
1.24 - * by Oracle in the GPL Version 2 section of the License file that
1.25 - * accompanied this code. If applicable, add the following below the
1.26 - * License Header, with the fields enclosed by brackets [] replaced by
1.27 - * your own identifying information:
1.28 - * "Portions Copyrighted [year] [name of copyright owner]"
1.29 - *
1.30 - * If you wish your version of this file to be governed by only the CDDL
1.31 - * or only the GPL Version 2, indicate your decision by adding
1.32 - * "[Contributor] elects to include this software in this distribution
1.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
1.34 - * single choice of license, a recipient has the option to distribute
1.35 - * your version of this file under either the CDDL, the GPL Version 2 or
1.36 - * to extend the choice of license to its licensees as provided above.
1.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
1.38 - * Version 2 license, then the option applies only if the new code is
1.39 - * made subject to such option by the copyright holder.
1.40 - *
1.41 - * Contributor(s):
1.42 - *
1.43 - * Portions Copyrighted 2009-2011 Sun Microsystems, Inc.
1.44 - */
1.45 -package org.netbeans.modules.java.hints.spiimpl.batch;
1.46 -
1.47 -import com.sun.tools.javac.api.JavacTaskImpl;
1.48 -import com.sun.tools.javac.util.Log;
1.49 -import java.io.IOException;
1.50 -import java.lang.reflect.Constructor;
1.51 -import java.lang.reflect.Method;
1.52 -import java.nio.ByteBuffer;
1.53 -import java.nio.charset.Charset;
1.54 -import java.util.ArrayList;
1.55 -import java.util.Collection;
1.56 -import java.util.Collections;
1.57 -import java.util.HashMap;
1.58 -import java.util.HashSet;
1.59 -import java.util.IdentityHashMap;
1.60 -import java.util.Iterator;
1.61 -import java.util.LinkedHashMap;
1.62 -import java.util.LinkedHashSet;
1.63 -import java.util.LinkedList;
1.64 -import java.util.List;
1.65 -import java.util.Map;
1.66 -import java.util.Map.Entry;
1.67 -import java.util.Properties;
1.68 -import java.util.Set;
1.69 -import java.util.concurrent.atomic.AtomicBoolean;
1.70 -import java.util.logging.Level;
1.71 -import java.util.logging.Logger;
1.72 -import javax.swing.text.BadLocationException;
1.73 -import javax.swing.text.Document;
1.74 -import org.netbeans.api.annotations.common.CheckForNull;
1.75 -import org.netbeans.api.annotations.common.NonNull;
1.76 -import org.netbeans.api.java.classpath.ClassPath;
1.77 -import org.netbeans.api.java.classpath.ClassPath.PathConversionMode;
1.78 -import org.netbeans.api.java.platform.JavaPlatformManager;
1.79 -import org.netbeans.api.java.source.ClasspathInfo;
1.80 -import org.netbeans.api.java.source.CompilationController;
1.81 -import org.netbeans.api.java.source.CompilationInfo;
1.82 -import org.netbeans.api.java.source.JavaSource;
1.83 -import org.netbeans.api.java.source.JavaSource.Phase;
1.84 -import org.netbeans.api.java.source.ModificationResult;
1.85 -import org.netbeans.api.java.source.ModificationResult.Difference;
1.86 -import org.netbeans.api.java.source.Task;
1.87 -import org.netbeans.api.java.source.WorkingCopy;
1.88 -import org.netbeans.api.project.FileOwnerQuery;
1.89 -import org.netbeans.api.project.Project;
1.90 -import org.netbeans.api.project.ProjectUtils;
1.91 -import org.netbeans.api.project.SourceGroup;
1.92 -import org.netbeans.api.project.Sources;
1.93 -import org.netbeans.api.queries.FileEncodingQuery;
1.94 -import org.netbeans.api.queries.VisibilityQuery;
1.95 -//import org.netbeans.modules.java.editor.semantic.SemanticHighlighter;
1.96 -import org.netbeans.modules.java.hints.spiimpl.JavaFixImpl;
1.97 -import org.netbeans.modules.java.hints.spiimpl.JavaFixImpl.Accessor;
1.98 -import org.netbeans.modules.java.hints.spiimpl.MessageImpl;
1.99 -import org.netbeans.modules.java.hints.spiimpl.SyntheticFix;
1.100 -import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.BatchResult;
1.101 -import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.Resource;
1.102 -import org.netbeans.modules.java.hints.spiimpl.ipi.upgrade.ProjectDependencyUpgrader;
1.103 -import org.netbeans.modules.java.source.JavaSourceAccessor;
1.104 -import org.netbeans.modules.java.source.parsing.CompilationInfoImpl;
1.105 -import org.netbeans.modules.java.source.save.DiffUtilities;
1.106 -import org.netbeans.modules.java.source.save.ElementOverlay;
1.107 -import org.netbeans.modules.parsing.api.Source;
1.108 -import org.netbeans.modules.refactoring.spi.RefactoringElementImplementation;
1.109 -import org.netbeans.spi.editor.hints.ErrorDescription;
1.110 -import org.netbeans.spi.editor.hints.Fix;
1.111 -import org.netbeans.spi.java.hints.HintContext.MessageKind;
1.112 -import org.netbeans.spi.java.hints.JavaFix;
1.113 -import org.openide.cookies.EditorCookie;
1.114 -import org.openide.filesystems.FileObject;
1.115 -import org.openide.filesystems.FileUtil;
1.116 -import org.openide.loaders.DataObject;
1.117 -import org.openide.loaders.DataObjectNotFoundException;
1.118 -import org.openide.util.Exceptions;
1.119 -import org.openide.util.Lookup;
1.120 -
1.121 -/**
1.122 - *
1.123 - * @author Jan Lahoda
1.124 - */
1.125 -public class BatchUtilities {
1.126 -
1.127 - private static final Logger LOG = Logger.getLogger(BatchUtilities.class.getName());
1.128 -
1.129 - public static Collection<ModificationResult> applyFixes(BatchResult candidates, @NonNull final ProgressHandleWrapper progress, AtomicBoolean cancel, final Collection<? super MessageImpl> problems) {
1.130 - return applyFixes(candidates, progress, cancel, new ArrayList<RefactoringElementImplementation>(), problems);
1.131 - }
1.132 -
1.133 - public static Collection<ModificationResult> applyFixes(BatchResult candidates, @NonNull final ProgressHandleWrapper progress, AtomicBoolean cancel, final Collection<? super RefactoringElementImplementation> fileChanges, final Collection<? super MessageImpl> problems) {
1.134 - return applyFixes(candidates, progress, cancel, fileChanges, null, problems);
1.135 - }
1.136 -
1.137 - public static Collection<ModificationResult> applyFixes(BatchResult candidates, @NonNull final ProgressHandleWrapper progress, AtomicBoolean cancel, final Collection<? super RefactoringElementImplementation> fileChanges, final Map<JavaFix, ModificationResult> changesPerFix, final Collection<? super MessageImpl> problems) {
1.138 - return applyFixes(candidates, progress, cancel, fileChanges, changesPerFix, false, problems);
1.139 - }
1.140 -
1.141 - public static Collection<ModificationResult> applyFixes(BatchResult candidates, @NonNull final ProgressHandleWrapper progress, AtomicBoolean cancel, final Collection<? super RefactoringElementImplementation> fileChanges, final Map<JavaFix, ModificationResult> changesPerFix, boolean doNotRegisterClassPath, final Collection<? super MessageImpl> problems) {
1.142 - final Map<Project, Set<String>> processedDependencyChanges = new IdentityHashMap<Project, Set<String>>();
1.143 - final Map<FileObject, List<ModificationResult.Difference>> result = new LinkedHashMap<FileObject, List<ModificationResult.Difference>>();
1.144 - final Map<FileObject, byte[]> resourceContentChanges = new HashMap<FileObject, byte[]>();
1.145 -
1.146 - BatchSearch.VerifiedSpansCallBack callback = new BatchSearch.VerifiedSpansCallBack() {
1.147 - private ElementOverlay overlay;
1.148 - public void groupStarted() {
1.149 - overlay = ElementOverlay.getOrCreateOverlay();
1.150 - }
1.151 - public boolean spansVerified(CompilationController wc, Resource r, Collection<? extends ErrorDescription> hints) throws Exception {
1.152 - if (hints.isEmpty()) return true;
1.153 -
1.154 - Constructor<WorkingCopy> wcConstr = WorkingCopy.class.getDeclaredConstructor(CompilationInfoImpl.class, ElementOverlay.class);
1.155 - wcConstr.setAccessible(true);
1.156 -
1.157 -// final WorkingCopy copy = new WorkingCopy(JavaSourceAccessor.getINSTANCE().getCompilationInfoImpl(parameter), overlay);
1.158 - WorkingCopy copy = wcConstr.newInstance(JavaSourceAccessor.getINSTANCE().getCompilationInfoImpl(wc), overlay);
1.159 - Method setJavaSource = CompilationInfo.class.getDeclaredMethod("setJavaSource", JavaSource.class);
1.160 - setJavaSource.setAccessible(true);
1.161 -
1.162 -// copy.setJavaSource(JavaSource.this);
1.163 - setJavaSource.invoke(copy, wc.getJavaSource());
1.164 -
1.165 - copy.toPhase(Phase.RESOLVED);
1.166 - progress.tick();
1.167 -
1.168 - if (applyFixes(copy, processedDependencyChanges, hints, resourceContentChanges, fileChanges, changesPerFix, problems)) {
1.169 - return false;
1.170 - }
1.171 -
1.172 - final JavacTaskImpl jt = JavaSourceAccessor.getINSTANCE().getJavacTask(copy);
1.173 - Log.instance(jt.getContext()).nerrors = 0;
1.174 - Method getChanges = WorkingCopy.class.getDeclaredMethod("getChanges", Map.class);
1.175 - getChanges.setAccessible(true);
1.176 -
1.177 - result.put(copy.getFileObject(), (List<ModificationResult.Difference>) getChanges.invoke(copy, new HashMap<Object, int[]>()));
1.178 -
1.179 - if (LOG.isLoggable(Level.FINE)) {
1.180 - LOG.log(Level.FINE, "fixes applied to: {0}", FileUtil.getFileDisplayName(wc.getFileObject()));
1.181 - }
1.182 -
1.183 - return true;
1.184 - }
1.185 -
1.186 - public void groupFinished() {
1.187 - overlay = null;
1.188 - }
1.189 -
1.190 - public void cannotVerifySpan(Resource r) {
1.191 - problems.add(new MessageImpl(MessageKind.WARNING, "Cannot parse: " + r.getRelativePath()));
1.192 - }
1.193 - };
1.194 -
1.195 - BatchSearch.getVerifiedSpans(candidates, progress, callback, doNotRegisterClassPath, problems, cancel);
1.196 -
1.197 - addResourceContentChanges(resourceContentChanges, result);
1.198 -
1.199 - return Collections.singletonList(JavaSourceAccessor.getINSTANCE().createModificationResult(result, Collections.<Object, int[]>emptyMap()));
1.200 - }
1.201 -
1.202 - public static void addResourceContentChanges(final Map<FileObject, byte[]> resourceContentChanges, final Map<FileObject, List<Difference>> result) {
1.203 - for (Entry<FileObject, byte[]> e : resourceContentChanges.entrySet()) {
1.204 - try {
1.205 - Charset encoding = FileEncodingQuery.getEncoding(e.getKey());
1.206 - final Document originalDocument = getDocument(e.getKey());
1.207 - final String[] origContent = new String[1];
1.208 - final Source[] s = new Source[1];
1.209 - if (originalDocument != null) {
1.210 - originalDocument.render(new Runnable() {
1.211 - @Override public void run() {
1.212 - try {
1.213 - origContent[0] = originalDocument.getText(0, originalDocument.getLength());
1.214 - s[0] = Source.create(originalDocument);
1.215 - } catch (BadLocationException ex) {
1.216 - Exceptions.printStackTrace(ex);
1.217 - }
1.218 - }
1.219 - });
1.220 - }
1.221 -
1.222 - if (origContent[0] == null) {
1.223 - byte[] origBytes = e.getKey().asBytes();
1.224 - origContent[0] = encoding.newDecoder().decode(ByteBuffer.wrap(origBytes)).toString();
1.225 - }
1.226 - String newContent = encoding.newDecoder().decode(ByteBuffer.wrap(e.getValue())).toString();
1.227 -
1.228 - result.put(e.getKey(), DiffUtilities.diff2ModificationResultDifference(e.getKey(), null, Collections.<Integer, String>emptyMap(), origContent[0], newContent, s[0]));
1.229 - } catch (BadLocationException ex) {
1.230 - Exceptions.printStackTrace(ex);
1.231 - } catch (IOException ex) {
1.232 - Exceptions.printStackTrace(ex);
1.233 - }
1.234 - }
1.235 - }
1.236 -
1.237 - public static @CheckForNull Document getDocument(@NonNull FileObject file) {
1.238 - try {
1.239 - DataObject od = DataObject.find(file);
1.240 - EditorCookie ec = od.getLookup().lookup(EditorCookie.class);
1.241 -
1.242 - if (ec == null) return null;
1.243 -
1.244 - return ec.getDocument();
1.245 - } catch (DataObjectNotFoundException ex) {
1.246 - LOG.log(Level.FINE, null, ex);
1.247 - return null;
1.248 - }
1.249 - }
1.250 -
1.251 - private static String positionToString(ErrorDescription ed) {
1.252 - try {
1.253 - return ed.getFile().getNameExt() + ":" + ed.getRange().getBegin().getLine();
1.254 - } catch (IOException ex) {
1.255 - LOG.log(Level.FINE, null, ex);
1.256 - return ed.getFile().getNameExt();
1.257 - }
1.258 - }
1.259 -
1.260 -// public static void removeUnusedImports(Collection<? extends FileObject> files) throws IOException {
1.261 -// Map<ClasspathInfo, Collection<FileObject>> sortedFastFiles = sortFiles(files);
1.262 -//
1.263 -// for (Entry<ClasspathInfo, Collection<FileObject>> e : sortedFastFiles.entrySet()) {
1.264 -// JavaSource.create(e.getKey(), e.getValue()).runModificationTask(new RemoveUnusedImports()).commit();
1.265 -// }
1.266 -// }
1.267 -//
1.268 -// private static final class RemoveUnusedImports implements Task<WorkingCopy> {
1.269 -// public void run(WorkingCopy wc) throws IOException {
1.270 -// Document doc = wc.getSnapshot().getSource().getDocument(true);
1.271 -//
1.272 -// if (wc.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0) {
1.273 -// return;
1.274 -// }
1.275 -//
1.276 -// //compute imports to remove:
1.277 -// List<TreePathHandle> unusedImports = SemanticHighlighter.computeUnusedImports(wc);
1.278 -// CompilationUnitTree cut = wc.getCompilationUnit();
1.279 -// // make the changes to the source
1.280 -// for (TreePathHandle handle : unusedImports) {
1.281 -// TreePath path = handle.resolve(wc);
1.282 -// assert path != null;
1.283 -// cut = wc.getTreeMaker().removeCompUnitImport(cut,
1.284 -// (ImportTree) path.getLeaf());
1.285 -// }
1.286 -//
1.287 -// if (!unusedImports.isEmpty()) {
1.288 -// wc.rewrite(wc.getCompilationUnit(), cut);
1.289 -// }
1.290 -// }
1.291 -// }
1.292 -
1.293 - public static boolean applyFixes(WorkingCopy copy, Map<Project, Set<String>> processedDependencyChanges, Collection<? extends ErrorDescription> hints, Map<FileObject, byte[]> resourceContentChanges, Collection<? super RefactoringElementImplementation> fileChanges, Collection<? super MessageImpl> problems) throws IllegalStateException, Exception {
1.294 - return applyFixes(copy, processedDependencyChanges, hints, resourceContentChanges, fileChanges, null, problems);
1.295 - }
1.296 -
1.297 - public static boolean applyFixes(WorkingCopy copy, Map<Project, Set<String>> processedDependencyChanges, Collection<? extends ErrorDescription> hints, Map<FileObject, byte[]> resourceContentChanges, Collection<? super RefactoringElementImplementation> fileChanges, Map<JavaFix, ModificationResult> changesPerFix, Collection<? super MessageImpl> problems) throws IllegalStateException, Exception {
1.298 - Set<JavaFix> fixes = new LinkedHashSet<JavaFix>();
1.299 - for (ErrorDescription ed : hints) {
1.300 - if (!ed.getFixes().isComputed()) {
1.301 - throw new IllegalStateException();//TODO: should be problem
1.302 - }
1.303 -
1.304 - Fix toApply = null;
1.305 -
1.306 - for (Fix f : ed.getFixes().getFixes()) {
1.307 - if (f instanceof SyntheticFix) continue;
1.308 - if (toApply == null) toApply = f;
1.309 - else problems.add(new MessageImpl(MessageKind.WARNING, "More than one fix for: " + ed.getDescription() + " at " + positionToString(ed) + ", only the first one will be used."));
1.310 - }
1.311 -
1.312 - if (toApply == null) {
1.313 - //TODO: currently giving a warning so that the hints can be augmented with "Options.QUERY", but that should be removed
1.314 - //if a non-query hint cannot produce any fix, it is likely Ok - if not, the hint should produce a warning itself
1.315 - boolean doWarning = false;
1.316 - assert doWarning = true;
1.317 - if (doWarning) {
1.318 - problems.add(new MessageImpl(MessageKind.WARNING, "No fix for: " + ed.getDescription() + " at " + positionToString(ed) + "."));
1.319 - }
1.320 - continue;
1.321 - }
1.322 -
1.323 - if (!(toApply instanceof JavaFixImpl)) {
1.324 - throw new IllegalStateException(toApply.getClass().getName());//XXX: hints need to provide JavaFixes
1.325 - }
1.326 -
1.327 -
1.328 - fixes.add(((JavaFixImpl) toApply).jf);
1.329 - }
1.330 - if (fixDependencies(copy.getFileObject(), fixes, processedDependencyChanges)) {
1.331 - return true;
1.332 - }
1.333 - for (JavaFix f : fixes) {
1.334 -// if (cancel.get()) return ;
1.335 -
1.336 - JavaFixImpl.Accessor.INSTANCE.process(f, copy, false, resourceContentChanges, fileChanges);
1.337 -
1.338 - if (changesPerFix != null) {
1.339 - ElementOverlay overlay = ElementOverlay.getOrCreateOverlay(); //XXX: will use the incorrect overlay?
1.340 - Constructor<WorkingCopy> wcConstr = WorkingCopy.class.getDeclaredConstructor(CompilationInfoImpl.class, ElementOverlay.class);
1.341 - wcConstr.setAccessible(true);
1.342 -
1.343 -// final WorkingCopy copy = new WorkingCopy(JavaSourceAccessor.getINSTANCE().getCompilationInfoImpl(parameter), overlay);
1.344 - WorkingCopy perFixCopy = wcConstr.newInstance(JavaSourceAccessor.getINSTANCE().getCompilationInfoImpl(copy), overlay);
1.345 - Method setJavaSource = CompilationInfo.class.getDeclaredMethod("setJavaSource", JavaSource.class);
1.346 - setJavaSource.setAccessible(true);
1.347 -
1.348 -// copy.setJavaSource(JavaSource.this);
1.349 - setJavaSource.invoke(perFixCopy, copy.getJavaSource());
1.350 -
1.351 - perFixCopy.toPhase(Phase.RESOLVED);
1.352 -
1.353 - final Map<FileObject, byte[]> perFixResourceContentChanges = new HashMap<FileObject, byte[]>();
1.354 -
1.355 - JavaFixImpl.Accessor.INSTANCE.process(f, perFixCopy, false, perFixResourceContentChanges, new ArrayList<RefactoringElementImplementation>());
1.356 -
1.357 - final JavacTaskImpl jt = JavaSourceAccessor.getINSTANCE().getJavacTask(perFixCopy);
1.358 - Log.instance(jt.getContext()).nerrors = 0;
1.359 - Method getChanges = WorkingCopy.class.getDeclaredMethod("getChanges", Map.class);
1.360 - getChanges.setAccessible(true);
1.361 -
1.362 - Map<FileObject, List<Difference>> changes = new HashMap<FileObject, List<Difference>>();
1.363 -
1.364 - changes.put(perFixCopy.getFileObject(), (List<ModificationResult.Difference>) getChanges.invoke(perFixCopy, new HashMap<Object, int[]>()));
1.365 -
1.366 - addResourceContentChanges(resourceContentChanges, changes);
1.367 -
1.368 - for (Iterator<Entry<FileObject, List<Difference>>> it = changes.entrySet().iterator(); it.hasNext();) {
1.369 - if (it.next().getValue().isEmpty()) it.remove();
1.370 - }
1.371 -
1.372 - if (!changes.isEmpty()) {
1.373 - ModificationResult perFixResult = JavaSourceAccessor.getINSTANCE().createModificationResult(changes, Collections.<Object, int[]>emptyMap());
1.374 -
1.375 - changesPerFix.put(f, perFixResult);
1.376 - }
1.377 - }
1.378 - }
1.379 - return false;
1.380 - }
1.381 -
1.382 - public static Collection<ModificationResult> applyFixes(final Map<FileObject, Collection<JavaFix>> toRun) {
1.383 - final Map<FileObject, List<ModificationResult.Difference>> result = new LinkedHashMap<FileObject, List<ModificationResult.Difference>>();
1.384 - final Map<FileObject, byte[]> resourceContentChanges = new HashMap<FileObject, byte[]>();
1.385 - Map<ClasspathInfo, Collection<FileObject>> cp2Files = BatchUtilities.sortFiles(toRun.keySet());
1.386 -
1.387 - for (Entry<ClasspathInfo, Collection<FileObject>> e : cp2Files.entrySet()) {
1.388 - try {
1.389 - ModificationResult mr = JavaSource.create(e.getKey(), e.getValue()).runModificationTask(new Task<WorkingCopy>() {
1.390 - @Override
1.391 - public void run(WorkingCopy parameter) throws Exception {
1.392 - if (parameter.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0) return ;
1.393 -
1.394 - for (JavaFix jf : toRun.get(parameter.getFileObject())) {
1.395 - JavaFixImpl.Accessor.INSTANCE.process(jf, parameter, false, resourceContentChanges, new ArrayList<RefactoringElementImplementation>());
1.396 - }
1.397 - }
1.398 - });
1.399 -
1.400 - result.putAll(JavaSourceAccessor.getINSTANCE().getDiffsFromModificationResult(mr));
1.401 - } catch (IOException ex) {
1.402 - Exceptions.printStackTrace(ex);
1.403 - }
1.404 - }
1.405 -
1.406 - addResourceContentChanges(resourceContentChanges, result);
1.407 -
1.408 - return Collections.singletonList(JavaSourceAccessor.getINSTANCE().createModificationResult(result, Collections.<Object, int[]>emptyMap()));
1.409 - }
1.410 -
1.411 - public static Collection<FileObject> getSourceGroups(Iterable<? extends Project> prjs) {
1.412 - List<FileObject> result = new LinkedList<FileObject>();
1.413 -
1.414 - for (Project p : prjs) {
1.415 - Sources s = ProjectUtils.getSources(p);
1.416 -
1.417 - for (SourceGroup sg : s.getSourceGroups("java")) {
1.418 - result.add(sg.getRootFolder());
1.419 - }
1.420 - }
1.421 -
1.422 - return result;
1.423 - }
1.424 -
1.425 - public static Map<ClasspathInfo, Collection<FileObject>> sortFiles(Collection<? extends FileObject> from) {
1.426 - Map<CPCategorizer, Collection<FileObject>> m = new HashMap<CPCategorizer, Collection<FileObject>>();
1.427 -
1.428 - for (FileObject f : from) {
1.429 - CPCategorizer cpCategorizer = new CPCategorizer(f);
1.430 -
1.431 - Collection<FileObject> files = m.get(cpCategorizer);
1.432 -
1.433 - if (files == null) {
1.434 - m.put(cpCategorizer, files = new LinkedList<FileObject>());
1.435 - }
1.436 -
1.437 - files.add(f);
1.438 - }
1.439 -
1.440 - Map<ClasspathInfo, Collection<FileObject>> result = new IdentityHashMap<ClasspathInfo, Collection<FileObject>>();
1.441 -
1.442 - for (Entry<CPCategorizer, Collection<FileObject>> e : m.entrySet()) {
1.443 - result.put(ClasspathInfo.create(e.getKey().boot, e.getKey().compile, e.getKey().source), e.getValue());
1.444 - }
1.445 -
1.446 - return result;
1.447 - }
1.448 -
1.449 - private static final ClassPath getClassPath(FileObject forFO, String id) {
1.450 - ClassPath result = ClassPath.getClassPath(forFO, id);
1.451 -
1.452 - if (result == null) {
1.453 - if (ClassPath.BOOT.equals(id)) {
1.454 - result = JavaPlatformManager.getDefault().getDefaultPlatform().getBootstrapLibraries();
1.455 - } else {
1.456 - result = ClassPath.EMPTY;
1.457 - }
1.458 - }
1.459 -
1.460 - return result;
1.461 - }
1.462 -
1.463 - private static final class CPCategorizer {
1.464 - private final String cps;
1.465 - private final ClassPath boot;
1.466 - private final ClassPath compile;
1.467 - private final ClassPath source;
1.468 - private final FileObject sourceRoot;
1.469 -
1.470 - public CPCategorizer(FileObject file) {
1.471 - this.boot = getClassPath(file, ClassPath.BOOT);
1.472 - this.compile = getClassPath(file, ClassPath.COMPILE);
1.473 - this.source = getClassPath(file, ClassPath.SOURCE);
1.474 - this.sourceRoot = source != null ? source.findOwnerRoot(file) : null;
1.475 -
1.476 - StringBuilder cps = new StringBuilder();
1.477 -
1.478 - if (boot != null) cps.append(boot.toString(PathConversionMode.PRINT));
1.479 - if (compile != null) cps.append(compile.toString(PathConversionMode.PRINT));
1.480 - if (source != null) cps.append(source.toString(PathConversionMode.PRINT));
1.481 -
1.482 - this.cps = cps.toString();
1.483 - }
1.484 -
1.485 - @Override
1.486 - public int hashCode() {
1.487 - int hash = 5;
1.488 - hash = 53 * hash + this.cps.hashCode();
1.489 - hash = 53 * hash + (this.sourceRoot != null ? this.sourceRoot.hashCode() : 0);
1.490 - return hash;
1.491 - }
1.492 -
1.493 - @Override
1.494 - public boolean equals(Object obj) {
1.495 - if (obj == null) {
1.496 - return false;
1.497 - }
1.498 - if (getClass() != obj.getClass()) {
1.499 - return false;
1.500 - }
1.501 - final CPCategorizer other = (CPCategorizer) obj;
1.502 - if (!this.cps.equals(other.cps)) {
1.503 - return false;
1.504 - }
1.505 - if (this.sourceRoot != other.sourceRoot && (this.sourceRoot == null || !this.sourceRoot.equals(other.sourceRoot))) {
1.506 - return false;
1.507 - }
1.508 - return true;
1.509 - }
1.510 -
1.511 - }
1.512 -
1.513 - public static final String ENSURE_DEPENDENCY = "ensure-dependency";
1.514 -
1.515 - public static boolean fixDependencies(FileObject file, Iterable<? extends JavaFix> toProcess, Map<Project, Set<String>> alreadyProcessed) {
1.516 - boolean modified = false;
1.517 -// for (FileObject file : toProcess.keySet()) {
1.518 - for (JavaFix fix : toProcess) {
1.519 - String updateTo = Accessor.INSTANCE.getOptions(fix).get(ENSURE_DEPENDENCY);
1.520 -
1.521 - if (updateTo != null) {
1.522 - Project p = FileOwnerQuery.getOwner(file);
1.523 -
1.524 - if (p != null) {
1.525 - Set<String> seen = alreadyProcessed.get(p);
1.526 -
1.527 - if (seen == null) {
1.528 - alreadyProcessed.put(p, seen = new HashSet<String>());
1.529 - }
1.530 -
1.531 - if (seen.add(updateTo)) {
1.532 - for (ProjectDependencyUpgrader up : Lookup.getDefault().lookupAll(ProjectDependencyUpgrader.class)) {
1.533 - if (up.ensureDependency(p, updateTo, false)) { //XXX: should check whether the given project was actually modified
1.534 - modified = true;
1.535 - break;
1.536 - }
1.537 - }
1.538 - //TODO: fail if cannot update the dependency?
1.539 - }
1.540 - }
1.541 - }
1.542 - }
1.543 -
1.544 - return modified;
1.545 -// }
1.546 - }
1.547 -
1.548 - public static void recursive(FileObject root, FileObject file, Collection<FileObject> collected, ProgressHandleWrapper progress, int depth, Properties timeStamps, Set<String> removedFiles, boolean recursive) {
1.549 - if (!VisibilityQuery.getDefault().isVisible(file)) return;
1.550 -
1.551 - if (file.isData()) {
1.552 - if (timeStamps != null) {
1.553 - String relativePath = FileUtil.getRelativePath(root, file);
1.554 - String lastModified = Long.toHexString(file.lastModified().getTime());
1.555 -
1.556 - removedFiles.remove(relativePath);
1.557 -
1.558 - if (lastModified.equals(timeStamps.getProperty(relativePath))) {
1.559 - return;
1.560 - }
1.561 -
1.562 - timeStamps.setProperty(relativePath, lastModified);
1.563 - }
1.564 -
1.565 - if (/*???:*/"java".equals(file.getExt()) || "text/x-java".equals(FileUtil.getMIMEType(file, "text/x-java"))) {
1.566 - collected.add(file);
1.567 - }
1.568 - } else {
1.569 - FileObject[] children = file.getChildren();
1.570 -
1.571 - if (children.length == 0) return;
1.572 -
1.573 - ProgressHandleWrapper inner = depth < 2 ? progress.startNextPartWithEmbedding(ProgressHandleWrapper.prepareParts(children.length)) : null;
1.574 -
1.575 - if (inner == null && progress != null) {
1.576 - progress.startNextPart(children.length);
1.577 - } else {
1.578 - progress = null;
1.579 - }
1.580 -
1.581 - for (FileObject c : children) {
1.582 - if (recursive || c.isData())
1.583 - recursive(root, c, collected, inner, depth + 1, timeStamps, removedFiles, recursive);
1.584 -
1.585 - if (progress != null) progress.tick();
1.586 - }
1.587 - }
1.588 - }
1.589 -}