PageRenderTime 148ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/netbeans-7.3/editor.errorstripe/src/org/netbeans/modules/editor/errorstripe/AnnotationViewDataImpl.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 733 lines | 529 code | 146 blank | 58 comment | 142 complexity | 3159a58cdb1f35aa4a521b8b6e6b0384 MD5 | raw file
  1. /*
  2. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  3. *
  4. * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  5. *
  6. * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  7. * Other names may be trademarks of their respective owners.
  8. *
  9. * The contents of this file are subject to the terms of either the GNU
  10. * General Public License Version 2 only ("GPL") or the Common
  11. * Development and Distribution License("CDDL") (collectively, the
  12. * "License"). You may not use this file except in compliance with the
  13. * License. You can obtain a copy of the License at
  14. * http://www.netbeans.org/cddl-gplv2.html
  15. * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  16. * specific language governing permissions and limitations under the
  17. * License. When distributing the software, include this License Header
  18. * Notice in each file and include the License file at
  19. * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
  20. * particular file as subject to the "Classpath" exception as provided
  21. * by Oracle in the GPL Version 2 section of the License file that
  22. * accompanied this code. If applicable, add the following below the
  23. * License Header, with the fields enclosed by brackets [] replaced by
  24. * your own identifying information:
  25. * "Portions Copyrighted [year] [name of copyright owner]"
  26. *
  27. * Contributor(s):
  28. *
  29. * The Original Software is NetBeans. The Initial Developer of the Original
  30. * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  31. * Microsystems, Inc. All Rights Reserved.
  32. *
  33. * If you wish your version of this file to be governed by only the CDDL
  34. * or only the GPL Version 2, indicate your decision by adding
  35. * "[Contributor] elects to include this software in this distribution
  36. * under the [CDDL or GPL Version 2] license." If you do not indicate a
  37. * single choice of license, a recipient has the option to distribute
  38. * your version of this file under either the CDDL, the GPL Version 2 or
  39. * to extend the choice of license to its licensees as provided above.
  40. * However, if you add GPL Version 2 code and therefore, elected the GPL
  41. * Version 2 license, then the option applies only if the new code is
  42. * made subject to such option by the copyright holder.
  43. */
  44. package org.netbeans.modules.editor.errorstripe;
  45. import java.beans.PropertyChangeEvent;
  46. import java.beans.PropertyChangeListener;
  47. import java.util.ArrayList;
  48. import java.util.Arrays;
  49. import java.util.Collection;
  50. import java.util.Collections;
  51. import java.util.Iterator;
  52. import java.util.LinkedHashSet;
  53. import java.util.List;
  54. import java.util.NoSuchElementException;
  55. import java.util.SortedMap;
  56. import java.util.TreeMap;
  57. import java.util.WeakHashMap;
  58. import java.util.logging.Level;
  59. import java.util.logging.Logger;
  60. import javax.swing.text.JTextComponent;
  61. import org.netbeans.api.editor.mimelookup.MimeLookup;
  62. import org.netbeans.api.editor.mimelookup.MimePath;
  63. import org.netbeans.editor.AnnotationDesc;
  64. import org.netbeans.editor.AnnotationType;
  65. import org.netbeans.editor.AnnotationType.Severity;
  66. import org.netbeans.editor.Annotations;
  67. import org.netbeans.editor.BaseDocument;
  68. import org.netbeans.lib.editor.util.swing.DocumentUtilities;
  69. import org.netbeans.modules.editor.errorstripe.privatespi.Mark;
  70. import org.netbeans.modules.editor.errorstripe.privatespi.MarkProvider;
  71. import org.netbeans.modules.editor.errorstripe.privatespi.MarkProviderCreator;
  72. import org.netbeans.modules.editor.errorstripe.privatespi.Status;
  73. import org.netbeans.spi.editor.errorstripe.UpToDateStatus;
  74. import org.netbeans.spi.editor.errorstripe.UpToDateStatusProvider;
  75. import org.netbeans.spi.editor.errorstripe.UpToDateStatusProviderFactory;
  76. import org.netbeans.spi.editor.mimelookup.InstanceProvider;
  77. import org.openide.ErrorManager;
  78. import org.netbeans.modules.editor.errorstripe.apimodule.SPIAccessor;
  79. import org.netbeans.spi.editor.mimelookup.MimeLocation;
  80. import org.openide.cookies.InstanceCookie;
  81. import org.openide.filesystems.FileObject;
  82. import org.openide.loaders.DataObject;
  83. import org.openide.util.NbCollections;
  84. /**
  85. *
  86. * @author Jan Lahoda
  87. */
  88. final class AnnotationViewDataImpl implements PropertyChangeListener, AnnotationViewData, Annotations.AnnotationsListener {
  89. private static final Logger LOG = Logger.getLogger(AnnotationViewDataImpl.class.getName());
  90. private static final String UP_TO_DATE_STATUS_PROVIDER_FOLDER_NAME = "UpToDateStatusProvider"; //NOI18N
  91. private static final String TEXT_BASE_PATH = "Editors/text/base/"; //NOI18N
  92. private AnnotationView view;
  93. private JTextComponent pane;
  94. private BaseDocument document;
  95. private List<MarkProvider> markProviders = new ArrayList<MarkProvider>();
  96. private List<UpToDateStatusProvider> statusProviders = new ArrayList<UpToDateStatusProvider>();
  97. private Collection<Mark> currentMarks = null;
  98. private SortedMap<Integer, List<Mark>> marksMap = null;
  99. private static WeakHashMap<String, Collection<? extends MarkProviderCreator>> mime2Creators = new WeakHashMap<String, Collection<? extends MarkProviderCreator>>();
  100. private static WeakHashMap<String, Collection<? extends UpToDateStatusProviderFactory>> mime2StatusProviders = new WeakHashMap<String, Collection<? extends UpToDateStatusProviderFactory>>();
  101. private static LegacyCrapProvider legacyCrap;
  102. /** Creates a new instance of AnnotationViewData */
  103. public AnnotationViewDataImpl(AnnotationView view, JTextComponent pane) {
  104. this.view = view;
  105. this.pane = pane;
  106. this.document = null;
  107. }
  108. public void register(BaseDocument document) {
  109. this.document = document;
  110. gatherProviders(pane);
  111. addListenersToProviders();
  112. if (document != null) {
  113. document.getAnnotations().addAnnotationsListener(this);
  114. }
  115. clear();
  116. }
  117. public void unregister() {
  118. if (document != null) {
  119. document.getAnnotations().removeAnnotationsListener(this);
  120. }
  121. removeListenersFromProviders();
  122. document = null;
  123. }
  124. public static void initProviders(String mimeType) {
  125. // Legacy mime path (text/base)
  126. MimePath legacyMimePath = MimePath.parse("text/base");
  127. legacyCrap = MimeLookup.getLookup(legacyMimePath).lookup(LegacyCrapProvider.class);
  128. lookupProviders(mimeType);
  129. }
  130. private static void lookupProviders(String mimeType) {
  131. MimePath mimePath = MimePath.parse(mimeType);
  132. // Mark providers
  133. mime2Creators.put(mimeType, MimeLookup.getLookup(mimePath).lookupAll(MarkProviderCreator.class));
  134. // Status providers
  135. mime2StatusProviders.put(mimeType, MimeLookup.getLookup(mimePath).lookupAll(UpToDateStatusProviderFactory.class));
  136. }
  137. private void gatherProviders(JTextComponent pane) {
  138. long start = System.currentTimeMillis();
  139. // Collect legacy mark providers
  140. List<MarkProvider> newMarkProviders = new ArrayList<MarkProvider>();
  141. if (legacyCrap != null) {
  142. createMarkProviders(legacyCrap.getMarkProviderCreators(), newMarkProviders, pane);
  143. }
  144. // Collect mark providers
  145. String mimeType = DocumentUtilities.getMimeType(pane);
  146. if (mimeType == null) {
  147. mimeType = pane.getUI().getEditorKit(pane).getContentType();
  148. }
  149. Collection<? extends MarkProviderCreator> creators =
  150. mime2Creators.get(mimeType);
  151. if (creators == null) { //nothing for current mimeType, probably wrong init
  152. lookupProviders(mimeType);
  153. creators = mime2Creators.get(mimeType);
  154. }
  155. createMarkProviders(creators, newMarkProviders, pane);
  156. this.markProviders = newMarkProviders;
  157. // Collect legacy status providers
  158. List<UpToDateStatusProvider> newStatusProviders = new ArrayList<UpToDateStatusProvider>();
  159. if (legacyCrap != null) {
  160. createStatusProviders(legacyCrap.getUpToDateStatusProviderFactories(), newStatusProviders, pane);
  161. }
  162. // Collect status providers
  163. Collection<? extends UpToDateStatusProviderFactory> factories =
  164. mime2StatusProviders.get(mimeType);
  165. createStatusProviders(factories, newStatusProviders, pane);
  166. this.statusProviders = newStatusProviders;
  167. long end = System.currentTimeMillis();
  168. if (AnnotationView.TIMING_ERR.isLoggable(ErrorManager.INFORMATIONAL)) {
  169. AnnotationView.TIMING_ERR.log(ErrorManager.INFORMATIONAL, "gather providers took: " + (end - start));
  170. }
  171. }
  172. private static void createMarkProviders(Collection<? extends MarkProviderCreator> creators, List<MarkProvider> providers, JTextComponent pane) {
  173. for (MarkProviderCreator creator : creators) {
  174. if (LOG.isLoggable(Level.FINE)) {
  175. LOG.fine("creator = " + creator);
  176. }
  177. MarkProvider provider = creator.createMarkProvider(pane);
  178. if (provider != null) {
  179. providers.add(provider);
  180. }
  181. }
  182. }
  183. private static void createStatusProviders(Collection<? extends UpToDateStatusProviderFactory> factories, List<UpToDateStatusProvider> providers, JTextComponent pane) {
  184. for(UpToDateStatusProviderFactory factory : factories) {
  185. if (LOG.isLoggable(Level.FINE)) {
  186. LOG.fine("factory = " + factory);
  187. }
  188. UpToDateStatusProvider provider = factory.createUpToDateStatusProvider(pane.getDocument());
  189. if (provider != null) {
  190. providers.add(provider);
  191. }
  192. }
  193. }
  194. private void addListenersToProviders() {
  195. for (Iterator p = statusProviders.iterator(); p.hasNext(); ) {
  196. UpToDateStatusProvider provider = (UpToDateStatusProvider) p.next();
  197. SPIAccessor.getDefault().addPropertyChangeListener(provider, this);
  198. }
  199. for (Iterator p = markProviders.iterator(); p.hasNext(); ) {
  200. MarkProvider provider = (MarkProvider) p.next();
  201. provider.addPropertyChangeListener(this);
  202. }
  203. }
  204. private void removeListenersFromProviders() {
  205. for (Iterator p = statusProviders.iterator(); p.hasNext(); ) {
  206. UpToDateStatusProvider provider = (UpToDateStatusProvider) p.next();
  207. SPIAccessor.getDefault().removePropertyChangeListener(provider, this);
  208. }
  209. for (Iterator p = markProviders.iterator(); p.hasNext(); ) {
  210. MarkProvider provider = (MarkProvider) p.next();
  211. provider.removePropertyChangeListener(this);
  212. }
  213. }
  214. /*package private*/ static Collection<Mark> createMergedMarks(List<MarkProvider> providers) {
  215. Collection<Mark> result = new LinkedHashSet<Mark>();
  216. for(MarkProvider provider : providers) {
  217. result.addAll(provider.getMarks());
  218. }
  219. return result;
  220. }
  221. /*package private for tests*/synchronized Collection<Mark> getMergedMarks() {
  222. if (currentMarks == null) {
  223. currentMarks = createMergedMarks(markProviders);
  224. }
  225. return new ArrayList<Mark>(currentMarks);
  226. }
  227. /*package private*/ static List<Mark> getStatusesForLineImpl(int line, SortedMap<Integer, List<Mark>> marks) {
  228. List<Mark> inside = marks.get(line);
  229. return inside == null ? Collections.<Mark>emptyList() : inside;
  230. }
  231. public Mark getMainMarkForBlock(int startLine, int endLine) {
  232. Mark m1;
  233. synchronized(this) {
  234. m1 = getMainMarkForBlockImpl(startLine, endLine, getMarkMap());
  235. }
  236. Mark m2 = getMainMarkForBlockAnnotations(startLine, endLine);
  237. if (m1 == null)
  238. return m2;
  239. if (m2 == null)
  240. return m1;
  241. if (isMoreImportant(m1, m2))
  242. return m1;
  243. else
  244. return m2;
  245. }
  246. /*package private*/ static Mark getMainMarkForBlockImpl(int startLine, int endLine, SortedMap<Integer, List<Mark>> marks) {
  247. int current = startLine - 1;
  248. Mark found = null;
  249. while ((current = findNextUsedLine(current, marks)) != Integer.MAX_VALUE && current <= endLine) {
  250. for (Mark newMark : getStatusesForLineImpl(/*doc, */current, marks)) {
  251. if (found == null || isMoreImportant(newMark, found)) {
  252. found = newMark;
  253. }
  254. }
  255. }
  256. return found;
  257. }
  258. private static boolean isMoreImportant(Mark m1, Mark m2) {
  259. int compared = m1.getStatus().compareTo(m2.getStatus());
  260. if (compared == 0)
  261. return m1.getPriority() < m2.getPriority();
  262. return compared > 0;
  263. }
  264. private boolean isMoreImportant(AnnotationDesc a1, AnnotationDesc a2) {
  265. AnnotationType t1 = a1.getAnnotationTypeInstance();
  266. AnnotationType t2 = a2.getAnnotationTypeInstance();
  267. int compared = t1.getSeverity().compareTo(t2.getSeverity());
  268. if (compared == 0)
  269. return t1.getPriority() < t2.getPriority();
  270. return compared > 0;
  271. }
  272. private boolean isValidForErrorStripe(AnnotationDesc a) {
  273. return a.getAnnotationTypeInstance().getSeverity() != AnnotationType.Severity.STATUS_NONE;
  274. }
  275. private Mark getMainMarkForBlockAnnotations(int startLine, int endLine) {
  276. AnnotationDesc foundDesc = null;
  277. for (AnnotationDesc desc : NbCollections.iterable(listAnnotations(startLine, endLine))) {
  278. if ((foundDesc == null || isMoreImportant(desc, foundDesc)) && isValidForErrorStripe(desc))
  279. foundDesc = desc;
  280. }
  281. if (foundDesc != null)
  282. return new AnnotationMark(foundDesc);
  283. else
  284. return null;
  285. }
  286. public int findNextUsedLine(int from) {
  287. int line1;
  288. synchronized (this) {
  289. line1 = findNextUsedLine(from, getMarkMap());
  290. }
  291. int line2 = document.getAnnotations().getNextLineWithAnnotation(from + 1);
  292. if (line2 == (-1))
  293. line2 = Integer.MAX_VALUE;
  294. return line1 < line2 ? line1 : line2;
  295. }
  296. /*package private*/ static int findNextUsedLine(int from, SortedMap<Integer, List<Mark>> marks) {
  297. SortedMap<Integer, List<Mark>> next = marks.tailMap(from + 1);
  298. if (LOG.isLoggable(Level.FINE)) {
  299. LOG.fine("AnnotationView.findNextUsedLine from: " + from + "; marks: " + marks + "; next: " + next); //NOI18N
  300. }
  301. if (next.isEmpty()) {
  302. return Integer.MAX_VALUE;
  303. }
  304. return next.firstKey().intValue();
  305. }
  306. private void registerMark(Mark mark) {
  307. int[] span = mark.getAssignedLines();
  308. if (LOG.isLoggable(Level.FINE)) {
  309. LOG.fine("AnnotationView.registerMark mark: " + mark + "; from-to: " + span[0] + "-" + span[1]); //NOI18N
  310. }
  311. for (int line = span[0]; line <= span[1]; line++) {
  312. List<Mark> inside = marksMap.get(line);
  313. if (inside == null) {
  314. inside = new ArrayList<Mark>();
  315. marksMap.put(line, inside);
  316. }
  317. inside.add(mark);
  318. }
  319. }
  320. private void unregisterMark(Mark mark) {
  321. int[] span = mark.getAssignedLines();
  322. if (LOG.isLoggable(Level.FINE)) {
  323. LOG.fine("AnnotationView.unregisterMark mark: " + mark + "; from-to: " + span[0] + "-" + span[1]); //NOI18N
  324. }
  325. for (int line = span[0]; line <= span[1]; line++) {
  326. List<Mark> inside = marksMap.get(line);
  327. if (inside != null) {
  328. inside.remove(mark);
  329. if (inside.size() == 0) {
  330. marksMap.remove(line);
  331. }
  332. }
  333. }
  334. }
  335. /*package private for tests*/synchronized SortedMap<Integer, List<Mark>> getMarkMap() {
  336. if (marksMap == null) {
  337. Collection<Mark> marks = getMergedMarks();
  338. marksMap = new TreeMap<Integer, List<Mark>>();
  339. for (Mark mark : marks) {
  340. registerMark(mark);
  341. }
  342. }
  343. return marksMap;
  344. }
  345. @Override
  346. public Status computeTotalStatus() {
  347. Status targetStatus = Status.STATUS_OK;
  348. Collection<Mark> marks = getMergedMarks();
  349. for(Mark mark : marks) {
  350. Status s = mark.getStatus();
  351. targetStatus = Status.getCompoundStatus(s, targetStatus);
  352. }
  353. for (AnnotationDesc desc : NbCollections.iterable(listAnnotations(-1, Integer.MAX_VALUE))) {
  354. Status s = get(desc.getAnnotationTypeInstance());
  355. if (s != null)
  356. targetStatus = Status.getCompoundStatus(s, targetStatus);
  357. }
  358. return targetStatus;
  359. }
  360. @Override
  361. public UpToDateStatus computeTotalStatusType() {
  362. if (statusProviders.isEmpty())
  363. return UpToDateStatus.UP_TO_DATE_DIRTY;
  364. UpToDateStatus statusType = UpToDateStatus.UP_TO_DATE_OK;
  365. for (Iterator p = statusProviders.iterator(); p.hasNext(); ) {
  366. UpToDateStatusProvider provider = (UpToDateStatusProvider) p.next();
  367. UpToDateStatus newType = provider.getUpToDate();
  368. if (newType.compareTo(statusType) > 0) {
  369. statusType = newType;
  370. }
  371. }
  372. return statusType;
  373. }
  374. @Override
  375. public void propertyChange(PropertyChangeEvent evt) {
  376. if ("marks".equals(evt.getPropertyName())) {
  377. synchronized (this) {
  378. @SuppressWarnings("unchecked")
  379. Collection<Mark> nue = (Collection<Mark>) evt.getNewValue();
  380. @SuppressWarnings("unchecked")
  381. Collection<Mark> old = (Collection<Mark>) evt.getOldValue();
  382. if (nue == null && evt.getSource() instanceof MarkProvider)
  383. nue = ((MarkProvider) evt.getSource()).getMarks();
  384. if (old != null && nue != null) {
  385. Collection<Mark> added = new LinkedHashSet<Mark>(nue);
  386. Collection<Mark> removed = new LinkedHashSet<Mark>(old);
  387. added.removeAll(old);
  388. removed.removeAll(nue);
  389. if (marksMap != null) {
  390. for(Mark mark : removed) {
  391. unregisterMark(mark);
  392. }
  393. for(Mark mark : added) {
  394. registerMark(mark);
  395. }
  396. }
  397. if (currentMarks != null) {
  398. LinkedHashSet<Mark> copy = new LinkedHashSet<Mark>(currentMarks);
  399. copy.removeAll(removed);
  400. copy.addAll(added);
  401. currentMarks = copy;
  402. }
  403. view.fullRepaint();
  404. } else {
  405. LOG.warning("For performance reasons, the providers should fill both old and new value in property changes. Problematic event: " + evt);
  406. clear();
  407. view.fullRepaint();
  408. }
  409. return ;
  410. }
  411. }
  412. if (UpToDateStatusProvider.PROP_UP_TO_DATE.equals(evt.getPropertyName())) {
  413. view.fullRepaint(false);
  414. return ;
  415. }
  416. }
  417. public synchronized void clear() {
  418. currentMarks = null;
  419. marksMap = null;
  420. }
  421. public int[] computeErrorsAndWarnings() {
  422. int errors = 0;
  423. int warnings = 0;
  424. Collection<Mark> marks = getMergedMarks();
  425. for(Mark mark : marks) {
  426. Status s = mark.getStatus();
  427. errors += s == Status.STATUS_ERROR ? 1 : 0;
  428. warnings += s == Status.STATUS_WARNING ? 1 : 0;
  429. }
  430. for (AnnotationDesc desc : NbCollections.iterable(listAnnotations(-1, Integer.MAX_VALUE))) {
  431. Status s = get(desc.getAnnotationTypeInstance());
  432. if (s != null) {
  433. errors += s == Status.STATUS_ERROR ? 1 : 0;
  434. warnings += s == Status.STATUS_WARNING ? 1 : 0;
  435. }
  436. }
  437. return new int[] {errors, warnings};
  438. }
  439. public void changedLine(int Line) {
  440. changedAll();
  441. }
  442. public void changedAll() {
  443. view.fullRepaint(false);
  444. }
  445. static Status get(Severity severity) {
  446. if (severity == Severity.STATUS_ERROR)
  447. return Status.STATUS_ERROR;
  448. if (severity == Severity.STATUS_WARNING)
  449. return Status.STATUS_WARNING;
  450. if (severity == Severity.STATUS_OK)
  451. return Status.STATUS_OK;
  452. return null;
  453. }
  454. static Status get(AnnotationType ann) {
  455. return get(ann.getSeverity());
  456. }
  457. private Iterator<? extends AnnotationDesc> listAnnotations(final int startLine, final int endLine) {
  458. final Annotations annotations = document.getAnnotations();
  459. return new Iterator<AnnotationDesc>() {
  460. private final List<AnnotationDesc> remaining = new ArrayList<AnnotationDesc>();
  461. private int line = startLine;
  462. private int last = (-1);
  463. private int unchagedLoops = 0;
  464. private boolean stop = false;
  465. @Override public boolean hasNext() {
  466. if (stop) return false;
  467. if (remaining.isEmpty()) {
  468. if ((line = annotations.getNextLineWithAnnotation(line)) <= endLine && line != (-1)) {
  469. if (last == line) {
  470. unchagedLoops++;
  471. if (unchagedLoops >= 100) {
  472. LOG.log(Level.WARNING, "Please add the following info to https://netbeans.org/bugzilla/show_bug.cgi?id=188843 : Possible infinite loop in getMainMarkForBlockAnnotations, debug data: {0}, unchaged loops: {1}", new Object[]{annotations.toString(), unchagedLoops});
  473. stop = true;
  474. return false;
  475. }
  476. } else {
  477. if (line < last) {
  478. LOG.log(Level.WARNING, "Please add the following info to https://netbeans.org/bugzilla/show_bug.cgi?id=188843 : line < last: {0} < {1}", new Object[]{line, last});
  479. stop = true;
  480. return false;
  481. }
  482. last = line;
  483. unchagedLoops = 0;
  484. }
  485. AnnotationDesc desc = annotations.getActiveAnnotation(line);
  486. if (desc != null) {
  487. remaining.add(desc);
  488. }
  489. if (annotations.getNumberOfAnnotations(line) > 1) {
  490. AnnotationDesc[] descriptions = annotations.getPassiveAnnotationsForLine(line);
  491. if (descriptions != null) {
  492. remaining.addAll(Arrays.asList(descriptions));
  493. }
  494. }
  495. line++;
  496. }
  497. }
  498. return !(stop = remaining.isEmpty());
  499. }
  500. @Override public AnnotationDesc next() {
  501. if (hasNext()) {
  502. return remaining.remove(0);
  503. } else {
  504. throw new NoSuchElementException();
  505. }
  506. }
  507. @Override public void remove() {
  508. throw new UnsupportedOperationException("Not supported yet.");
  509. }
  510. };
  511. }
  512. // XXX: This is here to help to deal with legacy code
  513. // that registered stuff in text/base. The artificial text/base
  514. // mime type is deprecated and should not be used anymore.
  515. @MimeLocation(subfolderName=UP_TO_DATE_STATUS_PROVIDER_FOLDER_NAME, instanceProviderClass=LegacyCrapProvider.class)
  516. public static final class LegacyCrapProvider implements InstanceProvider {
  517. private final List<FileObject> instanceFiles;
  518. private List<MarkProviderCreator> creators;
  519. private List<UpToDateStatusProviderFactory> factories;
  520. public LegacyCrapProvider() {
  521. this(null);
  522. }
  523. public LegacyCrapProvider(List<FileObject> files) {
  524. this.instanceFiles = files;
  525. }
  526. public Collection<? extends MarkProviderCreator> getMarkProviderCreators() {
  527. if (creators == null) {
  528. computeInstances();
  529. }
  530. return creators;
  531. }
  532. public Collection<? extends UpToDateStatusProviderFactory> getUpToDateStatusProviderFactories() {
  533. if (factories == null) {
  534. computeInstances();
  535. }
  536. return factories;
  537. }
  538. public Object createInstance(List fileObjectList) {
  539. ArrayList<FileObject> textBaseFilesList = new ArrayList<FileObject>();
  540. for(Object o : fileObjectList) {
  541. FileObject fileObject = null;
  542. if (o instanceof FileObject) {
  543. fileObject = (FileObject) o;
  544. } else {
  545. continue;
  546. }
  547. String fullPath = fileObject.getPath();
  548. int idx = fullPath.lastIndexOf(UP_TO_DATE_STATUS_PROVIDER_FOLDER_NAME);
  549. assert idx != -1 : "Expecting files with '" + UP_TO_DATE_STATUS_PROVIDER_FOLDER_NAME + "' in the path: " + fullPath; //NOI18N
  550. String path = fullPath.substring(0, idx);
  551. if (TEXT_BASE_PATH.equals(path)) {
  552. textBaseFilesList.add(fileObject);
  553. if (LOG.isLoggable(Level.WARNING)) {
  554. LOG.warning("The 'text/base' mime type is deprecated, please move your file to the root. Offending file: " + fullPath); //NOI18N
  555. }
  556. }
  557. }
  558. return new LegacyCrapProvider(textBaseFilesList);
  559. }
  560. private void computeInstances() {
  561. ArrayList<MarkProviderCreator> newCreators = new ArrayList<MarkProviderCreator>();
  562. ArrayList<UpToDateStatusProviderFactory> newFactories = new ArrayList<UpToDateStatusProviderFactory>();
  563. for(FileObject f : instanceFiles) {
  564. if (!f.isValid() || !f.isData()) {
  565. continue;
  566. }
  567. try {
  568. DataObject d = DataObject.find(f);
  569. InstanceCookie ic = d.getLookup().lookup(InstanceCookie.class);
  570. if (ic != null) {
  571. if (MarkProviderCreator.class.isAssignableFrom(ic.instanceClass())) {
  572. MarkProviderCreator creator = (MarkProviderCreator) ic.instanceCreate();
  573. newCreators.add(creator);
  574. } else if (UpToDateStatusProviderFactory.class.isAssignableFrom(ic.instanceClass())) {
  575. UpToDateStatusProviderFactory factory = (UpToDateStatusProviderFactory) ic.instanceCreate();
  576. newFactories.add(factory);
  577. }
  578. }
  579. } catch (Exception e) {
  580. LOG.log(Level.WARNING, null, e);
  581. }
  582. }
  583. this.creators = newCreators;
  584. this.factories = newFactories;
  585. }
  586. } // End of LegacyToolbarActionsProvider class
  587. }