1.1 --- a/nodejs/manifest.mf Sun Jun 05 17:21:05 2011 -0400
1.2 +++ b/nodejs/manifest.mf Mon Jun 06 00:50:24 2011 -0400
1.3 @@ -3,5 +3,5 @@
1.4 OpenIDE-Module-Layer: org/netbeans/modules/nodejs/layer.xml
1.5 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/nodejs/Bundle.properties
1.6 OpenIDE-Module-Requires: org.openide.modules.os.Unix
1.7 -OpenIDE-Module-Specification-Version: 1.12
1.8 +OpenIDE-Module-Specification-Version: 1.13
1.9
2.1 --- a/nodejs/src/org/netbeans/modules/nodejs/ProjectMetadataImpl.java Sun Jun 05 17:21:05 2011 -0400
2.2 +++ b/nodejs/src/org/netbeans/modules/nodejs/ProjectMetadataImpl.java Mon Jun 06 00:50:24 2011 -0400
2.3 @@ -49,11 +49,11 @@
2.4 import java.util.ArrayList;
2.5 import java.util.Arrays;
2.6 import java.util.Collections;
2.7 -import java.util.HashMap;
2.8 import java.util.Iterator;
2.9 import java.util.LinkedHashMap;
2.10 import java.util.List;
2.11 import java.util.Map;
2.12 +import java.util.concurrent.locks.ReentrantLock;
2.13 import java.util.logging.Level;
2.14 import java.util.logging.Logger;
2.15 import org.netbeans.api.project.Project;
2.16 @@ -67,6 +67,7 @@
2.17 import org.openide.filesystems.FileAlreadyLockedException;
2.18 import org.openide.filesystems.FileChangeAdapter;
2.19 import org.openide.filesystems.FileEvent;
2.20 +import org.openide.filesystems.FileLock;
2.21 import org.openide.filesystems.FileObject;
2.22 import org.openide.filesystems.FileSystem.AtomicAction;
2.23 import org.openide.filesystems.FileUtil;
2.24 @@ -106,7 +107,7 @@
2.25 return toString(getMap().get(key));
2.26 }
2.27 }
2.28 -
2.29 +
2.30 public List<?> getValues(String key) {
2.31 Object result = null;
2.32 if (key.indexOf('.') > 0) {
2.33 @@ -167,52 +168,69 @@
2.34 private volatile Map<String, Object> map;
2.35 private volatile boolean hasErrors;
2.36 private volatile boolean listening;
2.37 + private final ReentrantLock lock = new ReentrantLock();
2.38 +
2.39 + private Map<String, Object> load(FileObject fo) throws IOException {
2.40 + lock.lock();
2.41 + boolean err = false;
2.42 + try {
2.43 + synchronized (this) {
2.44 + if (map != null) {
2.45 + return map;
2.46 + }
2.47 + }
2.48 + FileLock fileLock = fo.lock();
2.49 + try {
2.50 + SimpleJSONParser p = new SimpleJSONParser(true); //permissive mode - will parse as much as it can
2.51 + Map<String, Object> m = p.parse(fo);
2.52 + ProjectMetadataImpl.this.hasErrors = err = p.hasErrors();
2.53 + synchronized (this) {
2.54 + map = Collections.synchronizedMap(m);
2.55 + return map;
2.56 + }
2.57 + } catch (JsonException ex) {
2.58 + Logger.getLogger(ProjectMetadataImpl.class.getName()).log(Level.INFO,
2.59 + "Bad package.json in " + fo.getPath(), ex);
2.60 + return new LinkedHashMap<String, Object>();
2.61 + } finally {
2.62 + fileLock.releaseLock();
2.63 + }
2.64 + } finally {
2.65 + lock.unlock();
2.66 + if (err) {
2.67 + StatusDisplayer.getDefault().setStatusText(NbBundle.getMessage(ProjectMetadataImpl.class, "ERROR_PARSING_PACKAGE_JSON", project.getLookup().lookup(ProjectInformation.class).getDisplayName()), 3);
2.68 + }
2.69 + }
2.70 + }
2.71
2.72 private final Map<String, Object> getMap() {
2.73 - if (map != null) {
2.74 + Map<String, Object> result = map;
2.75 + if (result == null) {
2.76 synchronized (this) {
2.77 - return map;
2.78 + result = map;
2.79 }
2.80 }
2.81 - final FileObject fo = project.getProjectDirectory().getFileObject("package.json");
2.82 - if (fo != null) {
2.83 + if (result == null) {
2.84 + final FileObject fo = project.getProjectDirectory().getFileObject("package.json");
2.85 + if (fo == null) {
2.86 + return new LinkedHashMap<String, Object>();
2.87 + }
2.88 + if (!listening) {
2.89 + listening = true;
2.90 + fo.addFileChangeListener(FileUtil.weakFileChangeListener(this, fo));
2.91 + }
2.92 try {
2.93 - final boolean[] err = new boolean[1];
2.94 - Map<String, Object> m = ProjectManager.mutex().readAccess(new Mutex.ExceptionAction<Map<String, Object>>() {
2.95 -
2.96 - @Override
2.97 - public Map<String, Object> run() throws Exception {
2.98 - if (!listening) {
2.99 - fo.addFileChangeListener(FileUtil.weakFileChangeListener(ProjectMetadataImpl.this, fo));
2.100 - listening = true;
2.101 - }
2.102 - try {
2.103 - SimpleJSONParser p = new SimpleJSONParser(true); //permissive mode - will parse as much as it can
2.104 - Map<String, Object> m = p.parse(fo);
2.105 - ProjectMetadataImpl.this.hasErrors = err[0] = p.hasErrors();
2.106 - synchronized (ProjectMetadataImpl.this) {
2.107 - map = Collections.synchronizedMap(m);
2.108 - }
2.109 - return m;
2.110 - } catch (JsonException ex) {
2.111 - throw new MutexException(ex);
2.112 - } catch (IOException ex) {
2.113 - throw new MutexException(ex);
2.114 - }
2.115 - }
2.116 - });
2.117 - if (err[0]) {
2.118 - StatusDisplayer.getDefault().setStatusText(NbBundle.getMessage(ProjectMetadataImpl.class, "ERROR_PARSING_PACKAGE_JSON", project.getLookup().lookup(ProjectInformation.class).getDisplayName()), 3);
2.119 + result = load(fo);
2.120 + synchronized (this) {
2.121 + map = result;
2.122 }
2.123 - return m;
2.124 - } catch (MutexException ex) {
2.125 + } catch (IOException ioe) {
2.126 Logger.getLogger(ProjectMetadataImpl.class.getName()).log(Level.INFO,
2.127 - "Bad package.json in " + fo.getPath(), ex);
2.128 + "Problems loading " + fo.getPath(), ioe);
2.129 + result = new LinkedHashMap<String,Object>();
2.130 }
2.131 }
2.132 - synchronized (this) {
2.133 - return map == null ? new LinkedHashMap<String, Object>() : map;
2.134 - }
2.135 + return result;
2.136 }
2.137 volatile int saveCount;
2.138
3.1 --- a/nodejs/src/org/netbeans/modules/nodejs/json/SimpleJSONParser.java Sun Jun 05 17:21:05 2011 -0400
3.2 +++ b/nodejs/src/org/netbeans/modules/nodejs/json/SimpleJSONParser.java Mon Jun 06 00:50:24 2011 -0400
3.3 @@ -57,7 +57,6 @@
3.4 import java.util.Stack;
3.5 import java.util.logging.Level;
3.6 import java.util.logging.Logger;
3.7 -import org.openide.filesystems.FileLock;
3.8 import org.openide.filesystems.FileObject;
3.9 import org.openide.filesystems.FileUtil;
3.10 import org.openide.util.Utilities;
3.11 @@ -108,12 +107,7 @@
3.12 }
3.13
3.14 public Map<String, Object> parse(FileObject in) throws JsonException, IOException {
3.15 - FileLock lock = in.lock();
3.16 - try {
3.17 - return parse(in.asText());
3.18 - } finally {
3.19 - lock.releaseLock();
3.20 - }
3.21 + return parse(in.asText());
3.22 }
3.23
3.24 public Map<String, Object> parse(InputStream in) throws JsonException, IOException {