Changeset 7447 in josm


Ignore:
Timestamp:
2014-08-27T17:40:39+02:00 (10 years ago)
Author:
bastiK
Message:

fixed #10425 - ConcurrentModificationException when auto update mappaint file

Location:
trunk/src/org/openstreetmap/josm
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java

    r7423 r7447  
    6969import org.openstreetmap.josm.gui.mappaint.StyleCache.StyleList;
    7070import org.openstreetmap.josm.gui.mappaint.TextElement;
     71import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource;
    7172import org.openstreetmap.josm.gui.mappaint.mapcss.Selector;
    7273import org.openstreetmap.josm.tools.CompositeList;
     
    13421343        @Override
    13431344        public List<StyleRecord> call() throws Exception {
    1344             for (int i = from; i<to; i++) {
    1345                 OsmPrimitive osm = input.get(i);
    1346                 if (osm.isDrawable()) {
    1347                     osm.accept(this);
    1348                 }
    1349             }
    1350             return output;
     1345            synchronized (MapCSSStyleSource.STYLE_SOURCE_LOCK) {
     1346                for (int i = from; i<to; i++) {
     1347                    OsmPrimitive osm = input.get(i);
     1348                    if (osm.isDrawable()) {
     1349                        osm.accept(this);
     1350                    }
     1351                }
     1352                return output;
     1353            }
    13511354        }
    13521355
  • trunk/src/org/openstreetmap/josm/gui/NavigatableComponent.java

    r7389 r7447  
    4949import org.openstreetmap.josm.gui.help.Helpful;
    5050import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
     51import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource;
    5152import org.openstreetmap.josm.gui.preferences.projection.ProjectionPreference;
    5253import org.openstreetmap.josm.tools.Predicate;
     
    9091            if (!prim.isSelectable()) return false;
    9192            // if it isn't displayed on screen, you cannot click on it
    92             return !MapPaintStyles.getStyles().get(prim, getDist100Pixel(), NavigatableComponent.this).isEmpty();
     93            synchronized (MapCSSStyleSource.STYLE_SOURCE_LOCK) {
     94                return !MapPaintStyles.getStyles().get(prim, getDist100Pixel(), NavigatableComponent.this).isEmpty();
     95            }
    9396        }
    9497    };
  • trunk/src/org/openstreetmap/josm/gui/dialogs/InspectPrimitiveDialog.java

    r7299 r7447  
    337337        double scale = nc.getDist100Pixel();
    338338
    339         for (OsmPrimitive osm : sel) {
    340             txtMappaint.append(tr("Styles Cache for \"{0}\":", osm.getDisplayName(DefaultNameFormatter.getInstance())));
    341 
    342             MultiCascade mc = new MultiCascade();
    343 
    344             for (StyleSource s : elemstyles.getStyleSources()) {
    345                 if (s.active) {
    346                     txtMappaint.append(tr("\n\n> applying {0} style \"{1}\"\n", getSort(s), s.getDisplayString()));
    347                     s.apply(mc, osm, scale, null, false);
    348                     txtMappaint.append(tr("\nRange:{0}", mc.range));
    349                     for (Entry<String, Cascade> e : mc.getLayers()) {
    350                         txtMappaint.append("\n " + e.getKey() + ": \n" + e.getValue());
     339        synchronized (MapCSSStyleSource.STYLE_SOURCE_LOCK) {
     340            for (OsmPrimitive osm : sel) {
     341                txtMappaint.append(tr("Styles Cache for \"{0}\":", osm.getDisplayName(DefaultNameFormatter.getInstance())));
     342
     343                MultiCascade mc = new MultiCascade();
     344
     345                for (StyleSource s : elemstyles.getStyleSources()) {
     346                    if (s.active) {
     347                        txtMappaint.append(tr("\n\n> applying {0} style \"{1}\"\n", getSort(s), s.getDisplayString()));
     348                        s.apply(mc, osm, scale, null, false);
     349                        txtMappaint.append(tr("\nRange:{0}", mc.range));
     350                        for (Entry<String, Cascade> e : mc.getLayers()) {
     351                            txtMappaint.append("\n " + e.getKey() + ": \n" + e.getValue());
     352                        }
     353                    } else {
     354                        txtMappaint.append(tr("\n\n> skipping \"{0}\" (not active)", s.getDisplayString()));
    351355                    }
    352                 } else {
    353                     txtMappaint.append(tr("\n\n> skipping \"{0}\" (not active)", s.getDisplayString()));
    354                 }
    355             }
    356             txtMappaint.append(tr("\n\nList of generated Styles:\n"));
    357             StyleList sl = elemstyles.get(osm, scale, nc);
    358             for (ElemStyle s : sl) {
    359                 txtMappaint.append(" * " + s + "\n");
    360             }
    361             txtMappaint.append("\n\n");
    362         }
    363 
     356                }
     357                txtMappaint.append(tr("\n\nList of generated Styles:\n"));
     358                StyleList sl = elemstyles.get(osm, scale, nc);
     359                for (ElemStyle s : sl) {
     360                    txtMappaint.append(" * " + s + "\n");
     361                }
     362                txtMappaint.append("\n\n");
     363            }
     364        }
    364365        if (sel.size() == 2) {
    365366            List<OsmPrimitive> selList = new ArrayList<>(sel);
  • trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java

    r7402 r7447  
    1818import org.openstreetmap.josm.gui.NavigatableComponent;
    1919import org.openstreetmap.josm.gui.mappaint.StyleCache.StyleList;
     20import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource;
    2021import org.openstreetmap.josm.gui.util.GuiHelper;
    2122import org.openstreetmap.josm.tools.Pair;
     
    446447     */
    447448    public static AreaElemStyle getAreaElemStyle(OsmPrimitive p, boolean pretendWayIsClosed) {
    448         if (MapPaintStyles.getStyles() == null)
     449        synchronized (MapCSSStyleSource.STYLE_SOURCE_LOCK) {
     450            if (MapPaintStyles.getStyles() == null)
     451                return null;
     452            for (ElemStyle s : MapPaintStyles.getStyles().generateStyles(p, 1.0, null, pretendWayIsClosed).a) {
     453                if (s instanceof AreaElemStyle)
     454                    return (AreaElemStyle) s;
     455            }
    449456            return null;
    450         for (ElemStyle s : MapPaintStyles.getStyles().generateStyles(p, 1.0, null, pretendWayIsClosed).a) {
    451             if (s instanceof AreaElemStyle)
    452                 return (AreaElemStyle) s;
    453         }
    454         return null;
     457        }
    455458    }
    456459
  • trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java

    r7436 r7447  
    143143            Node virtualNode = new Node(LatLon.ZERO);
    144144            virtualNode.put(tag.getKey(), tag.getValue());
    145             StyleList styleList = getStyles().generateStyles(virtualNode, 0.5, null, false).a;
     145            StyleList styleList;
     146            synchronized (MapCSSStyleSource.STYLE_SOURCE_LOCK) {
     147                styleList = getStyles().generateStyles(virtualNode, 0.5, null, false).a;
     148            }
    146149            if (styleList != null) {
    147150                for (ElemStyle style : styleList) {
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java

    r7193 r7447  
    400400                return e.osm.hasSameInterestingTags(Utils.firstNonNull(e.child, e.parent));
    401401            case "areaStyle":
     402                // only for validator
    402403                return ElemStyles.hasAreaElemStyle(e.osm, false);
    403404            case "unconnected":
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java

    r7248 r7447  
    7070
    7171    /**
     72     * This lock prevents concurrent execution of {@link MapCSSRuleIndex#clear() },
     73     * {@link MapCSSRuleIndex#initIndex()} and {@link MapCSSRuleIndex#getRuleCandidates }.
     74     *
     75     * For efficiency reasons, these methods are synchronized higher up the
     76     * stack trace.
     77     */
     78    public final static Object STYLE_SOURCE_LOCK = new Object();
     79   
     80    /**
    7281     * A collection of {@link MapCSSRule}s, that are indexed by tag key and value.
    7382     *
     
    91100        public final Set<MapCSSRule> remaining = new HashSet<>();
    92101       
     102        private static final boolean DEBUG_LOCKING = false;
     103       
    93104        public void add(MapCSSRule rule) {
    94105            rules.add(rule);
     
    97108        /**
    98109         * Initialize the index.
     110         *
     111         * You must own the lock STYLE_SOURCE_LOCK when calling this method.
    99112         */
    100113        public void initIndex() {
     114            if (DEBUG_LOCKING) {
     115                if (!Thread.holdsLock(STYLE_SOURCE_LOCK)) {
     116                    throw new RuntimeException();
     117                }
     118            }
    101119            for (MapCSSRule r: rules) {
    102120                // find the rightmost selector, this must be a GeneralSelector
     
    135153         * @return a Collection of rules that filters out most of the rules
    136154         * that cannot match, based on the tags of the primitive
     155         *
     156         * You must own the lock STYLE_SOURCE_LOCK when calling this method.
    137157         */
    138158        public Collection<MapCSSRule> getRuleCandidates(OsmPrimitive osm) {
     159            if (DEBUG_LOCKING) {
     160                if (!Thread.holdsLock(STYLE_SOURCE_LOCK)) {
     161                    throw new RuntimeException();
     162                }
     163            }
    139164            List<MapCSSRule> ruleCandidates = new ArrayList<>(remaining);
    140165            for (Map.Entry<String,String> e : osm.getKeys().entrySet()) {
     
    151176        }
    152177
     178        /**
     179         * Clear the index.
     180         *
     181         * You must own the lock STYLE_SOURCE_LOCK when calling this method.
     182         */
    153183        public void clear() {
     184            if (DEBUG_LOCKING) {
     185                if (!Thread.holdsLock(STYLE_SOURCE_LOCK)) {
     186                    throw new RuntimeException();
     187                }
     188            }
    154189            rules.clear();
    155190            index.clear();
     
    181216    @Override
    182217    public void loadStyleSource() {
    183         init();
    184         rules.clear();
    185         nodeRules.clear();
    186         wayRules.clear();
    187         wayNoAreaRules.clear();
    188         relationRules.clear();
    189         multipolygonRules.clear();
    190         canvasRules.clear();
    191         try (InputStream in = getSourceInputStream()) {
    192             try {
    193                 // evaluate @media { ... } blocks
    194                 MapCSSParser preprocessor = new MapCSSParser(in, "UTF-8", MapCSSParser.LexicalState.PREPROCESSOR);
    195                 String mapcss = preprocessor.pp_root(this);
    196 
    197                 // do the actual mapcss parsing
    198                 InputStream in2 = new ByteArrayInputStream(mapcss.getBytes(StandardCharsets.UTF_8));
    199                 MapCSSParser parser = new MapCSSParser(in2, "UTF-8", MapCSSParser.LexicalState.DEFAULT);
    200                 parser.sheet(this);
    201 
    202                 loadMeta();
    203                 loadCanvas();
    204             } finally {
    205                 closeSourceInputStream(in);
    206             }
    207         } catch (IOException e) {
    208             Main.warn(tr("Failed to load Mappaint styles from ''{0}''. Exception was: {1}", url, e.toString()));
    209             Main.error(e);
    210             logError(e);
    211         } catch (TokenMgrError e) {
    212             Main.warn(tr("Failed to parse Mappaint styles from ''{0}''. Error was: {1}", url, e.getMessage()));
    213             Main.error(e);
    214             logError(e);
    215         } catch (ParseException e) {
    216             Main.warn(tr("Failed to parse Mappaint styles from ''{0}''. Error was: {1}", url, e.getMessage()));
    217             Main.error(e);
    218             logError(new ParseException(e.getMessage())); // allow e to be garbage collected, it links to the entire token stream
    219         }
    220         // optimization: filter rules for different primitive types
    221         for (MapCSSRule r: rules) {
    222             // find the rightmost selector, this must be a GeneralSelector
    223             Selector selRightmost = r.selector;
    224             while (selRightmost instanceof ChildOrParentSelector) {
    225                 selRightmost = ((ChildOrParentSelector) selRightmost).right;
    226             }
    227             MapCSSRule optRule = new MapCSSRule(r.selector.optimizedBaseCheck(), r.declaration);
    228             final String base = ((GeneralSelector) selRightmost).getBase();
    229             switch (base) {
    230                 case "node":
    231                     nodeRules.add(optRule);
    232                     break;
    233                 case "way":
    234                     wayNoAreaRules.add(optRule);
    235                     wayRules.add(optRule);
    236                     break;
    237                 case "area":
    238                     wayRules.add(optRule);
    239                     multipolygonRules.add(optRule);
    240                     break;
    241                 case "relation":
    242                     relationRules.add(optRule);
    243                     multipolygonRules.add(optRule);
    244                     break;
    245                 case "*":
    246                     nodeRules.add(optRule);
    247                     wayRules.add(optRule);
    248                     wayNoAreaRules.add(optRule);
    249                     relationRules.add(optRule);
    250                     multipolygonRules.add(optRule);
    251                     break;
    252                 case "canvas":
    253                     canvasRules.add(r);
    254                     break;
    255                 case "meta":
    256                     break;
    257                 default:
    258                     final RuntimeException e = new RuntimeException(MessageFormat.format("Unknown MapCSS base selector {0}", base));
    259                     Main.warn(tr("Failed to parse Mappaint styles from ''{0}''. Error was: {1}", url, e.getMessage()));
    260                     Main.error(e);
    261                     logError(e);
    262             }
    263         }
    264         nodeRules.initIndex();
    265         wayRules.initIndex();
    266         wayNoAreaRules.initIndex();
    267         relationRules.initIndex();
    268         multipolygonRules.initIndex();
    269         canvasRules.initIndex();
     218        synchronized (STYLE_SOURCE_LOCK) {
     219            init();
     220            rules.clear();
     221            nodeRules.clear();
     222            wayRules.clear();
     223            wayNoAreaRules.clear();
     224            relationRules.clear();
     225            multipolygonRules.clear();
     226            canvasRules.clear();
     227            try (InputStream in = getSourceInputStream()) {
     228                try {
     229                    // evaluate @media { ... } blocks
     230                    MapCSSParser preprocessor = new MapCSSParser(in, "UTF-8", MapCSSParser.LexicalState.PREPROCESSOR);
     231                    String mapcss = preprocessor.pp_root(this);
     232
     233                    // do the actual mapcss parsing
     234                    InputStream in2 = new ByteArrayInputStream(mapcss.getBytes(StandardCharsets.UTF_8));
     235                    MapCSSParser parser = new MapCSSParser(in2, "UTF-8", MapCSSParser.LexicalState.DEFAULT);
     236                    parser.sheet(this);
     237
     238                    loadMeta();
     239                    loadCanvas();
     240                } finally {
     241                    closeSourceInputStream(in);
     242                }
     243            } catch (IOException e) {
     244                Main.warn(tr("Failed to load Mappaint styles from ''{0}''. Exception was: {1}", url, e.toString()));
     245                Main.error(e);
     246                logError(e);
     247            } catch (TokenMgrError e) {
     248                Main.warn(tr("Failed to parse Mappaint styles from ''{0}''. Error was: {1}", url, e.getMessage()));
     249                Main.error(e);
     250                logError(e);
     251            } catch (ParseException e) {
     252                Main.warn(tr("Failed to parse Mappaint styles from ''{0}''. Error was: {1}", url, e.getMessage()));
     253                Main.error(e);
     254                logError(new ParseException(e.getMessage())); // allow e to be garbage collected, it links to the entire token stream
     255            }
     256            // optimization: filter rules for different primitive types
     257            for (MapCSSRule r: rules) {
     258                // find the rightmost selector, this must be a GeneralSelector
     259                Selector selRightmost = r.selector;
     260                while (selRightmost instanceof ChildOrParentSelector) {
     261                    selRightmost = ((ChildOrParentSelector) selRightmost).right;
     262                }
     263                MapCSSRule optRule = new MapCSSRule(r.selector.optimizedBaseCheck(), r.declaration);
     264                final String base = ((GeneralSelector) selRightmost).getBase();
     265                switch (base) {
     266                    case "node":
     267                        nodeRules.add(optRule);
     268                        break;
     269                    case "way":
     270                        wayNoAreaRules.add(optRule);
     271                        wayRules.add(optRule);
     272                        break;
     273                    case "area":
     274                        wayRules.add(optRule);
     275                        multipolygonRules.add(optRule);
     276                        break;
     277                    case "relation":
     278                        relationRules.add(optRule);
     279                        multipolygonRules.add(optRule);
     280                        break;
     281                    case "*":
     282                        nodeRules.add(optRule);
     283                        wayRules.add(optRule);
     284                        wayNoAreaRules.add(optRule);
     285                        relationRules.add(optRule);
     286                        multipolygonRules.add(optRule);
     287                        break;
     288                    case "canvas":
     289                        canvasRules.add(r);
     290                        break;
     291                    case "meta":
     292                        break;
     293                    default:
     294                        final RuntimeException e = new RuntimeException(MessageFormat.format("Unknown MapCSS base selector {0}", base));
     295                        Main.warn(tr("Failed to parse Mappaint styles from ''{0}''. Error was: {1}", url, e.getMessage()));
     296                        Main.error(e);
     297                        logError(e);
     298                }
     299            }
     300            nodeRules.initIndex();
     301            wayRules.initIndex();
     302            wayNoAreaRules.initIndex();
     303            relationRules.initIndex();
     304            multipolygonRules.initIndex();
     305            canvasRules.initIndex();
     306        }
    270307    }
    271308   
Note: See TracChangeset for help on using the changeset viewer.